Skip to content

Commit e52ee50

Browse files
committed
renderer/cm: allow gamma 2.2 instead of sRGB EOTF
1 parent da04afa commit e52ee50

File tree

7 files changed

+52
-15
lines changed

7 files changed

+52
-15
lines changed

src/config/ConfigDescriptions.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,13 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
15421542
.type = CONFIG_OPTION_CHOICE,
15431543
.data = SConfigOptionDescription::SChoiceData{0, "disable,always,ondemand,ignore"},
15441544
},
1545+
SConfigOptionDescription{
1546+
.value = "render:cm_sdr_eotf",
1547+
.description = "Default transfer function for displaying SDR apps. 0 - Treat unspecified as sRGB, 1 - Treat unspecified as Gamma 2.2, 2 - Treat "
1548+
"unspecified and sRGB as Gamma 2.2",
1549+
.type = CONFIG_OPTION_CHOICE,
1550+
.data = SConfigOptionDescription::SChoiceData{0, "srgb,gamma22,gamma22force"},
1551+
},
15451552

15461553
/*
15471554
* cursor:

src/config/ConfigManager.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,7 @@ CConfigManager::CConfigManager() {
781781
registerConfigVar("render:cm_auto_hdr", Hyprlang::INT{1});
782782
registerConfigVar("render:new_render_scheduling", Hyprlang::INT{0});
783783
registerConfigVar("render:non_shader_cm", Hyprlang::INT{2});
784+
registerConfigVar("render:cm_sdr_eotf", Hyprlang::INT{0});
784785

785786
registerConfigVar("ecosystem:no_update_news", Hyprlang::INT{0});
786787
registerConfigVar("ecosystem:no_donation_nag", Hyprlang::INT{0});
@@ -842,6 +843,7 @@ CConfigManager::CConfigManager() {
842843
m_config->addSpecialConfigValue("monitorv2", "mirror", {STRVAL_EMPTY});
843844
m_config->addSpecialConfigValue("monitorv2", "bitdepth", {STRVAL_EMPTY}); // TODO use correct type
844845
m_config->addSpecialConfigValue("monitorv2", "cm", {"auto"});
846+
m_config->addSpecialConfigValue("monitorv2", "sdr_eotf", Hyprlang::INT{0});
845847
m_config->addSpecialConfigValue("monitorv2", "sdrbrightness", Hyprlang::FLOAT{1.0});
846848
m_config->addSpecialConfigValue("monitorv2", "sdrsaturation", Hyprlang::FLOAT{1.0});
847849
m_config->addSpecialConfigValue("monitorv2", "vrr", Hyprlang::INT{0});
@@ -1115,6 +1117,9 @@ std::optional<std::string> CConfigManager::handleMonitorv2(const std::string& ou
11151117
VAL = m_config->getSpecialConfigValuePtr("monitorv2", "cm", output.c_str());
11161118
if (VAL && VAL->m_bSetByUser)
11171119
parser.parseCM(std::any_cast<Hyprlang::STRING>(VAL->getValue()));
1120+
VAL = m_config->getSpecialConfigValuePtr("monitorv2", "sdr_eotf", output.c_str());
1121+
if (VAL && VAL->m_bSetByUser)
1122+
parser.rule().sdrEotf = std::any_cast<Hyprlang::INT>(VAL->getValue());
11181123
VAL = m_config->getSpecialConfigValuePtr("monitorv2", "sdrbrightness", output.c_str());
11191124
if (VAL && VAL->m_bSetByUser)
11201125
parser.rule().sdrBrightness = std::any_cast<Hyprlang::FLOAT>(VAL->getValue());

src/helpers/Monitor.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -465,32 +465,41 @@ void CMonitor::onDisconnect(bool destroy) {
465465
std::erase_if(g_pCompositor->m_monitors, [&](PHLMONITOR& el) { return el.get() == this; });
466466
}
467467

468-
void CMonitor::applyCMType(NCMType::eCMType cmType) {
469-
auto oldImageDescription = m_imageDescription;
468+
void CMonitor::applyCMType(NCMType::eCMType cmType, int cmSdrEotf) {
469+
auto oldImageDescription = m_imageDescription;
470+
static auto PSDREOTF = CConfigValue<Hyprlang::INT>("render:cm_sdr_eotf");
471+
auto chosenSdrEotf = cmSdrEotf == 0 ? (*PSDREOTF > 0 ? NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22 : NColorManagement::CM_TRANSFER_FUNCTION_SRGB) :
472+
(cmSdrEotf == 1 ? NColorManagement::CM_TRANSFER_FUNCTION_SRGB : NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22);
473+
470474
switch (cmType) {
471-
case NCMType::CM_SRGB: m_imageDescription = {}; break; // assumes SImageDescirption defaults to sRGB
475+
case NCMType::CM_SRGB: m_imageDescription = {.transferFunction = chosenSdrEotf}; break; // assumes SImageDescription defaults to sRGB
472476
case NCMType::CM_WIDE:
473-
m_imageDescription = {.primariesNameSet = true,
477+
m_imageDescription = {.transferFunction = chosenSdrEotf,
478+
.primariesNameSet = true,
474479
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
475480
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020)};
476481
break;
477482
case NCMType::CM_DCIP3:
478-
m_imageDescription = {.primariesNameSet = true,
483+
m_imageDescription = {.transferFunction = chosenSdrEotf,
484+
.primariesNameSet = true,
479485
.primariesNamed = NColorManagement::CM_PRIMARIES_DCI_P3,
480486
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_DCI_P3)};
481487
break;
482488
case NCMType::CM_DP3:
483-
m_imageDescription = {.primariesNameSet = true,
489+
m_imageDescription = {.transferFunction = chosenSdrEotf,
490+
.primariesNameSet = true,
484491
.primariesNamed = NColorManagement::CM_PRIMARIES_DISPLAY_P3,
485492
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_DISPLAY_P3)};
486493
break;
487494
case NCMType::CM_ADOBE:
488-
m_imageDescription = {.primariesNameSet = true,
495+
m_imageDescription = {.transferFunction = chosenSdrEotf,
496+
.primariesNameSet = true,
489497
.primariesNamed = NColorManagement::CM_PRIMARIES_ADOBE_RGB,
490498
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_ADOBE_RGB)};
491499
break;
492500
case NCMType::CM_EDID:
493-
m_imageDescription = {.primariesNameSet = false,
501+
m_imageDescription = {.transferFunction = chosenSdrEotf,
502+
.primariesNameSet = true,
494503
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
495504
.primaries = {
496505
.red = {.x = m_output->parsedEDID.chromaticityCoords->red.x, .y = m_output->parsedEDID.chromaticityCoords->red.y},
@@ -868,14 +877,16 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) {
868877
default: break;
869878
}
870879

880+
m_sdrEotf = RULE->sdrEotf;
881+
871882
m_sdrMinLuminance = RULE->sdrMinLuminance;
872883
m_sdrMaxLuminance = RULE->sdrMaxLuminance;
873884

874885
m_minLuminance = RULE->minLuminance;
875886
m_maxLuminance = RULE->maxLuminance;
876887
m_maxAvgLuminance = RULE->maxAvgLuminance;
877888

878-
applyCMType(m_cmType);
889+
applyCMType(m_cmType, m_sdrEotf);
879890

880891
m_sdrSaturation = RULE->sdrSaturation;
881892
m_sdrBrightness = RULE->sdrBrightness;

src/helpers/Monitor.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct SMonitorRule {
4848
std::string mirrorOf = "";
4949
bool enable10bit = false;
5050
NCMType::eCMType cmType = NCMType::CM_SRGB;
51+
int sdrEotf = 0;
5152
float sdrSaturation = 1.0f; // SDR -> HDR
5253
float sdrBrightness = 1.0f; // SDR -> HDR
5354

@@ -131,6 +132,7 @@ class CMonitor {
131132
bool m_vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
132133
bool m_enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
133134
NCMType::eCMType m_cmType = NCMType::CM_SRGB;
135+
int m_sdrEotf = 0;
134136
float m_sdrSaturation = 1.0f;
135137
float m_sdrBrightness = 1.0f;
136138
float m_sdrMinLuminance = 0.2f;
@@ -272,7 +274,7 @@ class CMonitor {
272274
// methods
273275
void onConnect(bool noRule);
274276
void onDisconnect(bool destroy = false);
275-
void applyCMType(NCMType::eCMType cmType);
277+
void applyCMType(NCMType::eCMType cmType, int cmSdrEotf);
276278
bool applyMonitorRule(SMonitorRule* pMonitorRule, bool force = false);
277279
void addDamage(const pixman_region32_t* rg);
278280
void addDamage(const CRegion& rg);

src/render/OpenGL.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,14 +1552,25 @@ static std::map<std::pair<uint32_t, uint32_t>, std::array<GLfloat, 9>> primaries
15521552

15531553
static bool isSDR2HDR(const NColorManagement::SImageDescription& imageDescription, const NColorManagement::SImageDescription& targetImageDescription) {
15541554
// might be too strict
1555-
return imageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_SRGB &&
1555+
return (imageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_SRGB ||
1556+
imageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22) &&
15561557
(targetImageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ||
15571558
targetImageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_HLG);
15581559
}
15591560

15601561
void CHyprOpenGLImpl::passCMUniforms(SShader& shader, const NColorManagement::SImageDescription& imageDescription,
15611562
const NColorManagement::SImageDescription& targetImageDescription, bool modifySDR, float sdrMinLuminance, int sdrMaxLuminance) {
1562-
shader.setUniformInt(SHADER_SOURCE_TF, imageDescription.transferFunction);
1563+
static auto PSDREOTF = CConfigValue<Hyprlang::INT>("render:cm_sdr_eotf");
1564+
1565+
if (m_renderData.surface.valid() &&
1566+
((!m_renderData.surface->m_colorManagement.valid() && *PSDREOTF >= 1) ||
1567+
(*PSDREOTF == 2 && m_renderData.surface->m_colorManagement.valid() &&
1568+
imageDescription.transferFunction == NColorManagement::eTransferFunction::CM_TRANSFER_FUNCTION_SRGB))) {
1569+
shader.setUniformInt(SHADER_SOURCE_TF, NColorManagement::eTransferFunction::CM_TRANSFER_FUNCTION_GAMMA22);
1570+
} else {
1571+
shader.setUniformInt(SHADER_SOURCE_TF, imageDescription.transferFunction);
1572+
}
1573+
15631574
shader.setUniformInt(SHADER_TARGET_TF, targetImageDescription.transferFunction);
15641575

15651576
const auto targetPrimaries = targetImageDescription.primariesNameSet || targetImageDescription.primaries == SPCPRimaries{} ?

src/render/Renderer.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,9 +1555,10 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
15551555
if (*PAUTOHDR && !(pMonitor->inHDR() && configuredHDR)) {
15561556
// modify or restore monitor image description for auto-hdr
15571557
// FIXME ok for now, will need some other logic if monitor image description can be modified some other way
1558-
const auto targetCM = wantHDR ? (*PAUTOHDR == 2 ? NCMType::CM_HDR_EDID : NCMType::CM_HDR) : pMonitor->m_cmType;
1558+
const auto targetCM = wantHDR ? (*PAUTOHDR == 2 ? NCMType::CM_HDR_EDID : NCMType::CM_HDR) : pMonitor->m_cmType;
1559+
const auto targetSDREOTF = pMonitor->m_sdrEotf;
15591560
Debug::log(INFO, "[CM] Auto HDR: changing monitor cm to {}", sc<uint8_t>(targetCM));
1560-
pMonitor->applyCMType(targetCM);
1561+
pMonitor->applyCMType(targetCM, targetSDREOTF);
15611562
pMonitor->m_previousFSWindow.reset(); // trigger CTM update
15621563
}
15631564
Debug::log(INFO, wantHDR ? "[CM] Updating HDR metadata from monitor" : "[CM] Restoring SDR mode");

src/render/shaders/glsl/CM.glsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ vec4 doColorManagement(vec4 pixColor, int srcTF, int dstTF, mat4x2 dstPrimaries)
416416
mat3 dstxyz = primaries2xyz(dstPrimaries);
417417
pixColor = tonemap(pixColor, dstxyz);
418418
pixColor = fromLinearNit(pixColor, dstTF, dstTFRange);
419-
if (srcTF == CM_TRANSFER_FUNCTION_SRGB && dstTF == CM_TRANSFER_FUNCTION_ST2084_PQ) {
419+
if ((srcTF == CM_TRANSFER_FUNCTION_SRGB || srcTF == CM_TRANSFER_FUNCTION_GAMMA22) && dstTF == CM_TRANSFER_FUNCTION_ST2084_PQ) {
420420
pixColor = saturate(pixColor, dstxyz, sdrSaturation);
421421
pixColor.rgb *= sdrBrightnessMultiplier;
422422
}

0 commit comments

Comments
 (0)