Skip to content

Commit a545cac

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

File tree

7 files changed

+49
-14
lines changed

7 files changed

+49
-14
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_srgb_eotf",
1547+
.description = "Default transfer function for displaying sRGB apps in HDR 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_srgb_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", "cm_srgb_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", "cm_srgb_eotf", output.c_str());
1121+
if (VAL && VAL->m_bSetByUser)
1122+
parser.rule().cmSrgbEotf = 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: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -465,32 +465,39 @@ 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) {
468+
void CMonitor::applyCMType(NCMType::eCMType cmType, int cmSrgbEotf) {
469469
auto oldImageDescription = m_imageDescription;
470470
switch (cmType) {
471-
case NCMType::CM_SRGB: m_imageDescription = {}; break; // assumes SImageDescirption defaults to sRGB
471+
case NCMType::CM_SRGB:
472+
m_imageDescription = {.transferFunction = cmSrgbEotf == 0 ? NColorManagement::CM_TRANSFER_FUNCTION_SRGB : NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22};
473+
break; // assumes SImageDescription defaults to sRGB
472474
case NCMType::CM_WIDE:
473-
m_imageDescription = {.primariesNameSet = true,
475+
m_imageDescription = {.transferFunction = cmSrgbEotf == 0 ? NColorManagement::CM_TRANSFER_FUNCTION_SRGB : NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22,
476+
.primariesNameSet = true,
474477
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
475478
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020)};
476479
break;
477480
case NCMType::CM_DCIP3:
478-
m_imageDescription = {.primariesNameSet = true,
481+
m_imageDescription = {.transferFunction = cmSrgbEotf == 0 ? NColorManagement::CM_TRANSFER_FUNCTION_SRGB : NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22,
482+
.primariesNameSet = true,
479483
.primariesNamed = NColorManagement::CM_PRIMARIES_DCI_P3,
480484
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_DCI_P3)};
481485
break;
482486
case NCMType::CM_DP3:
483-
m_imageDescription = {.primariesNameSet = true,
487+
m_imageDescription = {.transferFunction = cmSrgbEotf == 0 ? NColorManagement::CM_TRANSFER_FUNCTION_SRGB : NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22,
488+
.primariesNameSet = true,
484489
.primariesNamed = NColorManagement::CM_PRIMARIES_DISPLAY_P3,
485490
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_DISPLAY_P3)};
486491
break;
487492
case NCMType::CM_ADOBE:
488-
m_imageDescription = {.primariesNameSet = true,
493+
m_imageDescription = {.transferFunction = cmSrgbEotf == 0 ? NColorManagement::CM_TRANSFER_FUNCTION_SRGB : NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22,
494+
.primariesNameSet = true,
489495
.primariesNamed = NColorManagement::CM_PRIMARIES_ADOBE_RGB,
490496
.primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_ADOBE_RGB)};
491497
break;
492498
case NCMType::CM_EDID:
493-
m_imageDescription = {.primariesNameSet = false,
499+
m_imageDescription = {.transferFunction = cmSrgbEotf == 0 ? NColorManagement::CM_TRANSFER_FUNCTION_SRGB : NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22,
500+
.primariesNameSet = true,
494501
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
495502
.primaries = {
496503
.red = {.x = m_output->parsedEDID.chromaticityCoords->red.x, .y = m_output->parsedEDID.chromaticityCoords->red.y},
@@ -868,14 +875,16 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) {
868875
default: break;
869876
}
870877

878+
m_cmSrgbEotf = RULE->cmSrgbEotf;
879+
871880
m_sdrMinLuminance = RULE->sdrMinLuminance;
872881
m_sdrMaxLuminance = RULE->sdrMaxLuminance;
873882

874883
m_minLuminance = RULE->minLuminance;
875884
m_maxLuminance = RULE->maxLuminance;
876885
m_maxAvgLuminance = RULE->maxAvgLuminance;
877886

878-
applyCMType(m_cmType);
887+
applyCMType(m_cmType, m_cmSrgbEotf);
879888

880889
m_sdrSaturation = RULE->sdrSaturation;
881890
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 cmSrgbEotf = 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_cmSrgbEotf = 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 cmSrgbEotf);
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 PSRGBEOTF = CConfigValue<Hyprlang::INT>("render:cm_srgb_eotf");
1564+
1565+
if (m_renderData.surface.valid() &&
1566+
((!m_renderData.surface->m_colorManagement.valid() && *PSRGBEOTF >= 1) ||
1567+
(*PSRGBEOTF == 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 targetSRGBEOTF = pMonitor->m_cmSrgbEotf;
15591560
Debug::log(INFO, "[CM] Auto HDR: changing monitor cm to {}", sc<uint8_t>(targetCM));
1560-
pMonitor->applyCMType(targetCM);
1561+
pMonitor->applyCMType(targetCM, targetSRGBEOTF);
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)