From f37ee3a024ca08a76182e4b1168c4e97affa9821 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 11 Oct 2016 15:43:12 +0200 Subject: [PATCH] Add bgra support to OpenGLSWFrameBuffer --- src/gl/system/gl_framebuffer.cpp | 2 +- src/gl/system/gl_swframebuffer.cpp | 43 ++++++++++++++++++++---------- src/gl/system/gl_swframebuffer.h | 2 +- src/posix/cocoa/i_video.mm | 4 +-- src/posix/cocoa/sdlglvideo.h | 2 +- src/posix/sdl/sdlglvideo.cpp | 4 +-- src/posix/sdl/sdlglvideo.h | 2 +- src/win32/win32gliface.cpp | 8 +++--- src/win32/win32gliface.h | 4 +-- 9 files changed, 44 insertions(+), 27 deletions(-) diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 6264352f6..57e0cd679 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -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! diff --git a/src/gl/system/gl_swframebuffer.cpp b/src/gl/system/gl_swframebuffer.cpp index 40d76aab1..286066fc9 100644 --- a/src/gl/system/gl_swframebuffer.cpp +++ b/src/gl/system/gl_swframebuffer.cpp @@ -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,28 +1279,31 @@ 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); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_RED, GL_UNSIGNED_BYTE, 0); + 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,7 +1320,10 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d) memset(Constant, 0, sizeof(Constant)); SetAlphaBlend(0); EnableAlphaTest(false); - SetPixelShader(Shaders[SHADER_NormalColorPal]); + if (IsBgra()) + SetPixelShader(Shaders[SHADER_NormalColor]); + else + SetPixelShader(Shaders[SHADER_NormalColorPal]); if (copy3d) { FBVERTEX verts[4]; @@ -1330,7 +1339,10 @@ 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); - SetPixelShader(Shaders[SHADER_SpecialColormapPal]); + if (IsBgra()) + SetPixelShader(Shaders[SHADER_SpecialColormap]); + else + SetPixelShader(Shaders[SHADER_SpecialColormapPal]); } } else @@ -1341,7 +1353,10 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d) CalcFullscreenCoords(verts, Accel2D, false, color0, color1); DrawTriangleFans(2, verts); } - SetPixelShader(Shaders[SHADER_NormalColorPal]); + if (IsBgra()) + SetPixelShader(Shaders[SHADER_NormalColor]); + else + SetPixelShader(Shaders[SHADER_NormalColorPal]); } //========================================================================== diff --git a/src/gl/system/gl_swframebuffer.h b/src/gl/system/gl_swframebuffer.h index 1cf0288ce..96e331389 100644 --- a/src/gl/system/gl_swframebuffer.h +++ b/src/gl/system/gl_swframebuffer.h @@ -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; diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index 7dc7a6eed..8c773fce9 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -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) { diff --git a/src/posix/cocoa/sdlglvideo.h b/src/posix/cocoa/sdlglvideo.h index fcbf23f2a..43f2c9c43 100644 --- a/src/posix/cocoa/sdlglvideo.h +++ b/src/posix/cocoa/sdlglvideo.h @@ -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); diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index 86371bd49..58cfc9a23 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -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; diff --git a/src/posix/sdl/sdlglvideo.h b/src/posix/sdl/sdlglvideo.h index 3b84f83c4..01e70caac 100644 --- a/src/posix/sdl/sdlglvideo.h +++ b/src/posix/sdl/sdlglvideo.h @@ -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); diff --git a/src/win32/win32gliface.cpp b/src/win32/win32gliface.cpp index d46f45a02..0079271a3 100644 --- a/src/win32/win32gliface.cpp +++ b/src/win32/win32gliface.cpp @@ -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; diff --git a/src/win32/win32gliface.h b/src/win32/win32gliface.h index d16c0dcc3..fbaf34bd5 100644 --- a/src/win32/win32gliface.h +++ b/src/win32/win32gliface.h @@ -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];