diff --git a/3rdParty/SDL2/CMakeLists.txt b/3rdParty/SDL2/CMakeLists.txt index 787c8eb49..5bc504513 100644 --- a/3rdParty/SDL2/CMakeLists.txt +++ b/3rdParty/SDL2/CMakeLists.txt @@ -19,8 +19,8 @@ if(TARGET_PLATFORM STREQUAL "dos") set(DOS ON) FetchContent_Declare(SDL2 # branch: dos-vbe-rebase - URL https://github.com/diasurgical/SDL/archive/d9cf9066d9cb796b56d1d70c9c560c055a32149b.tar.gz - URL_HASH MD5=9ad9ae69ee0266c895e79cf05a1e0e49 + URL https://github.com/diasurgical/SDL/archive/b55cac0c06aa191dcc7a3e63ae6fe6656593026e.tar.gz + URL_HASH MD5=99eabd2fc675f5539e055b1d8fa519e4 ) else() FetchContent_Declare(SDL2 diff --git a/CMake/Definitions.cmake b/CMake/Definitions.cmake index ab85b1f8f..6be176e0d 100644 --- a/CMake/Definitions.cmake +++ b/CMake/Definitions.cmake @@ -93,7 +93,8 @@ foreach( REMAP_KEYBOARD_KEYS DEVILUTIONX_DEFAULT_RESAMPLER STREAM_ALL_AUDIO_MIN_FILE_SIZE - DEVILUTIONX_DISPLAY_TEXTURE_FORMAT + DEVILUTIONX_DISPLAY_PIXELFORMAT # SDL2-only + DEVILUTIONX_DISPLAY_TEXTURE_FORMAT # SDL2-only DEVILUTIONX_SCREENSHOT_FORMAT DARWIN_MAJOR_VERSION DARWIN_MINOR_VERSION diff --git a/CMake/platforms/dos.cmake b/CMake/platforms/dos.cmake index 4d1d873e3..0032b5b95 100644 --- a/CMake/platforms/dos.cmake +++ b/CMake/platforms/dos.cmake @@ -16,6 +16,7 @@ set(DEVILUTIONX_SYSTEM_SDL2 OFF) set(DEVILUTIONX_STATIC_SDL2 ON) set(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF) set(DEVILUTIONX_SYSTEM_LIBPNG OFF) +set(DEVILUTIONX_DISPLAY_PIXELFORMAT SDL_PIXELFORMAT_INDEX8) set(DEVILUTIONX_PLATFORM_FILE_UTIL_LINK_LIBRARIES "") diff --git a/Source/engine/dx.cpp b/Source/engine/dx.cpp index 0e1a5689e..344667f4d 100644 --- a/Source/engine/dx.cpp +++ b/Source/engine/dx.cpp @@ -63,7 +63,12 @@ bool CanRenderDirectlyToOutputSurface() && outputSurface->format->BitsPerPixel == 8); #endif #else // !USE_SDL1 - return false; + if (renderer != nullptr) return false; + SDL_Surface *outputSurface = GetOutputSurface(); + // Assumes double-buffering is available. + return outputSurface->w == static_cast(gnScreenWidth) + && outputSurface->h == static_cast(gnScreenHeight) + && outputSurface->format->BitsPerPixel == 8; #endif } diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index 8f996df82..44e3587a1 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -180,6 +180,11 @@ void UpdatePalette() if (SDL_SetSurfacePalette(SVidSurface.get(), SVidPalette.get()) <= -1) { ErrSdl(); } + if (GetOutputSurface()->format->BitsPerPixel == 8) { + if (SDL_SetSurfacePalette(GetOutputSurface(), SVidPalette.get()) <= -1) { + ErrSdl(); + } + } #endif } @@ -311,6 +316,15 @@ bool SVidPlayBegin(const char *filename, int flags) ErrSdl(); } } +#if defined(DEVILUTIONX_DISPLAY_PIXELFORMAT) && DEVILUTIONX_DISPLAY_PIXELFORMAT == SDL_PIXELFORMAT_INDEX8 + else { + const Size windowSize = { static_cast(SVidWidth), static_cast(SVidHeight) }; + SDL_DisplayMode nearestDisplayMode = GetNearestDisplayMode(windowSize, DEVILUTIONX_DISPLAY_PIXELFORMAT); + if (SDL_SetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) { + ErrSdl(); + } + } +#endif #else TrySetVideoModeToSVidForSDL1(); #endif @@ -405,6 +419,15 @@ void SVidPlayEnd() ErrSdl(); } } +#if defined(DEVILUTIONX_DISPLAY_PIXELFORMAT) && DEVILUTIONX_DISPLAY_PIXELFORMAT == SDL_PIXELFORMAT_INDEX8 + else { + const Size windowSize = { static_cast(gnScreenWidth), static_cast(gnScreenHeight) }; + SDL_DisplayMode nearestDisplayMode = GetNearestDisplayMode(windowSize, DEVILUTIONX_DISPLAY_PIXELFORMAT); + if (SDL_SetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) { + ErrSdl(); + } + } +#endif #else if (IsSVidVideoMode) { SetVideoModeToPrimary(IsFullScreen(), gnScreenWidth, gnScreenHeight); diff --git a/Source/utils/display.cpp b/Source/utils/display.cpp index fd89a9158..491de1cc3 100644 --- a/Source/utils/display.cpp +++ b/Source/utils/display.cpp @@ -107,37 +107,6 @@ void CalculatePreferredWindowSize(int &width, int &height) height = mode.h * width / mode.w; } } - -SDL_DisplayMode GetNearestDisplayMode(Size preferredSize) -{ - SDL_DisplayMode nearestDisplayMode; - if (SDL_GetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) - ErrSdl(); - - const int displayIndex = SDL_GetWindowDisplayIndex(ghMainWnd); - const int modeCount = SDL_GetNumDisplayModes(displayIndex); - for (int modeIndex = 0; modeIndex < modeCount; modeIndex++) { - SDL_DisplayMode displayMode; - if (SDL_GetDisplayMode(displayIndex, modeIndex, &displayMode) != 0) - continue; - - const int diffHeight = std::abs(nearestDisplayMode.h - preferredSize.height) - std::abs(displayMode.h - preferredSize.height); - const int diffWidth = std::abs(nearestDisplayMode.w - preferredSize.width) - std::abs(displayMode.w - preferredSize.width); - if (diffHeight < 0) - continue; - if (diffHeight == 0 && diffWidth < 0) - continue; - nearestDisplayMode = displayMode; - } - - LogVerbose("Nearest display mode to {}x{} is {}x{} {}bpp {}Hz", - preferredSize.width, preferredSize.height, - nearestDisplayMode.w, nearestDisplayMode.h, - SDL_BITSPERPIXEL(nearestDisplayMode.format), - nearestDisplayMode.refresh_rate); - - return nearestDisplayMode; -} #endif void CalculateUIRectangle() @@ -299,6 +268,59 @@ const auto OptionChangeHandlerVSync = (GetOptions().Graphics.frameRateControl.Se } // namespace +#if SDL_VERSION_ATLEAST(2, 0, 0) +SDL_DisplayMode GetNearestDisplayMode(Size preferredSize, SDL_PixelFormatEnum preferredPixelFormat) +{ + SDL_DisplayMode nearestDisplayMode; + if (SDL_GetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) + ErrSdl(); + + const int displayIndex = SDL_GetWindowDisplayIndex(ghMainWnd); + const int modeCount = SDL_GetNumDisplayModes(displayIndex); + + // First, find the best mode among the modes with the requested pixel format. + SDL_PixelFormatEnum bestPixelFormat = SDL_PIXELFORMAT_UNKNOWN; + for (int modeIndex = 0; modeIndex < modeCount; modeIndex++) { + SDL_DisplayMode displayMode; + if (SDL_GetDisplayMode(displayIndex, modeIndex, &displayMode) != 0) + continue; + const int diffHeight = std::abs(nearestDisplayMode.h - preferredSize.height) - std::abs(displayMode.h - preferredSize.height); + const int diffWidth = std::abs(nearestDisplayMode.w - preferredSize.width) - std::abs(displayMode.w - preferredSize.width); + if (diffHeight < 0) + continue; + if (diffHeight == 0 && diffWidth < 0) + continue; + if (preferredPixelFormat == SDL_PIXELFORMAT_UNKNOWN + || displayMode.format == preferredPixelFormat) { + nearestDisplayMode = displayMode; + } + } + if (preferredPixelFormat != SDL_PIXELFORMAT_UNKNOWN && bestPixelFormat == SDL_PIXELFORMAT_UNKNOWN) { + // If no mode with the preferred pixel format was found, allow any pixel format: + for (int modeIndex = 0; modeIndex < modeCount; modeIndex++) { + SDL_DisplayMode displayMode; + if (SDL_GetDisplayMode(displayIndex, modeIndex, &displayMode) != 0) + continue; + const int diffHeight = std::abs(nearestDisplayMode.h - preferredSize.height) - std::abs(displayMode.h - preferredSize.height); + const int diffWidth = std::abs(nearestDisplayMode.w - preferredSize.width) - std::abs(displayMode.w - preferredSize.width); + if (diffHeight < 0) + continue; + if (diffHeight == 0 && diffWidth < 0) + continue; + nearestDisplayMode = displayMode; + } + } + + LogVerbose("Nearest display mode to {}x{} is {}x{} {}bpp {}Hz", + preferredSize.width, preferredSize.height, + nearestDisplayMode.w, nearestDisplayMode.h, + SDL_BITSPERPIXEL(nearestDisplayMode.format), + nearestDisplayMode.refresh_rate); + + return nearestDisplayMode; +} +#endif + void AdjustToScreenGeometry(Size windowSize) { gnScreenWidth = windowSize.width; @@ -455,6 +477,13 @@ bool SpawnWindow(const char *lpWindowName) ghMainWnd = SDL_CreateWindow(lpWindowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowSize.width, windowSize.height, flags); +#if defined(DEVILUTIONX_DISPLAY_PIXELFORMAT) + SDL_DisplayMode nearestDisplayMode = GetNearestDisplayMode(windowSize, DEVILUTIONX_DISPLAY_PIXELFORMAT); + if (SDL_SetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) { + ErrSdl(); + } +#endif + // Note: https://github.com/libsdl-org/SDL/issues/962 // This is a solution to a problem related to SDL mouse grab. // See https://github.com/diasurgical/devilutionX/issues/4251 diff --git a/Source/utils/display.h b/Source/utils/display.h index 93d14c224..f0e70b423 100644 --- a/Source/utils/display.h +++ b/Source/utils/display.h @@ -109,4 +109,8 @@ void LogicalToOutput(T *x, T *y) #endif } +#if SDL_VERSION_ATLEAST(2, 0, 0) +SDL_DisplayMode GetNearestDisplayMode(Size preferredSize, SDL_PixelFormatEnum preferredPixelFormat = SDL_PIXELFORMAT_UNKNOWN); +#endif + } // namespace devilution