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

This commit is contained in:
Magnus Norddahl 2017-01-24 01:43:45 +01:00
parent 6586877ac5
commit 55d9392fb8
7 changed files with 108 additions and 293 deletions

View file

@ -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<FGLDebug>();
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,11 +193,36 @@ 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<FGLDebug>();
Debug->Update();
//Windowed = !(static_cast<Win32Video *>(Video)->GoFullscreen(fullscreen));
TrueHeight = height;
CreateResources();
Valid = CreateResources();
if (Valid)
SetInitialState();
}
@ -1077,7 +1081,7 @@ int OpenGLSWFrameBuffer::GetPageCount()
bool OpenGLSWFrameBuffer::IsValid()
{
return true;
return Valid;
}
//==========================================================================

View file

@ -422,6 +422,7 @@ private:
template<typename T> static void SafeRelease(T &x) { if (x != nullptr) { delete x; x = nullptr; } }
bool Valid = false;
std::shared_ptr<FGLDebug> Debug;
std::unique_ptr<HWVertexBuffer> StreamVertexBuffer, StreamVertexBufferBurn;
@ -452,7 +453,6 @@ private:
bool UpdatePending;
bool NeedPalUpdate;
bool NeedGammaUpdate;
bool VSync;
LTRBRect BlendingRect;
int In2D;
bool InScene;

View file

@ -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");

View file

@ -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<SDLGLFB *> (old);
SDLBaseFB *fb = static_cast<SDLBaseFB *> (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<SDLGLFB *>(CreateFrameBuffer (width, height, false, fullscreen, NULL));
fb = static_cast<SDLBaseFB *>(CreateFrameBuffer (width, height, false, fullscreen, NULL));
}
// fb->SetFlash (flashColor, flashAmount);

View file

@ -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);

View file

@ -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<SDLFB *> (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<SDLFB *>(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)

View file

@ -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() {}
};