mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-12-12 19:37:01 +00:00
GX2: Implement GX2SetTVGamma and GX2SetDRCGamma (#1682)
This commit is contained in:
parent
4fa0df6dcf
commit
5390f9338c
22 changed files with 239 additions and 46 deletions
|
|
@ -54,6 +54,8 @@ struct LatteGPUState_t
|
||||||
// temporary (replace with proper solution later)
|
// temporary (replace with proper solution later)
|
||||||
bool tvBufferUsesSRGB;
|
bool tvBufferUsesSRGB;
|
||||||
bool drcBufferUsesSRGB;
|
bool drcBufferUsesSRGB;
|
||||||
|
float tvGamma = 0.0f;
|
||||||
|
float drcGamma = 0.0f;
|
||||||
// draw state
|
// draw state
|
||||||
bool activeShaderHasError; // if try, at least one currently bound shader stage has an error and cannot be used for drawing
|
bool activeShaderHasError; // if try, at least one currently bound shader stage has an error and cannot be used for drawing
|
||||||
bool repeatTextureInitialization; // if set during rendertarget or texture initialization, repeat the process (textures likely have been invalidated)
|
bool repeatTextureInitialization; // if set during rendertarget or texture initialization, repeat the process (textures likely have been invalidated)
|
||||||
|
|
|
||||||
|
|
@ -120,16 +120,6 @@ uint8* LatteTextureLoader_getInputLinearOptimized(LatteTextureLoaderCtx* texture
|
||||||
|
|
||||||
#define LatteTextureLoader_getInputLinearOptimized_(__textureLoader,__x,__y,__stepX,__stepY,__bpp,__sliceIndex,__numSlices,__sample,__pitch,__height) (textureLoader->inputData+((__x/__stepX) + __pitch * (__y/__stepY) + (__sliceIndex + __numSlices * __sample) * __height * __pitch)*(__bpp/8))
|
#define LatteTextureLoader_getInputLinearOptimized_(__textureLoader,__x,__y,__stepX,__stepY,__bpp,__sliceIndex,__numSlices,__sample,__pitch,__height) (textureLoader->inputData+((__x/__stepX) + __pitch * (__y/__stepY) + (__sliceIndex + __numSlices * __sample) * __height * __pitch)*(__bpp/8))
|
||||||
|
|
||||||
float SRGB_to_RGB(float cs)
|
|
||||||
{
|
|
||||||
float cl;
|
|
||||||
if (cs <= 0.04045f)
|
|
||||||
cl = cs / 12.92f;
|
|
||||||
else
|
|
||||||
cl = powf(((cs + 0.055f) / 1.055f), 2.4f);
|
|
||||||
return cl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void decodeBC1Block(uint8* inputData, float* output4x4RGBA)
|
void decodeBC1Block(uint8* inputData, float* output4x4RGBA)
|
||||||
{
|
{
|
||||||
// read colors
|
// read colors
|
||||||
|
|
|
||||||
|
|
@ -603,7 +603,7 @@ void OpenGLRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
|
||||||
shader_unbind(RendererShader::ShaderType::kGeometry);
|
shader_unbind(RendererShader::ShaderType::kGeometry);
|
||||||
shader_bind(shader->GetVertexShader());
|
shader_bind(shader->GetVertexShader());
|
||||||
shader_bind(shader->GetFragmentShader());
|
shader_bind(shader->GetFragmentShader());
|
||||||
shader->SetUniformParameters(*texView, {imageWidth, imageHeight});
|
shader->SetUniformParameters(*texView, {imageWidth, imageHeight}, padView);
|
||||||
|
|
||||||
// set viewport
|
// set viewport
|
||||||
glViewportIndexedf(0, imageX, imageY, imageWidth, imageHeight);
|
glViewportIndexedf(0, imageX, imageY, imageWidth, imageHeight);
|
||||||
|
|
@ -620,13 +620,11 @@ void OpenGLRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, useLinearTexFilter ? GL_LINEAR : GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, useLinearTexFilter ? GL_LINEAR : GL_NEAREST);
|
||||||
texViewGL->samplerState.filterMag = 0xFFFFFFFF;
|
texViewGL->samplerState.filterMag = 0xFFFFFFFF;
|
||||||
|
|
||||||
if ((!padView && !LatteGPUState.tvBufferUsesSRGB) || (padView && !LatteGPUState.drcBufferUsesSRGB))
|
|
||||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||||
|
|
||||||
uint16 indexData[6] = { 0,1,2,3,4,5 };
|
uint16 indexData[6] = { 0,1,2,3,4,5 };
|
||||||
glDrawRangeElements(GL_TRIANGLES, 0, 5, 6, GL_UNSIGNED_SHORT, indexData);
|
glDrawRangeElements(GL_TRIANGLES, 0, 5, 6, GL_UNSIGNED_SHORT, indexData);
|
||||||
|
|
||||||
if ((!padView && !LatteGPUState.tvBufferUsesSRGB) || (padView && !LatteGPUState.drcBufferUsesSRGB))
|
|
||||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||||
|
|
||||||
// unbind texture
|
// unbind texture
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,16 @@ sint32 RendererShaderGL::GetUniformLocation(const char* name)
|
||||||
return glGetUniformLocation(m_program, name);
|
return glGetUniformLocation(m_program, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererShaderGL::SetUniform1i(sint32 location, sint32 value)
|
||||||
|
{
|
||||||
|
glProgramUniform1i(m_program, location, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RendererShaderGL::SetUniform1f(sint32 location, float value)
|
||||||
|
{
|
||||||
|
glProgramUniform1f(m_program, location, value);
|
||||||
|
}
|
||||||
|
|
||||||
void RendererShaderGL::SetUniform2fv(sint32 location, void* data, sint32 count)
|
void RendererShaderGL::SetUniform2fv(sint32 location, void* data, sint32 count)
|
||||||
{
|
{
|
||||||
glProgramUniform2fv(m_program, location, count, (const GLfloat*)data);
|
glProgramUniform2fv(m_program, location, count, (const GLfloat*)data);
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ public:
|
||||||
GLuint GetShaderObject() const { cemu_assert_debug(m_isCompiled); return m_shader_object; }
|
GLuint GetShaderObject() const { cemu_assert_debug(m_isCompiled); return m_shader_object; }
|
||||||
|
|
||||||
sint32 GetUniformLocation(const char* name) override;
|
sint32 GetUniformLocation(const char* name) override;
|
||||||
|
|
||||||
|
void SetUniform1i(sint32 location, sint32 value) override;
|
||||||
|
void SetUniform1f(sint32 location, float value) override;
|
||||||
void SetUniform2fv(sint32 location, void* data, sint32 count) override;
|
void SetUniform2fv(sint32 location, void* data, sint32 count) override;
|
||||||
void SetUniform4iv(sint32 location, void* data, sint32 count) override;
|
void SetUniform4iv(sint32 location, void* data, sint32 count) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
#include "Cafe/HW/Latte/Renderer/RendererOuputShader.h"
|
#include "Cafe/HW/Latte/Renderer/RendererOuputShader.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h"
|
#include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h"
|
||||||
|
#include "config/ActiveSettings.h"
|
||||||
|
|
||||||
const std::string RendererOutputShader::s_copy_shader_source =
|
const std::string RendererOutputShader::s_copy_shader_source =
|
||||||
R"(
|
R"(
|
||||||
void main()
|
void outputShader()
|
||||||
{
|
{
|
||||||
colorOut0 = vec4(texture(textureSrc, passUV).rgb,1.0);
|
colorOut0 = vec4(texture(textureSrc, passUV).rgb,1.0);
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +50,7 @@ vec4 bcFilter(vec2 uv, vec4 texelSize)
|
||||||
mix(sample1, sample0, sx), sy);
|
mix(sample1, sample0, sx), sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(){
|
void outputShader(){
|
||||||
vec4 texelSize = vec4( 1.0 / textureSrcResolution.xy, textureSrcResolution.xy);
|
vec4 texelSize = vec4( 1.0 / textureSrcResolution.xy, textureSrcResolution.xy);
|
||||||
colorOut0 = vec4(bcFilter(passUV, texelSize).rgb,1.0);
|
colorOut0 = vec4(bcFilter(passUV, texelSize).rgb,1.0);
|
||||||
}
|
}
|
||||||
|
|
@ -108,7 +109,7 @@ vec3 BicubicHermiteTexture(vec2 uv, vec4 texelSize)
|
||||||
return CubicHermite(CP0X, CP1X, CP2X, CP3X, frac.y);
|
return CubicHermite(CP0X, CP1X, CP2X, CP3X, frac.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(){
|
void outputShader(){
|
||||||
vec4 texelSize = vec4( 1.0 / textureSrcResolution.xy, textureSrcResolution.xy);
|
vec4 texelSize = vec4( 1.0 / textureSrcResolution.xy, textureSrcResolution.xy);
|
||||||
colorOut0 = vec4(BicubicHermiteTexture(passUV, texelSize), 1.0);
|
colorOut0 = vec4(BicubicHermiteTexture(passUV, texelSize), 1.0);
|
||||||
}
|
}
|
||||||
|
|
@ -135,14 +136,20 @@ RendererOutputShader::RendererOutputShader(const std::string& vertex_source, con
|
||||||
m_uniformLocations[0].m_loc_textureSrcResolution = m_vertex_shader->GetUniformLocation("textureSrcResolution");
|
m_uniformLocations[0].m_loc_textureSrcResolution = m_vertex_shader->GetUniformLocation("textureSrcResolution");
|
||||||
m_uniformLocations[0].m_loc_nativeResolution = m_vertex_shader->GetUniformLocation("nativeResolution");
|
m_uniformLocations[0].m_loc_nativeResolution = m_vertex_shader->GetUniformLocation("nativeResolution");
|
||||||
m_uniformLocations[0].m_loc_outputResolution = m_vertex_shader->GetUniformLocation("outputResolution");
|
m_uniformLocations[0].m_loc_outputResolution = m_vertex_shader->GetUniformLocation("outputResolution");
|
||||||
|
m_uniformLocations[0].m_loc_applySRGBEncoding = m_vertex_shader->GetUniformLocation("applySRGBEncoding");
|
||||||
|
m_uniformLocations[0].m_loc_targetGamma = m_fragment_shader->GetUniformLocation("targetGamma");
|
||||||
|
m_uniformLocations[0].m_loc_displayGamma = m_fragment_shader->GetUniformLocation("displayGamma");
|
||||||
|
|
||||||
m_uniformLocations[1].m_loc_textureSrcResolution = m_fragment_shader->GetUniformLocation("textureSrcResolution");
|
m_uniformLocations[1].m_loc_textureSrcResolution = m_fragment_shader->GetUniformLocation("textureSrcResolution");
|
||||||
m_uniformLocations[1].m_loc_nativeResolution = m_fragment_shader->GetUniformLocation("nativeResolution");
|
m_uniformLocations[1].m_loc_nativeResolution = m_fragment_shader->GetUniformLocation("nativeResolution");
|
||||||
m_uniformLocations[1].m_loc_outputResolution = m_fragment_shader->GetUniformLocation("outputResolution");
|
m_uniformLocations[1].m_loc_outputResolution = m_fragment_shader->GetUniformLocation("outputResolution");
|
||||||
|
m_uniformLocations[1].m_loc_applySRGBEncoding = m_fragment_shader->GetUniformLocation("applySRGBEncoding");
|
||||||
|
m_uniformLocations[1].m_loc_targetGamma = m_fragment_shader->GetUniformLocation("targetGamma");
|
||||||
|
m_uniformLocations[1].m_loc_displayGamma = m_fragment_shader->GetUniformLocation("displayGamma");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOutputShader::SetUniformParameters(const LatteTextureView& texture_view, const Vector2i& output_res) const
|
void RendererOutputShader::SetUniformParameters(const LatteTextureView& texture_view, const Vector2i& output_res, const bool padView) const
|
||||||
{
|
{
|
||||||
sint32 effectiveWidth, effectiveHeight;
|
sint32 effectiveWidth, effectiveHeight;
|
||||||
texture_view.baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0);
|
texture_view.baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0);
|
||||||
|
|
@ -168,6 +175,22 @@ void RendererOutputShader::SetUniformParameters(const LatteTextureView& texture_
|
||||||
res[1] = (float)output_res.y;
|
res[1] = (float)output_res.y;
|
||||||
shader->SetUniform2fv(locations.m_loc_outputResolution, res, 1);
|
shader->SetUniform2fv(locations.m_loc_outputResolution, res, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (locations.m_loc_applySRGBEncoding != -1)
|
||||||
|
{
|
||||||
|
shader->SetUniform1i(locations.m_loc_applySRGBEncoding, padView ? LatteGPUState.drcBufferUsesSRGB : LatteGPUState.tvBufferUsesSRGB);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locations.m_loc_targetGamma != -1)
|
||||||
|
{
|
||||||
|
shader->SetUniform1f(locations.m_loc_targetGamma, padView ? ActiveSettings::GetDRCGamma() : ActiveSettings::GetTVGamma());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locations.m_loc_displayGamma != -1)
|
||||||
|
{
|
||||||
|
shader->SetUniform1f(locations.m_loc_displayGamma, GetConfig().userDisplayGamma);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
setUniforms(m_vertex_shader.get(), m_uniformLocations[0]);
|
setUniforms(m_vertex_shader.get(), m_uniformLocations[0]);
|
||||||
setUniforms(m_fragment_shader.get(), m_uniformLocations[1]);
|
setUniforms(m_fragment_shader.get(), m_uniformLocations[1]);
|
||||||
|
|
@ -290,16 +313,52 @@ layout(push_constant) uniform pc {
|
||||||
vec2 textureSrcResolution;
|
vec2 textureSrcResolution;
|
||||||
vec2 nativeResolution;
|
vec2 nativeResolution;
|
||||||
vec2 outputResolution;
|
vec2 outputResolution;
|
||||||
|
bool applySRGBEncoding; // true = app requested sRGB encoding
|
||||||
|
float targetGamma;
|
||||||
|
float displayGamma;
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
uniform vec2 textureSrcResolution;
|
uniform vec2 textureSrcResolution;
|
||||||
uniform vec2 nativeResolution;
|
uniform vec2 nativeResolution;
|
||||||
uniform vec2 outputResolution;
|
uniform vec2 outputResolution;
|
||||||
|
uniform bool applySRGBEncoding;
|
||||||
|
uniform float targetGamma;
|
||||||
|
uniform float displayGamma;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
layout(location = 0) smooth in vec2 passUV;
|
layout(location = 0) smooth in vec2 passUV;
|
||||||
layout(binding = 0) uniform sampler2D textureSrc;
|
layout(binding = 0) uniform sampler2D textureSrc;
|
||||||
layout(location = 0) out vec4 colorOut0;
|
layout(location = 0) out vec4 colorOut0;
|
||||||
|
|
||||||
|
float sRGBEncode(float linear)
|
||||||
|
{
|
||||||
|
if(linear <= 0.0031308)
|
||||||
|
return 12.92f * linear;
|
||||||
|
else
|
||||||
|
return 1.055f * pow(linear, 1.0f / 2.4f) - 0.055f;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 sRGBEncode(vec3 linear)
|
||||||
|
{
|
||||||
|
return vec3(sRGBEncode(linear.r), sRGBEncode(linear.g), sRGBEncode(linear.b));
|
||||||
|
}
|
||||||
|
|
||||||
|
// fwd. declaration
|
||||||
|
void outputShader();
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
outputShader(); // sets colorOut0
|
||||||
|
if(applySRGBEncoding)
|
||||||
|
colorOut0 = vec4(sRGBEncode(colorOut0.rgb), 1.0f);
|
||||||
|
|
||||||
|
if (displayGamma > 0.0f)
|
||||||
|
colorOut0 = pow(colorOut0, vec4(targetGamma / displayGamma) );
|
||||||
|
else
|
||||||
|
colorOut0 = vec4( sRGBEncode( pow(colorOut0.rgb, vec3(targetGamma)) ), 1.0f);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
)" + shaderSrc;
|
)" + shaderSrc;
|
||||||
}
|
}
|
||||||
void RendererOutputShader::InitializeStatic()
|
void RendererOutputShader::InitializeStatic()
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ public:
|
||||||
RendererOutputShader(const std::string& vertex_source, const std::string& fragment_source);
|
RendererOutputShader(const std::string& vertex_source, const std::string& fragment_source);
|
||||||
virtual ~RendererOutputShader() = default;
|
virtual ~RendererOutputShader() = default;
|
||||||
|
|
||||||
void SetUniformParameters(const LatteTextureView& texture_view, const Vector2i& output_res) const;
|
void SetUniformParameters(const LatteTextureView& texture_view, const Vector2i& output_res, const bool padView) const;
|
||||||
|
|
||||||
RendererShader* GetVertexShader() const
|
RendererShader* GetVertexShader() const
|
||||||
{
|
{
|
||||||
|
|
@ -55,6 +55,9 @@ protected:
|
||||||
sint32 m_loc_textureSrcResolution = -1;
|
sint32 m_loc_textureSrcResolution = -1;
|
||||||
sint32 m_loc_nativeResolution = -1;
|
sint32 m_loc_nativeResolution = -1;
|
||||||
sint32 m_loc_outputResolution = -1;
|
sint32 m_loc_outputResolution = -1;
|
||||||
|
sint32 m_loc_applySRGBEncoding = -1;
|
||||||
|
sint32 m_loc_targetGamma = -1;
|
||||||
|
sint32 m_loc_displayGamma = -1;
|
||||||
} m_uniformLocations[2]{};
|
} m_uniformLocations[2]{};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ public:
|
||||||
|
|
||||||
virtual sint32 GetUniformLocation(const char* name) = 0;
|
virtual sint32 GetUniformLocation(const char* name) = 0;
|
||||||
|
|
||||||
|
virtual void SetUniform1i(sint32 location, sint32 value) = 0;
|
||||||
|
virtual void SetUniform1f(sint32 location, float value) = 0;
|
||||||
virtual void SetUniform2fv(sint32 location, void* data, sint32 count) = 0;
|
virtual void SetUniform2fv(sint32 location, void* data, sint32 count) = 0;
|
||||||
virtual void SetUniform4iv(sint32 location, void* data, sint32 count) = 0;
|
virtual void SetUniform4iv(sint32 location, void* data, sint32 count) = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -232,6 +232,16 @@ sint32 RendererShaderVk::GetUniformLocation(const char* name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererShaderVk::SetUniform1i(sint32 location, sint32 value)
|
||||||
|
{
|
||||||
|
cemu_assert_suspicious();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RendererShaderVk::SetUniform1f(sint32 location, float value)
|
||||||
|
{
|
||||||
|
cemu_assert_suspicious();
|
||||||
|
}
|
||||||
|
|
||||||
void RendererShaderVk::SetUniform2fv(sint32 location, void* data, sint32 count)
|
void RendererShaderVk::SetUniform2fv(sint32 location, void* data, sint32 count)
|
||||||
{
|
{
|
||||||
cemu_assert_suspicious();
|
cemu_assert_suspicious();
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ public:
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
|
|
||||||
sint32 GetUniformLocation(const char* name) override;
|
sint32 GetUniformLocation(const char* name) override;
|
||||||
|
void SetUniform1i(sint32 location, sint32 value) override;
|
||||||
|
void SetUniform1f(sint32 location, float value) override;
|
||||||
void SetUniform2fv(sint32 location, void* data, sint32 count) override;
|
void SetUniform2fv(sint32 location, void* data, sint32 count) override;
|
||||||
void SetUniform4iv(sint32 location, void* data, sint32 count) override;
|
void SetUniform4iv(sint32 location, void* data, sint32 count) override;
|
||||||
VkShaderModule& GetShaderModule() { return m_shader_module; }
|
VkShaderModule& GetShaderModule() { return m_shader_module; }
|
||||||
|
|
|
||||||
|
|
@ -318,20 +318,10 @@ VkSurfaceFormatKHR SwapchainInfoVk::ChooseSurfaceFormat(const std::vector<VkSurf
|
||||||
return{ VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
return{ VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||||
|
|
||||||
for (const auto& format : formats)
|
for (const auto& format : formats)
|
||||||
{
|
|
||||||
bool useSRGB = mainWindow ? LatteGPUState.tvBufferUsesSRGB : LatteGPUState.drcBufferUsesSRGB;
|
|
||||||
|
|
||||||
if (useSRGB)
|
|
||||||
{
|
|
||||||
if (format.format == VK_FORMAT_B8G8R8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
|
||||||
return format;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (format.format == VK_FORMAT_B8G8R8A8_UNORM && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
if (format.format == VK_FORMAT_B8G8R8A8_UNORM && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return formats[0];
|
return formats[0];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,6 @@ struct SwapchainInfoVk
|
||||||
bool mainWindow{};
|
bool mainWindow{};
|
||||||
|
|
||||||
bool m_shouldRecreate = false;
|
bool m_shouldRecreate = false;
|
||||||
bool m_usesSRGB = false;
|
|
||||||
VSync m_vsyncState = VSync::Immediate;
|
VSync m_vsyncState = VSync::Immediate;
|
||||||
bool hasDefinedSwapchainImage{}; // indicates if the swapchain image is in a defined state
|
bool hasDefinedSwapchainImage{}; // indicates if the swapchain image is in a defined state
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2590,7 +2590,6 @@ VkPipeline VulkanRenderer::backbufferBlit_createGraphicsPipeline(VkDescriptorSet
|
||||||
uint64 hash = 0;
|
uint64 hash = 0;
|
||||||
hash += (uint64)vertexRendererShader;
|
hash += (uint64)vertexRendererShader;
|
||||||
hash += (uint64)fragmentRendererShader;
|
hash += (uint64)fragmentRendererShader;
|
||||||
hash += (uint64)(chainInfo.m_usesSRGB);
|
|
||||||
hash += ((uint64)padView) << 1;
|
hash += ((uint64)padView) << 1;
|
||||||
|
|
||||||
const auto it = m_backbufferBlitPipelineCache.find(hash);
|
const auto it = m_backbufferBlitPipelineCache.find(hash);
|
||||||
|
|
@ -2660,6 +2659,8 @@ VkPipeline VulkanRenderer::backbufferBlit_createGraphicsPipeline(VkDescriptorSet
|
||||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = 3 * sizeof(float) * 2 // 3 vec2's
|
.size = 3 * sizeof(float) * 2 // 3 vec2's
|
||||||
|
+ 4 // + 1 VkBool32
|
||||||
|
+ 4 * 2 // + 2 float
|
||||||
};
|
};
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
||||||
|
|
@ -2771,10 +2772,6 @@ bool VulkanRenderer::UpdateSwapchainProperties(bool mainWindow)
|
||||||
if(chainInfo.m_vsyncState != configValue)
|
if(chainInfo.m_vsyncState != configValue)
|
||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
|
|
||||||
const bool latteBufferUsesSRGB = mainWindow ? LatteGPUState.tvBufferUsesSRGB : LatteGPUState.drcBufferUsesSRGB;
|
|
||||||
if (chainInfo.m_usesSRGB != latteBufferUsesSRGB)
|
|
||||||
stateChanged = true;
|
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
if (mainWindow)
|
if (mainWindow)
|
||||||
WindowSystem::GetWindowPhysSize(width, height);
|
WindowSystem::GetWindowPhysSize(width, height);
|
||||||
|
|
@ -2799,7 +2796,6 @@ bool VulkanRenderer::UpdateSwapchainProperties(bool mainWindow)
|
||||||
|
|
||||||
chainInfo.m_shouldRecreate = false;
|
chainInfo.m_shouldRecreate = false;
|
||||||
chainInfo.m_vsyncState = configValue;
|
chainInfo.m_vsyncState = configValue;
|
||||||
chainInfo.m_usesSRGB = latteBufferUsesSRGB;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3046,24 +3042,35 @@ void VulkanRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
|
||||||
|
|
||||||
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, &descriptSet, 0, nullptr);
|
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, &descriptSet, 0, nullptr);
|
||||||
|
|
||||||
|
|
||||||
// update push constants
|
// update push constants
|
||||||
Vector2f pushData[3];
|
struct
|
||||||
|
{
|
||||||
|
Vector2f vecs[3];
|
||||||
|
VkBool32 applySRGBEncoding;
|
||||||
|
float targetGamma;
|
||||||
|
float displayGamma;
|
||||||
|
} pushData;
|
||||||
|
|
||||||
// textureSrcResolution
|
// textureSrcResolution
|
||||||
sint32 effectiveWidth, effectiveHeight;
|
sint32 effectiveWidth, effectiveHeight;
|
||||||
texView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0);
|
texView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0);
|
||||||
pushData[0] = {(float)effectiveWidth, (float)effectiveHeight};
|
pushData.vecs[0] = {(float)effectiveWidth, (float)effectiveHeight};
|
||||||
|
|
||||||
// nativeResolution
|
// nativeResolution
|
||||||
pushData[1] = {
|
pushData.vecs[1] = {
|
||||||
(float)texViewVk->baseTexture->width,
|
(float)texViewVk->baseTexture->width,
|
||||||
(float)texViewVk->baseTexture->height,
|
(float)texViewVk->baseTexture->height,
|
||||||
};
|
};
|
||||||
|
|
||||||
// outputResolution
|
// outputResolution
|
||||||
pushData[2] = {(float)imageWidth,(float)imageHeight};
|
pushData.vecs[2] = {(float)imageWidth,(float)imageHeight};
|
||||||
|
|
||||||
vkCmdPushConstants(m_state.currentCommandBuffer, m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(float) * 2 * 3, &pushData);
|
pushData.applySRGBEncoding = padView ? LatteGPUState.drcBufferUsesSRGB : LatteGPUState.tvBufferUsesSRGB;
|
||||||
|
pushData.targetGamma = padView ? ActiveSettings::GetDRCGamma() : ActiveSettings::GetTVGamma();
|
||||||
|
pushData.displayGamma = GetConfig().userDisplayGamma;
|
||||||
|
|
||||||
|
vkCmdPushConstants(m_state.currentCommandBuffer, m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(pushData), &pushData);
|
||||||
|
|
||||||
vkCmdDraw(m_state.currentCommandBuffer, 6, 1, 0, 0);
|
vkCmdDraw(m_state.currentCommandBuffer, 6, 1, 0, 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -206,8 +206,12 @@ namespace GX2
|
||||||
|
|
||||||
void GX2SetTVGamma(float gamma)
|
void GX2SetTVGamma(float gamma)
|
||||||
{
|
{
|
||||||
if (abs(gamma - 1.0f) > 0.01f)
|
LatteGPUState.tvGamma = (1.0f - gamma);
|
||||||
cemuLog_logDebug(LogType::Force, "TV gamma set to {} which is not supported", gamma);
|
}
|
||||||
|
|
||||||
|
void GX2SetDRCGamma(float gamma)
|
||||||
|
{
|
||||||
|
LatteGPUState.drcGamma = (1.0f - gamma);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GX2GetLastFrame(uint32 deviceId, GX2Texture* textureOut)
|
bool GX2GetLastFrame(uint32 deviceId, GX2Texture* textureOut)
|
||||||
|
|
@ -307,6 +311,7 @@ namespace GX2
|
||||||
|
|
||||||
cafeExportRegister("gx2", GX2SetTVBuffer, LogType::GX2);
|
cafeExportRegister("gx2", GX2SetTVBuffer, LogType::GX2);
|
||||||
cafeExportRegister("gx2", GX2SetTVGamma, LogType::GX2);
|
cafeExportRegister("gx2", GX2SetTVGamma, LogType::GX2);
|
||||||
|
cafeExportRegister("gx2", GX2SetDRCGamma, LogType::GX2);
|
||||||
|
|
||||||
cafeExportRegister("gx2", GX2GetLastFrame, LogType::GX2);
|
cafeExportRegister("gx2", GX2GetLastFrame, LogType::GX2);
|
||||||
cafeExportRegister("gx2", GX2GetLastFrameGammaA, LogType::GX2);
|
cafeExportRegister("gx2", GX2GetLastFrameGammaA, LogType::GX2);
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ GLFUNC(PFNGLPROGRAMUNIFORM1IPROC, glProgramUniform1i)
|
||||||
GLFUNC(PFNGLPROGRAMUNIFORM2IPROC, glProgramUniform2i)
|
GLFUNC(PFNGLPROGRAMUNIFORM2IPROC, glProgramUniform2i)
|
||||||
GLFUNC(PFNGLPROGRAMUNIFORM1IVPROC, glProgramUniform1iv)
|
GLFUNC(PFNGLPROGRAMUNIFORM1IVPROC, glProgramUniform1iv)
|
||||||
GLFUNC(PFNGLPROGRAMUNIFORM4IVPROC, glProgramUniform4iv)
|
GLFUNC(PFNGLPROGRAMUNIFORM4IVPROC, glProgramUniform4iv)
|
||||||
|
GLFUNC(PFNGLPROGRAMUNIFORM1IPROC, glProgramUniform1f)
|
||||||
GLFUNC(PFNGLPROGRAMUNIFORM1FVPROC, glProgramUniform1fv)
|
GLFUNC(PFNGLPROGRAMUNIFORM1FVPROC, glProgramUniform1fv)
|
||||||
GLFUNC(PFNGLPROGRAMUNIFORM2FVPROC, glProgramUniform2fv)
|
GLFUNC(PFNGLPROGRAMUNIFORM2FVPROC, glProgramUniform2fv)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include "config/ActiveSettings.h"
|
#include "config/ActiveSettings.h"
|
||||||
#include "config/LaunchSettings.h"
|
#include "config/LaunchSettings.h"
|
||||||
#include "util/helpers/helpers.h"
|
#include "util/helpers/helpers.h"
|
||||||
|
#include "Cafe/HW/Latte/Core/Latte.h"
|
||||||
|
|
||||||
void ActiveSettings::SetPaths(bool isPortableMode,
|
void ActiveSettings::SetPaths(bool isPortableMode,
|
||||||
const fs::path& executablePath,
|
const fs::path& executablePath,
|
||||||
|
|
@ -112,6 +113,18 @@ GraphicAPI ActiveSettings::GetGraphicsAPI()
|
||||||
return api;
|
return api;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float ActiveSettings::GetTVGamma()
|
||||||
|
{
|
||||||
|
const auto& config = GetConfig();
|
||||||
|
return config.overrideGammaValue.GetValue() + LatteGPUState.tvGamma * !config.overrideAppGammaPreference.GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
float ActiveSettings::GetDRCGamma()
|
||||||
|
{
|
||||||
|
const auto& config = GetConfig();
|
||||||
|
return config.overrideGammaValue.GetValue() + LatteGPUState.drcGamma * !config.overrideAppGammaPreference.GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
bool ActiveSettings::AudioOutputOnlyAux()
|
bool ActiveSettings::AudioOutputOnlyAux()
|
||||||
{
|
{
|
||||||
return s_audio_aux_only;
|
return s_audio_aux_only;
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,10 @@ public:
|
||||||
[[nodiscard]] static bool WaitForGX2DrawDoneEnabled();
|
[[nodiscard]] static bool WaitForGX2DrawDoneEnabled();
|
||||||
[[nodiscard]] static GraphicAPI GetGraphicsAPI();
|
[[nodiscard]] static GraphicAPI GetGraphicsAPI();
|
||||||
|
|
||||||
|
// gamma
|
||||||
|
[[nodiscard]] static float GetTVGamma();
|
||||||
|
[[nodiscard]] static float GetDRCGamma();
|
||||||
|
|
||||||
// audio
|
// audio
|
||||||
[[nodiscard]] static bool AudioOutputOnlyAux();
|
[[nodiscard]] static bool AudioOutputOnlyAux();
|
||||||
static void EnableAudioOnlyAux(bool state);
|
static void EnableAudioOnlyAux(bool state);
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,13 @@ XMLConfigParser CemuConfig::Load(XMLConfigParser& parser)
|
||||||
graphic_api = graphic.get("api", kOpenGL);
|
graphic_api = graphic.get("api", kOpenGL);
|
||||||
graphic.get("device", graphic_device_uuid);
|
graphic.get("device", graphic_device_uuid);
|
||||||
vsync = graphic.get("VSync", 0);
|
vsync = graphic.get("VSync", 0);
|
||||||
|
overrideAppGammaPreference = graphic.get("OverrideAppGammaPreference", false);
|
||||||
|
overrideGammaValue = graphic.get("OverrideGammaValue", 2.2f);
|
||||||
|
if(overrideGammaValue < 0)
|
||||||
|
overrideGammaValue = 2.2f;
|
||||||
|
userDisplayGamma = graphic.get("UserDisplayGamma", 2.2f);
|
||||||
|
if(userDisplayGamma < 0)
|
||||||
|
userDisplayGamma = 2.2f;
|
||||||
gx2drawdone_sync = graphic.get("GX2DrawdoneSync", true);
|
gx2drawdone_sync = graphic.get("GX2DrawdoneSync", true);
|
||||||
upscale_filter = graphic.get("UpscaleFilter", kBicubicHermiteFilter);
|
upscale_filter = graphic.get("UpscaleFilter", kBicubicHermiteFilter);
|
||||||
downscale_filter = graphic.get("DownscaleFilter", kLinearFilter);
|
downscale_filter = graphic.get("DownscaleFilter", kLinearFilter);
|
||||||
|
|
@ -346,6 +353,9 @@ XMLConfigParser CemuConfig::Save(XMLConfigParser& parser)
|
||||||
graphic.set("api", graphic_api);
|
graphic.set("api", graphic_api);
|
||||||
graphic.set("device", graphic_device_uuid);
|
graphic.set("device", graphic_device_uuid);
|
||||||
graphic.set("VSync", vsync);
|
graphic.set("VSync", vsync);
|
||||||
|
graphic.set("OverrideAppGammaPreference", overrideAppGammaPreference);
|
||||||
|
graphic.set("OverrideGammaValue", overrideGammaValue);
|
||||||
|
graphic.set("UserDisplayGamma", userDisplayGamma);
|
||||||
graphic.set("GX2DrawdoneSync", gx2drawdone_sync);
|
graphic.set("GX2DrawdoneSync", gx2drawdone_sync);
|
||||||
//graphic.set("PrecompiledShaders", precompiled_shaders.GetValue());
|
//graphic.set("PrecompiledShaders", precompiled_shaders.GetValue());
|
||||||
graphic.set("UpscaleFilter", upscale_filter);
|
graphic.set("UpscaleFilter", upscale_filter);
|
||||||
|
|
|
||||||
|
|
@ -389,6 +389,11 @@ struct CemuConfig
|
||||||
ConfigValue<bool> render_upside_down{ false };
|
ConfigValue<bool> render_upside_down{ false };
|
||||||
ConfigValue<bool> async_compile{ true };
|
ConfigValue<bool> async_compile{ true };
|
||||||
|
|
||||||
|
// Gamma
|
||||||
|
ConfigValue<bool> overrideAppGammaPreference{ false };
|
||||||
|
ConfigValue<float> overrideGammaValue{ 2.2f };
|
||||||
|
ConfigValue<float> userDisplayGamma { 2.2f }; // 0 = sRGB, >0 gamma
|
||||||
|
|
||||||
ConfigValue<bool> vk_accurate_barriers{ true };
|
ConfigValue<bool> vk_accurate_barriers{ true };
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|
|
|
||||||
|
|
@ -295,6 +295,10 @@ bool CemuApp::OnInit()
|
||||||
{
|
{
|
||||||
MSWEnableDarkMode(DarkMode_Always);
|
MSWEnableDarkMode(DarkMode_Always);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extend tooltip duration to the maximum possible value
|
||||||
|
wxToolTip::SetDelay(-1);
|
||||||
|
wxToolTip::SetAutoPop(MAKELPARAM(std::numeric_limits<short>::max(),0));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (auto&& path : failedWriteAccess)
|
for (auto&& path : failedWriteAccess)
|
||||||
|
|
|
||||||
|
|
@ -377,6 +377,55 @@ wxPanel* GeneralSettings2::AddGraphicsPage(wxNotebook* notebook)
|
||||||
graphics_panel_sizer->Add(box_sizer, 0, wxEXPAND | wxALL, 5);
|
graphics_panel_sizer->Add(box_sizer, 0, wxEXPAND | wxALL, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto box = new wxStaticBox(graphics_panel, wxID_ANY, _("Gamma settings"));
|
||||||
|
auto box_sizer = new wxStaticBoxSizer(box, wxVERTICAL);
|
||||||
|
auto row = new wxFlexGridSizer(0, 2, 0, 0);
|
||||||
|
row->SetFlexibleDirection(wxBOTH);
|
||||||
|
row->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
|
||||||
|
|
||||||
|
auto targetGammaLabel = new wxStaticText(box, wxID_ANY, _("Target Gamma"));
|
||||||
|
row->Add(targetGammaLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||||
|
m_overrideGammaValue = new wxSpinCtrlDouble(box, wxID_ANY, "2.2f", wxDefaultPosition, {230, -1}, wxSP_ARROW_KEYS, 0.1f, 4.0f, 2.2f, 0.1f);
|
||||||
|
row->Add(m_overrideGammaValue, 0, wxALL, 5);
|
||||||
|
auto targetGammaTooltip = _("The display gamma to reproduce\nIf you are unsure, set this to 2.2");
|
||||||
|
targetGammaLabel->SetToolTip(targetGammaTooltip);
|
||||||
|
m_overrideGammaValue->SetToolTip(targetGammaTooltip);
|
||||||
|
|
||||||
|
|
||||||
|
auto displayGammaLabel = new wxStaticText(box, wxID_ANY, _("Display Gamma"));
|
||||||
|
row->Add(displayGammaLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||||
|
|
||||||
|
wxBoxSizer* srgbCheckBoxSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
row->Add(srgbCheckBoxSizer);
|
||||||
|
m_userDisplayGamma = new wxSpinCtrlDouble(box, wxID_ANY, "2.2f", wxDefaultPosition, {230, -1}, wxSP_ARROW_KEYS, 0.1f, 4.0f, 2.2f, 0.1f);
|
||||||
|
|
||||||
|
auto displayGammaTooltip = _("The gamma of your monitor\nIf you are unsure, set this to 2.2");
|
||||||
|
m_userDisplayGamma->SetToolTip(displayGammaTooltip);
|
||||||
|
displayGammaLabel->SetToolTip(displayGammaTooltip);
|
||||||
|
|
||||||
|
m_userDisplayisSRGB = new wxCheckBox(box, wxID_ANY, "sRGB", wxDefaultPosition, wxDefaultSize);
|
||||||
|
m_userDisplayisSRGB->SetToolTip(_("Select this if Cemu is being displayed using a piecewise sRGB gamma curve.\n"
|
||||||
|
"This is typically not the case so you can probably leave this unchecked.\n"
|
||||||
|
"Exceptions include HDR displays (with HDR enabled), calibrated SDR displays with Windows 11's Auto Color Management enabled, "
|
||||||
|
"or when using a display profile with a VCGT tag that targets piecewise sRGB.\n"
|
||||||
|
"When this box is selected Cemu will compensate for the piecewise curve to approximate the pure gamma curve of a TV.\n"
|
||||||
|
"Colors will be more accurate, especially in dark scenes, but this may result in banding or crushed shadows, "
|
||||||
|
"so it is best if you display Cemu with pure gamma and do not use this setting."));
|
||||||
|
m_userDisplayisSRGB->Bind(wxEVT_CHECKBOX, &GeneralSettings2::OnUserDisplaySRGBSelected, this);
|
||||||
|
|
||||||
|
srgbCheckBoxSizer->Add(m_userDisplayGamma, 0, wxALL, 5);
|
||||||
|
srgbCheckBoxSizer->Add(m_userDisplayisSRGB, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||||
|
|
||||||
|
row->Add(new wxStaticText(box, wxID_ANY, _("Override Gamma")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||||
|
m_overrideGamma = new wxCheckBox(box, wxID_ANY, "", wxDefaultPosition, {230, -1});
|
||||||
|
m_overrideGamma->SetToolTip(_("Ignore title's gamma preference"));
|
||||||
|
row->Add(m_overrideGamma, 0, wxALL, 5);
|
||||||
|
|
||||||
|
box_sizer->Add(row, 0, wxEXPAND, 5);
|
||||||
|
graphics_panel_sizer->Add(box_sizer, 0, wxEXPAND | wxALL, 5);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
wxString choices[] = { _("Bilinear"), _("Bicubic"), _("Hermite"), _("Nearest Neighbor") };
|
wxString choices[] = { _("Bilinear"), _("Bicubic"), _("Hermite"), _("Nearest Neighbor") };
|
||||||
m_upscale_filter = new wxRadioBox(graphics_panel, wxID_ANY, _("Upscale filter"), wxDefaultPosition, wxDefaultSize, std::size(choices), choices, 5, wxRA_SPECIFY_COLS);
|
m_upscale_filter = new wxRadioBox(graphics_panel, wxID_ANY, _("Upscale filter"), wxDefaultPosition, wxDefaultSize, std::size(choices), choices, 5, wxRA_SPECIFY_COLS);
|
||||||
|
|
@ -1104,6 +1153,9 @@ void GeneralSettings2::StoreConfig()
|
||||||
|
|
||||||
|
|
||||||
config.vsync = m_vsync->GetSelection();
|
config.vsync = m_vsync->GetSelection();
|
||||||
|
config.overrideAppGammaPreference = m_overrideGamma->IsChecked();
|
||||||
|
config.overrideGammaValue = m_overrideGammaValue->GetValue();
|
||||||
|
config.userDisplayGamma = m_userDisplayGamma->GetValue() * !m_userDisplayisSRGB->GetValue();
|
||||||
config.gx2drawdone_sync = m_gx2drawdone_sync->IsChecked();
|
config.gx2drawdone_sync = m_gx2drawdone_sync->IsChecked();
|
||||||
config.async_compile = m_async_compile->IsChecked();
|
config.async_compile = m_async_compile->IsChecked();
|
||||||
|
|
||||||
|
|
@ -1681,6 +1733,15 @@ void GeneralSettings2::ApplyConfig()
|
||||||
// graphics
|
// graphics
|
||||||
m_graphic_api->SetSelection(config.graphic_api);
|
m_graphic_api->SetSelection(config.graphic_api);
|
||||||
m_vsync->SetSelection(config.vsync);
|
m_vsync->SetSelection(config.vsync);
|
||||||
|
m_overrideGamma->SetValue(config.overrideAppGammaPreference);
|
||||||
|
m_overrideGammaValue->SetValue(config.overrideGammaValue);
|
||||||
|
m_userDisplayisSRGB->SetValue(config.userDisplayGamma == 0.0f);
|
||||||
|
m_userDisplayGamma->SetValue(config.userDisplayGamma);
|
||||||
|
if(m_userDisplayisSRGB->GetValue())
|
||||||
|
{
|
||||||
|
m_userDisplayGamma->Disable();
|
||||||
|
m_userDisplayGamma->SetValue(2.2f);
|
||||||
|
}
|
||||||
m_async_compile->SetValue(config.async_compile);
|
m_async_compile->SetValue(config.async_compile);
|
||||||
m_gx2drawdone_sync->SetValue(config.gx2drawdone_sync);
|
m_gx2drawdone_sync->SetValue(config.gx2drawdone_sync);
|
||||||
m_upscale_filter->SetSelection(config.upscale_filter);
|
m_upscale_filter->SetSelection(config.upscale_filter);
|
||||||
|
|
@ -2037,6 +2098,15 @@ void GeneralSettings2::OnGraphicAPISelected(wxCommandEvent& event)
|
||||||
HandleGraphicsApiSelection();
|
HandleGraphicsApiSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GeneralSettings2::OnUserDisplaySRGBSelected(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
m_userDisplayGamma->SetValue(2.2f);
|
||||||
|
if(event.GetInt())
|
||||||
|
m_userDisplayGamma->Disable();
|
||||||
|
else
|
||||||
|
m_userDisplayGamma->Enable();
|
||||||
|
}
|
||||||
|
|
||||||
void GeneralSettings2::OnAddPathClicked(wxCommandEvent& event)
|
void GeneralSettings2::OnAddPathClicked(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
wxDirDialog path_dialog(this, _("Select a directory containing games."), wxEmptyString, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
|
wxDirDialog path_dialog(this, _("Select a directory containing games."), wxEmptyString, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,11 @@ private:
|
||||||
// Graphics
|
// Graphics
|
||||||
wxChoice* m_graphic_api, * m_graphic_device;
|
wxChoice* m_graphic_api, * m_graphic_device;
|
||||||
wxChoice* m_vsync;
|
wxChoice* m_vsync;
|
||||||
|
wxCheckBox* m_overrideGamma;
|
||||||
|
wxSpinCtrlDouble* m_overrideGammaValue;
|
||||||
|
wxSpinCtrlDouble* m_userDisplayGamma;
|
||||||
|
wxCheckBox* m_userDisplayisSRGB;
|
||||||
|
|
||||||
wxCheckBox *m_async_compile, *m_gx2drawdone_sync;
|
wxCheckBox *m_async_compile, *m_gx2drawdone_sync;
|
||||||
wxRadioBox* m_upscale_filter, *m_downscale_filter, *m_fullscreen_scaling;
|
wxRadioBox* m_upscale_filter, *m_downscale_filter, *m_fullscreen_scaling;
|
||||||
wxChoice* m_overlay_position, *m_notification_position, *m_overlay_scale, *m_notification_scale;
|
wxChoice* m_overlay_position, *m_notification_position, *m_overlay_scale, *m_notification_scale;
|
||||||
|
|
@ -95,6 +100,7 @@ private:
|
||||||
void OnAudioDeviceSelected(wxCommandEvent& event);
|
void OnAudioDeviceSelected(wxCommandEvent& event);
|
||||||
void OnAudioChannelsSelected(wxCommandEvent& event);
|
void OnAudioChannelsSelected(wxCommandEvent& event);
|
||||||
void OnGraphicAPISelected(wxCommandEvent& event);
|
void OnGraphicAPISelected(wxCommandEvent& event);
|
||||||
|
void OnUserDisplaySRGBSelected(wxCommandEvent& event);
|
||||||
void OnAddPathClicked(wxCommandEvent& event);
|
void OnAddPathClicked(wxCommandEvent& event);
|
||||||
void OnRemovePathClicked(wxCommandEvent& event);
|
void OnRemovePathClicked(wxCommandEvent& event);
|
||||||
void OnActiveAccountChanged(wxCommandEvent& event);
|
void OnActiveAccountChanged(wxCommandEvent& event);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue