renderer/cm: allow gamma 2.2 instead of sRGB EOTF (#12094)
This commit is contained in:
parent
ce9787b3f4
commit
ff50dc36e9
7 changed files with 51 additions and 15 deletions
|
|
@ -1542,6 +1542,13 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||||
.type = CONFIG_OPTION_CHOICE,
|
.type = CONFIG_OPTION_CHOICE,
|
||||||
.data = SConfigOptionDescription::SChoiceData{0, "disable,always,ondemand,ignore"},
|
.data = SConfigOptionDescription::SChoiceData{0, "disable,always,ondemand,ignore"},
|
||||||
},
|
},
|
||||||
|
SConfigOptionDescription{
|
||||||
|
.value = "render:cm_sdr_eotf",
|
||||||
|
.description = "Default transfer function for displaying SDR apps. 0 - Treat unspecified as sRGB, 1 - Treat unspecified as Gamma 2.2, 2 - Treat "
|
||||||
|
"unspecified and sRGB as Gamma 2.2",
|
||||||
|
.type = CONFIG_OPTION_CHOICE,
|
||||||
|
.data = SConfigOptionDescription::SChoiceData{0, "srgb,gamma22,gamma22force"},
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cursor:
|
* cursor:
|
||||||
|
|
|
||||||
|
|
@ -781,6 +781,7 @@ CConfigManager::CConfigManager() {
|
||||||
registerConfigVar("render:cm_auto_hdr", Hyprlang::INT{1});
|
registerConfigVar("render:cm_auto_hdr", Hyprlang::INT{1});
|
||||||
registerConfigVar("render:new_render_scheduling", Hyprlang::INT{0});
|
registerConfigVar("render:new_render_scheduling", Hyprlang::INT{0});
|
||||||
registerConfigVar("render:non_shader_cm", Hyprlang::INT{2});
|
registerConfigVar("render:non_shader_cm", Hyprlang::INT{2});
|
||||||
|
registerConfigVar("render:cm_sdr_eotf", Hyprlang::INT{0});
|
||||||
|
|
||||||
registerConfigVar("ecosystem:no_update_news", Hyprlang::INT{0});
|
registerConfigVar("ecosystem:no_update_news", Hyprlang::INT{0});
|
||||||
registerConfigVar("ecosystem:no_donation_nag", Hyprlang::INT{0});
|
registerConfigVar("ecosystem:no_donation_nag", Hyprlang::INT{0});
|
||||||
|
|
@ -842,6 +843,7 @@ CConfigManager::CConfigManager() {
|
||||||
m_config->addSpecialConfigValue("monitorv2", "mirror", {STRVAL_EMPTY});
|
m_config->addSpecialConfigValue("monitorv2", "mirror", {STRVAL_EMPTY});
|
||||||
m_config->addSpecialConfigValue("monitorv2", "bitdepth", {STRVAL_EMPTY}); // TODO use correct type
|
m_config->addSpecialConfigValue("monitorv2", "bitdepth", {STRVAL_EMPTY}); // TODO use correct type
|
||||||
m_config->addSpecialConfigValue("monitorv2", "cm", {"auto"});
|
m_config->addSpecialConfigValue("monitorv2", "cm", {"auto"});
|
||||||
|
m_config->addSpecialConfigValue("monitorv2", "sdr_eotf", Hyprlang::INT{0});
|
||||||
m_config->addSpecialConfigValue("monitorv2", "sdrbrightness", Hyprlang::FLOAT{1.0});
|
m_config->addSpecialConfigValue("monitorv2", "sdrbrightness", Hyprlang::FLOAT{1.0});
|
||||||
m_config->addSpecialConfigValue("monitorv2", "sdrsaturation", Hyprlang::FLOAT{1.0});
|
m_config->addSpecialConfigValue("monitorv2", "sdrsaturation", Hyprlang::FLOAT{1.0});
|
||||||
m_config->addSpecialConfigValue("monitorv2", "vrr", Hyprlang::INT{0});
|
m_config->addSpecialConfigValue("monitorv2", "vrr", Hyprlang::INT{0});
|
||||||
|
|
@ -1115,6 +1117,9 @@ std::optional<std::string> CConfigManager::handleMonitorv2(const std::string& ou
|
||||||
VAL = m_config->getSpecialConfigValuePtr("monitorv2", "cm", output.c_str());
|
VAL = m_config->getSpecialConfigValuePtr("monitorv2", "cm", output.c_str());
|
||||||
if (VAL && VAL->m_bSetByUser)
|
if (VAL && VAL->m_bSetByUser)
|
||||||
parser.parseCM(std::any_cast<Hyprlang::STRING>(VAL->getValue()));
|
parser.parseCM(std::any_cast<Hyprlang::STRING>(VAL->getValue()));
|
||||||
|
VAL = m_config->getSpecialConfigValuePtr("monitorv2", "sdr_eotf", output.c_str());
|
||||||
|
if (VAL && VAL->m_bSetByUser)
|
||||||
|
parser.rule().sdrEotf = std::any_cast<Hyprlang::INT>(VAL->getValue());
|
||||||
VAL = m_config->getSpecialConfigValuePtr("monitorv2", "sdrbrightness", output.c_str());
|
VAL = m_config->getSpecialConfigValuePtr("monitorv2", "sdrbrightness", output.c_str());
|
||||||
if (VAL && VAL->m_bSetByUser)
|
if (VAL && VAL->m_bSetByUser)
|
||||||
parser.rule().sdrBrightness = std::any_cast<Hyprlang::FLOAT>(VAL->getValue());
|
parser.rule().sdrBrightness = std::any_cast<Hyprlang::FLOAT>(VAL->getValue());
|
||||||
|
|
|
||||||
|
|
@ -465,32 +465,41 @@ void CMonitor::onDisconnect(bool destroy) {
|
||||||
std::erase_if(g_pCompositor->m_monitors, [&](PHLMONITOR& el) { return el.get() == this; });
|
std::erase_if(g_pCompositor->m_monitors, [&](PHLMONITOR& el) { return el.get() == this; });
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitor::applyCMType(NCMType::eCMType cmType) {
|
void CMonitor::applyCMType(NCMType::eCMType cmType, int cmSdrEotf) {
|
||||||
auto oldImageDescription = m_imageDescription;
|
auto oldImageDescription = m_imageDescription;
|
||||||
|
static auto PSDREOTF = CConfigValue<Hyprlang::INT>("render:cm_sdr_eotf");
|
||||||
|
auto chosenSdrEotf = cmSdrEotf == 0 ? (*PSDREOTF > 0 ? NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22 : NColorManagement::CM_TRANSFER_FUNCTION_SRGB) :
|
||||||
|
(cmSdrEotf == 1 ? NColorManagement::CM_TRANSFER_FUNCTION_SRGB : NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22);
|
||||||
|
|
||||||
switch (cmType) {
|
switch (cmType) {
|
||||||
case NCMType::CM_SRGB: m_imageDescription = {}; break; // assumes SImageDescirption defaults to sRGB
|
case NCMType::CM_SRGB: m_imageDescription = {.transferFunction = chosenSdrEotf}; break; // assumes SImageDescription defaults to sRGB
|
||||||
case NCMType::CM_WIDE:
|
case NCMType::CM_WIDE:
|
||||||
m_imageDescription = {.primariesNameSet = true,
|
m_imageDescription = {.transferFunction = chosenSdrEotf,
|
||||||
|
.primariesNameSet = true,
|
||||||
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
|
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
|
||||||
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020)};
|
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020)};
|
||||||
break;
|
break;
|
||||||
case NCMType::CM_DCIP3:
|
case NCMType::CM_DCIP3:
|
||||||
m_imageDescription = {.primariesNameSet = true,
|
m_imageDescription = {.transferFunction = chosenSdrEotf,
|
||||||
|
.primariesNameSet = true,
|
||||||
.primariesNamed = NColorManagement::CM_PRIMARIES_DCI_P3,
|
.primariesNamed = NColorManagement::CM_PRIMARIES_DCI_P3,
|
||||||
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_DCI_P3)};
|
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_DCI_P3)};
|
||||||
break;
|
break;
|
||||||
case NCMType::CM_DP3:
|
case NCMType::CM_DP3:
|
||||||
m_imageDescription = {.primariesNameSet = true,
|
m_imageDescription = {.transferFunction = chosenSdrEotf,
|
||||||
|
.primariesNameSet = true,
|
||||||
.primariesNamed = NColorManagement::CM_PRIMARIES_DISPLAY_P3,
|
.primariesNamed = NColorManagement::CM_PRIMARIES_DISPLAY_P3,
|
||||||
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_DISPLAY_P3)};
|
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_DISPLAY_P3)};
|
||||||
break;
|
break;
|
||||||
case NCMType::CM_ADOBE:
|
case NCMType::CM_ADOBE:
|
||||||
m_imageDescription = {.primariesNameSet = true,
|
m_imageDescription = {.transferFunction = chosenSdrEotf,
|
||||||
|
.primariesNameSet = true,
|
||||||
.primariesNamed = NColorManagement::CM_PRIMARIES_ADOBE_RGB,
|
.primariesNamed = NColorManagement::CM_PRIMARIES_ADOBE_RGB,
|
||||||
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_ADOBE_RGB)};
|
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_ADOBE_RGB)};
|
||||||
break;
|
break;
|
||||||
case NCMType::CM_EDID:
|
case NCMType::CM_EDID:
|
||||||
m_imageDescription = {.primariesNameSet = false,
|
m_imageDescription = {.transferFunction = chosenSdrEotf,
|
||||||
|
.primariesNameSet = true,
|
||||||
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
|
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
|
||||||
.primaries = {
|
.primaries = {
|
||||||
.red = {.x = m_output->parsedEDID.chromaticityCoords->red.x, .y = m_output->parsedEDID.chromaticityCoords->red.y},
|
.red = {.x = m_output->parsedEDID.chromaticityCoords->red.x, .y = m_output->parsedEDID.chromaticityCoords->red.y},
|
||||||
|
|
@ -868,6 +877,8 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) {
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_sdrEotf = RULE->sdrEotf;
|
||||||
|
|
||||||
m_sdrMinLuminance = RULE->sdrMinLuminance;
|
m_sdrMinLuminance = RULE->sdrMinLuminance;
|
||||||
m_sdrMaxLuminance = RULE->sdrMaxLuminance;
|
m_sdrMaxLuminance = RULE->sdrMaxLuminance;
|
||||||
|
|
||||||
|
|
@ -875,7 +886,7 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) {
|
||||||
m_maxLuminance = RULE->maxLuminance;
|
m_maxLuminance = RULE->maxLuminance;
|
||||||
m_maxAvgLuminance = RULE->maxAvgLuminance;
|
m_maxAvgLuminance = RULE->maxAvgLuminance;
|
||||||
|
|
||||||
applyCMType(m_cmType);
|
applyCMType(m_cmType, m_sdrEotf);
|
||||||
|
|
||||||
m_sdrSaturation = RULE->sdrSaturation;
|
m_sdrSaturation = RULE->sdrSaturation;
|
||||||
m_sdrBrightness = RULE->sdrBrightness;
|
m_sdrBrightness = RULE->sdrBrightness;
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ struct SMonitorRule {
|
||||||
std::string mirrorOf = "";
|
std::string mirrorOf = "";
|
||||||
bool enable10bit = false;
|
bool enable10bit = false;
|
||||||
NCMType::eCMType cmType = NCMType::CM_SRGB;
|
NCMType::eCMType cmType = NCMType::CM_SRGB;
|
||||||
|
int sdrEotf = 0;
|
||||||
float sdrSaturation = 1.0f; // SDR -> HDR
|
float sdrSaturation = 1.0f; // SDR -> HDR
|
||||||
float sdrBrightness = 1.0f; // SDR -> HDR
|
float sdrBrightness = 1.0f; // SDR -> HDR
|
||||||
|
|
||||||
|
|
@ -132,6 +133,7 @@ class CMonitor {
|
||||||
bool m_vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
bool m_vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||||
bool m_enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
bool m_enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
||||||
NCMType::eCMType m_cmType = NCMType::CM_SRGB;
|
NCMType::eCMType m_cmType = NCMType::CM_SRGB;
|
||||||
|
int m_sdrEotf = 0;
|
||||||
float m_sdrSaturation = 1.0f;
|
float m_sdrSaturation = 1.0f;
|
||||||
float m_sdrBrightness = 1.0f;
|
float m_sdrBrightness = 1.0f;
|
||||||
float m_sdrMinLuminance = 0.2f;
|
float m_sdrMinLuminance = 0.2f;
|
||||||
|
|
@ -275,7 +277,7 @@ class CMonitor {
|
||||||
// methods
|
// methods
|
||||||
void onConnect(bool noRule);
|
void onConnect(bool noRule);
|
||||||
void onDisconnect(bool destroy = false);
|
void onDisconnect(bool destroy = false);
|
||||||
void applyCMType(NCMType::eCMType cmType);
|
void applyCMType(NCMType::eCMType cmType, int cmSdrEotf);
|
||||||
bool applyMonitorRule(SMonitorRule* pMonitorRule, bool force = false);
|
bool applyMonitorRule(SMonitorRule* pMonitorRule, bool force = false);
|
||||||
void addDamage(const pixman_region32_t* rg);
|
void addDamage(const pixman_region32_t* rg);
|
||||||
void addDamage(const CRegion& rg);
|
void addDamage(const CRegion& rg);
|
||||||
|
|
|
||||||
|
|
@ -1552,14 +1552,24 @@ static std::map<std::pair<uint32_t, uint32_t>, std::array<GLfloat, 9>> primaries
|
||||||
|
|
||||||
static bool isSDR2HDR(const NColorManagement::SImageDescription& imageDescription, const NColorManagement::SImageDescription& targetImageDescription) {
|
static bool isSDR2HDR(const NColorManagement::SImageDescription& imageDescription, const NColorManagement::SImageDescription& targetImageDescription) {
|
||||||
// might be too strict
|
// might be too strict
|
||||||
return imageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_SRGB &&
|
return (imageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_SRGB ||
|
||||||
|
imageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22) &&
|
||||||
(targetImageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ||
|
(targetImageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ||
|
||||||
targetImageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_HLG);
|
targetImageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_HLG);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::passCMUniforms(SShader& shader, const NColorManagement::SImageDescription& imageDescription,
|
void CHyprOpenGLImpl::passCMUniforms(SShader& shader, const NColorManagement::SImageDescription& imageDescription,
|
||||||
const NColorManagement::SImageDescription& targetImageDescription, bool modifySDR, float sdrMinLuminance, int sdrMaxLuminance) {
|
const NColorManagement::SImageDescription& targetImageDescription, bool modifySDR, float sdrMinLuminance, int sdrMaxLuminance) {
|
||||||
shader.setUniformInt(SHADER_SOURCE_TF, imageDescription.transferFunction);
|
static auto PSDREOTF = CConfigValue<Hyprlang::INT>("render:cm_sdr_eotf");
|
||||||
|
|
||||||
|
if (m_renderData.surface.valid() &&
|
||||||
|
((!m_renderData.surface->m_colorManagement.valid() && *PSDREOTF >= 1) ||
|
||||||
|
(*PSDREOTF == 2 && m_renderData.surface->m_colorManagement.valid() &&
|
||||||
|
imageDescription.transferFunction == NColorManagement::eTransferFunction::CM_TRANSFER_FUNCTION_SRGB))) {
|
||||||
|
shader.setUniformInt(SHADER_SOURCE_TF, NColorManagement::eTransferFunction::CM_TRANSFER_FUNCTION_GAMMA22);
|
||||||
|
} else
|
||||||
|
shader.setUniformInt(SHADER_SOURCE_TF, imageDescription.transferFunction);
|
||||||
|
|
||||||
shader.setUniformInt(SHADER_TARGET_TF, targetImageDescription.transferFunction);
|
shader.setUniformInt(SHADER_TARGET_TF, targetImageDescription.transferFunction);
|
||||||
|
|
||||||
const auto targetPrimaries = targetImageDescription.primariesNameSet || targetImageDescription.primaries == SPCPRimaries{} ?
|
const auto targetPrimaries = targetImageDescription.primariesNameSet || targetImageDescription.primaries == SPCPRimaries{} ?
|
||||||
|
|
|
||||||
|
|
@ -1555,9 +1555,10 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
|
||||||
if (*PAUTOHDR && !(pMonitor->inHDR() && configuredHDR)) {
|
if (*PAUTOHDR && !(pMonitor->inHDR() && configuredHDR)) {
|
||||||
// modify or restore monitor image description for auto-hdr
|
// modify or restore monitor image description for auto-hdr
|
||||||
// FIXME ok for now, will need some other logic if monitor image description can be modified some other way
|
// FIXME ok for now, will need some other logic if monitor image description can be modified some other way
|
||||||
const auto targetCM = wantHDR ? (*PAUTOHDR == 2 ? NCMType::CM_HDR_EDID : NCMType::CM_HDR) : pMonitor->m_cmType;
|
const auto targetCM = wantHDR ? (*PAUTOHDR == 2 ? NCMType::CM_HDR_EDID : NCMType::CM_HDR) : pMonitor->m_cmType;
|
||||||
|
const auto targetSDREOTF = pMonitor->m_sdrEotf;
|
||||||
Debug::log(INFO, "[CM] Auto HDR: changing monitor cm to {}", sc<uint8_t>(targetCM));
|
Debug::log(INFO, "[CM] Auto HDR: changing monitor cm to {}", sc<uint8_t>(targetCM));
|
||||||
pMonitor->applyCMType(targetCM);
|
pMonitor->applyCMType(targetCM, targetSDREOTF);
|
||||||
pMonitor->m_previousFSWindow.reset(); // trigger CTM update
|
pMonitor->m_previousFSWindow.reset(); // trigger CTM update
|
||||||
}
|
}
|
||||||
Debug::log(INFO, wantHDR ? "[CM] Updating HDR metadata from monitor" : "[CM] Restoring SDR mode");
|
Debug::log(INFO, wantHDR ? "[CM] Updating HDR metadata from monitor" : "[CM] Restoring SDR mode");
|
||||||
|
|
|
||||||
|
|
@ -416,7 +416,7 @@ vec4 doColorManagement(vec4 pixColor, int srcTF, int dstTF, mat4x2 dstPrimaries)
|
||||||
mat3 dstxyz = primaries2xyz(dstPrimaries);
|
mat3 dstxyz = primaries2xyz(dstPrimaries);
|
||||||
pixColor = tonemap(pixColor, dstxyz);
|
pixColor = tonemap(pixColor, dstxyz);
|
||||||
pixColor = fromLinearNit(pixColor, dstTF, dstTFRange);
|
pixColor = fromLinearNit(pixColor, dstTF, dstTFRange);
|
||||||
if (srcTF == CM_TRANSFER_FUNCTION_SRGB && dstTF == CM_TRANSFER_FUNCTION_ST2084_PQ) {
|
if ((srcTF == CM_TRANSFER_FUNCTION_SRGB || srcTF == CM_TRANSFER_FUNCTION_GAMMA22) && dstTF == CM_TRANSFER_FUNCTION_ST2084_PQ) {
|
||||||
pixColor = saturate(pixColor, dstxyz, sdrSaturation);
|
pixColor = saturate(pixColor, dstxyz, sdrSaturation);
|
||||||
pixColor.rgb *= sdrBrightnessMultiplier;
|
pixColor.rgb *= sdrBrightnessMultiplier;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue