Add bgra support to OpenGLSWFrameBuffer

This commit is contained in:
Magnus Norddahl 2016-10-11 15:43:12 +02:00
parent f5c069c759
commit f37ee3a024
9 changed files with 44 additions and 27 deletions

View File

@ -79,7 +79,7 @@ CUSTOM_CVAR(Int, vid_hwgamma, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITC
//========================================================================== //==========================================================================
OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen) : OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen) :
Super(hMonitor, width, height, bits, refreshHz, fullscreen) Super(hMonitor, width, height, bits, refreshHz, fullscreen, false)
{ {
// SetVSync needs to be at the very top to workaround a bug in Nvidia's OpenGL driver. // 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! // If wglSwapIntervalEXT is called after glBindFramebuffer in a frame the setting is not changed!

View File

@ -120,8 +120,8 @@ const char *const OpenGLSWFrameBuffer::ShaderDefines[OpenGLSWFrameBuffer::NUM_SH
"#define EGAMMACORRECTION", // GammaCorrection "#define EGAMMACORRECTION", // GammaCorrection
}; };
OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen) : OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen, bool bgra) :
Super(hMonitor, width, height, bits, refreshHz, fullscreen) Super(hMonitor, width, height, bits, refreshHz, fullscreen, bgra)
{ {
// To do: this needs to cooperate with the same static in OpenGLFrameBuffer::InitializeState // To do: this needs to cooperate with the same static in OpenGLFrameBuffer::InitializeState
static bool first = true; static bool first = true;
@ -892,7 +892,7 @@ void OpenGLSWFrameBuffer::KillNativeTexs()
bool OpenGLSWFrameBuffer::CreateFBTexture() bool OpenGLSWFrameBuffer::CreateFBTexture()
{ {
CreateTexture("FBTexture", Width, Height, 1, GL_R8, &FBTexture); CreateTexture("FBTexture", Width, Height, 1, IsBgra() ? GL_RGBA8 : GL_R8, &FBTexture);
FBWidth = Width; FBWidth = Width;
FBHeight = Height; FBHeight = Height;
return true; return true;
@ -1262,13 +1262,16 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
{ {
if (copy3d) if (copy3d)
{ {
int pixelsize = IsBgra() ? 4 : 1;
int size = Width * Height * pixelsize;
if (FBTexture->Buffers[0] == 0) if (FBTexture->Buffers[0] == 0)
{ {
glGenBuffers(2, (GLuint*)FBTexture->Buffers); glGenBuffers(2, (GLuint*)FBTexture->Buffers);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, FBTexture->Buffers[0]); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, FBTexture->Buffers[0]);
glBufferData(GL_PIXEL_UNPACK_BUFFER, Width * Height, nullptr, GL_STREAM_DRAW); glBufferData(GL_PIXEL_UNPACK_BUFFER, size, nullptr, GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, FBTexture->Buffers[1]); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, FBTexture->Buffers[1]);
glBufferData(GL_PIXEL_UNPACK_BUFFER, Width * Height, nullptr, GL_STREAM_DRAW); glBufferData(GL_PIXEL_UNPACK_BUFFER, size, nullptr, GL_STREAM_DRAW);
} }
else else
{ {
@ -1276,27 +1279,30 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
FBTexture->CurrentBuffer = (FBTexture->CurrentBuffer + 1) & 1; FBTexture->CurrentBuffer = (FBTexture->CurrentBuffer + 1) & 1;
} }
uint8_t *dest = (uint8_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, Width * Height, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); uint8_t *dest = (uint8_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
if (dest) if (dest)
{ {
if (Pitch == Width) if (Pitch == Width)
{ {
memcpy(dest, MemBuffer, Width * Height); memcpy(dest, MemBuffer, Width * Height * pixelsize);
} }
else else
{ {
uint8_t *src = MemBuffer; uint8_t *src = MemBuffer;
for (int y = 0; y < Height; y++) for (int y = 0; y < Height; y++)
{ {
memcpy(dest, src, Width); memcpy(dest, src, Width * pixelsize);
dest += Width; dest += Width * pixelsize;
src += Pitch; src += Pitch * pixelsize;
} }
} }
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
GLint oldBinding = 0; GLint oldBinding = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding); glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding);
glBindTexture(GL_TEXTURE_2D, FBTexture->Texture); glBindTexture(GL_TEXTURE_2D, FBTexture->Texture);
if (IsBgra())
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
else
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_RED, GL_UNSIGNED_BYTE, 0); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_RED, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, oldBinding); glBindTexture(GL_TEXTURE_2D, oldBinding);
} }
@ -1314,6 +1320,9 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
memset(Constant, 0, sizeof(Constant)); memset(Constant, 0, sizeof(Constant));
SetAlphaBlend(0); SetAlphaBlend(0);
EnableAlphaTest(false); EnableAlphaTest(false);
if (IsBgra())
SetPixelShader(Shaders[SHADER_NormalColor]);
else
SetPixelShader(Shaders[SHADER_NormalColorPal]); SetPixelShader(Shaders[SHADER_NormalColorPal]);
if (copy3d) if (copy3d)
{ {
@ -1330,6 +1339,9 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
{ {
color0 = ColorValue(realfixedcolormap->ColorizeStart[0] / 2, realfixedcolormap->ColorizeStart[1] / 2, realfixedcolormap->ColorizeStart[2] / 2, 0); color0 = ColorValue(realfixedcolormap->ColorizeStart[0] / 2, realfixedcolormap->ColorizeStart[1] / 2, realfixedcolormap->ColorizeStart[2] / 2, 0);
color1 = ColorValue(realfixedcolormap->ColorizeEnd[0] / 2, realfixedcolormap->ColorizeEnd[1] / 2, realfixedcolormap->ColorizeEnd[2] / 2, 1); color1 = ColorValue(realfixedcolormap->ColorizeEnd[0] / 2, realfixedcolormap->ColorizeEnd[1] / 2, realfixedcolormap->ColorizeEnd[2] / 2, 1);
if (IsBgra())
SetPixelShader(Shaders[SHADER_SpecialColormap]);
else
SetPixelShader(Shaders[SHADER_SpecialColormapPal]); SetPixelShader(Shaders[SHADER_SpecialColormapPal]);
} }
} }
@ -1341,6 +1353,9 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
CalcFullscreenCoords(verts, Accel2D, false, color0, color1); CalcFullscreenCoords(verts, Accel2D, false, color0, color1);
DrawTriangleFans(2, verts); DrawTriangleFans(2, verts);
} }
if (IsBgra())
SetPixelShader(Shaders[SHADER_NormalColor]);
else
SetPixelShader(Shaders[SHADER_NormalColorPal]); SetPixelShader(Shaders[SHADER_NormalColorPal]);
} }

