mirror of
https://github.com/libretro/RetroArch
synced 2025-01-30 12:32:52 +00:00
Fixed numerous issues with HDR (#12979)
* Fix for warning and fix for incorrect comment * Fixed contrast to be more correct - now scales from 0-10 linearly and behaves more the way you'd expect it to - changed name to ditch legacy settings users may have Added ability to skip inverse tonemapper to the shader via the constant buffer using 'inverse_tonemap' - set to 0.0f to skip Fixed potential bug when swapping between hdr and sdr and the bit depth not being set correctly Fixed dx11's blend, rasterizer and topology states not being set to the sames when using hdr and leaving the menu - caused issues with PCSX2's Shadow of the Colossus Added numerous helper functions to help create the correct values to colour the UI - normally the white UI elements should be rendered at paper white not max brightness for various reasons * Fix stylistic issues - * Don't use camelcase for variables and function names * Use '(void)' for function declarations instead of () in C code * Declare variables at the top of a function or code block * Make sure functions that return a value always have a default return path that is not encapsulated by an else block * Use more unique names for retro_math functions which are less likely to overlap with other libraries' function symbols Co-authored-by: twinaphex <libretro@gmail.com>
This commit is contained in:
parent
e24440d4a9
commit
3c6bdfd0d8
@ -421,8 +421,8 @@
|
||||
/* The number of nits that paper white is at */
|
||||
#define DEFAULT_VIDEO_HDR_PAPER_WHITE_NITS 200.0f
|
||||
|
||||
/* The contrast setting for hdr used to calculate the display gamma by dividing gamma 2.2 by this value */
|
||||
#define DEFAULT_VIDEO_HDR_CONTRAST 1.0f
|
||||
/* The contrast setting for hdr used to calculate the display gamma by dividing this value by gamma 2.2 */
|
||||
#define DEFAULT_VIDEO_HDR_CONTRAST 5.0f
|
||||
|
||||
/* Should we expand the colour gamut when using hdr */
|
||||
#define DEFAULT_VIDEO_HDR_EXPAND_GAMUT true
|
||||
|
@ -2043,7 +2043,7 @@ static struct config_float_setting *populate_settings_float(
|
||||
|
||||
SETTING_FLOAT("video_hdr_max_nits", &settings->floats.video_hdr_max_nits, true, DEFAULT_VIDEO_HDR_MAX_NITS, false);
|
||||
SETTING_FLOAT("video_hdr_paper_white_nits", &settings->floats.video_hdr_paper_white_nits, true, DEFAULT_VIDEO_HDR_PAPER_WHITE_NITS, false);
|
||||
SETTING_FLOAT("video_hdr_contrast", &settings->floats.video_hdr_contrast, true, DEFAULT_VIDEO_HDR_CONTRAST, false);
|
||||
SETTING_FLOAT("video_hdr_display_contrast", &settings->floats.video_hdr_display_contrast, true, DEFAULT_VIDEO_HDR_CONTRAST, false);
|
||||
|
||||
*size = count;
|
||||
|
||||
|
@ -347,7 +347,7 @@ typedef struct settings
|
||||
float video_msg_bgcolor_opacity;
|
||||
float video_hdr_max_nits;
|
||||
float video_hdr_paper_white_nits;
|
||||
float video_hdr_contrast;
|
||||
float video_hdr_display_contrast;
|
||||
|
||||
float menu_scale_factor;
|
||||
float menu_widget_scale_factor;
|
||||
|
@ -20,10 +20,11 @@
|
||||
typedef struct ALIGN(16)
|
||||
{
|
||||
math_matrix_4x4 mvp;
|
||||
float contrast; /* 2.0f */
|
||||
float paperWhiteNits; /* 200.0f */
|
||||
float maxNits; /* 1000.0f */
|
||||
float expandGamut; /* 1.0f */
|
||||
float contrast; /* 2.0f */
|
||||
float paper_white_nits; /* 200.0f */
|
||||
float max_nits; /* 1000.0f */
|
||||
float expand_gamut; /* 1.0f */
|
||||
float inverse_tonemap; /* 1.0f */
|
||||
} dxgi_hdr_uniform_t;
|
||||
|
||||
enum dxgi_swapchain_bit_depth
|
||||
|
@ -262,7 +262,7 @@ static void d3d11_set_hdr_max_nits(void *data, float max_nits)
|
||||
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
|
||||
|
||||
d3d11->hdr.max_output_nits = max_nits;
|
||||
d3d11->hdr.ubo_values.maxNits = max_nits;
|
||||
d3d11->hdr.ubo_values.max_nits = max_nits;
|
||||
|
||||
D3D11MapBuffer(d3d11->context, d3d11->hdr.ubo,
|
||||
0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped_ubo);
|
||||
@ -289,7 +289,7 @@ static void d3d11_set_hdr_paper_white_nits(void* data, float paper_white_nits)
|
||||
dxgi_hdr_uniform_t *ubo = NULL;
|
||||
d3d11_video_t *d3d11 = (d3d11_video_t*)data;
|
||||
|
||||
d3d11->hdr.ubo_values.paperWhiteNits = paper_white_nits;
|
||||
d3d11->hdr.ubo_values.paper_white_nits = paper_white_nits;
|
||||
|
||||
D3D11MapBuffer(d3d11->context, d3d11->hdr.ubo,
|
||||
0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo);
|
||||
@ -319,7 +319,7 @@ static void d3d11_set_hdr_expand_gamut(void* data, bool expand_gamut)
|
||||
dxgi_hdr_uniform_t *ubo = NULL;
|
||||
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
|
||||
|
||||
d3d11->hdr.ubo_values.expandGamut = expand_gamut;
|
||||
d3d11->hdr.ubo_values.expand_gamut = expand_gamut;
|
||||
|
||||
D3D11MapBuffer(d3d11->context, d3d11->hdr.ubo, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo);
|
||||
ubo = (dxgi_hdr_uniform_t*)mapped_ubo.pData;
|
||||
@ -1144,16 +1144,17 @@ static void *d3d11_gfx_init(const video_info_t* video,
|
||||
D3D11_SUBRESOURCE_DATA ubo_data;
|
||||
matrix_4x4_ortho(d3d11->mvp_no_rot, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
|
||||
|
||||
d3d11->hdr.ubo_values.mvp =
|
||||
d3d11->hdr.ubo_values.mvp =
|
||||
d3d11->mvp_no_rot;
|
||||
d3d11->hdr.ubo_values.maxNits =
|
||||
d3d11->hdr.ubo_values.max_nits =
|
||||
settings->floats.video_hdr_max_nits;
|
||||
d3d11->hdr.ubo_values.paperWhiteNits =
|
||||
d3d11->hdr.ubo_values.paper_white_nits =
|
||||
settings->floats.video_hdr_paper_white_nits;
|
||||
d3d11->hdr.ubo_values.contrast =
|
||||
settings->floats.video_hdr_contrast;
|
||||
d3d11->hdr.ubo_values.expandGamut =
|
||||
d3d11->hdr.ubo_values.contrast =
|
||||
VIDEO_HDR_MAX_CONTRAST - settings->floats.video_hdr_display_contrast;
|
||||
d3d11->hdr.ubo_values.expand_gamut =
|
||||
settings->bools.video_hdr_expand_gamut;
|
||||
d3d11->hdr.ubo_values.inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */
|
||||
|
||||
desc.ByteWidth = sizeof(dxgi_hdr_uniform_t);
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
@ -1743,13 +1744,19 @@ static bool d3d11_gfx_frame(
|
||||
d3d11->swapChain,
|
||||
&d3d11->chain_color_space,
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
|
||||
|
||||
d3d11->chain_bit_depth = DXGI_SWAPCHAIN_BIT_DEPTH_10;
|
||||
}
|
||||
else
|
||||
{
|
||||
dxgi_swapchain_color_space(
|
||||
d3d11->swapChain,
|
||||
&d3d11->chain_color_space,
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709);
|
||||
|
||||
d3d11->chain_bit_depth = DXGI_SWAPCHAIN_BIT_DEPTH_8;
|
||||
}
|
||||
|
||||
dxgi_set_hdr_metadata(
|
||||
d3d11->swapChain,
|
||||
d3d11->hdr.support,
|
||||
@ -2103,6 +2110,9 @@ static bool d3d11_gfx_frame(
|
||||
D3D11Draw(context, 4, 0);
|
||||
|
||||
D3D11SetPShaderResources(context, 0, 1, nullSRV);
|
||||
D3D11SetRasterizerState(context, d3d11->scissor_enabled);
|
||||
D3D11SetBlendState(d3d11->context, d3d11->blend_enable, NULL, D3D11_DEFAULT_SAMPLE_MASK);
|
||||
D3D11SetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -238,14 +238,6 @@ static void d3d12_get_overlay_interface(void* data, const video_overlay_interfac
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
d3d12->hdr.max_output_nits = settings->floats.video_hdr_max_nits;
|
||||
d3d12->hdr.ubo_values.maxNits = settings->floats.video_hdr_max_nits;
|
||||
d3d12->hdr.ubo_values.paperWhiteNits = settings->floats.video_hdr_paper_white_nits;
|
||||
d3d12->hdr.ubo_values.contrast = settings->floats.video_hdr_contrast;
|
||||
d3d12->hdr.ubo_values.expandGamut = settings->bools.video_hdr_expand_gamut;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DXGI_HDR
|
||||
static void d3d12_set_hdr_max_nits(void* data, float max_nits)
|
||||
{
|
||||
@ -254,7 +246,7 @@ static void d3d12_set_hdr_max_nits(void* data, float max_nits)
|
||||
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
d3d12->hdr.max_output_nits = max_nits;
|
||||
d3d12->hdr.ubo_values.maxNits = max_nits;
|
||||
d3d12->hdr.ubo_values.max_nits = max_nits;
|
||||
|
||||
D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo);
|
||||
*mapped_ubo = d3d12->hdr.ubo_values;
|
||||
@ -277,7 +269,7 @@ static void d3d12_set_hdr_paper_white_nits(void* data, float paper_white_nits)
|
||||
dxgi_hdr_uniform_t *mapped_ubo = NULL;
|
||||
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
d3d12->hdr.ubo_values.paperWhiteNits = paper_white_nits;
|
||||
d3d12->hdr.ubo_values.paper_white_nits = paper_white_nits;
|
||||
|
||||
D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo);
|
||||
*mapped_ubo = d3d12->hdr.ubo_values;
|
||||
@ -303,7 +295,7 @@ static void d3d12_set_hdr_expand_gamut(void* data, bool expand_gamut)
|
||||
dxgi_hdr_uniform_t *mapped_ubo = NULL;
|
||||
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
d3d12->hdr.ubo_values.expandGamut = expand_gamut;
|
||||
d3d12->hdr.ubo_values.expand_gamut = expand_gamut;
|
||||
D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo);
|
||||
*mapped_ubo = d3d12->hdr.ubo_values;
|
||||
D3D12Unmap(d3d12->hdr.ubo, 0, NULL);
|
||||
@ -1153,10 +1145,11 @@ static void *d3d12_gfx_init(const video_info_t* video,
|
||||
d3d12_create_buffer(d3d12->device, d3d12->hdr.ubo_view.SizeInBytes, &d3d12->hdr.ubo);
|
||||
|
||||
d3d12->hdr.ubo_values.mvp = d3d12->mvp_no_rot;
|
||||
d3d12->hdr.ubo_values.maxNits = settings->floats.video_hdr_max_nits;
|
||||
d3d12->hdr.ubo_values.paperWhiteNits = settings->floats.video_hdr_paper_white_nits;
|
||||
d3d12->hdr.ubo_values.contrast = settings->floats.video_hdr_contrast;
|
||||
d3d12->hdr.ubo_values.expandGamut = settings->bools.video_hdr_expand_gamut;
|
||||
d3d12->hdr.ubo_values.max_nits = settings->floats.video_hdr_max_nits;
|
||||
d3d12->hdr.ubo_values.paper_white_nits = settings->floats.video_hdr_paper_white_nits;
|
||||
d3d12->hdr.ubo_values.contrast = VIDEO_HDR_MAX_CONTRAST - settings->floats.video_hdr_display_contrast;
|
||||
d3d12->hdr.ubo_values.expand_gamut = settings->bools.video_hdr_expand_gamut;
|
||||
d3d12->hdr.ubo_values.inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */
|
||||
|
||||
{
|
||||
dxgi_hdr_uniform_t* mapped_ubo;
|
||||
@ -1443,12 +1436,18 @@ static bool d3d12_gfx_frame(
|
||||
dxgi_swapchain_color_space(d3d12->chain.handle,
|
||||
&d3d12->chain.color_space,
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
|
||||
|
||||
d3d12->chain.bit_depth = DXGI_SWAPCHAIN_BIT_DEPTH_10;
|
||||
}
|
||||
else
|
||||
{
|
||||
dxgi_swapchain_color_space(d3d12->chain.handle,
|
||||
&d3d12->chain.color_space,
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709);
|
||||
|
||||
d3d12->chain.bit_depth = DXGI_SWAPCHAIN_BIT_DEPTH_8;
|
||||
}
|
||||
|
||||
dxgi_set_hdr_metadata(
|
||||
d3d12->chain.handle,
|
||||
d3d12->hdr.support,
|
||||
|
@ -4,10 +4,11 @@ SRC(
|
||||
struct UBO
|
||||
{
|
||||
float4x4 modelViewProj;
|
||||
float contrast; /* 2.0f; */
|
||||
float paperWhiteNits; /* 200.0f; */
|
||||
float maxNits; /* 1000.0f; */
|
||||
float expandGamut; /* 1.0f; */
|
||||
float contrast; /* 2.0f; */
|
||||
float paper_white_nits; /* 200.0f; */
|
||||
float max_nits; /* 1000.0f; */
|
||||
float expand_gamut; /* 1.0f; */
|
||||
float inverse_tonemap;
|
||||
};
|
||||
uniform UBO global;
|
||||
|
||||
@ -73,39 +74,48 @@ SRC(
|
||||
|
||||
float4 Hdr(float4 sdr)
|
||||
{
|
||||
sdr.xyz = pow(abs(sdr.xyz), 2.2f / global.contrast ); /* Display Gamma - needs to be determined by calibration screen */
|
||||
float3 hdr;
|
||||
|
||||
float luma = dot(sdr.xyz, float3(0.2126, 0.7152, 0.0722)); /* Rec BT.709 luma coefficients - https://en.wikipedia.org/wiki/Luma_(video) */
|
||||
if(global.inverse_tonemap)
|
||||
{
|
||||
sdr.xyz = pow(abs(sdr.xyz), global.contrast / 2.2f ); /* Display Gamma - needs to be determined by calibration screen */
|
||||
|
||||
/* Inverse reinhard tonemap */
|
||||
float maxValue = (global.maxNits / global.paperWhiteNits) + kEpsilon;
|
||||
float elbow = maxValue / (maxValue - 1.0f); /* Convert (1.0 + epsilon) to infinite to range 1001 -> 1.0 */
|
||||
float offset = 1.0f - ((0.5f * elbow) / (elbow - 0.5f)); /* Convert 1001 to 1.0 to range 0.5 -> 1.0 */
|
||||
float luma = dot(sdr.xyz, float3(0.2126, 0.7152, 0.0722)); /* Rec BT.709 luma coefficients - https://en.wikipedia.org/wiki/Luma_(video) */
|
||||
|
||||
float hdrLumaInvTonemap = offset + ((luma * elbow) / (elbow - luma));
|
||||
float sdrLumaInvTonemap = luma / ((1.0f + kEpsilon) - luma); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */
|
||||
/* Inverse reinhard tonemap */
|
||||
float maxValue = (global.max_nits / global.paper_white_nits) + kEpsilon;
|
||||
float elbow = maxValue / (maxValue - 1.0f); /* Convert (1.0 + epsilon) to infinite to range 1001 -> 1.0 */
|
||||
float offset = 1.0f - ((0.5f * elbow) / (elbow - 0.5f)); /* Convert 1001 to 1.0 to range 0.5 -> 1.0 */
|
||||
|
||||
float lumaInvTonemap = (luma > 0.5f) ? hdrLumaInvTonemap : sdrLumaInvTonemap;
|
||||
float3 perLuma = sdr.xyz / (luma + kEpsilon) * lumaInvTonemap;
|
||||
float hdrLumaInvTonemap = offset + ((luma * elbow) / (elbow - luma));
|
||||
float sdrLumaInvTonemap = luma / ((1.0f + kEpsilon) - luma); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */
|
||||
|
||||
float3 hdrInvTonemap = offset + ((sdr.xyz * elbow) / (elbow - sdr.xyz));
|
||||
float3 sdrInvTonemap = sdr.xyz / ((1.0f + kEpsilon) - sdr.xyz); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */
|
||||
float lumaInvTonemap = (luma > 0.5f) ? hdrLumaInvTonemap : sdrLumaInvTonemap;
|
||||
float3 perLuma = sdr.xyz / (luma + kEpsilon) * lumaInvTonemap;
|
||||
|
||||
float3 perChannel = float3(sdr.x > 0.5f ? hdrInvTonemap.x : sdrInvTonemap.x,
|
||||
sdr.y > 0.5f ? hdrInvTonemap.y : sdrInvTonemap.y,
|
||||
sdr.z > 0.5f ? hdrInvTonemap.z : sdrInvTonemap.z);
|
||||
float3 hdrInvTonemap = offset + ((sdr.xyz * elbow) / (elbow - sdr.xyz));
|
||||
float3 sdrInvTonemap = sdr.xyz / ((1.0f + kEpsilon) - sdr.xyz); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */
|
||||
|
||||
float3 hdr = lerp(perLuma, perChannel, kLumaChannelRatio);
|
||||
float3 perChannel = float3(sdr.x > 0.5f ? hdrInvTonemap.x : sdrInvTonemap.x,
|
||||
sdr.y > 0.5f ? hdrInvTonemap.y : sdrInvTonemap.y,
|
||||
sdr.z > 0.5f ? hdrInvTonemap.z : sdrInvTonemap.z);
|
||||
|
||||
hdr = lerp(perLuma, perChannel, kLumaChannelRatio);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdr = SRGBToLinear(sdr.xyz);
|
||||
}
|
||||
|
||||
/* Now convert into HDR10 */
|
||||
float3 rec2020 = mul(k709to2020, hdr);
|
||||
|
||||
if(global.expandGamut > 0.0f)
|
||||
if(global.expand_gamut > 0.0f)
|
||||
{
|
||||
rec2020 = mul( kExpanded709to2020, hdr);
|
||||
}
|
||||
|
||||
float3 linearColour = rec2020 * (global.paperWhiteNits / kMaxNitsFor2084);
|
||||
float3 linearColour = rec2020 * (global.paper_white_nits / kMaxNitsFor2084);
|
||||
float3 hdr10 = LinearToST2084(linearColour);
|
||||
|
||||
return float4(hdr10, sdr.w);
|
||||
|
@ -91,4 +91,100 @@ static INLINE uint32_t prev_pow2(uint32_t v)
|
||||
return v - (v >> 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* clamp:
|
||||
* @v : initial value
|
||||
*
|
||||
* Get the clamped value based on initial value.
|
||||
*
|
||||
* Returns: clamped value (derived from @v).
|
||||
**/
|
||||
static INLINE float clamp_value(float v, float min, float max)
|
||||
{
|
||||
return v <= min ? min : v >= max ? max : v;
|
||||
}
|
||||
|
||||
/**
|
||||
* saturate_value:
|
||||
* @v : initial value
|
||||
*
|
||||
* Get the clamped 0.0-1.0 value based on initial value.
|
||||
*
|
||||
* Returns: clamped 0.0-1.0 value (derived from @v).
|
||||
**/
|
||||
static INLINE float saturate_value(float v)
|
||||
{
|
||||
return clamp_value(v, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* dot_product:
|
||||
* @a : left hand vector value
|
||||
* @b : right hand vector value
|
||||
*
|
||||
* Get the dot product of the two passed in vectors.
|
||||
*
|
||||
* Returns: dot product value (derived from @a and @b).
|
||||
**/
|
||||
static INLINE float dot_product(const float* a, const float* b)
|
||||
{
|
||||
return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* retro_rgb_to_yxy:
|
||||
* @rgb : in RGB colour space value
|
||||
* @Yxy : out Yxy colour space value
|
||||
*
|
||||
* Convert from RGB colour space to Yxy colour space.
|
||||
*
|
||||
* Returns: Yxy colour space value (derived from @rgb).
|
||||
**/
|
||||
static INLINE void convert_rgb_to_yxy(const float* rgb, float* Yxy)
|
||||
{
|
||||
float inv;
|
||||
float xyz[3];
|
||||
float one[3] = {1.0, 1.0, 1.0};
|
||||
float rgb_xyz[3][3] = {
|
||||
{0.4124564, 0.3575761, 0.1804375},
|
||||
{0.2126729, 0.7151522, 0.0721750},
|
||||
{0.0193339, 0.1191920, 0.9503041}
|
||||
};
|
||||
|
||||
xyz[0] = dot_product(rgb_xyz[0], rgb);
|
||||
xyz[1] = dot_product(rgb_xyz[1], rgb);
|
||||
xyz[2] = dot_product(rgb_xyz[2], rgb);
|
||||
|
||||
inv = 1.0f / dot_product(xyz, one);
|
||||
Yxy[0] = xyz[1];
|
||||
Yxy[1] = xyz[0] * inv;
|
||||
Yxy[2] = xyz[1] * inv;
|
||||
}
|
||||
|
||||
/**
|
||||
* yxy_to_rgb:
|
||||
* @rgb : in Yxy colour space value
|
||||
* @Yxy : out rgb colour space value
|
||||
*
|
||||
* Convert from Yxy colour space to rgb colour space.
|
||||
*
|
||||
* Returns: rgb colour space value (derived from @Yxy).
|
||||
**/
|
||||
static INLINE void convert_yxy_to_rgb(const float* Yxy, float* rgb)
|
||||
{
|
||||
float xyz[3];
|
||||
float xyz_rgb[3][3] = {
|
||||
{3.2404542, -1.5371385, -0.4985314},
|
||||
{-0.9692660, 1.8760108, 0.0415560},
|
||||
{0.0556434, -0.2040259, 1.0572252}
|
||||
};
|
||||
xyz[0] = Yxy[0] * Yxy[1] / Yxy[2];
|
||||
xyz[1] = Yxy[0];
|
||||
xyz[2] = Yxy[0] * (1.0 - Yxy[1] - Yxy[2]) / Yxy[2];
|
||||
|
||||
rgb[0] = dot_product(xyz_rgb[0], xyz);
|
||||
rgb[1] = dot_product(xyz_rgb[1], xyz);
|
||||
rgb[2] = dot_product(xyz_rgb[2], xyz);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -7738,9 +7738,9 @@ static void general_write_handler(rarch_setting_t *setting)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
settings->modified = true;
|
||||
settings->floats.video_hdr_contrast = *setting->value.target.fraction;
|
||||
settings->floats.video_hdr_display_contrast = *setting->value.target.fraction;
|
||||
|
||||
video_driver_set_hdr_contrast(settings->floats.video_hdr_contrast);
|
||||
video_driver_set_hdr_contrast(settings->floats.video_hdr_display_contrast);
|
||||
}
|
||||
break;
|
||||
case MENU_ENUM_LABEL_VIDEO_HDR_EXPAND_GAMUT:
|
||||
@ -11924,7 +11924,7 @@ static bool setting_append_list(
|
||||
|
||||
CONFIG_FLOAT(
|
||||
list, list_info,
|
||||
&settings->floats.video_hdr_contrast,
|
||||
&settings->floats.video_hdr_display_contrast,
|
||||
MENU_ENUM_LABEL_VIDEO_HDR_CONTRAST,
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_CONTRAST,
|
||||
DEFAULT_VIDEO_HDR_CONTRAST,
|
||||
@ -11935,7 +11935,7 @@ static bool setting_append_list(
|
||||
general_write_handler,
|
||||
general_read_handler);
|
||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||
menu_settings_list_current_add_range(list, list_info, 0.1, 3.0, 0.01, true, true);
|
||||
menu_settings_list_current_add_range(list, list_info, 0.0, VIDEO_HDR_MAX_CONTRAST, 0.1, true, true);
|
||||
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
|
128
retroarch.c
128
retroarch.c
@ -24868,53 +24868,147 @@ void *video_driver_read_frame_raw(unsigned *width,
|
||||
unsigned *height, size_t *pitch)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
if (!p_rarch->current_video || !p_rarch->current_video->read_frame_raw)
|
||||
return NULL;
|
||||
return p_rarch->current_video->read_frame_raw(
|
||||
p_rarch->video_driver_data, width,
|
||||
height, pitch);
|
||||
if ( p_rarch->current_video
|
||||
&& p_rarch->current_video->read_frame_raw)
|
||||
return p_rarch->current_video->read_frame_raw(
|
||||
p_rarch->video_driver_data, width,
|
||||
height, pitch);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void video_driver_set_filtering(unsigned index, bool smooth, bool ctx_scaling)
|
||||
void video_driver_set_filtering(unsigned index,
|
||||
bool smooth, bool ctx_scaling)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
if (p_rarch->video_driver_poke && p_rarch->video_driver_poke->set_filtering)
|
||||
p_rarch->video_driver_poke->set_filtering(p_rarch->video_driver_data,
|
||||
if ( p_rarch->video_driver_poke
|
||||
&& p_rarch->video_driver_poke->set_filtering)
|
||||
p_rarch->video_driver_poke->set_filtering(
|
||||
p_rarch->video_driver_data,
|
||||
index, smooth, ctx_scaling);
|
||||
}
|
||||
|
||||
void video_driver_set_hdr_max_nits(float max_nits)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
if (p_rarch->video_driver_poke && p_rarch->video_driver_poke->set_hdr_max_nits)
|
||||
p_rarch->video_driver_poke->set_hdr_max_nits(p_rarch->video_driver_data,
|
||||
if ( p_rarch->video_driver_poke
|
||||
&& p_rarch->video_driver_poke->set_hdr_max_nits)
|
||||
p_rarch->video_driver_poke->set_hdr_max_nits(
|
||||
p_rarch->video_driver_data,
|
||||
max_nits);
|
||||
}
|
||||
|
||||
void video_driver_set_hdr_paper_white_nits(float paper_white_nits)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
if (p_rarch->video_driver_poke && p_rarch->video_driver_poke->set_hdr_paper_white_nits)
|
||||
p_rarch->video_driver_poke->set_hdr_paper_white_nits(p_rarch->video_driver_data,
|
||||
if ( p_rarch->video_driver_poke
|
||||
&& p_rarch->video_driver_poke->set_hdr_paper_white_nits)
|
||||
p_rarch->video_driver_poke->set_hdr_paper_white_nits(
|
||||
p_rarch->video_driver_data,
|
||||
paper_white_nits);
|
||||
}
|
||||
|
||||
void video_driver_set_hdr_contrast(float contrast)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
if (p_rarch->video_driver_poke && p_rarch->video_driver_poke->set_hdr_contrast)
|
||||
p_rarch->video_driver_poke->set_hdr_contrast(p_rarch->video_driver_data,
|
||||
contrast);
|
||||
if ( p_rarch->video_driver_poke
|
||||
&& p_rarch->video_driver_poke->set_hdr_contrast)
|
||||
p_rarch->video_driver_poke->set_hdr_contrast(
|
||||
p_rarch->video_driver_data,
|
||||
VIDEO_HDR_MAX_CONTRAST - contrast);
|
||||
}
|
||||
|
||||
void video_driver_set_hdr_expand_gamut(bool expand_gamut)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
if (p_rarch->video_driver_poke && p_rarch->video_driver_poke->set_hdr_expand_gamut)
|
||||
p_rarch->video_driver_poke->set_hdr_expand_gamut(p_rarch->video_driver_data,
|
||||
if ( p_rarch->video_driver_poke
|
||||
&& p_rarch->video_driver_poke->set_hdr_expand_gamut)
|
||||
p_rarch->video_driver_poke->set_hdr_expand_gamut(
|
||||
p_rarch->video_driver_data,
|
||||
expand_gamut);
|
||||
}
|
||||
|
||||
/* Use this value as a replacement for anywhere
|
||||
* where a pure white colour value is used in the UI.
|
||||
*
|
||||
* When HDR is turned on 1,1,1,1 should never really
|
||||
* be used as this is peak brightness and could cause
|
||||
* damage to displays over long periods of time
|
||||
* and be quite hard to look at on really bright displays.
|
||||
*
|
||||
* Use paper white instead which is always defined as
|
||||
* 0.5, 0.5, 0.5, 1.0 or in other words is the top of
|
||||
* the old SDR (Standard Dynamic Range) range
|
||||
*/
|
||||
unsigned video_driver_get_hdr_paper_white(void)
|
||||
{
|
||||
/* 0.5, 0.5, 0.5, 1 */
|
||||
if ( video_driver_supports_hdr()
|
||||
&& config_get_ptr()->bools.video_hdr_enable)
|
||||
return 0x7f7f7fff;
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
/* Same as above but returns the white value in floats */
|
||||
float *video_driver_get_hdr_paper_white_float(void)
|
||||
{
|
||||
static float paper_white[4] = { 0.5f, 0.5f, 0.5f, 1.0f};
|
||||
static float sdr_white [4] = { 1.0f, 1.0f, 1.0f, 1.0f};
|
||||
if( video_driver_supports_hdr()
|
||||
&& config_get_ptr()->bools.video_hdr_enable)
|
||||
return paper_white;
|
||||
return sdr_white;
|
||||
}
|
||||
|
||||
/* This is useful to create a HDR (High Dynamic Range) white
|
||||
* based off of some passed in nit level - say you want a
|
||||
* slightly brighter than paper white value for some parts
|
||||
* of the UI
|
||||
*/
|
||||
float video_driver_get_hdr_luminace(float nits)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
if(video_driver_supports_hdr() && settings->bools.video_hdr_enable)
|
||||
{
|
||||
float luminance = nits /
|
||||
settings->floats.video_hdr_paper_white_nits;
|
||||
return luminance / (1.0f + luminance);
|
||||
}
|
||||
return nits;
|
||||
}
|
||||
|
||||
/* Get reinhard tone mapped colour value for UI elements
|
||||
* when using HDR and its inverse tonemapper - normally don't use
|
||||
* but useful if you want a specific colour to look the same
|
||||
* after inverse tonemapping has been applied */
|
||||
unsigned video_driver_get_hdr_color(unsigned color)
|
||||
{
|
||||
if( video_driver_supports_hdr()
|
||||
&& config_get_ptr()->bools.video_hdr_enable)
|
||||
{
|
||||
float luminance;
|
||||
float rgb[3];
|
||||
float yxy[3];
|
||||
|
||||
rgb[0] = (float)((color >> 24) & 0xFF) / 255.0f;
|
||||
rgb[1] = (float)((color >> 16) & 0xFF) / 255.0f;
|
||||
rgb[2] = (float)((color >> 8 ) & 0xFF) / 255.0f;
|
||||
|
||||
convert_rgb_to_yxy(rgb, yxy);
|
||||
|
||||
/* TODO: We should probably scale this by average luminance */
|
||||
luminance = yxy[0];
|
||||
yxy[0] = luminance / (1.0f + luminance);
|
||||
|
||||
convert_yxy_to_rgb(rgb, yxy);
|
||||
|
||||
return ( (unsigned)(saturate_value(rgb[0]) * 255.0f) << 24)
|
||||
| ((unsigned)(saturate_value(rgb[1]) * 255.0f) << 16)
|
||||
| ((unsigned)(saturate_value(rgb[2]) * 255.0f) << 8)
|
||||
| (color & 0xFF);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
void video_driver_cached_frame_set(const void *data, unsigned width,
|
||||
unsigned height, size_t pitch)
|
||||
{
|
||||
|
10
retroarch.h
10
retroarch.h
@ -806,6 +806,8 @@ void recording_driver_update_streaming_url(void);
|
||||
#define VIDEO_SHADER_MENU_6 (GFX_MAX_SHADERS - 7)
|
||||
#define VIDEO_SHADER_STOCK_HDR (GFX_MAX_SHADERS - 8)
|
||||
|
||||
#define VIDEO_HDR_MAX_CONTRAST 10.0f
|
||||
|
||||
#if defined(_XBOX360)
|
||||
#define DEFAULT_SHADER_TYPE RARCH_SHADER_HLSL
|
||||
#elif defined(__PSL1GHT__) || defined(HAVE_OPENGLES2) || defined(HAVE_GLSL)
|
||||
@ -1598,6 +1600,14 @@ void video_driver_unset_hdr_support(void);
|
||||
|
||||
bool video_driver_supports_hdr(void);
|
||||
|
||||
unsigned video_driver_get_hdr_color(unsigned color);
|
||||
|
||||
float video_driver_get_hdr_luminace(float nits);
|
||||
|
||||
unsigned video_driver_get_hdr_paper_white(void);
|
||||
|
||||
float* video_driver_get_hdr_paper_white_float(void);
|
||||
|
||||
bool video_driver_get_next_video_out(void);
|
||||
|
||||
bool video_driver_get_prev_video_out(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user