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...
# - override the host settings (for cross compiles
# - 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"
_cp=cp
_windowspath=""
_sdlconfig=sdl2-config
_sdlpath="$PATH"
_prefix=/usr/local
@ -817,8 +816,8 @@ fi
#
# Now, add the appropriate defines/libraries/headers
#
echo
find_sdlconfig
#echo
#find_sdlconfig
SRC="src"
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="$INCLUDES `$_sdlconfig --cflags`"
if test "$_build_static" = yes ; then
_sdl_conf_libs="--static-libs"
LDFLAGS="-static $LDFLAGS"
else
_sdl_conf_libs="--libs"
fi
#INCLUDES="$INCLUDES `$_sdlconfig --cflags`"
#if test "$_build_static" = yes ; then
# _sdl_conf_libs="--static-libs"
# LDFLAGS="-static $LDFLAGS"
#else
# _sdl_conf_libs="--libs"
#fi
#if test "$_libpng" = yes ; then #FIXME:
LIBS="$LIBS `$_pkg_config --libs sdl3`"
#fi
LIBS="$LIBS `$_sdlconfig $_sdl_conf_libs`"
LD=$CXX
case $_host_os in

View File

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

View File

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

View File

@ -35,7 +35,7 @@ FBBackendSDL::FBBackendSDL(OSystem& osystem)
ASSERT_MAIN_THREAD;
// Initialize SDL context
if(SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
if(!SDL_InitSubSystem(SDL_INIT_VIDEO))
{
ostringstream buf;
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)
// since the structure may be needed before any FBSurface's have
// been created
myPixelFormat = SDL_AllocFormat(SDL_PIXELFORMAT_ARGB8888);
myPixelFormat = SDL_GetPixelFormatDetails(SDL_PIXELFORMAT_ARGB8888);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -55,8 +55,6 @@ FBBackendSDL::~FBBackendSDL()
{
ASSERT_MAIN_THREAD;
SDL_FreeFormat(myPixelFormat);
if(myRenderer)
{
SDL_DestroyRenderer(myRenderer);
@ -69,7 +67,7 @@ FBBackendSDL::~FBBackendSDL()
SDL_DestroyWindow(myWindow);
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;
// 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
SDL_DisplayMode display{};
for(int i = 0; i < myNumDisplays; ++i)
// Get the maximum fullscreen and windowed desktop resolutions
for(uInt32 i = 0; i < myNumDisplays; ++i)
{
SDL_GetDesktopDisplayMode(i, &display);
fullscreenRes.emplace_back(display.w, display.h);
// Fullscreen mode
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)
const int numModes = SDL_GetNumDisplayModes(i);
ostringstream s;
@ -113,46 +123,21 @@ void FBBackendSDL::queryHardware(vector<Common::Size>& fullscreenRes,
s << " " << lastRes << ": ";
}
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 << "* ";
else
s << " ";
}
Logger::debug(s.view());
#endif
}
// 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
SDL_free(displays);
struct RenderName
{
string sdlName;
string stellaName;
string_view sdlName;
string_view stellaName;
};
// Create name map for all currently known SDL renderers
static const std::array<RenderName, 8> RENDERER_NAMES = {{
@ -169,22 +154,22 @@ void FBBackendSDL::queryHardware(vector<Common::Size>& fullscreenRes,
const int numDrivers = SDL_GetNumRenderDrivers();
for(int i = 0; i < numDrivers; ++i)
{
SDL_RendererInfo info;
if(SDL_GetRenderDriverInfo(i, &info) == 0)
const char* const rendername = SDL_GetRenderDriver(i);
if(rendername)
{
// Map SDL names into nicer Stella names (if available)
bool found = false;
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;
break;
}
}
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;
return !myCenter
&& myWindow && !(SDL_GetWindowFlags(myWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP);
return myWindow && !fullScreen() && !myCenter;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -210,11 +194,11 @@ Common::Point FBBackendSDL::getCurrentWindowPos() const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int32 FBBackendSDL::getCurrentDisplayIndex() const
uInt32 FBBackendSDL::getCurrentDisplayID() const
{
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;
// cerr << mode << '\n';
// If not initialized by this point, then immediately fail
if(SDL_WasInit(SDL_INIT_VIDEO) == 0)
return false;
const bool fullScreen = mode.fsIndex != -1;
const Int32 displayIndex = std::min(myNumDisplays - 1, winIdx);
const uInt32 displayIndex = std::min<uInt32>(myNumDisplays, winIdx);
int posX = 0, posY = 0;
myCenter = myOSystem.settings().getBool("center");
@ -259,11 +243,12 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
posY = BSPF::clamp(posY, y0 + 50, y1 - 50);
}
#if 0 // FIXME: adaptable
#ifdef ADAPTABLE_REFRESH_SUPPORT
SDL_DisplayMode adaptedSdlMode{};
const int gameRefreshRate =
myOSystem.hasConsole() ? myOSystem.console().gameRefreshRate() : 0;
const bool shouldAdapt = fullScreen
const bool shouldAdapt = mode.fullscreen
&& myOSystem.settings().getBool("tia.fs_refresh")
&& gameRefreshRate
// take care of 59.94 Hz
@ -274,21 +259,19 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
#else
const bool adaptRefresh = false;
#endif
const uInt32 flags = SDL_WINDOW_ALLOW_HIGHDPI
| (fullScreen ? adaptRefresh ? SDL_WINDOW_FULLSCREEN :
SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
#endif
// 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
if(myWindow)
{
const int d = SDL_GetWindowDisplayIndex(myWindow);
const uInt32 d = getCurrentDisplayID();
int w{0}, h{0};
SDL_GetWindowSize(myWindow, &w, &h);
if(d != displayIndex ||
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
SDL_DestroyRenderer(myRenderer);
@ -306,8 +289,27 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
}
else
{
myWindow = SDL_CreateWindow(myScreenTitle.c_str(), posX, posY,
mode.screenS.w, mode.screenS.h, flags);
// Re-create with new properties
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)
{
const string msg = "ERROR: Unable to open SDL window: " + string(SDL_GetError());
@ -318,6 +320,7 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
setWindowIcon();
}
#if 0 // FIXME: adaptable
#ifdef ADAPTABLE_REFRESH_SUPPORT
if(adaptRefresh)
{
@ -339,15 +342,26 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
cerr << setSdlMode.refresh_rate << "Hz\n";
}
}
#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,
SDL_DisplayMode& adaptedSdlMode)
{
#if 0 // FIXME: adaptable
ASSERT_MAIN_THREAD;
SDL_DisplayMode sdlMode;
@ -402,6 +416,8 @@ bool FBBackendSDL::adaptRefreshRate(Int32 displayIndex,
// Only change if the display supports a better refresh rate
return adapt;
#endif
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -411,32 +427,40 @@ bool FBBackendSDL::createRenderer()
// A new renderer is only created when necessary:
// - no renderer existing
// - different renderer flags
// - 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;
uInt32 renderFlags = SDL_RENDERER_ACCELERATED;
const string& video = myOSystem.settings().getString("video"); // Render hint
SDL_RendererInfo renderInfo{};
if(myRenderer)
{
recreate = recreate || video != SDL_GetRendererName(myRenderer);
if(myOSystem.settings().getBool("vsync")
&& !myOSystem.settings().getBool("turbo")) // V'synced blits option
renderFlags |= SDL_RENDERER_PRESENTVSYNC;
// check renderer flags and name
recreate |= (SDL_GetRendererInfo(myRenderer, &renderInfo) != 0)
|| ((renderInfo.flags & (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)) != renderFlags
|| (video != renderInfo.name));
SDL_PropertiesID props = SDL_GetRendererProperties(myRenderer);
const bool currentVSync = SDL_GetNumberProperty(props,
SDL_PROP_RENDERER_VSYNC_NUMBER, 0) != 0;
recreate = recreate || currentVSync != enableVSync;
}
if(recreate)
{
//cerr << "Create new renderer for buffer type #" << int(myBufferType) << '\n';
if(myRenderer)
SDL_DestroyRenderer(myRenderer);
// Re-create with new properties
SDL_PropertiesID props = SDL_CreateProperties();
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();
determineDimensions();
@ -450,10 +474,9 @@ bool FBBackendSDL::createRenderer()
}
clear();
SDL_RendererInfo renderinfo;
if(SDL_GetRendererInfo(myRenderer, &renderinfo) >= 0)
myOSystem.settings().setValue("video", renderinfo.name);
const char* const detectedvideo = SDL_GetRendererName(myRenderer);
if(detectedvideo)
myOSystem.settings().setValue("video", detectedvideo);
return true;
}
@ -466,7 +489,7 @@ void FBBackendSDL::setTitle(string_view title)
myScreenTitle = title;
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;
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';
if(info.max_texture_width > 0 && info.max_texture_height > 0)
out << " Max texture: " << info.max_texture_width << "x"
<< info.max_texture_height << '\n';
out << " Renderer: "
<< SDL_GetStringProperty(props, SDL_PROP_RENDERER_NAME_STRING, "")
<< '\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: "
<< ((info.flags & SDL_RENDERER_PRESENTVSYNC) ? "+" : "-") << "vsync, "
<< ((info.flags & SDL_RENDERER_ACCELERATED) ? "+" : "-") << "accel"
<< (usingVSync ? "+" : "-") << "vsync"
<< '\n';
}
return out.str();
@ -496,7 +524,8 @@ void FBBackendSDL::showCursor(bool show)
{
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;
SDL_SetRelativeMouseMode(grab ? SDL_TRUE : SDL_FALSE);
SDL_SetWindowMouseGrab(myWindow, grab);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -513,7 +542,7 @@ bool FBBackendSDL::fullScreen() const
ASSERT_MAIN_THREAD;
#ifdef WINDOWED_SUPPORT
return SDL_GetWindowFlags(myWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP;
return myIsFullscreen; // TODO: should query SDL directly
#else
return true;
#endif
@ -524,11 +553,11 @@ int FBBackendSDL::refreshRate() const
{
ASSERT_MAIN_THREAD;
const uInt32 displayIndex = SDL_GetWindowDisplayIndex(myWindow);
SDL_DisplayMode sdlMode;
const SDL_DisplayID displayID = getCurrentDisplayID();
const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(displayID);
if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) == 0)
return sdlMode.refresh_rate;
if(mode)
return mode->refresh_rate;
if(myWindow != nullptr)
Logger::error("Could not retrieve current display mode");
@ -552,10 +581,10 @@ void FBBackendSDL::setWindowIcon()
#include "stella_icon.hxx"
ASSERT_MAIN_THREAD;
SDL_Surface* surface = SDL_CreateRGBSurfaceFrom(stella_icon, 32, 32, 32,
32 * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
SDL_Surface* surface =
SDL_CreateSurfaceFrom(32, 32, SDL_PIXELFORMAT_ARGB8888, stella_icon, 32 * 4);
SDL_SetWindowIcon(myWindow, surface);
SDL_FreeSurface(surface);
SDL_DestroySurface(surface);
#endif
}
@ -575,6 +604,10 @@ unique_ptr<FBSurface> FBBackendSDL::createSurface(
void FBBackendSDL::readPixels(uInt8* buffer, size_t pitch,
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;
SDL_Rect r;
@ -582,6 +615,7 @@ void FBBackendSDL::readPixels(uInt8* buffer, size_t pitch,
r.w = rect.w(); r.h = rect.h();
SDL_RenderReadPixels(myRenderer, &r, 0, buffer, static_cast<int>(pitch));
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -609,25 +643,9 @@ bool FBBackendSDL::detectRenderTargetSupport()
if(myRenderer == nullptr)
return false;
SDL_RendererInfo info;
SDL_GetRendererInfo(myRenderer, &info);
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;
// All texture modes except software support render targets
const char* const detectedvideo = SDL_GetRendererName(myRenderer);
return detectedvideo && !BSPF::equalsIgnoreCase(detectedvideo, "software");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -643,5 +661,5 @@ void FBBackendSDL::determineDimensions()
myRenderH = myWindowH;
}
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.
*/
const SDL_PixelFormat& pixelFormat() const { return *myPixelFormat; }
const SDL_PixelFormatDetails& pixelFormat() const { return *myPixelFormat; }
/**
Does the renderer support render targets?
@ -99,7 +99,7 @@ class FBBackendSDL : public FBBackend
@param b The blue component of the color
*/
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.
@ -111,7 +111,7 @@ class FBBackendSDL : public FBBackend
@param a The alpha component of the color.
*/
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.
@ -121,7 +121,7 @@ class FBBackendSDL : public FBBackend
@param b The blue component of the color.
*/
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.
@ -132,7 +132,7 @@ class FBBackendSDL : public FBBackend
@param a The alpha component of the color.
*/
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
@ -167,10 +167,9 @@ class FBBackendSDL : public FBBackend
This method is called to query the video hardware for the index
of the display the current window is displayed on
@return the current display index or a negative value if no
window is displayed
@return the current display index or a 0 if no window is displayed
*/
Int32 getCurrentDisplayIndex() const override;
uInt32 getCurrentDisplayID() const override;
/**
Clear the frame buffer.
@ -286,7 +285,14 @@ class FBBackendSDL : public FBBackend
SDL_Renderer* myRenderer{nullptr};
// 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
bool myCenter{false};
@ -298,7 +304,7 @@ class FBBackendSDL : public FBBackend
string myScreenTitle;
// Number of displays
int myNumDisplays{1};
uInt32 myNumDisplays{0};
// Window and renderer dimensions
int myWindowW{0}, myWindowH{0}, myRenderW{0}, myRenderH{0};

View File

@ -59,7 +59,7 @@ FBSurfaceSDL::~FBSurfaceSDL()
if(mySurface)
{
SDL_FreeSurface(mySurface);
SDL_DestroySurface(mySurface);
mySurface = nullptr;
}
}
@ -75,7 +75,7 @@ void FBSurfaceSDL::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, ColorId colo
tmp.y = y;
tmp.w = w;
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;
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;
// Note: Transparency has to be 0 to clear the rectangle foreground
// 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;
if(mySurface)
SDL_FreeSurface(mySurface);
SDL_DestroySurface(mySurface);
// NOTE: Currently, a resize changes a 'static' surface to 'streaming'
// 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;
// Create a surface in the same format as the parent GL class
const SDL_PixelFormat& pf = myBackend.pixelFormat();
mySurface = SDL_CreateRGBSurface(0, width, height,
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
const SDL_PixelFormatDetails& pf = myBackend.pixelFormat();
mySurface = SDL_CreateSurface(width, height, pf.format);
//SDL_SetSurfaceBlendMode(mySurface, SDL_BLENDMODE_ADD); // default: SDL_BLENDMODE_BLEND
// 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
myPixels = static_cast<uInt32*>(mySurface->pixels);
myPitch = mySurface->pitch / pf.BytesPerPixel;
myPitch = mySurface->pitch / pf.bytes_per_pixel;
////////////////////////////////////////////////////
myIsStatic = data != nullptr;

View File

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

View File

@ -78,10 +78,6 @@ class AudioSettings;
implementations for the various ports of Stella, and always returns a
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
*/
class MediaFactory
@ -181,15 +177,6 @@ class MediaFactory
#endif
}
static bool supportsURL()
{
#if defined(SDL_SUPPORT)
return SDLSupportsURL();
#else
return false;
#endif
}
static bool openURL(const string& url)
{
#if defined(SDL_SUPPORT)

View File

@ -33,48 +33,30 @@
#pragma clang diagnostic ignored "-Wold-style-cast"
#pragma clang diagnostic ignored "-Wreserved-identifier"
#pragma clang diagnostic ignored "-Wswitch-default"
#include <SDL.h>
#include <SDL3/SDL.h>
#pragma clang diagnostic pop
#elif defined(BSPF_WINDOWS)
#pragma warning(push, 0)
#include <SDL.h>
#include <SDL3/SDL.h>
#pragma warning(pop)
#else
#include <SDL.h>
#include <SDL3/SDL.h>
#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()
{
ostringstream buf;
SDL_version ver;
SDL_GetVersion(&ver);
buf << "SDL " << static_cast<int>(ver.major) << "." << static_cast<int>(ver.minor)
<< "." << static_cast<int>(ver.patch);
const int ver = SDL_GetVersion();
buf << "SDL "
<< SDL_VERSIONNUM_MAJOR(ver) << "."
<< SDL_VERSIONNUM_MINOR(ver) << "."
<< SDL_VERSIONNUM_MICRO(ver);
return buf.str();
}
static inline bool SDLSupportsURL()
{
return SDL_VERSION_ATLEAST(2,0,14);
}
static inline bool SDLOpenURL(const string& url)
{
#if SDL_VERSION_ATLEAST(2,0,14)
return SDL_OpenURL(url.c_str()) == 0;
#else
cerr << "OpenURL requires at least SDL 2.0.14\n";
return false;
#endif
return SDL_OpenURL(url.c_str());
}
#endif // SDL_LIB_HXX

View File

@ -104,7 +104,7 @@ bool SoundSDL::openDevice()
SDL_AudioSpec desired;
desired.freq = myAudioSettings.sampleRate();
desired.format = AUDIO_F32SYS;
desired.format = SDL_AUDIO_F32;
desired.channels = 2;
desired.samples = static_cast<Uint16>(myAudioSettings.fragmentSize());
desired.callback = callback;
@ -218,7 +218,12 @@ bool SoundSDL::pause(bool enable)
const bool wasPaused = SDL_GetAudioDeviceStatus(myDevice) == SDL_AUDIO_PAUSED;
if(myIsInitializedFlag)
{
SDL_PauseAudioDevice(myDevice, enable ? 1 : 0);
if (enable ? 1 : 0) {
SDL_PauseAudioDevice(myDevice);
}
else {
SDL_ResumeAudioDevice(myDevice);
}
myWavHandler.pause(enable);
}
return wasPaused;
@ -415,7 +420,7 @@ bool SoundSDL::WavHandlerSDL::play(
{
if(myBuffer)
{
SDL_FreeWAV(myBuffer);
SDL_free(myBuffer);
myBuffer = nullptr;
}
SDL_zero(mySpec);
@ -457,7 +462,7 @@ void SoundSDL::WavHandlerSDL::stop()
// Clean up
myRemaining = 0;
SDL_CloseAudioDevice(myDevice); myDevice = 0;
SDL_FreeWAV(myBuffer); myBuffer = nullptr;
SDL_free(myBuffer); myBuffer = nullptr;
}
if(myCvtBuffer)
{
@ -537,7 +542,12 @@ SoundSDL::WavHandlerSDL::~WavHandlerSDL()
void SoundSDL::WavHandlerSDL::pause(bool state) const
{
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_F24 = 115,
KBDK_EXECUTE = 116,
KBDK_HELP = 117,
KBDK_MENU = 118,
KBDK_HELP = 117, /**< AL Integrated Help Center */
KBDK_MENU = 118, /**< Menu (show menu) */
KBDK_SELECT = 119,
KBDK_STOP = 120,
KBDK_AGAIN = 121, /**< redo */
KBDK_UNDO = 122,
KBDK_CUT = 123,
KBDK_COPY = 124,
KBDK_PASTE = 125,
KBDK_FIND = 126,
KBDK_STOP = 120, /**< AC Stop */
KBDK_AGAIN = 121, /**< AC Redo/Repeat */
KBDK_UNDO = 122, /**< AC Undo */
KBDK_CUT = 123, /**< AC Cut */
KBDK_COPY = 124, /**< AC Copy */
KBDK_PASTE = 125, /**< AC Paste */
KBDK_FIND = 126, /**< AC Find */
KBDK_MUTE = 127,
KBDK_VOLUMEUP = 128,
KBDK_VOLUMEDOWN = 129,
@ -261,9 +261,9 @@ enum StellaKey // NOLINT: use 32-bit, even though 16-bit is sufficient
KBDK_LANG8 = 151, /**< reserved */
KBDK_LANG9 = 152, /**< reserved */
KBDK_ALTERASE = 153, /**< Erase-Eaze */
KBDK_ALTERASE = 153, /**< Erase-Eaze */
KBDK_SYSREQ = 154,
KBDK_CANCEL = 155,
KBDK_CANCEL = 155, /**< AC Cancel */
KBDK_CLEAR = 156,
KBDK_PRIOR = 157,
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_RGUI = 231, /**< windows, command (apple), meta */
KBDK_MODE = 257, /**< ALT-GR(aph) key on non-American keyboards
* This is like pressing KBDK_RALT + KBDK_RCTRL
* on some keyboards
*/
KBDK_MODE = 257, /**< I'm not sure if this is really not covered
* by any of the above, but since there's a
* special SDL_KMOD_MODE for it I'm adding it here
*/
/* @} *//* Usage page 0x07 */
@ -341,77 +341,98 @@ enum StellaKey // NOLINT: use 32-bit, even though 16-bit is sufficient
* \name Usage page 0x0C
*
* 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_AUDIOPREV = 259,
KBDK_AUDIOSTOP = 260,
KBDK_AUDIOPLAY = 261,
KBDK_AUDIOMUTE = 262,
KBDK_MEDIASELECT = 263,
KBDK_WWW = 264,
KBDK_MAIL = 265,
KBDK_CALCULATOR = 266,
KBDK_COMPUTER = 267,
KBDK_AC_SEARCH = 268,
KBDK_AC_HOME = 269,
KBDK_AC_BACK = 270,
KBDK_AC_FORWARD = 271,
KBDK_AC_STOP = 272,
KBDK_AC_REFRESH = 273,
KBDK_AC_BOOKMARKS = 274,
KBDK_SLEEP = 258, /**< Sleep */
KBDK_WAKE = 259, /**< Wake */
KBDK_CHANNEL_INCREMENT = 260, /**< Channel Increment */
KBDK_CHANNEL_DECREMENT = 261, /**< Channel Decrement */
KBDK_MEDIA_PLAY = 262, /**< Play */
KBDK_MEDIA_PAUSE = 263, /**< Pause */
KBDK_MEDIA_RECORD = 264, /**< Record */
KBDK_MEDIA_FAST_FORWARD = 265, /**< Fast Forward */
KBDK_MEDIA_REWIND = 266, /**< Rewind */
KBDK_MEDIA_NEXT_TRACK = 267, /**< Next Track */
KBDK_MEDIA_PREVIOUS_TRACK = 268, /**< Previous Track */
KBDK_MEDIA_STOP = 269, /**< Stop */
KBDK_MEDIA_EJECT = 270, /**< Eject */
KBDK_MEDIA_PLAY_PAUSE = 271, /**< Play / Pause */
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 */
/**
* \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_BRIGHTNESSUP = 276,
KBDK_DISPLAYSWITCH = 277, /**< display mirroring/dual display
switch, video mode switch */
KBDK_KBDILLUMTOGGLE = 278,
KBDK_KBDILLUMDOWN = 279,
KBDK_KBDILLUMUP = 280,
KBDK_EJECT = 281,
KBDK_SLEEP = 282,
KBDK_SOFTLEFT = 287, /**< Usually situated below the display on phones and
used as a multi-function feature key for selecting
a software defined function shown on the bottom left
of the display. */
KBDK_SOFTRIGHT = 288, /**< Usually situated below the display on phones and
used as a multi-function feature key for selecting
a software defined function shown on the bottom right
of the display. */
KBDK_CALL = 289, /**< Used for accepting phone calls. */
KBDK_ENDCALL = 290, /**< Used for rejecting phone calls. */
KBDK_APP1 = 283,
KBDK_APP2 = 284,
/* @} *//* Walther keys */
/* @} *//* Mobile keys */
/* Add any other keys here. */
KBDK_LAST = 512 /**< not a key, just marks the number of scancodes
for array bounds */
KBDK_RESERVED = 400, /**< 400-500 reserved for dynamic keycodes */
KBDK_COUNT = 512 /**< not a key, just marks the number of scancodes for array bounds */
};
// This comes directly from SDL_keycode.h
enum StellaMod: uInt16
{
KBDM_NONE = 0x0000,
KBDM_LSHIFT = 0x0001,
KBDM_RSHIFT = 0x0002,
KBDM_LCTRL = 0x0040,
KBDM_RCTRL = 0x0080,
KBDM_LALT = 0x0100,
KBDM_RALT = 0x0200,
KBDM_LGUI = 0x0400,
KBDM_RGUI = 0x0800,
KBDM_NUM = 0x1000,
KBDM_CAPS = 0x2000,
KBDM_MODE = 0x4000,
KBDM_RESERVED = 0x8000,
KBDM_CTRL = (KBDM_LCTRL|KBDM_RCTRL),
KBDM_SHIFT = (KBDM_LSHIFT|KBDM_RSHIFT),
KBDM_ALT = (KBDM_LALT|KBDM_RALT),
KBDM_GUI = (KBDM_LGUI|KBDM_RGUI)
KBDM_NONE = 0x0000U, /**< no modifier is applicable. */
KBDM_LSHIFT = 0x0001U, /**< the left Shift key is down. */
KBDM_RSHIFT = 0x0002U, /**< the right Shift key is down. */
KBDM_LEVEL5 = 0x0004U, /**< the Level 5 Shift key is down. */
KBDM_LCTRL = 0x0040U, /**< the left Ctrl (Control) key is down. */
KBDM_RCTRL = 0x0080U, /**< the right Ctrl (Control) key is down. */
KBDM_LALT = 0x0100U, /**< the left Alt key is down. */
KBDM_RALT = 0x0200U, /**< the right Alt key is down. */
KBDM_LGUI = 0x0400U, /**< the left GUI key (often the Windows key) is down. */
KBDM_RGUI = 0x0800U, /**< the right GUI key (often the Windows key) is down. */
KBDM_NUM = 0x1000U, /**< the Num Lock key (may be located on an extended keypad) is down. */
KBDM_CAPS = 0x2000U, /**< the Caps Lock key is down. */
KBDM_MODE = 0x4000U, /**< the !AltGr key is down. */
KBDM_SCROLL = 0x8000U, /**< the Scroll Lock key is down. */
KBDM_CTRL = (KBDM_LCTRL | KBDM_RCTRL), /**< Any Ctrl key is down. */
KBDM_SHIFT = (KBDM_LSHIFT | KBDM_RSHIFT), /**< Any Shift key is down. */
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

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;
myFSIndex = fsIndex;
myFullscreen = fullscreen;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const VideoModeHandler::Mode&
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
if(inTIAMode)
@ -53,7 +53,7 @@ const VideoModeHandler::Mode&
// Image and screen (aka window) dimensions are the same
// Overscan is not applicable in this mode
myMode = Mode(myImage.w, myImage.h,
Mode::Stretch::Fill, myFSIndex,
Mode::Stretch::Fill, myFullscreen,
desc.view(), zoom, bezelInfo);
}
else
@ -74,7 +74,7 @@ const VideoModeHandler::Mode&
{
myMode = Mode(myImage.w, myImage.h,
myDisplay.w, myDisplay.h,
Mode::Stretch::Preserve, myFSIndex,
Mode::Stretch::Preserve, myFullscreen,
"Fullscreen: Preserve aspect, no stretch",
zoom, overscan, bezelInfo);
}
@ -82,7 +82,7 @@ const VideoModeHandler::Mode&
{
myMode = Mode(myImage.w, myImage.h,
myDisplay.w, myDisplay.h,
Mode::Stretch::Fill, myFSIndex,
Mode::Stretch::Fill, myFullscreen,
"Fullscreen: Ignore aspect, full stretch",
zoom, overscan, bezelInfo);
}
@ -94,31 +94,31 @@ const VideoModeHandler::Mode&
myMode = Mode(myImage.w, myImage.h, Mode::Stretch::None);
else
myMode = Mode(myImage.w, myImage.h, myDisplay.w, myDisplay.h,
Mode::Stretch::None, myFSIndex);
Mode::Stretch::None, myFullscreen);
}
return myMode;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, Stretch smode,
Int32 fsindex, string_view desc,
bool fullscreen, string_view desc,
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,
Stretch smode, Int32 fsindex, string_view desc,
Stretch smode, bool fs, string_view desc,
double zoomLevel, double overscan, Bezel::Info bezelInfo)
: screenS{sw, sh},
stretch{smode},
description{desc},
zoom{zoomLevel}, //hZoom{zoomLevel}, vZoom{zoomLevel},
fsIndex{fsindex}
fullscreen{fs}
{
// Now resize based on windowed/fullscreen mode and stretch factor
if(fsIndex != -1) // fullscreen mode
if(fullscreen)
{
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 wy = bezelInfo.window().y() * ih / bezelInfo.window().h();
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,
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
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};
string description;
double zoom{1.};
Int32 fsIndex{-1}; // -1 indicates windowed mode
bool fullscreen{false}; // false indicates windowed mode
Mode() = default;
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.,
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.,
Bezel::Info bezelInfo = Bezel::Info());
@ -63,7 +63,7 @@ class VideoModeHandler
<< " stretch=" << (vm.stretch == Stretch::Preserve ? "preserve" :
vm.stretch == Stretch::Fill ? "fill" : "none")
<< " desc=" << vm.description << " zoom=" << vm.zoom
<< " fsIndex= " << vm.fsIndex;
<< " fullscreen= " << vm.fullscreen;
return os;
}
};
@ -84,10 +84,10 @@ class VideoModeHandler
Set the size of the display. This could be either the desktop size,
or the size of the monitor currently active.
@param display The dimensions of the enclosing display
@param fsIndex Fullscreen mode in use (-1 indicates windowed mode)
@param display The dimensions of the enclosing display
@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
@ -103,7 +103,7 @@ class VideoModeHandler
private:
Common::Size myImage, myDisplay;
Int32 myFSIndex{-1};
bool myFullscreen{false};
Mode myMode;

View File

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

View File

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

View File

@ -46,6 +46,7 @@ class BilinearBlitter : public Blitter {
SDL_Texture* myTexture{nullptr};
SDL_Texture* mySecondaryTexture{nullptr};
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;
bool myInterpolate{false};

View File

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

View File

@ -49,9 +49,14 @@ class QisBlitter : public Blitter {
SDL_Texture* mySrcTexture{nullptr};
SDL_Texture* mySecondarySrcTexture{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;
bool myTexturesAreAllocated{false};

View File

@ -191,10 +191,9 @@ class FBBackend
This method is called to query the video hardware for the index
of the display the current window is displayed on.
@return The current display index or a negative value if no
window is displayed
@return The current display id or a 0 if no 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.

View File

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

View File

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

View File

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

View File

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

View File

@ -277,7 +277,7 @@ void LauncherDialog::addPathWidgets(int& ypos)
buttonWidth, buttonHeight, helpIcon, kHelpCmd);
const string key = instance().eventHandler().getMappingDesc(Event::UIHelp, EventMode::kMenuMode);
myHelpButton->setToolTip("Click for help. (" + key + ")");
myHelpButton->setEnabled(MediaFactory::supportsURL());
myHelpButton->setEnabled(true);
wid.push_back(myHelpButton);
}
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 { }
bool isCurrentWindowPositioned() const override { return true; }
Common::Point getCurrentWindowPos() const override { return Common::Point{}; }
Int32 getCurrentDisplayIndex() const override { return 0; }
uInt32 getCurrentDisplayID() const override { return 0; }
void clear() override { }
bool setVideoMode(const VideoModeHandler::Mode&,
int, const Common::Point&) override { return true; }