From 55d9392fb8f33fb3860dce1b8121e5949950aa69 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 24 Jan 2017 01:43:45 +0100 Subject: [PATCH] Add fallback code to Linux target so if OpenGL is either unavailable or can't be used it falls back to the old software SDL FB --- src/gl/system/gl_swframebuffer.cpp | 54 ++++--- src/gl/system/gl_swframebuffer.h | 2 +- src/posix/sdl/hardware.cpp | 5 +- src/posix/sdl/sdlglvideo.cpp | 22 ++- src/posix/sdl/sdlglvideo.h | 14 +- src/posix/sdl/sdlvideo.cpp | 243 ----------------------------- src/posix/sdl/sdlvideo.h | 61 ++++++-- 7 files changed, 108 insertions(+), 293 deletions(-) diff --git a/src/gl/system/gl_swframebuffer.cpp b/src/gl/system/gl_swframebuffer.cpp index 1ad965c6a2..7bcb71f6bc 100644 --- a/src/gl/system/gl_swframebuffer.cpp +++ b/src/gl/system/gl_swframebuffer.cpp @@ -149,27 +149,6 @@ const char *const OpenGLSWFrameBuffer::ShaderDefines[OpenGLSWFrameBuffer::NUM_SH OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen, bool bgra) : Super(hMonitor, ClampWidth(width), ClampHeight(height), bits, refreshHz, fullscreen, bgra) { - // To do: this needs to cooperate with the same static in OpenGLFrameBuffer::InitializeState - static bool first = true; - if (first) - { - ogl_LoadFunctions(); - } - gl_LoadExtensions(); - InitializeState(); - if (first) - { - gl_PrintStartupLog(); - first = false; - } - - // SetVSync needs to be at the very top to workaround a bug in Nvidia's OpenGL driver. - // If wglSwapIntervalEXT is called after glBindFramebuffer in a frame the setting is not changed! - Super::SetVSync(vid_vsync); - - Debug = std::make_shared(); - Debug->Update(); - VertexBuffer = nullptr; IndexBuffer = nullptr; FBTexture = nullptr; @@ -181,7 +160,7 @@ OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height, { Shaders[i] = nullptr; } - VSync = vid_vsync; + BlendingRect.left = 0; BlendingRect.top = 0; BlendingRect.right = Width; @@ -214,12 +193,37 @@ OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height, memcpy(SourcePalette, GPalette.BaseColors, sizeof(PalEntry) * 256); + // To do: this needs to cooperate with the same static in OpenGLFrameBuffer::InitializeState + static bool first = true; + if (first) + { + ogl_LoadFunctions(); + } + gl_LoadExtensions(); + InitializeState(); + if (first) + { + gl_PrintStartupLog(); + first = false; + } + + if (!glGetString) + return; + + // SetVSync needs to be at the very top to workaround a bug in Nvidia's OpenGL driver. + // If wglSwapIntervalEXT is called after glBindFramebuffer in a frame the setting is not changed! + Super::SetVSync(vid_vsync); + + Debug = std::make_shared(); + Debug->Update(); + //Windowed = !(static_cast(Video)->GoFullscreen(fullscreen)); TrueHeight = height; - CreateResources(); - SetInitialState(); + Valid = CreateResources(); + if (Valid) + SetInitialState(); } OpenGLSWFrameBuffer::~OpenGLSWFrameBuffer() @@ -1077,7 +1081,7 @@ int OpenGLSWFrameBuffer::GetPageCount() bool OpenGLSWFrameBuffer::IsValid() { - return true; + return Valid; } //========================================================================== diff --git a/src/gl/system/gl_swframebuffer.h b/src/gl/system/gl_swframebuffer.h index a4ba4e4267..e211b3e51f 100644 --- a/src/gl/system/gl_swframebuffer.h +++ b/src/gl/system/gl_swframebuffer.h @@ -422,6 +422,7 @@ private: template static void SafeRelease(T &x) { if (x != nullptr) { delete x; x = nullptr; } } + bool Valid = false; std::shared_ptr Debug; std::unique_ptr StreamVertexBuffer, StreamVertexBufferBurn; @@ -452,7 +453,6 @@ private: bool UpdatePending; bool NeedPalUpdate; bool NeedGammaUpdate; - bool VSync; LTRBRect BlendingRect; int In2D; bool InScene; diff --git a/src/posix/sdl/hardware.cpp b/src/posix/sdl/hardware.cpp index d8e714ccc4..84508b728e 100644 --- a/src/posix/sdl/hardware.cpp +++ b/src/posix/sdl/hardware.cpp @@ -56,8 +56,6 @@ EXTERN_CVAR (Bool, fullscreen) EXTERN_CVAR (Bool, swtruecolor) EXTERN_CVAR (Float, vid_winscale) -CVAR (Bool, vid_sdl, 0, 0); - IVideo *Video; extern int NewWidth, NewHeight, NewBits, DisplayBits; @@ -122,8 +120,7 @@ void I_InitGraphics () ticker.SetGenericRepDefault (val, CVAR_Bool); //currentrenderer = vid_renderer; - if (currentrenderer==1 || vid_sdl==0) Video = new SDLGLVideo(0); - else Video = new SDLVideo (0); + Video = new SDLGLVideo(0); if (Video == NULL) I_FatalError ("Failed to initialize display"); diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index e8b61ef026..18f1edf166 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -13,6 +13,7 @@ #include "c_console.h" #include "sdlglvideo.h" +#include "sdlvideo.h" #include "gl/system/gl_system.h" #include "r_defs.h" #include "gl/gl_functions.h" @@ -29,6 +30,7 @@ // TYPES ------------------------------------------------------------------- +IMPLEMENT_CLASS(SDLBaseFB, true, false) IMPLEMENT_CLASS(SDLGLFB, true, false) struct MiniModeInfo @@ -171,15 +173,15 @@ DFrameBuffer *SDLGLVideo::CreateFrameBuffer (int width, int height, bool bgra, b if (old != NULL) { // Reuse the old framebuffer if its attributes are the same - SDLGLFB *fb = static_cast (old); + SDLBaseFB *fb = static_cast (old); if (fb->Width == width && fb->Height == height) { - bool fsnow = (SDL_GetWindowFlags (fb->Screen) & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0; + bool fsnow = (SDL_GetWindowFlags (fb->GetSDLWindow()) & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0; if (fsnow != fullscreen) { - SDL_SetWindowFullscreen (fb->Screen, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); + SDL_SetWindowFullscreen (fb->GetSDLWindow(), fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); } return old; } @@ -192,11 +194,17 @@ DFrameBuffer *SDLGLVideo::CreateFrameBuffer (int width, int height, bool bgra, b // flashAmount = 0; } - SDLGLFB *fb; + SDLBaseFB *fb; if (vid_renderer == 1) - fb = new OpenGLFrameBuffer (0, width, height, 32, 60, fullscreen); + { + fb = new OpenGLFrameBuffer(0, width, height, 32, 60, fullscreen); + } else - fb = (SDLGLFB*)CreateGLSWFrameBuffer (width, height, bgra, fullscreen); + { + fb = (SDLBaseFB*)CreateGLSWFrameBuffer(width, height, bgra, fullscreen); + if (!fb->IsValid()) + fb = new SDLFB(width, height, bgra, fullscreen, nullptr); + } retry = 0; @@ -240,7 +248,7 @@ DFrameBuffer *SDLGLVideo::CreateFrameBuffer (int width, int height, bool bgra, b } ++retry; - fb = static_cast(CreateFrameBuffer (width, height, false, fullscreen, NULL)); + fb = static_cast(CreateFrameBuffer (width, height, false, fullscreen, NULL)); } // fb->SetFlash (flashColor, flashAmount); diff --git a/src/posix/sdl/sdlglvideo.h b/src/posix/sdl/sdlglvideo.h index 01e70caac3..7acb0fa1be 100644 --- a/src/posix/sdl/sdlglvideo.h +++ b/src/posix/sdl/sdlglvideo.h @@ -34,9 +34,17 @@ private: int IteratorMode; int IteratorBits; }; -class SDLGLFB : public DFrameBuffer + +class SDLBaseFB : public DFrameBuffer { - DECLARE_CLASS(SDLGLFB, DFrameBuffer) + DECLARE_CLASS(SDLBaseFB, DFrameBuffer) +public: + virtual SDL_Window *GetSDLWindow() = 0; +}; + +class SDLGLFB : public SDLBaseFB +{ + DECLARE_CLASS(SDLGLFB, SDLBaseFB) public: // this must have the same parameters as the Windows version, even if they are not used! SDLGLFB (void *hMonitor, int width, int height, int, int, bool fullscreen, bool bgra); @@ -61,6 +69,8 @@ public: int GetClientWidth(); int GetClientHeight(); + SDL_Window *GetSDLWindow() override { return Screen; } + protected: bool CanUpdate(); void SetGammaTable(WORD *tbl); diff --git a/src/posix/sdl/sdlvideo.cpp b/src/posix/sdl/sdlvideo.cpp index 8c5c370753..c88d688a5e 100644 --- a/src/posix/sdl/sdlvideo.cpp +++ b/src/posix/sdl/sdlvideo.cpp @@ -24,61 +24,6 @@ // TYPES ------------------------------------------------------------------- -class SDLFB : public DFrameBuffer -{ - DECLARE_CLASS(SDLFB, DFrameBuffer) -public: - SDLFB (int width, int height, bool bgra, bool fullscreen, SDL_Window *oldwin); - ~SDLFB (); - - bool Lock (bool buffer); - void Unlock (); - bool Relock (); - void ForceBuffering (bool force); - bool IsValid (); - void Update (); - PalEntry *GetPalette (); - void GetFlashedPalette (PalEntry pal[256]); - void UpdatePalette (); - bool SetGamma (float gamma); - bool SetFlash (PalEntry rgb, int amount); - void GetFlash (PalEntry &rgb, int &amount); - void SetFullscreen (bool fullscreen); - int GetPageCount (); - bool IsFullscreen (); - - friend class SDLVideo; - - virtual void SetVSync (bool vsync); - virtual void ScaleCoordsFromWindow(SWORD &x, SWORD &y); - -private: - PalEntry SourcePalette[256]; - BYTE GammaTable[3][256]; - PalEntry Flash; - int FlashAmount; - float Gamma; - bool UpdatePending; - - SDL_Window *Screen; - SDL_Renderer *Renderer; - union - { - SDL_Texture *Texture; - SDL_Surface *Surface; - }; - - bool UsingRenderer; - bool NeedPalUpdate; - bool NeedGammaUpdate; - bool NotPaletted; - - void UpdateColors (); - void ResetSDLRenderer (); - - SDLFB () {} -}; - IMPLEMENT_CLASS(SDLFB, false, false) struct MiniModeInfo @@ -132,72 +77,6 @@ CUSTOM_CVAR (Float, bgamma, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // PRIVATE DATA DEFINITIONS ------------------------------------------------ -// Dummy screen sizes to pass when windowed -static MiniModeInfo WinModes[] = -{ - { 320, 200 }, - { 320, 240 }, - { 400, 225 }, // 16:9 - { 400, 300 }, - { 480, 270 }, // 16:9 - { 480, 360 }, - { 512, 288 }, // 16:9 - { 512, 384 }, - { 640, 360 }, // 16:9 - { 640, 400 }, - { 640, 480 }, - { 720, 480 }, // 16:10 - { 720, 540 }, - { 800, 450 }, // 16:9 - { 800, 480 }, - { 800, 500 }, // 16:10 - { 800, 600 }, - { 848, 480 }, // 16:9 - { 960, 600 }, // 16:10 - { 960, 720 }, - { 1024, 576 }, // 16:9 - { 1024, 600 }, // 17:10 - { 1024, 640 }, // 16:10 - { 1024, 768 }, - { 1088, 612 }, // 16:9 - { 1152, 648 }, // 16:9 - { 1152, 720 }, // 16:10 - { 1152, 864 }, - { 1280, 540 }, // 21:9 - { 1280, 720 }, // 16:9 - { 1280, 854 }, - { 1280, 800 }, // 16:10 - { 1280, 960 }, - { 1280, 1024 }, // 5:4 - { 1360, 768 }, // 16:9 - { 1366, 768 }, - { 1400, 787 }, // 16:9 - { 1400, 875 }, // 16:10 - { 1400, 1050 }, - { 1440, 900 }, - { 1440, 960 }, - { 1440, 1080 }, - { 1600, 900 }, // 16:9 - { 1600, 1000 }, // 16:10 - { 1600, 1200 }, - { 1680, 1050 }, // 16:10 - { 1920, 1080 }, - { 1920, 1200 }, - { 2048, 1536 }, - { 2560, 1080 }, // 21:9 - { 2560, 1440 }, - { 2560, 1600 }, - { 2560, 2048 }, - { 2880, 1800 }, - { 3200, 1800 }, - { 3440, 1440 }, // 21:9 - { 3840, 2160 }, - { 3840, 2400 }, - { 4096, 2160 }, - { 5120, 2160 }, // 21:9 - { 5120, 2880 } -}; - static cycle_t BlitCycles; static cycle_t SDLFlipCycles; @@ -228,128 +107,6 @@ void ScaleWithAspect (int &w, int &h, int Width, int Height) h = y; } -SDLVideo::SDLVideo (int parm) -{ - IteratorBits = 0; -} - -SDLVideo::~SDLVideo () -{ -} - -void SDLVideo::StartModeIterator (int bits, bool fs) -{ - IteratorMode = 0; - IteratorBits = bits; -} - -bool SDLVideo::NextMode (int *width, int *height, bool *letterbox) -{ - if (IteratorBits != 8) - return false; - - if ((unsigned)IteratorMode < sizeof(WinModes)/sizeof(WinModes[0])) - { - *width = WinModes[IteratorMode].Width; - *height = WinModes[IteratorMode].Height; - ++IteratorMode; - return true; - } - return false; -} - -DFrameBuffer *SDLVideo::CreateFrameBuffer (int width, int height, bool bgra, bool fullscreen, DFrameBuffer *old) -{ - static int retry = 0; - static int owidth, oheight; - - PalEntry flashColor; - int flashAmount; - - SDL_Window *oldwin = NULL; - - if (old != NULL) - { // Reuse the old framebuffer if its attributes are the same - SDLFB *fb = static_cast (old); - if (fb->Width == width && - fb->Height == height && - fb->Bgra == bgra) - { - bool fsnow = (SDL_GetWindowFlags (fb->Screen) & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0; - - if (fsnow != fullscreen) - { - fb->SetFullscreen (fullscreen); - } - return old; - } - - oldwin = fb->Screen; - fb->Screen = NULL; - - old->GetFlash (flashColor, flashAmount); - old->ObjectFlags |= OF_YesReallyDelete; - if (screen == old) screen = NULL; - delete old; - } - else - { - flashColor = 0; - flashAmount = 0; - } - - SDLFB *fb = new SDLFB (width, height, bgra, fullscreen, oldwin); - - // If we could not create the framebuffer, try again with slightly - // different parameters in this order: - // 1. Try with the closest size - // 2. Try in the opposite screen mode with the original size - // 3. Try in the opposite screen mode with the closest size - // This is a somewhat confusing mass of recursion here. - - while (fb == NULL || !fb->IsValid ()) - { - if (fb != NULL) - { - delete fb; - } - - switch (retry) - { - case 0: - owidth = width; - oheight = height; - case 2: - // Try a different resolution. Hopefully that will work. - I_ClosestResolution (&width, &height, 8); - break; - - case 1: - // Try changing fullscreen mode. Maybe that will work. - width = owidth; - height = oheight; - fullscreen = !fullscreen; - break; - - default: - // I give up! - I_FatalError ("Could not create new screen (%d x %d)", owidth, oheight); - } - - ++retry; - fb = static_cast(CreateFrameBuffer (width, height, bgra, fullscreen, NULL)); - } - retry = 0; - - fb->SetFlash (flashColor, flashAmount); - - return fb; -} - -void SDLVideo::SetWindowedScale (float scale) -{ -} - // FrameBuffer implementation ----------------------------------------------- SDLFB::SDLFB (int width, int height, bool bgra, bool fullscreen, SDL_Window *oldwin) diff --git a/src/posix/sdl/sdlvideo.h b/src/posix/sdl/sdlvideo.h index 385733bc15..d0888daba6 100644 --- a/src/posix/sdl/sdlvideo.h +++ b/src/posix/sdl/sdlvideo.h @@ -1,21 +1,60 @@ #include "hardware.h" #include "v_video.h" +#include "sdlglvideo.h" -class SDLVideo : public IVideo +class SDLFB : public DFrameBuffer { - public: - SDLVideo (int parm); - ~SDLVideo (); + DECLARE_CLASS(SDLFB, SDLBaseFB) +public: + SDLFB(int width, int height, bool bgra, bool fullscreen, SDL_Window *oldwin); + ~SDLFB(); - EDisplayType GetDisplayType () { return DISPLAY_Both; } - void SetWindowedScale (float scale); + bool Lock(bool buffer); + void Unlock(); + bool Relock(); + void ForceBuffering(bool force); + bool IsValid(); + void Update(); + PalEntry *GetPalette(); + void GetFlashedPalette(PalEntry pal[256]); + void UpdatePalette(); + bool SetGamma(float gamma); + bool SetFlash(PalEntry rgb, int amount); + void GetFlash(PalEntry &rgb, int &amount); + void SetFullscreen(bool fullscreen); + int GetPageCount(); + bool IsFullscreen(); - DFrameBuffer *CreateFrameBuffer (int width, int height, bool bgra, bool fs, DFrameBuffer *old); + friend class SDLGLVideo; - void StartModeIterator (int bits, bool fs); - bool NextMode (int *width, int *height, bool *letterbox); + virtual void SetVSync(bool vsync); + virtual void ScaleCoordsFromWindow(SWORD &x, SWORD &y); + + SDL_Window *GetSDLWindow() override { return Screen; } private: - int IteratorMode; - int IteratorBits; + PalEntry SourcePalette[256]; + BYTE GammaTable[3][256]; + PalEntry Flash; + int FlashAmount; + float Gamma; + bool UpdatePending; + + SDL_Window *Screen; + SDL_Renderer *Renderer; + union + { + SDL_Texture *Texture; + SDL_Surface *Surface; + }; + + bool UsingRenderer; + bool NeedPalUpdate; + bool NeedGammaUpdate; + bool NotPaletted; + + void UpdateColors(); + void ResetSDLRenderer(); + + SDLFB() {} };