diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index 97da4360a..399e7eda8 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -955,3 +955,20 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface) return result == VK_SUCCESS; } #endif + +void I_PolyPresentInit() +{ +} + +uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch) +{ + return nullptr; +} + +void I_PolyPresentUnlock(int x, int y, int w, int h) +{ +} + +void I_PolyPresentDeinit() +{ +} diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index 49463e0ac..ed04451fe 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -57,6 +57,8 @@ #include "rendering/vulkan/system/vk_framebuffer.h" #endif +#include "rendering/polyrenderer/backend/poly_framebuffer.h" + // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- @@ -113,6 +115,7 @@ namespace Priv SDL_Window *window; bool vulkanEnabled; + bool softpolyEnabled; bool fullscreenSwitch; void CreateWindow(uint32_t extraFlags) @@ -230,6 +233,101 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface) } #endif +namespace +{ + SDL_Surface* polysurface = nullptr; +} + +void I_PolyPresentInit() +{ + assert(Priv::softpolyEnabled); + assert(Priv::window != nullptr); +} + +uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch) +{ + if (!polysurface || polysurface->w != w || polysurface->h != h) + { + if (polysurface) + { + SDL_FreeSurface(polysurface); + polysurface = nullptr; + } + polysurface = SDL_CreateRGBSurface(0, w, h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); + SDL_SetSurfaceBlendMode(polysurface, SDL_BLENDMODE_NONE); + } + + SDL_LockSurface(polysurface); + pitch = polysurface->pitch; + return (uint8_t*)polysurface->pixels; +} + +void I_PolyPresentUnlock(int x, int y, int width, int height) +{ + SDL_UnlockSurface(polysurface); + + SDL_Surface* windowsurface = SDL_GetWindowSurface(Priv::window); + int ClientWidth = windowsurface->w; + int ClientHeight = windowsurface->h; + + SDL_Rect clearrects[4]; + int count = 0; + if (y > 0) + { + clearrects[count].x = 0; + clearrects[count].y = 0; + clearrects[count].w = ClientWidth; + clearrects[count].h = y; + count++; + } + if (y + height < ClientHeight) + { + clearrects[count].x = 0; + clearrects[count].y = y + height; + clearrects[count].w = ClientWidth; + clearrects[count].h = ClientHeight - clearrects[count].y; + count++; + } + if (x > 0) + { + clearrects[count].x = 0; + clearrects[count].y = y; + clearrects[count].w = x; + clearrects[count].h = height; + count++; + } + if (x + width < ClientWidth) + { + clearrects[count].x = x + width; + clearrects[count].y = y; + clearrects[count].x = ClientWidth - clearrects[count].x; + clearrects[count].y = height - clearrects[count].y; + count++; + } + + if (count > 0) + SDL_FillRects(windowsurface, clearrects, count, 0xff000000); + + SDL_Rect dstrect; + dstrect.x = x; + dstrect.y = y; + dstrect.w = width; + dstrect.h = height; + SDL_BlitScaled(polysurface, nullptr, windowsurface, &dstrect); + + SDL_UpdateWindowSurface(Priv::window); +} + +void I_PolyPresentDeinit() +{ + if (polysurface) + { + SDL_FreeSurface(polysurface); + polysurface = nullptr; + } +} + + SDLVideo::SDLVideo () { @@ -248,6 +346,7 @@ SDLVideo::SDLVideo () #ifdef HAVE_VULKAN Priv::vulkanEnabled = vid_preferbackend == 1 && Priv::Vulkan_GetDrawableSize && Priv::Vulkan_GetInstanceExtensions && Priv::Vulkan_CreateSurface; + Priv::softpolyEnabled = vid_preferbackend == 2; if (Priv::vulkanEnabled) { @@ -258,6 +357,10 @@ SDLVideo::SDLVideo () Priv::vulkanEnabled = false; } } + else if (Priv::softpolyEnabled) + { + Priv::CreateWindow(SDL_WINDOW_HIDDEN); + } #endif } @@ -294,6 +397,11 @@ DFrameBuffer *SDLVideo::CreateFrameBuffer () } #endif + if (Priv::softpolyEnabled) + { + fb = new PolyFrameBuffer(nullptr, fullscreen); + } + if (fb == nullptr) { fb = new OpenGLRenderer::OpenGLFrameBuffer(0, fullscreen); @@ -325,6 +433,11 @@ int SystemBaseFrameBuffer::GetClientWidth() { int width = 0; + if (Priv::softpolyEnabled) + { + return SDL_GetWindowSurface(Priv::window)->w; + } + #ifdef HAVE_VULKAN assert(Priv::vulkanEnabled); Priv::Vulkan_GetDrawableSize(Priv::window, &width, nullptr); @@ -336,6 +449,11 @@ int SystemBaseFrameBuffer::GetClientWidth() int SystemBaseFrameBuffer::GetClientHeight() { int height = 0; + + if (Priv::softpolyEnabled) + { + return SDL_GetWindowSurface(Priv::window)->h; + } #ifdef HAVE_VULKAN assert(Priv::vulkanEnabled); diff --git a/src/rendering/i_video.h b/src/rendering/i_video.h index d67891201..f2c1abeda 100644 --- a/src/rendering/i_video.h +++ b/src/rendering/i_video.h @@ -22,6 +22,11 @@ void I_ShutdownGraphics(); extern IVideo *Video; +void I_PolyPresentInit(); +uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch); +void I_PolyPresentUnlock(int x, int y, int w, int h); +void I_PolyPresentDeinit(); + // Pause a bit. // [RH] Despite the name, it apparently never waited for the VBL, even in diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index 8edca2e0e..1915b3177 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -8,6 +8,8 @@ #include "g_game.h" #include "gamedata/fonts/v_text.h" +#include "rendering/i_video.h" + #include "hwrenderer/utility/hw_clock.h" #include "hwrenderer/utility/hw_vrmodes.h" #include "hwrenderer/utility/hw_cvars.h" @@ -47,18 +49,6 @@ extern bool gpuStatActive; extern bool keepGpuStatActive; extern FString gpuStatOutput; -#ifdef WIN32 -void I_PolyPresentInit(); -uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch); -void I_PolyPresentUnlock(int x, int y, int w, int h); -void I_PolyPresentDeinit(); -#else -void I_PolyPresentInit() { } -uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch) { pitch = 0; return nullptr; } -void I_PolyPresentUnlock(int x, int y, int w, int h) { } -void I_PolyPresentDeinit() { } -#endif - PolyFrameBuffer::PolyFrameBuffer(void *hMonitor, bool fullscreen) : Super(hMonitor, fullscreen) { I_PolyPresentInit();