steamcompmgr, color_helpers: Added atoms for color gains
GAMESCOPE_HDR_INPUT_GAIN GAMESCOPE_SDR_INPUT_GAIN
This commit is contained in:
parent
378cfa5b7b
commit
cfcea1433e
5 changed files with 72 additions and 34 deletions
|
@ -210,7 +210,7 @@ glm::vec3 calcEOTFToLinear( const glm::vec3 & input, EOTF eotf, const tonemappin
|
|||
{
|
||||
if ( eotf == EOTF_Gamma22 )
|
||||
{
|
||||
return glm::pow( input, glm::vec3( 2.2f ) ) * tonemapping.g22_luminance_tolinear;
|
||||
return glm::pow( input, glm::vec3( 2.2f ) ) * tonemapping.g22_luminance;
|
||||
}
|
||||
else if ( eotf == EOTF_PQ )
|
||||
{
|
||||
|
@ -225,9 +225,9 @@ glm::vec3 calcLinearToEOTF( const glm::vec3 & input, EOTF eotf, const tonemappin
|
|||
if ( eotf == EOTF_Gamma22 )
|
||||
{
|
||||
glm::vec3 val = input;
|
||||
if ( tonemapping.g22_luminance_fromlinear > 0.f )
|
||||
if ( tonemapping.g22_luminance > 0.f )
|
||||
{
|
||||
val = glm::clamp( input / tonemapping.g22_luminance_fromlinear, glm::vec3( 0.f ), glm::vec3( 1.f ) );
|
||||
val = glm::clamp( input / tonemapping.g22_luminance, glm::vec3( 0.f ), glm::vec3( 1.f ) );
|
||||
}
|
||||
return glm::pow( val, glm::vec3( 1.f/2.2f ) );
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ glm::vec3 calcLinearToEOTF( const glm::vec3 & input, EOTF eotf, const tonemappin
|
|||
|
||||
// input is from 0->1
|
||||
// TODO: use tone-mapping for white, black, contrast ratio
|
||||
glm::vec3 applyShaper( const glm::vec3 & input, EOTF source, EOTF dest, const tonemapping_t & tonemapping, bool bInvert )
|
||||
glm::vec3 applyShaper( const glm::vec3 & input, EOTF source, EOTF dest, const tonemapping_t & tonemapping, float flGain, bool bInvert )
|
||||
{
|
||||
if ( source == dest || !tonemapping.bUseShaper )
|
||||
{
|
||||
|
@ -252,16 +252,17 @@ glm::vec3 applyShaper( const glm::vec3 & input, EOTF source, EOTF dest, const to
|
|||
{
|
||||
// (once we do tone mapping this gets more complicated
|
||||
std::swap( source, dest );
|
||||
flGain = 1.f / flGain;
|
||||
}
|
||||
|
||||
return calcLinearToEOTF( calcEOTFToLinear( input, source, tonemapping ), dest, tonemapping );
|
||||
return calcLinearToEOTF( flGain * calcEOTFToLinear( input, source, tonemapping ), dest, tonemapping );
|
||||
}
|
||||
|
||||
void calcColorTransform( uint16_t * pRgbxData1d, int nLutSize1d,
|
||||
uint16_t * pRgbxData3d, int nLutEdgeSize3d,
|
||||
const displaycolorimetry_t & source, EOTF sourceEOTF,
|
||||
const displaycolorimetry_t & dest, EOTF destEOTF,
|
||||
const colormapping_t & mapping, const nightmode_t & nightmode, const tonemapping_t & tonemapping )
|
||||
const colormapping_t & mapping, const nightmode_t & nightmode, const tonemapping_t & tonemapping, float flGain )
|
||||
{
|
||||
glm::mat3 xyz_from_dest = normalised_primary_matrix( dest.primaries, dest.white, 1.f );
|
||||
glm::mat3 dest_from_xyz = glm::inverse( xyz_from_dest );
|
||||
|
@ -281,7 +282,7 @@ void calcColorTransform( uint16_t * pRgbxData1d, int nLutSize1d,
|
|||
for ( int nVal=0; nVal<nLutSize1d; ++nVal )
|
||||
{
|
||||
glm::vec3 sourceColorEOTFEncoded = { nVal * flScale, nVal * flScale, nVal * flScale };
|
||||
glm::vec3 shapedSourceColor = applyShaper( sourceColorEOTFEncoded, sourceEOTF, destEOTF, tonemapping, false );
|
||||
glm::vec3 shapedSourceColor = applyShaper( sourceColorEOTFEncoded, sourceEOTF, destEOTF, tonemapping, flGain, false );
|
||||
pRgbxData1d[nVal * 4 + 0] = drm_quantize_lut_value( shapedSourceColor.x );
|
||||
pRgbxData1d[nVal * 4 + 1] = drm_quantize_lut_value( shapedSourceColor.y );
|
||||
pRgbxData1d[nVal * 4 + 2] = drm_quantize_lut_value( shapedSourceColor.z );
|
||||
|
@ -306,7 +307,7 @@ void calcColorTransform( uint16_t * pRgbxData1d, int nLutSize1d,
|
|||
for ( int nRed=0; nRed<nLutEdgeSize3d; ++nRed )
|
||||
{
|
||||
glm::vec3 shapedSourceColor = { nRed * flScale, nGreen * flScale, nBlue * flScale };
|
||||
glm::vec3 sourceColorEOTFEncoded = applyShaper( shapedSourceColor, sourceEOTF, destEOTF, tonemapping, true );
|
||||
glm::vec3 sourceColorEOTFEncoded = applyShaper( shapedSourceColor, sourceEOTF, destEOTF, tonemapping, flGain, true );
|
||||
|
||||
// Convert to linearized display referred for source colorimetry
|
||||
glm::vec3 sourceColorLinear = calcEOTFToLinear( sourceColorEOTFEncoded, sourceEOTF, tonemapping );
|
||||
|
@ -322,7 +323,7 @@ void calcColorTransform( uint16_t * pRgbxData1d, int nLutSize1d,
|
|||
destColorLinear = glm::mix( destColorLinear, sourceColorLinear, amount );
|
||||
|
||||
// Apply night mode
|
||||
destColorLinear = vNightModeMultLinear * destColorLinear;
|
||||
destColorLinear = vNightModeMultLinear * destColorLinear * glm::vec3( flGain );
|
||||
|
||||
// Apply dest EOTF
|
||||
glm::vec3 destColorEOTFEncoded = calcLinearToEOTF( destColorLinear, destEOTF, tonemapping );
|
||||
|
|
|
@ -151,8 +151,7 @@ colormapping_t lerp( const colormapping_t & a, const colormapping_t & b, float t
|
|||
struct tonemapping_t
|
||||
{
|
||||
bool bUseShaper = true;
|
||||
float g22_luminance_tolinear = 1.f; // what luminance should be applied for g22 EOTF conversions?
|
||||
float g22_luminance_fromlinear = 1.f; // what luminance should be applied for g22 EOTF conversions?
|
||||
float g22_luminance = 1.f; // what luminance should be applied for g22 EOTF conversions?
|
||||
};
|
||||
|
||||
// Generate a color transform from the source colorspace, to the dest colorspace,
|
||||
|
@ -167,7 +166,8 @@ void calcColorTransform( uint16_t * pRgbxData1d, int nLutSize1d,
|
|||
uint16_t * pRgbxData3d, int nLutEdgeSize3d,
|
||||
const displaycolorimetry_t & source, EOTF sourceEOTF,
|
||||
const displaycolorimetry_t & dest, EOTF destEOTF,
|
||||
const colormapping_t & mapping, const nightmode_t & nightmode, const tonemapping_t & tonemapping );
|
||||
const colormapping_t & mapping, const nightmode_t & nightmode, const tonemapping_t & tonemapping,
|
||||
float flGain );
|
||||
|
||||
int writeRawLut( const char * outputFilename, uint16_t * pData, size_t nSize );
|
||||
|
||||
|
|
|
@ -360,6 +360,8 @@ struct gamescope_color_mgmt_t
|
|||
float sdrGamutWideness; // user property to widen gamut
|
||||
float flInternalDisplayBrightness = 500.f;
|
||||
float flSDROnHDRBrightness = 203.f;
|
||||
float flHDRInputGain = 1.f;
|
||||
float flSDRInputGain = 1.f;
|
||||
|
||||
// the native colorimetry capabilities of the display
|
||||
displaycolorimetry_t displayColorimetry;
|
||||
|
|
|
@ -165,30 +165,21 @@ update_color_mgmt()
|
|||
tonemapping.bUseShaper = true;
|
||||
|
||||
EOTF inputEOTF = static_cast<EOTF>( nInputEOTF );
|
||||
float flGain = 1.f;
|
||||
|
||||
if ( inputEOTF == EOTF_Gamma22 )
|
||||
{
|
||||
flGain = g_ColorMgmt.pending.flSDRInputGain;
|
||||
if ( g_ColorMgmt.pending.outputEncodingEOTF == EOTF_Gamma22 )
|
||||
{
|
||||
if ( g_bForceHDRSupportDebug )
|
||||
{
|
||||
tonemapping.g22_luminance_tolinear = g_ColorMgmt.pending.flSDROnHDRBrightness;
|
||||
tonemapping.g22_luminance_fromlinear = g_ColorMgmt.pending.flInternalDisplayBrightness;
|
||||
// xwm_log.infof("G22 -> G22 (force HDR) %f %f", tonemapping.g22_luminance_tolinear, tonemapping.g22_luminance_fromlinear );
|
||||
}
|
||||
else
|
||||
{
|
||||
// G22 -> G22. Does not matter what the g22 mult is
|
||||
tonemapping.g22_luminance_tolinear = 1.f;
|
||||
tonemapping.g22_luminance_fromlinear = 1.f;
|
||||
// xwm_log.infof("G22 -> G22");
|
||||
}
|
||||
|
||||
// G22 -> G22. Does not matter what the g22 mult is
|
||||
tonemapping.g22_luminance = 1.f;
|
||||
// xwm_log.infof("G22 -> G22");
|
||||
}
|
||||
else if ( g_ColorMgmt.pending.outputEncodingEOTF == EOTF_PQ )
|
||||
{
|
||||
// G22 -> PQ. SDR content going on an HDR output
|
||||
tonemapping.g22_luminance_tolinear = g_ColorMgmt.pending.flSDROnHDRBrightness;
|
||||
tonemapping.g22_luminance_fromlinear = g_ColorMgmt.pending.flSDROnHDRBrightness;
|
||||
tonemapping.g22_luminance = g_ColorMgmt.pending.flSDROnHDRBrightness;
|
||||
// xwm_log.infof("G22 -> PQ");
|
||||
}
|
||||
|
||||
|
@ -199,18 +190,17 @@ update_color_mgmt()
|
|||
}
|
||||
else if ( inputEOTF == EOTF_PQ )
|
||||
{
|
||||
flGain = g_ColorMgmt.pending.flHDRInputGain;
|
||||
if ( g_ColorMgmt.pending.outputEncodingEOTF == EOTF_Gamma22 )
|
||||
{
|
||||
// PQ -> G22 Leverage the display's native brightness
|
||||
tonemapping.g22_luminance_tolinear = g_ColorMgmt.pending.flInternalDisplayBrightness;
|
||||
tonemapping.g22_luminance_fromlinear = g_ColorMgmt.pending.flInternalDisplayBrightness;
|
||||
// xwm_log.infof("PQ -> 2.2 - tonemapping.g22_luminance %f", tonemapping.g22_luminance_tolinear );
|
||||
tonemapping.g22_luminance = g_ColorMgmt.pending.flInternalDisplayBrightness;
|
||||
// xwm_log.infof("PQ -> 2.2 - tonemapping.g22_luminance %f", tonemapping.g22_luminance );
|
||||
}
|
||||
else if ( g_ColorMgmt.pending.outputEncodingEOTF == EOTF_PQ )
|
||||
{
|
||||
// PQ -> PQ. Better not matter what the g22 mult is
|
||||
tonemapping.g22_luminance_tolinear = 1.f;
|
||||
tonemapping.g22_luminance_fromlinear = 1.f;
|
||||
tonemapping.g22_luminance = 1.f;
|
||||
// xwm_log.infof("PQ -> PQ");
|
||||
}
|
||||
|
||||
|
@ -219,7 +209,7 @@ update_color_mgmt()
|
|||
|
||||
calcColorTransform( &lut1d[0], nLutSize1d, &lut3d[0], nLutEdgeSize3d, inputColorimetry, inputEOTF,
|
||||
outputEncodingColorimetry, g_ColorMgmt.pending.outputEncodingEOTF,
|
||||
colorMapping, g_ColorMgmt.pending.nightmode, tonemapping );
|
||||
colorMapping, g_ColorMgmt.pending.nightmode, tonemapping, flGain );
|
||||
|
||||
if ( !g_ColorMgmtLutsOverride[nInputEOTF].lut3d.empty() && !g_ColorMgmtLutsOverride[nInputEOTF].lut1d.empty() )
|
||||
{
|
||||
|
@ -293,6 +283,35 @@ bool set_sdr_on_hdr_brightness( float flVal )
|
|||
return g_ColorMgmt.pending.enabled;
|
||||
}
|
||||
|
||||
bool set_hdr_input_gain( float flVal )
|
||||
{
|
||||
if ( flVal < 0.f )
|
||||
{
|
||||
flVal = 1.f;
|
||||
}
|
||||
|
||||
if ( g_ColorMgmt.pending.flHDRInputGain == flVal )
|
||||
return false;
|
||||
|
||||
g_ColorMgmt.pending.flHDRInputGain = flVal;
|
||||
|
||||
return g_ColorMgmt.pending.enabled;
|
||||
}
|
||||
|
||||
bool set_sdr_input_gain( float flVal )
|
||||
{
|
||||
if ( flVal < 0.f )
|
||||
{
|
||||
flVal = 1.f;
|
||||
}
|
||||
|
||||
if ( g_ColorMgmt.pending.flSDRInputGain == flVal )
|
||||
return false;
|
||||
|
||||
g_ColorMgmt.pending.flSDRInputGain = flVal;
|
||||
return g_ColorMgmt.pending.enabled;
|
||||
}
|
||||
|
||||
bool set_color_nightmode( const nightmode_t &nightmode )
|
||||
{
|
||||
if ( g_ColorMgmt.pending.nightmode == nightmode )
|
||||
|
@ -4953,6 +4972,18 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev)
|
|||
if ( set_internal_display_brightness( bit_cast<float>(val) ) )
|
||||
hasRepaint = true;
|
||||
}
|
||||
if ( ev->atom == ctx->atoms.gamescopeHDRInputGain )
|
||||
{
|
||||
uint32_t val = get_prop( ctx, ctx->root, ctx->atoms.gamescopeHDRInputGain, 0 );
|
||||
if ( set_hdr_input_gain( bit_cast<float>(val) ) )
|
||||
hasRepaint = true;
|
||||
}
|
||||
if ( ev->atom == ctx->atoms.gamescopeSDRInputGain )
|
||||
{
|
||||
uint32_t val = get_prop( ctx, ctx->root, ctx->atoms.gamescopeSDRInputGain, 0 );
|
||||
if ( set_sdr_input_gain( bit_cast<float>(val) ) )
|
||||
hasRepaint = true;
|
||||
}
|
||||
if ( ev->atom == ctx->atoms.gamescopeForceWindowsFullscreen )
|
||||
{
|
||||
ctx->force_windows_fullscreen = !!get_prop( ctx, ctx->root, ctx->atoms.gamescopeForceWindowsFullscreen, 0 );
|
||||
|
@ -6149,6 +6180,8 @@ void init_xwayland_ctx(uint32_t serverId, gamescope_xwayland_server_t *xwayland_
|
|||
ctx->atoms.gamescopeHDROutputFeedback = XInternAtom( ctx->dpy, "GAMESCOPE_HDR_OUTPUT_FEEDBACK", false );
|
||||
ctx->atoms.gamescopeSDROnHDRContentBrightness = XInternAtom( ctx->dpy, "GAMESCOPE_SDR_ON_HDR_CONTENT_BRIGHTNESS", false );
|
||||
ctx->atoms.gamescopeInternalDisplayBrightness = XInternAtom( ctx->dpy, "GAMESCOPE_INTERNAL_DISPLAY_BRIGHTNESS", false );
|
||||
ctx->atoms.gamescopeHDRInputGain = XInternAtom( ctx->dpy, "GAMESCOPE_HDR_INPUT_GAIN", false );
|
||||
ctx->atoms.gamescopeSDRInputGain = XInternAtom( ctx->dpy, "GAMESCOPE_SDR_INPUT_GAIN", false );
|
||||
ctx->atoms.gamescopeHDRItmEnable = XInternAtom( ctx->dpy, "GAMESCOPE_HDR_ITM_ENABLE", false );
|
||||
ctx->atoms.gamescopeHDRItmSDRNits = XInternAtom( ctx->dpy, "GAMESCOPE_HDR_ITM_SDR_NITS", false );
|
||||
ctx->atoms.gamescopeHDRItmTargetNits = XInternAtom( ctx->dpy, "GAMESCOPE_HDR_ITM_TARGET_NITS", false );
|
||||
|
|
|
@ -179,6 +179,8 @@ struct xwayland_ctx_t
|
|||
Atom gamescopeHDROutputFeedback;
|
||||
Atom gamescopeSDROnHDRContentBrightness;
|
||||
Atom gamescopeInternalDisplayBrightness;
|
||||
Atom gamescopeHDRInputGain;
|
||||
Atom gamescopeSDRInputGain;
|
||||
Atom gamescopeHDRItmEnable;
|
||||
Atom gamescopeHDRItmSDRNits;
|
||||
Atom gamescopeHDRItmTargetNits;
|
||||
|
|
Loading…
Reference in a new issue