mirror of
https://github.com/hyprwm/Hyprland
synced 2026-05-07 18:38:00 +02:00
use a better work space, not linear, only for sdr
This commit is contained in:
parent
158f580983
commit
19175706eb
13 changed files with 77 additions and 98 deletions
|
|
@ -2549,9 +2549,29 @@ bool CMonitor::useFP16() {
|
|||
return shouldUse;
|
||||
}
|
||||
|
||||
PImageDescription CMonitor::workBufferImageDescription() {
|
||||
if (!useFP16())
|
||||
return m_imageDescription;
|
||||
|
||||
const auto& value = m_imageDescription->value();
|
||||
|
||||
const bool isHDRLikeTF =
|
||||
value.transferFunction == CM_TRANSFER_FUNCTION_ST2084_PQ || value.transferFunction == CM_TRANSFER_FUNCTION_HLG || value.transferFunction == CM_TRANSFER_FUNCTION_EXT_LINEAR;
|
||||
|
||||
if (isHDRLikeTF || value.windowsScRGB)
|
||||
return LINEAR_IMAGE_DESCRIPTION;
|
||||
|
||||
return CImageDescription::from(SImageDescription{
|
||||
.transferFunction = chooseTF(m_sdrEotf),
|
||||
.primariesNameSet = true,
|
||||
.primariesNamed = NColorManagement::CM_PRIMARIES_BT2020,
|
||||
.primaries = NColorPrimaries::BT2020,
|
||||
});
|
||||
}
|
||||
|
||||
WP<CMonitorResources> CMonitor::resources() {
|
||||
const auto DRM_FORMAT = useFP16() ? DRM_FORMAT_ABGR16161616F : m_output->state->state().drmFormat;
|
||||
const auto DESC = useFP16() ? LINEAR_IMAGE_DESCRIPTION : m_imageDescription;
|
||||
const auto DESC = workBufferImageDescription();
|
||||
|
||||
if (!m_resources || m_resources->m_drmFormat != DRM_FORMAT || m_resources->m_size != m_pixelSize)
|
||||
m_resources = makeUnique<CMonitorResources>(m_self, DRM_FORMAT, m_pixelSize, DESC);
|
||||
|
|
|
|||
|
|
@ -393,10 +393,11 @@ class CMonitor {
|
|||
return m_position == rhs.m_position && m_size == rhs.m_size && m_name == rhs.m_name;
|
||||
}
|
||||
|
||||
bool needsACopyFB();
|
||||
bool needsUnmodifiedCopy();
|
||||
bool useFP16();
|
||||
WP<Monitor::CMonitorResources> resources();
|
||||
bool needsACopyFB();
|
||||
bool needsUnmodifiedCopy();
|
||||
bool useFP16();
|
||||
NColorManagement::PImageDescription workBufferImageDescription();
|
||||
WP<Monitor::CMonitorResources> resources();
|
||||
|
||||
private:
|
||||
void updateMatrix();
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ void CMonitorResources::setImageDescription(NColorManagement::PImageDescription
|
|||
for (const auto& res : m_workBuffers)
|
||||
res.buffer->setImageDescription(imageDescription);
|
||||
if (m_monitorMirrorFB)
|
||||
m_monitorMirrorFB->setImageDescription(NColorManagement::getDefaultImageDescription());
|
||||
m_monitorMirrorFB->setImageDescription(getMirrorTexImageDescription());
|
||||
if (m_mirrorTex)
|
||||
m_mirrorTex->m_imageDescription = getMirrorTexImageDescription();
|
||||
}
|
||||
|
|
@ -78,8 +78,8 @@ SP<Render::IFramebuffer> CMonitorResources::mirrorFB() {
|
|||
m_monitorMirrorFB = g_pHyprRenderer->createFB(std::format("Monitor {} mirror FB", m_monitor->m_name));
|
||||
|
||||
if (!m_monitorMirrorFB->isAllocated()) {
|
||||
m_monitorMirrorFB->alloc(m_size.x, m_size.y, DRM_FORMAT_XRGB8888);
|
||||
m_monitorMirrorFB->setImageDescription(NColorManagement::getDefaultImageDescription());
|
||||
m_monitorMirrorFB->alloc(m_size.x, m_size.y, m_monitor->m_activeMonitorRule.m_enable10bit ? DRM_FORMAT_XRGB2101010 : DRM_FORMAT_XRGB8888);
|
||||
m_monitorMirrorFB->setImageDescription(getMirrorTexImageDescription());
|
||||
}
|
||||
|
||||
return m_monitorMirrorFB;
|
||||
|
|
@ -90,20 +90,16 @@ SP<Render::ITexture> CMonitorResources::getMirrorTexture() {
|
|||
}
|
||||
|
||||
NColorManagement::PImageDescription CMonitorResources::getMirrorTexImageDescription() {
|
||||
return CImageDescription::from(SImageDescription{
|
||||
.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_SRGB,
|
||||
.primariesNameSet = m_imageDescription->value().primariesNameSet,
|
||||
.primariesNamed = m_imageDescription->value().primariesNamed,
|
||||
.primaries = m_imageDescription->value().primaries,
|
||||
.luminances = {.min = SDR_MIN_LUMINANCE, .max = 80, .reference = 80},
|
||||
});
|
||||
if (!m_monitor)
|
||||
return DEFAULT_SRGB_IMAGE_DESCRIPTION;
|
||||
return m_monitor->workBufferImageDescription();
|
||||
}
|
||||
|
||||
void CMonitorResources::enableMirror() {
|
||||
if (m_mirrorTex)
|
||||
return;
|
||||
m_mirrorTex = g_pHyprRenderer->createTexture();
|
||||
m_mirrorTex->allocate({m_size.x, m_size.y}, DRM_FORMAT_XRGB8888);
|
||||
m_mirrorTex->allocate({m_size.x, m_size.y}, m_monitor->m_activeMonitorRule.m_enable10bit ? DRM_FORMAT_XRGB2101010 : DRM_FORMAT_XRGB8888);
|
||||
m_mirrorTex->m_imageDescription = getMirrorTexImageDescription();
|
||||
m_monitor->m_blurFBDirty = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,11 +196,10 @@ void CScreenshareFrame::renderMonitor() {
|
|||
g_pHyprRenderer->startRenderPass();
|
||||
g_pHyprRenderer->draw(
|
||||
CTexPassElement::SRenderData{
|
||||
.tex = TEXTURE,
|
||||
.box = monbox,
|
||||
.flipEndFrame = true,
|
||||
.cmBackToSRGB = !IS_CM_AWARE,
|
||||
.cmBackToSRGBSource = !IS_CM_AWARE ? PMONITOR : nullptr,
|
||||
.tex = TEXTURE,
|
||||
.box = monbox,
|
||||
.flipEndFrame = true,
|
||||
.cmBackToSRGB = !IS_CM_AWARE,
|
||||
},
|
||||
{0, 0, PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y});
|
||||
g_pHyprRenderer->m_renderData.renderModif.enabled = OLD;
|
||||
|
|
|
|||
|
|
@ -1298,7 +1298,7 @@ WP<CShader> CHyprOpenGLImpl::renderToFBInternal(SP<ITexture> tex, const STexture
|
|||
shaderFeatures &= ~SH_FEAT_RGBA;
|
||||
|
||||
const auto surface = g_pHyprRenderer->m_renderData.surface;
|
||||
const auto WORK_BUFFER_IMAGE_DESCRIPTION = g_pHyprRenderer->workBufferImageDescription();
|
||||
const auto WORK_BUFFER_IMAGE_DESCRIPTION = g_pHyprRenderer->m_renderData.pMonitor->workBufferImageDescription();
|
||||
|
||||
// chosenSdrEotf contains the valid eotf for this display
|
||||
|
||||
|
|
@ -1311,7 +1311,7 @@ WP<CShader> CHyprOpenGLImpl::renderToFBInternal(SP<ITexture> tex, const STexture
|
|||
return CImageDescription::from(surface->m_colorManagement->imageDescription());
|
||||
|
||||
if (data.cmBackToSRGB)
|
||||
return g_pHyprRenderer->m_renderData.pMonitor->m_imageDescription;
|
||||
return tex->m_imageDescription ? tex->m_imageDescription : WORK_BUFFER_IMAGE_DESCRIPTION;
|
||||
|
||||
// otherwise, if we are CM'ing back into source, use chosen, because that's what our work buffer is in
|
||||
// the same applies to the final monitor CM
|
||||
|
|
@ -1349,14 +1349,6 @@ WP<CShader> CHyprOpenGLImpl::renderToFBInternal(SP<ITexture> tex, const STexture
|
|||
|| !SOURCE_IMAGE_DESCRIPTION->needsCM(TARGET_IMAGE_DESCRIPTION) /* Source and target have matching image descriptions */
|
||||
;
|
||||
|
||||
const auto sourceTF = SOURCE_IMAGE_DESCRIPTION->value().transferFunction;
|
||||
const bool sourceIsUnmanagedSDRSurface = surface.valid() && !surface->m_colorManagement.valid() &&
|
||||
(sourceTF == CM_TRANSFER_FUNCTION_SRGB || sourceTF == CM_TRANSFER_FUNCTION_GAMMA22 || sourceTF == CM_TRANSFER_FUNCTION_EXT_SRGB || sourceTF == CM_TRANSFER_FUNCTION_BT1886);
|
||||
const bool targetIsLinearWorkBuffer = TARGET_IMAGE_DESCRIPTION->value().transferFunction == CM_TRANSFER_FUNCTION_EXT_LINEAR;
|
||||
|
||||
if (!skipCM && !data.finalMonitorCM && !data.cmBackToSRGB && sourceIsUnmanagedSDRSurface && targetIsLinearWorkBuffer)
|
||||
shaderFeatures |= SH_FEAT_SDR_PREMUL_COMPAT;
|
||||
|
||||
if (g_pHyprRenderer->m_renderData.pMonitor->needsACopyFB())
|
||||
Log::logger->log(Log::TRACE, "CM: render to FB skip={} {} -> {}", skipCM, SOURCE_IMAGE_DESCRIPTION->value(), TARGET_IMAGE_DESCRIPTION->value());
|
||||
|
||||
|
|
@ -2395,7 +2387,8 @@ void CHyprOpenGLImpl::saveBufferForMirror(const CBox& box) {
|
|||
Log::logger->log(Log::ERR, "Invalid source texture for mirror");
|
||||
return;
|
||||
}
|
||||
auto guard = g_pHyprRenderer->bindTempFB(g_pHyprRenderer->m_renderData.pMonitor->resources()->mirrorFB());
|
||||
auto fb = g_pHyprRenderer->m_renderData.pMonitor->resources()->mirrorFB();
|
||||
auto guard = g_pHyprRenderer->bindTempFB(fb);
|
||||
|
||||
Log::logger->log(Log::TRACE, "CM: saveBufferForMirror {} -> {}", TEX->m_imageDescription->value(), g_pHyprRenderer->m_renderData.currentFB->imageDescription()->value());
|
||||
|
||||
|
|
@ -2408,7 +2401,6 @@ void CHyprOpenGLImpl::saveBufferForMirror(const CBox& box) {
|
|||
.round = 0,
|
||||
.discardActive = false,
|
||||
.allowCustomUV = false,
|
||||
.cmBackToSRGB = true,
|
||||
});
|
||||
|
||||
blend(true);
|
||||
|
|
|
|||
|
|
@ -174,7 +174,6 @@ namespace Render::GL {
|
|||
GLenum wrapX = GL_CLAMP_TO_EDGE, wrapY = GL_CLAMP_TO_EDGE;
|
||||
bool cmBackToSRGB = false;
|
||||
bool finalMonitorCM = false;
|
||||
SP<CMonitor> cmBackToSRGBSource;
|
||||
|
||||
uint32_t discardMode = DISCARD_OPAQUE;
|
||||
float discardOpacity = 0.f;
|
||||
|
|
|
|||
|
|
@ -3270,17 +3270,10 @@ void IHyprRenderer::renderSnapshot(WP<Desktop::View::CPopup> popup) {
|
|||
}
|
||||
|
||||
NColorManagement::PImageDescription IHyprRenderer::workBufferImageDescription() {
|
||||
// TODO
|
||||
// const bool IS_MONITOR_ICC = m_renderData.pMonitor->m_imageDescription.valid() && m_renderData.pMonitor->m_imageDescription->value().icc.present;
|
||||
// const auto sdrEOTF = NTransferFunction::fromConfig(IS_MONITOR_ICC);
|
||||
// const auto CHOSEN_SDR_EOTF = sdrEOTF != NTransferFunction::TF_SRGB ? NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22 : NColorManagement::CM_TRANSFER_FUNCTION_SRGB;
|
||||
|
||||
if (!m_renderData.pMonitor)
|
||||
return LINEAR_IMAGE_DESCRIPTION;
|
||||
|
||||
return m_renderData.pMonitor->useFP16() ?
|
||||
LINEAR_IMAGE_DESCRIPTION :
|
||||
m_renderData.pMonitor->m_imageDescription; //CImageDescription::from(NColorManagement::SImageDescription{.transferFunction = CHOSEN_SDR_EOTF});
|
||||
return m_renderData.pMonitor->workBufferImageDescription();
|
||||
}
|
||||
|
||||
bool IHyprRenderer::shouldBlur(PHLLS ls) {
|
||||
|
|
|
|||
|
|
@ -67,17 +67,10 @@ void CShaderLoader::include(const std::string& filename) {
|
|||
std::string CShaderLoader::getDefines(ShaderFeatureFlags features) {
|
||||
std::string res = "";
|
||||
std::map<std::string, std::string> defines = {
|
||||
{"USE_RGBA", features & SH_FEAT_RGBA ? "1" : "0"},
|
||||
{"USE_DISCARD", features & SH_FEAT_DISCARD ? "1" : "0"},
|
||||
{"USE_TINT", features & SH_FEAT_TINT ? "1" : "0"},
|
||||
{"USE_ROUNDING", features & SH_FEAT_ROUNDING ? "1" : "0"},
|
||||
{"USE_CM", features & SH_FEAT_CM ? "1" : "0"},
|
||||
{"USE_TONEMAP", features & SH_FEAT_TONEMAP ? "1" : "0"},
|
||||
{"USE_SDR_MOD", features & SH_FEAT_SDR_MOD ? "1" : "0"},
|
||||
{"USE_BLUR", features & SH_FEAT_BLUR ? "1" : "0"},
|
||||
{"USE_ICC", features & SH_FEAT_ICC ? "1" : "0"},
|
||||
{"USE_RGBA", features & SH_FEAT_RGBA ? "1" : "0"}, {"USE_DISCARD", features & SH_FEAT_DISCARD ? "1" : "0"}, {"USE_TINT", features & SH_FEAT_TINT ? "1" : "0"},
|
||||
{"USE_ROUNDING", features & SH_FEAT_ROUNDING ? "1" : "0"}, {"USE_CM", features & SH_FEAT_CM ? "1" : "0"}, {"USE_TONEMAP", features & SH_FEAT_TONEMAP ? "1" : "0"},
|
||||
{"USE_SDR_MOD", features & SH_FEAT_SDR_MOD ? "1" : "0"}, {"USE_BLUR", features & SH_FEAT_BLUR ? "1" : "0"}, {"USE_ICC", features & SH_FEAT_ICC ? "1" : "0"},
|
||||
{"USE_MIRROR", features & SH_FEAT_MIRROR ? "1" : "0"},
|
||||
{"USE_SDR_PREMUL_COMPAT", features & SH_FEAT_SDR_PREMUL_COMPAT ? "1" : "0"},
|
||||
};
|
||||
for (const auto& [name, value] : defines) {
|
||||
res += std::format("#define {} {}\n", name, value);
|
||||
|
|
|
|||
|
|
@ -11,17 +11,16 @@ namespace Render {
|
|||
enum ePreparedFragmentShaderFeature : uint16_t {
|
||||
SH_FEAT_UNKNOWN = 0, // all features just in case
|
||||
|
||||
SH_FEAT_RGBA = (1 << 0), // RGBA/RGBX texture sampling
|
||||
SH_FEAT_DISCARD = (1 << 1), // RGBA/RGBX texture sampling
|
||||
SH_FEAT_TINT = (1 << 2), // uniforms: tint; condition: applyTint
|
||||
SH_FEAT_ROUNDING = (1 << 3), // uniforms: radius, roundingPower, topLeft, fullSize; condition: radius > 0
|
||||
SH_FEAT_CM = (1 << 4), // uniforms: srcTFRange, dstTFRange, srcRefLuminance, convertMatrix; condition: !skipCM
|
||||
SH_FEAT_TONEMAP = (1 << 5), // uniforms: maxLuminance, dstMaxLuminance, dstRefLuminance; condition: maxLuminance < dstMaxLuminance * 1.01
|
||||
SH_FEAT_SDR_MOD = (1 << 6), // uniforms: sdrSaturation, sdrBrightnessMultiplier; condition: SDR <-> HDR && (sdrSaturation != 1 || sdrBrightnessMultiplier != 1)
|
||||
SH_FEAT_BLUR = (1 << 7), // condition: render:use_shader_blur_blend
|
||||
SH_FEAT_ICC = (1 << 8), //
|
||||
SH_FEAT_MIRROR = (1 << 9), // condition: mirror or screenshare
|
||||
SH_FEAT_SDR_PREMUL_COMPAT = (1 << 10), // condition: unmanaged SDR surfaces drawn into linear workbuffer
|
||||
SH_FEAT_RGBA = (1 << 0), // RGBA/RGBX texture sampling
|
||||
SH_FEAT_DISCARD = (1 << 1), // RGBA/RGBX texture sampling
|
||||
SH_FEAT_TINT = (1 << 2), // uniforms: tint; condition: applyTint
|
||||
SH_FEAT_ROUNDING = (1 << 3), // uniforms: radius, roundingPower, topLeft, fullSize; condition: radius > 0
|
||||
SH_FEAT_CM = (1 << 4), // uniforms: srcTFRange, dstTFRange, srcRefLuminance, convertMatrix; condition: !skipCM
|
||||
SH_FEAT_TONEMAP = (1 << 5), // uniforms: maxLuminance, dstMaxLuminance, dstRefLuminance; condition: maxLuminance < dstMaxLuminance * 1.01
|
||||
SH_FEAT_SDR_MOD = (1 << 6), // uniforms: sdrSaturation, sdrBrightnessMultiplier; condition: SDR <-> HDR && (sdrSaturation != 1 || sdrBrightnessMultiplier != 1)
|
||||
SH_FEAT_BLUR = (1 << 7), // condition: render:use_shader_blur_blend
|
||||
SH_FEAT_ICC = (1 << 8), //
|
||||
SH_FEAT_MIRROR = (1 << 9), // condition: mirror or screenshare
|
||||
|
||||
// uniforms: targetPrimariesXYZ; condition: SH_FEAT_TONEMAP || SH_FEAT_SDR_MOD
|
||||
};
|
||||
|
|
|
|||
|
|
@ -114,19 +114,18 @@ void CGLElementRenderer::draw(WP<CTexPassElement> element, const CRegion& damage
|
|||
.blurredBG = m_data.blurredBG,
|
||||
|
||||
// common settings
|
||||
.damage = m_data.damage.empty() ? &damage : &m_data.damage,
|
||||
.surface = m_data.surface,
|
||||
.a = m_data.a,
|
||||
.round = m_data.round,
|
||||
.roundingPower = m_data.roundingPower,
|
||||
.discardActive = m_data.discardActive,
|
||||
.allowCustomUV = m_data.allowCustomUV,
|
||||
.cmBackToSRGB = m_data.cmBackToSRGB,
|
||||
.cmBackToSRGBSource = m_data.cmBackToSRGBSource,
|
||||
.discardMode = m_data.ignoreAlpha.has_value() ? sc<uint32_t>(DISCARD_ALPHA) : m_data.discardMode,
|
||||
.discardOpacity = m_data.ignoreAlpha.has_value() ? *m_data.ignoreAlpha : m_data.discardOpacity,
|
||||
.clipRegion = m_data.clipRegion,
|
||||
.currentLS = m_data.currentLS,
|
||||
.damage = m_data.damage.empty() ? &damage : &m_data.damage,
|
||||
.surface = m_data.surface,
|
||||
.a = m_data.a,
|
||||
.round = m_data.round,
|
||||
.roundingPower = m_data.roundingPower,
|
||||
.discardActive = m_data.discardActive,
|
||||
.allowCustomUV = m_data.allowCustomUV,
|
||||
.cmBackToSRGB = m_data.cmBackToSRGB,
|
||||
.discardMode = m_data.ignoreAlpha.has_value() ? sc<uint32_t>(DISCARD_ALPHA) : m_data.discardMode,
|
||||
.discardOpacity = m_data.ignoreAlpha.has_value() ? *m_data.ignoreAlpha : m_data.discardOpacity,
|
||||
.clipRegion = m_data.clipRegion,
|
||||
.currentLS = m_data.currentLS,
|
||||
|
||||
.primarySurfaceUVTopLeft = g_pHyprRenderer->m_renderData.primarySurfaceUVTopLeft,
|
||||
.primarySurfaceUVBottomRight = g_pHyprRenderer->m_renderData.primarySurfaceUVBottomRight,
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ class CTexPassElement : public IPassElement {
|
|||
std::optional<float> ignoreAlpha;
|
||||
std::optional<bool> blockBlurOptimization;
|
||||
bool cmBackToSRGB = false;
|
||||
SP<CMonitor> cmBackToSRGBSource;
|
||||
|
||||
bool discardActive = false;
|
||||
bool allowCustomUV = false;
|
||||
|
|
|
|||
|
|
@ -224,25 +224,15 @@ vec4
|
|||
#endif
|
||||
#endif
|
||||
) {
|
||||
#if USE_SDR_PREMUL_COMPAT
|
||||
// Compatibility path for unmanaged SDR translucent surfaces rendered into a linear workbuffer.
|
||||
// Keep premultiplication during source TF decoding to avoid low-alpha hue/opacity drift.
|
||||
pixColor.rgb = toLinearRGB(pixColor.rgb, srcTF);
|
||||
#else
|
||||
pixColor.rgb /= max(pixColor.a, 0.001);
|
||||
pixColor.rgb = toLinearRGB(pixColor.rgb, srcTF);
|
||||
#endif
|
||||
#if USE_ICC
|
||||
pixColor.rgb = applyIcc3DLut(pixColor.rgb, iccLut3D, iccLutSize);
|
||||
pixColor.rgb *= pixColor.a;
|
||||
#else
|
||||
pixColor.rgb = convertMatrix * pixColor.rgb;
|
||||
#if USE_SDR_PREMUL_COMPAT
|
||||
pixColor.rgb = pixColor.rgb * (srcTFRange[1] - srcTFRange[0]) + srcTFRange[0] * pixColor.a;
|
||||
#else
|
||||
pixColor = toNit(pixColor, srcTFRange);
|
||||
pixColor.rgb *= pixColor.a;
|
||||
#endif
|
||||
#if USE_TONEMAP
|
||||
pixColor = tonemap(pixColor, dstxyz, maxLuminance, dstMaxLuminance, dstRefLuminance, srcRefLuminance);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,14 +2,13 @@
|
|||
// Values here are only for highlighting and static checking
|
||||
// 1 assumes that a shader either supports this feature or doesn't use any code supporting it
|
||||
// 0 assumes that shader uses some code supporting the feature but will never have this feature enabled
|
||||
#define USE_RGBA 1
|
||||
#define USE_DISCARD 1
|
||||
#define USE_TINT 1
|
||||
#define USE_ROUNDING 1
|
||||
#define USE_CM 1
|
||||
#define USE_TONEMAP 1
|
||||
#define USE_SDR_MOD 1
|
||||
#define USE_BLUR 1
|
||||
#define USE_ICC 0
|
||||
#define USE_MIRROR 0
|
||||
#define USE_SDR_PREMUL_COMPAT 1
|
||||
#define USE_RGBA 1
|
||||
#define USE_DISCARD 1
|
||||
#define USE_TINT 1
|
||||
#define USE_ROUNDING 1
|
||||
#define USE_CM 1
|
||||
#define USE_TONEMAP 1
|
||||
#define USE_SDR_MOD 1
|
||||
#define USE_BLUR 1
|
||||
#define USE_ICC 0
|
||||
#define USE_MIRROR 0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue