From 5b8a016cadd2266a415113c578b67e718c3123b8 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 29 Jul 2018 18:48:28 +0200 Subject: [PATCH] - add vid_hdr cvar that enables higher than 8bpc output for monitors that support it --- src/gl/renderer/gl_postprocess.cpp | 8 +++ src/v_video.cpp | 8 +++ src/win32/win32glvideo.cpp | 97 +++++++++++++++++++----------- 3 files changed, 77 insertions(+), 36 deletions(-) diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index 5694912cb..8caf938c9 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -47,6 +47,8 @@ #include "gl/textures/gl_hwtexture.h" #include "r_videoscale.h" +extern bool vid_hdr_active; + void FGLRenderer::RenderScreenQuad() { mVBO->BindVBO(); @@ -224,6 +226,12 @@ void FGLRenderer::DrawPresentTexture(const IntRect &box, bool applyGamma) mPresentShader->Uniforms->Saturation = clamp(vid_saturation, -15.0f, 15.f); mPresentShader->Uniforms->GrayFormula = static_cast(gl_satformula); } + if (vid_hdr_active && framebuffer->IsFullscreen()) + { + // Full screen exclusive mode treats a rgba16f frame buffer as linear. + // It probably will eventually in desktop mode too, but the DWM doesn't seem to support that. + mPresentShader->Uniforms->InvGamma *= 2.2f; + } mPresentShader->Uniforms->Scale = { screen->mScreenViewport.width / (float)mBuffers->GetWidth(), screen->mScreenViewport.height / (float)mBuffers->GetHeight() }; mPresentShader->Uniforms.Set(); RenderScreenQuad(); diff --git a/src/v_video.cpp b/src/v_video.cpp index 44f562622..76b8770dc 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -65,6 +65,7 @@ #include "vm.h" #include "r_videoscale.h" #include "i_time.h" +#include "version.h" EXTERN_CVAR(Bool, cl_capfps) @@ -884,12 +885,19 @@ CUSTOM_CVAR(Bool, fullscreen, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOIN setmodeneeded = true; } +CUSTOM_CVAR(Bool, vid_hdr, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +{ + Printf("This won't take effect until " GAMENAME " is restarted.\n"); +} + CCMD(vid_listadapters) { if (Video != NULL) Video->DumpAdapters(); } +bool vid_hdr_active = false; + DEFINE_GLOBAL(SmallFont) DEFINE_GLOBAL(SmallFont2) DEFINE_GLOBAL(BigFont) diff --git a/src/win32/win32glvideo.cpp b/src/win32/win32glvideo.cpp index 273a70053..c3650a807 100644 --- a/src/win32/win32glvideo.cpp +++ b/src/win32/win32glvideo.cpp @@ -55,12 +55,15 @@ EXTERN_CVAR(Int, vid_adapter) EXTERN_CVAR(Bool, vr_enable_quadbuffered) +EXTERN_CVAR(Bool, vid_hdr) CUSTOM_CVAR(Bool, gl_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { Printf("This won't take effect until " GAMENAME " is restarted.\n"); } +extern bool vid_hdr_active; + // these get used before GLEW is initialized so we have to use separate pointers with different names PFNWGLCHOOSEPIXELFORMATARBPROC myWglChoosePixelFormatARB; // = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); PFNWGLCREATECONTEXTATTRIBSARBPROC myWglCreateContextAttribsARB; @@ -233,12 +236,16 @@ bool Win32GLVideo::SetPixelFormat() // //========================================================================== +static void append(std::vector &list1, std::initializer_list list2) +{ + list1.insert(list1.end(), list2); +} + bool Win32GLVideo::SetupPixelFormat(int multisample) { - int i; int colorDepth; HDC deskDC; - int attributes[28]; + std::vector attributes; int pixelFormat; unsigned int numFormats; float attribsFloat[] = { 0.0f, 0.0f }; @@ -250,59 +257,77 @@ bool Win32GLVideo::SetupPixelFormat(int multisample) if (myWglChoosePixelFormatARB) { again: - attributes[0] = WGL_RED_BITS_ARB; //bits - attributes[1] = 8; - attributes[2] = WGL_GREEN_BITS_ARB; //bits - attributes[3] = 8; - attributes[4] = WGL_BLUE_BITS_ARB; //bits - attributes[5] = 8; - attributes[6] = WGL_ALPHA_BITS_ARB; - attributes[7] = 8; - attributes[8] = WGL_DEPTH_BITS_ARB; - attributes[9] = 24; - attributes[10] = WGL_STENCIL_BITS_ARB; - attributes[11] = 8; + append(attributes, { WGL_DEPTH_BITS_ARB, 24 }); + append(attributes, { WGL_STENCIL_BITS_ARB, 8 }); - attributes[12] = WGL_DRAW_TO_WINDOW_ARB; //required to be true - attributes[13] = true; - attributes[14] = WGL_SUPPORT_OPENGL_ARB; - attributes[15] = true; - attributes[16] = WGL_DOUBLE_BUFFER_ARB; - attributes[17] = true; + //required to be true + append(attributes, { WGL_DRAW_TO_WINDOW_ARB, GL_TRUE }); + append(attributes, { WGL_SUPPORT_OPENGL_ARB, GL_TRUE }); + append(attributes, { WGL_DOUBLE_BUFFER_ARB, GL_TRUE }); if (multisample > 0) { - attributes[18] = WGL_SAMPLE_BUFFERS_ARB; - attributes[19] = true; - attributes[20] = WGL_SAMPLES_ARB; - attributes[21] = multisample; - i = 22; - } - else - { - i = 18; + append(attributes, { WGL_SAMPLE_BUFFERS_ARB, GL_TRUE }); + append(attributes, { WGL_SAMPLES_ARB, multisample }); } - attributes[i++] = WGL_ACCELERATION_ARB; //required to be FULL_ACCELERATION_ARB - attributes[i++] = WGL_FULL_ACCELERATION_ARB; + append(attributes, { WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB }); //required to be FULL_ACCELERATION_ARB if (vr_enable_quadbuffered) { // [BB] Starting with driver version 314.07, NVIDIA GeForce cards support OpenGL quad buffered // stereo rendering with 3D Vision hardware. Select the corresponding attribute here. - attributes[i++] = WGL_STEREO_ARB; - attributes[i++] = true; + append(attributes, { WGL_STEREO_ARB, GL_TRUE }); } - attributes[i++] = 0; - attributes[i++] = 0; + size_t bitsPos = attributes.size(); - if (!myWglChoosePixelFormatARB(m_hDC, attributes, attribsFloat, 1, &pixelFormat, &numFormats)) + if (vid_hdr) + { + append(attributes, { WGL_RED_BITS_ARB, 16 }); + append(attributes, { WGL_GREEN_BITS_ARB, 16 }); + append(attributes, { WGL_BLUE_BITS_ARB, 16 }); + append(attributes, { WGL_ALPHA_BITS_ARB, 16 }); + append(attributes, { WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_FLOAT_ARB }); + } + else + { + append(attributes, { WGL_RED_BITS_ARB, 8 }); + append(attributes, { WGL_GREEN_BITS_ARB, 8 }); + append(attributes, { WGL_BLUE_BITS_ARB, 8 }); + append(attributes, { WGL_ALPHA_BITS_ARB, 8 }); + } + + append(attributes, { 0, 0 }); + + if (!myWglChoosePixelFormatARB(m_hDC, attributes.data(), attribsFloat, 1, &pixelFormat, &numFormats)) { Printf("R_OPENGL: Couldn't choose pixel format. Retrying in compatibility mode\n"); goto oldmethod; } + if (vid_hdr && numFormats == 0) // This card/driver doesn't support the rgb16f pixel format. Fall back to 8bpc + { + Printf("R_OPENGL: This card/driver does not support RGBA16F. HDR will not work.\n"); + + attributes.erase(attributes.begin() + bitsPos, attributes.end()); + append(attributes, { WGL_RED_BITS_ARB, 8 }); + append(attributes, { WGL_GREEN_BITS_ARB, 8 }); + append(attributes, { WGL_BLUE_BITS_ARB, 8 }); + append(attributes, { WGL_ALPHA_BITS_ARB, 8 }); + append(attributes, { 0, 0 }); + + if (!myWglChoosePixelFormatARB(m_hDC, attributes.data(), attribsFloat, 1, &pixelFormat, &numFormats)) + { + Printf("R_OPENGL: Couldn't choose pixel format. Retrying in compatibility mode\n"); + goto oldmethod; + } + } + else if (vid_hdr) + { + vid_hdr_active = true; + } + if (numFormats == 0) { if (vr_enable_quadbuffered)