diff --git a/configure b/configure index b4d962448..2c7e80755 100755 --- a/configure +++ b/configure @@ -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 diff --git a/src/common/EventHandlerSDL.cxx b/src/common/EventHandlerSDL.cxx index b1da636dd..8171154c0 100644 --- a/src/common/EventHandlerSDL.cxx +++ b/src/common/EventHandlerSDL.cxx @@ -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 (SDL_GetKeyFromScancode(static_cast(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(myEvent.key.keysym.scancode), - static_cast(myEvent.key.keysym.mod), - myEvent.key.type == SDL_KEYDOWN, + handleKeyEvent(static_cast(myEvent.key.scancode), + static_cast(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(x), static_cast(y)); else if(myEvent.wheel.y > 0) - handleMouseButtonEvent(MouseButton::WHEELUP, true, x, y); + handleMouseButtonEvent(MouseButton::WHEELUP, true, + static_cast(x), static_cast(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 diff --git a/src/common/EventHandlerSDL.hxx b/src/common/EventHandlerSDL.hxx index 2fee43d90..eb3648bef 100644 --- a/src/common/EventHandlerSDL.hxx +++ b/src/common/EventHandlerSDL.hxx @@ -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 diff --git a/src/common/FBBackendSDL.cxx b/src/common/FBBackendSDL.cxx index 1586a11f7..2c76517af 100644 --- a/src/common/FBBackendSDL.cxx +++ b/src/common/FBBackendSDL.cxx @@ -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& 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(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& 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 RENDERER_NAMES = {{ @@ -169,22 +154,22 @@ void FBBackendSDL::queryHardware(vector& 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(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 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(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); } diff --git a/src/common/FBBackendSDL.hxx b/src/common/FBBackendSDL.hxx index e1986c4ad..29df61052 100644 --- a/src/common/FBBackendSDL.hxx +++ b/src/common/FBBackendSDL.hxx @@ -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}; diff --git a/src/common/FBSurfaceSDL.cxx b/src/common/FBSurfaceSDL.cxx index 9f000cc5a..0d032c80e 100644 --- a/src/common/FBSurfaceSDL.cxx +++ b/src/common/FBSurfaceSDL.cxx @@ -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(mySurface->pixels); - myPitch = mySurface->pitch / pf.BytesPerPixel; + myPitch = mySurface->pitch / pf.bytes_per_pixel; //////////////////////////////////////////////////// myIsStatic = data != nullptr; diff --git a/src/common/KeyMap.cxx b/src/common/KeyMap.cxx index e89dca215..3f7c51436 100644 --- a/src/common/KeyMap.cxx +++ b/src/common/KeyMap.cxx @@ -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; diff --git a/src/common/MediaFactory.hxx b/src/common/MediaFactory.hxx index 8d33fe306..c4d024f23 100644 --- a/src/common/MediaFactory.hxx +++ b/src/common/MediaFactory.hxx @@ -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) diff --git a/src/common/SDL_lib.hxx b/src/common/SDL_lib.hxx index 9bd5aa636..99ced7943 100644 --- a/src/common/SDL_lib.hxx +++ b/src/common/SDL_lib.hxx @@ -33,48 +33,30 @@ #pragma clang diagnostic ignored "-Wold-style-cast" #pragma clang diagnostic ignored "-Wreserved-identifier" #pragma clang diagnostic ignored "-Wswitch-default" - #include + #include #pragma clang diagnostic pop #elif defined(BSPF_WINDOWS) #pragma warning(push, 0) - #include + #include #pragma warning(pop) #else - #include + #include #endif -/* - * Seems to be needed for ppc64le, doesn't hurt other archs - * Note that this is a problem in SDL2, which includes - * 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(ver.major) << "." << static_cast(ver.minor) - << "." << static_cast(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 diff --git a/src/common/SoundSDL.cxx b/src/common/SoundSDL.cxx index b3751e41d..b9d5da945 100644 --- a/src/common/SoundSDL.cxx +++ b/src/common/SoundSDL.cxx @@ -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(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); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/StellaKeys.hxx b/src/common/StellaKeys.hxx index aa264b6f3..4f8c05982 100644 --- a/src/common/StellaKeys.hxx +++ b/src/common/StellaKeys.hxx @@ -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 diff --git a/src/common/VideoModeHandler.cxx b/src/common/VideoModeHandler.cxx index f09d94958..3742404a1 100644 --- a/src/common/VideoModeHandler.cxx +++ b/src/common/VideoModeHandler.cxx @@ -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(std::round(iw * bezelInfo.ratioW()))); + static_cast(std::round(iw * bezelInfo.ratioW()))); const uInt32 bezelH = std::min(screenS.h, - static_cast(std::round(ih * bezelInfo.ratioH()))); + static_cast(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); diff --git a/src/common/VideoModeHandler.hxx b/src/common/VideoModeHandler.hxx index 6e9a2ed97..3e12f4585 100644 --- a/src/common/VideoModeHandler.hxx +++ b/src/common/VideoModeHandler.hxx @@ -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; diff --git a/src/common/jsonDefinitions.hxx b/src/common/jsonDefinitions.hxx index 5bea6239f..e42a4596e 100644 --- a/src/common/jsonDefinitions.hxx +++ b/src/common/jsonDefinitions.hxx @@ -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"}, diff --git a/src/common/sdl_blitter/BilinearBlitter.cxx b/src/common/sdl_blitter/BilinearBlitter.cxx index f98cd74ab..bbe8a7b79 100644 --- a/src/common/sdl_blitter/BilinearBlitter.cxx +++ b/src/common/sdl_blitter/BilinearBlitter.cxx @@ -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 textures = { myTexture, mySecondaryTexture }; + const std::array 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); diff --git a/src/common/sdl_blitter/BilinearBlitter.hxx b/src/common/sdl_blitter/BilinearBlitter.hxx index a8636409a..6f2885553 100644 --- a/src/common/sdl_blitter/BilinearBlitter.hxx +++ b/src/common/sdl_blitter/BilinearBlitter.hxx @@ -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}; diff --git a/src/common/sdl_blitter/QisBlitter.cxx b/src/common/sdl_blitter/QisBlitter.cxx index a29f29278..2df3c4151 100644 --- a/src/common/sdl_blitter/QisBlitter.cxx +++ b/src/common/sdl_blitter/QisBlitter.cxx @@ -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 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(myAttributes.blendalpha * 2.55); const std::array textures = { - myIntermediateTexture, mySecondaryIntermedateTexture + myIntermediateTexture, mySecondaryIntermediateTexture }; for (SDL_Texture* texture: textures) { if (!texture) continue; diff --git a/src/common/sdl_blitter/QisBlitter.hxx b/src/common/sdl_blitter/QisBlitter.hxx index ffdbfa9fa..4c7d54c1d 100644 --- a/src/common/sdl_blitter/QisBlitter.hxx +++ b/src/common/sdl_blitter/QisBlitter.hxx @@ -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}; diff --git a/src/emucore/FBBackend.hxx b/src/emucore/FBBackend.hxx index 80a9a7828..93de7b5d5 100644 --- a/src/emucore/FBBackend.hxx +++ b/src/emucore/FBBackend.hxx @@ -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. diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index a71b31067..87a3589f5 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -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(); diff --git a/src/gui/AboutDialog.cxx b/src/gui/AboutDialog.cxx index 45af38ae9..a8f55b917 100644 --- a/src/gui/AboutDialog.cxx +++ b/src/gui/AboutDialog.cxx @@ -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; } diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index bc81a0a4e..39a524ff4 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -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); diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 3024abfa3..0cef5694f 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -1378,7 +1378,7 @@ void GameInfoDialog::updateLink() || startsWithIgnoreCase(link, "https://") || startsWithIgnoreCase(link, "www."); - myUrlButton->setEnabled(enable && MediaFactory::supportsURL()); + myUrlButton->setEnabled(enable); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/HelpDialog.cxx b/src/gui/HelpDialog.cxx index c6f621b78..da39bdc4f 100644 --- a/src/gui/HelpDialog.cxx +++ b/src/gui/HelpDialog.cxx @@ -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; diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index 6ee66b44f..7a6137b50 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -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; diff --git a/src/os/libretro/FBBackendLIBRETRO.hxx b/src/os/libretro/FBBackendLIBRETRO.hxx index 922f9938f..91d899925 100644 --- a/src/os/libretro/FBBackendLIBRETRO.hxx +++ b/src/os/libretro/FBBackendLIBRETRO.hxx @@ -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; }