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) :
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.
// 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
};
OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen) :
Super(hMonitor, width, height, bits, refreshHz, fullscreen)
OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen, bool bgra) :
Super(hMonitor, width, height, bits, refreshHz, fullscreen, bgra)
{
// To do: this needs to cooperate with the same static in OpenGLFrameBuffer::InitializeState
static bool first = true;
@ -892,7 +892,7 @@ void OpenGLSWFrameBuffer::KillNativeTexs()
bool OpenGLSWFrameBuffer::CreateFBTexture()
{
CreateTexture("FBTexture", Width, Height, 1, GL_R8, &FBTexture);
CreateTexture("FBTexture", Width, Height, 1, IsBgra() ? GL_RGBA8 : GL_R8, &FBTexture);
FBWidth = Width;
FBHeight = Height;
return true;
@ -1262,13 +1262,16 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
{
if (copy3d)
{
int pixelsize = IsBgra() ? 4 : 1;
int size = Width * Height * pixelsize;
if (FBTexture->Buffers[0] == 0)
{
glGenBuffers(2, (GLuint*)FBTexture->Buffers);
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]);
glBufferData(GL_PIXEL_UNPACK_BUFFER, Width * Height, nullptr, GL_STREAM_DRAW);
glBufferData(GL_PIXEL_UNPACK_BUFFER, size, nullptr, GL_STREAM_DRAW);
}
else
{
@ -1276,27 +1279,30 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
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 (Pitch == Width)
{
memcpy(dest, MemBuffer, Width * Height);
memcpy(dest, MemBuffer, Width * Height * pixelsize);
}
else
{
uint8_t *src = MemBuffer;
for (int y = 0; y < Height; y++)
{
memcpy(dest, src, Width);
dest += Width;
src += Pitch;
memcpy(dest, src, Width * pixelsize);
dest += Width * pixelsize;
src += Pitch * pixelsize;
}
}
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
GLint oldBinding = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding);
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);
glBindTexture(GL_TEXTURE_2D, oldBinding);
}
@ -1314,6 +1320,9 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
memset(Constant, 0, sizeof(Constant));
SetAlphaBlend(0);
EnableAlphaTest(false);
if (IsBgra())
SetPixelShader(Shaders[SHADER_NormalColor]);
else
SetPixelShader(Shaders[SHADER_NormalColorPal]);
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);
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]);
}
}
@ -1341,6 +1353,9 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
CalcFullscreenCoords(verts, Accel2D, false, color0, color1);
DrawTriangleFans(2, verts);
}
if (IsBgra())
SetPixelShader(Shaders[SHADER_NormalColor]);
else
SetPixelShader(Shaders[SHADER_NormalColorPal]);
}

View file

@ -29,7 +29,7 @@ class OpenGLFrameBuffer : public SDLGLFB
public:
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();
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)
: DFrameBuffer(width, height, false)
SDLGLFB::SDLGLFB(void*, const int width, const int height, int, int, const bool fullscreen, bool bgra)
: DFrameBuffer(width, height, bgra)
, m_lock(-1)
, m_isUpdatePending(false)
{

View file

@ -52,7 +52,7 @@ class SDLGLFB : public DFrameBuffer
{
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);
SDLGLFB(void *hMonitor, int width, int height, int, int, bool fullscreen, bool bgra);
~SDLGLFB();
virtual bool Lock(bool buffered = true);

View file

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

View file

@ -39,7 +39,7 @@ class SDLGLFB : public DFrameBuffer
DECLARE_CLASS(SDLGLFB, DFrameBuffer)
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);
SDLGLFB (void *hMonitor, int width, int height, int, int, bool fullscreen, bool bgra);
~SDLGLFB ();
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_Bits == m_DisplayBits &&
fb->m_RefreshHz == m_DisplayHz &&
fb->m_Fullscreen == fs)
fb->m_Fullscreen == fs &&
fb->m_Bgra == bgra)
{
return old;
}
@ -391,7 +392,7 @@ DFrameBuffer *Win32GLVideo::CreateFrameBuffer(int width, int height, bool bgra,
if (vid_renderer == 1)
fb = new OpenGLFrameBuffer(m_hMonitor, m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz, fs);
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;
}
@ -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_Height = height;
m_Bits = bits;
m_RefreshHz = refreshHz;
m_Fullscreen = fullscreen;
m_Bgra = bgra;
m_Lock=0;
RECT r;

View file

@ -101,7 +101,7 @@ public:
Win32GLFrameBuffer() {}
// Actually, hMonitor is a HMONITOR, but it's passed as a void * as there
// 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();
@ -143,7 +143,7 @@ protected:
float m_Gamma, m_Brightness, m_Contrast;
WORD m_origGamma[768];
BOOL m_supportsGamma;
bool m_Fullscreen;
bool m_Fullscreen, m_Bgra;
int m_Width, m_Height, m_Bits, m_RefreshHz;
int m_Lock;
char m_displayDeviceNameBuffer[CCHDEVICENAME];