View File

@ -29,7 +29,7 @@ class OpenGLFrameBuffer : public SDLGLFB
public: public:
explicit OpenGLSWFrameBuffer() {} explicit OpenGLSWFrameBuffer() {}
OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen); OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen, bool bgra);
~OpenGLSWFrameBuffer(); ~OpenGLSWFrameBuffer();
bool IsValid() override; bool IsValid() override;

View File

@ -1126,8 +1126,8 @@ void CocoaFrameBuffer::Flip()
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
SDLGLFB::SDLGLFB(void*, const int width, const int height, int, int, const bool fullscreen) SDLGLFB::SDLGLFB(void*, const int width, const int height, int, int, const bool fullscreen, bool bgra)
: DFrameBuffer(width, height, false) : DFrameBuffer(width, height, bgra)
, m_lock(-1) , m_lock(-1)
, m_isUpdatePending(false) , m_isUpdatePending(false)
{ {

View File

@ -52,7 +52,7 @@ class SDLGLFB : public DFrameBuffer
{ {
public: public:
// This must have the same parameters as the Windows version, even if they are not used! // 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); SDLGLFB(void *hMonitor, int width, int height, int, int, bool fullscreen, bool bgra);
~SDLGLFB(); ~SDLGLFB();
virtual bool Lock(bool buffered = true); virtual bool Lock(bool buffered = true);

View File

@ -314,8 +314,8 @@ bool SDLGLVideo::InitHardware (bool allowsoftware, int multisample)
// FrameBuffer implementation ----------------------------------------------- // FrameBuffer implementation -----------------------------------------------
SDLGLFB::SDLGLFB (void *, int width, int height, int, int, bool fullscreen) SDLGLFB::SDLGLFB (void *, int width, int height, int, int, bool fullscreen, bool bgra)
: DFrameBuffer (width, height, false) : DFrameBuffer (width, height, bgra)
{ {
int i; int i;

View File

@ -39,7 +39,7 @@ class SDLGLFB : public DFrameBuffer
DECLARE_CLASS(SDLGLFB, DFrameBuffer) DECLARE_CLASS(SDLGLFB, DFrameBuffer)
public: public:
// this must have the same parameters as the Windows version, even if they are not used! // 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); SDLGLFB (void *hMonitor, int width, int height, int, int, bool fullscreen, bool bgra);
~SDLGLFB (); ~SDLGLFB ();
void ForceBuffering (bool force); void ForceBuffering (bool force);

View File

@ -381,7 +381,8 @@ DFrameBuffer *Win32GLVideo::CreateFrameBuffer(int width, int height, bool bgra,
fb->m_Height == m_DisplayHeight && fb->m_Height == m_DisplayHeight &&
fb->m_Bits == m_DisplayBits && fb->m_Bits == m_DisplayBits &&
fb->m_RefreshHz == m_DisplayHz && fb->m_RefreshHz == m_DisplayHz &&
fb->m_Fullscreen == fs) fb->m_Fullscreen == fs &&
fb->m_Bgra == bgra)
{ {
return old; return old;
} }
@ -391,7 +392,7 @@ DFrameBuffer *Win32GLVideo::CreateFrameBuffer(int width, int height, bool bgra,
if (vid_renderer == 1) if (vid_renderer == 1)
fb = new OpenGLFrameBuffer(m_hMonitor, m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz, fs); fb = new OpenGLFrameBuffer(m_hMonitor, m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz, fs);
else else
fb = new OpenGLSWFrameBuffer(m_hMonitor, m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz, fs); fb = new OpenGLSWFrameBuffer(m_hMonitor, m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz, fs, bgra);
return fb; return fb;
} }
@ -867,13 +868,14 @@ IMPLEMENT_ABSTRACT_CLASS(Win32GLFrameBuffer)
// //
//========================================================================== //==========================================================================
Win32GLFrameBuffer::Win32GLFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen) : BaseWinFB(width, height, false) Win32GLFrameBuffer::Win32GLFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen, bool bgra) : BaseWinFB(width, height, bgra)
{ {
m_Width = width; m_Width = width;
m_Height = height; m_Height = height;
m_Bits = bits; m_Bits = bits;
m_RefreshHz = refreshHz; m_RefreshHz = refreshHz;
m_Fullscreen = fullscreen; m_Fullscreen = fullscreen;
m_Bgra = bgra;
m_Lock=0; m_Lock=0;
RECT r; RECT r;

View File

@ -101,7 +101,7 @@ public:
Win32GLFrameBuffer() {} Win32GLFrameBuffer() {}
// Actually, hMonitor is a HMONITOR, but it's passed as a void * as there // Actually, hMonitor is a HMONITOR, but it's passed as a void * as there
// look to be some cross-platform bits in the way. // look to be some cross-platform bits in the way.
Win32GLFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen); Win32GLFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen, bool bgra);
virtual ~Win32GLFrameBuffer(); virtual ~Win32GLFrameBuffer();
@ -143,7 +143,7 @@ protected:
float m_Gamma, m_Brightness, m_Contrast; float m_Gamma, m_Brightness, m_Contrast;
WORD m_origGamma[768]; WORD m_origGamma[768];
BOOL m_supportsGamma; BOOL m_supportsGamma;
bool m_Fullscreen; bool m_Fullscreen, m_Bgra;
int m_Width, m_Height, m_Bits, m_RefreshHz; int m_Width, m_Height, m_Bits, m_RefreshHz;
int m_Lock; int m_Lock;
char m_displayDeviceNameBuffer[CCHDEVICENAME]; char m_displayDeviceNameBuffer[CCHDEVICENAME];