summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
Diffstat (limited to 'src/render')
-rw-r--r--src/render/OpenGL.cpp50
-rw-r--r--src/render/OpenGL.hpp1
-rw-r--r--src/render/Renderer.cpp29
-rw-r--r--src/render/Shader.cpp1
-rw-r--r--src/render/Shader.hpp1
-rw-r--r--src/render/gl/GLElementRenderer.cpp25
-rw-r--r--src/render/gl/GLFramebuffer.cpp11
-rw-r--r--src/render/gl/GLFramebuffer.hpp6
-rw-r--r--src/render/pass/TexPassElement.hpp1
-rw-r--r--src/render/shaders/glsl/blur1.glsl8
-rw-r--r--src/render/shaders/glsl/blurFinish.glsl6
-rw-r--r--src/render/shaders/glsl/cm_helpers.glsl11
-rw-r--r--src/render/shaders/glsl/constants.h1
-rw-r--r--src/render/shaders/glsl/inner_glow.frag41
-rw-r--r--src/render/shaders/glsl/inner_glow.glsl55
-rw-r--r--src/render/shaders/glsl/quad.frag7
-rw-r--r--src/render/shaders/glsl/shadow.frag34
-rw-r--r--src/render/shaders/glsl/shadow.glsl58
-rw-r--r--src/render/shaders/glsl/tonemap.glsl25
19 files changed, 135 insertions, 236 deletions
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index 6bb04cfa..0a53442e 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -34,6 +34,7 @@
#include "../managers/screenshare/ScreenshareManager.hpp"
#include "../notification/NotificationOverlay.hpp"
#include "errorOverlay/Overlay.hpp"
+#include "helpers/Color.hpp"
#include "macros.hpp"
#include "pass/TexPassElement.hpp"
#include "pass/RectPassElement.hpp"
@@ -758,6 +759,7 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, SP<IFra
g_pHyprRenderer->bindFB(g_pHyprRenderer->m_renderData.pMonitor->resources()->getUnusedWorkBuffer());
m_offloadedFramebuffer = true;
+ GLFB(g_pHyprRenderer->m_renderData.currentFB)->clearAfterInvalidation();
g_pHyprRenderer->m_renderData.mainFB = g_pHyprRenderer->m_renderData.currentFB;
g_pHyprRenderer->m_renderData.outFB = fb ? fb : dc<CHyprGLRenderer*>(g_pHyprRenderer.get())->m_currentRenderbuffer->getFB();
@@ -1062,6 +1064,19 @@ void CHyprOpenGLImpl::renderRectWithBlurInternal(const CBox& box, const CHyprCol
renderRectWithDamageInternal(box, col, data);
}
+using ColorConversionKey = std::tuple<float, float, float, float, uint64_t>;
+static std::map<ColorConversionKey, CHyprColor> colorConversionCache;
+
+static CHyprColor getConvertedColor(const CHyprColor& color) {
+ const auto targetId = g_pHyprRenderer->workBufferImageDescription()->id();
+ const ColorConversionKey key = {color.r, color.g, color.b, color.a, targetId};
+ if (colorConversionCache.contains(key))
+ return colorConversionCache[key];
+ const auto converted = convertColor(color, DEFAULT_SRGB_IMAGE_DESCRIPTION, g_pHyprRenderer->workBufferImageDescription());
+ colorConversionCache[key] = converted;
+ return converted;
+}
+
void CHyprOpenGLImpl::renderRectWithDamageInternal(const CBox& box, const CHyprColor& col, const SRectRenderData& data) {
auto& m_renderData = g_pHyprRenderer->m_renderData;
RASSERT((box.width > 0 && box.height > 0), "Tried to render rect with width/height < 0!");
@@ -1078,7 +1093,10 @@ void CHyprOpenGLImpl::renderRectWithDamageInternal(const CBox& box, const CHyprC
shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix());
// premultiply the color as well as we don't work with straight alpha
- shader->setUniformFloat4(SHADER_COLOR, col.r * col.a, col.g * col.a, col.b * col.a, col.a);
+ const auto premultiplied = CHyprColor(col.r * col.a, col.g * col.a, col.b * col.a, col.a);
+ const auto converted = getConvertedColor(premultiplied);
+ shader->setUniformFloat4(SHADER_COLOR, converted.r, converted.g, converted.b, converted.a);
+ shader->setUniformFloat4(SHADER_COLOR_SRGB, premultiplied.r, premultiplied.g, premultiplied.b, premultiplied.a);
CBox transformedBox = box;
transformedBox.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x,
@@ -1298,7 +1316,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 +1329,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
@@ -1660,6 +1678,7 @@ SP<IFramebuffer> CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* or
static auto PBLEND = CConfigValue<Config::INTEGER>("render:use_shader_blur_blend");
PMIRRORSWAPFB->bind();
+ GLFB(PMIRRORSWAPFB)->clearAfterInvalidation();
glActiveTexture(GL_TEXTURE0);
@@ -1754,6 +1773,7 @@ SP<IFramebuffer> CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* or
// draw the things.
// first draw is swap -> mirr
PMIRRORFB->bind();
+ GLFB(PMIRRORFB)->clearAfterInvalidation();
PMIRRORSWAPFB->getTexture()->bind();
// damage region will be scaled, make a temp
@@ -2240,14 +2260,12 @@ void CHyprOpenGLImpl::renderRoundedShadow(const CBox& box, int round, float roun
blend(true);
- const bool IS_ICC = g_pHyprRenderer->workBufferImageDescription()->value().icc.present;
- const bool skipCM = !m_cmSupported || !g_pHyprRenderer->workBufferImageDescription()->needsCM(getDefaultImageDescription());
- auto shader = useShader(getShaderVariant(SH_FRAG_SHADOW, skipCM ? 0 : SH_FEAT_CM | (IS_ICC ? SH_FEAT_ICC : SH_FEAT_TONEMAP | SH_FEAT_SDR_MOD) | globalFeatures()));
- if (!skipCM)
- passCMUniforms(shader, getDefaultImageDescription());
+ auto shader = useShader(getShaderVariant(SH_FRAG_SHADOW, globalFeatures()));
shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix());
- shader->setUniformFloat4(SHADER_COLOR, col.r, col.g, col.b, col.a * a);
+ const auto converted = getConvertedColor(col);
+ shader->setUniformFloat4(SHADER_COLOR, converted.r, converted.g, converted.b, converted.a * a);
+ shader->setUniformFloat4(SHADER_COLOR_SRGB, col.r, col.g, col.b, col.a * a);
const auto TOPLEFT = Vector2D(range + round, range + round);
const auto BOTTOMRIGHT = Vector2D(newBox.width - (range + round), newBox.height - (range + round));
@@ -2334,14 +2352,12 @@ void CHyprOpenGLImpl::renderInnerGlow(const CBox& box, int round, float rounding
blend(true);
- const bool IS_ICC = g_pHyprRenderer->workBufferImageDescription()->value().icc.present;
- const bool skipCM = !m_cmSupported || !g_pHyprRenderer->workBufferImageDescription()->needsCM(getDefaultImageDescription());
- auto shader = useShader(getShaderVariant(SH_FRAG_INNER_GLOW, skipCM ? 0 : SH_FEAT_CM | (IS_ICC ? SH_FEAT_ICC : SH_FEAT_TONEMAP | SH_FEAT_SDR_MOD)));
- if (!skipCM)
- passCMUniforms(shader, getDefaultImageDescription());
+ auto shader = useShader(getShaderVariant(SH_FRAG_INNER_GLOW, globalFeatures()));
shader->setUniformMatrix3fv(SHADER_PROJ, 1, GL_TRUE, glMatrix.getMatrix());
- shader->setUniformFloat4(SHADER_COLOR, col.r, col.g, col.b, col.a * a);
+ const auto converted = getConvertedColor(col);
+ shader->setUniformFloat4(SHADER_COLOR, converted.r, converted.g, converted.b, converted.a * a);
+ shader->setUniformFloat4(SHADER_COLOR_SRGB, col.r, col.g, col.b, col.a * a);
const auto TOPLEFT = Vector2D(round, round);
const auto BOTTOMRIGHT = Vector2D(newBox.width - round, newBox.height - round);
@@ -2385,7 +2401,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());
@@ -2398,7 +2415,6 @@ void CHyprOpenGLImpl::saveBufferForMirror(const CBox& box) {
.round = 0,
.discardActive = false,
.allowCustomUV = false,
- .cmBackToSRGB = true,
});
blend(true);
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index 82b8f054..2434c0ed 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -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;
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 635bef55..0cb713f1 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -2020,18 +2020,8 @@ void IHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) {
}
handleFullscreenSettings(pMonitor);
return;
- } else if (!pMonitor->m_lastScanout.expired() || pMonitor->m_directScanoutIsActive) {
- Log::logger->log(Log::DEBUG, "Left a direct scanout.");
- pMonitor->m_lastScanout.reset();
- pMonitor->m_previousFSWindow.reset(); // recalc fs settings
- pMonitor->m_directScanoutIsActive = false;
-
- // reset DRM format, but only if needed since it might modeset
- if (pMonitor->m_output->state->state().drmFormat != pMonitor->m_prevDrmFormat)
- pMonitor->m_output->state->setFormat(pMonitor->m_prevDrmFormat);
-
- pMonitor->m_drmFormat = pMonitor->m_prevDrmFormat;
- }
+ } else if (!pMonitor->m_lastScanout.expired() || pMonitor->m_directScanoutIsActive)
+ pMonitor->handleDSleave();
}
Event::bus()->m_events.render.pre.emit(pMonitor);
@@ -3049,6 +3039,7 @@ void IHyprRenderer::makeSnapshot(PHLWINDOW pWindow) {
const auto PFRAMEBUFFER = ref->m_snapshotFB;
PFRAMEBUFFER->alloc(PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, DRM_FORMAT_ABGR8888);
+ PFRAMEBUFFER->setImageDescription(workBufferImageDescription());
beginFullFakeRender(PMONITOR, fakeDamage, PFRAMEBUFFER);
@@ -3090,6 +3081,7 @@ void IHyprRenderer::makeSnapshot(PHLLS pLayer) {
const auto PFRAMEBUFFER = pLayer->m_snapshotFB;
PFRAMEBUFFER->alloc(PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, DRM_FORMAT_ABGR8888);
+ PFRAMEBUFFER->setImageDescription(workBufferImageDescription());
beginFullFakeRender(PMONITOR, fakeDamage, PFRAMEBUFFER);
@@ -3132,6 +3124,7 @@ void IHyprRenderer::makeSnapshot(WP<Desktop::View::CPopup> popup) {
const auto PFRAMEBUFFER = popup->m_snapshotFB;
PFRAMEBUFFER->alloc(PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, DRM_FORMAT_ABGR8888);
+ PFRAMEBUFFER->setImageDescription(workBufferImageDescription());
beginFullFakeRender(PMONITOR, fakeDamage, PFRAMEBUFFER);
@@ -3314,14 +3307,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;
-
- return m_renderData.pMonitor->useFP16() ?
- LINEAR_IMAGE_DESCRIPTION :
- m_renderData.pMonitor->m_imageDescription; //CImageDescription::from(NColorManagement::SImageDescription{.transferFunction = CHOSEN_SDR_EOTF});
+ if (!m_renderData.pMonitor)
+ return LINEAR_IMAGE_DESCRIPTION;
+
+ return m_renderData.pMonitor->workBufferImageDescription();
}
bool IHyprRenderer::shouldBlur(PHLLS ls) {
diff --git a/src/render/Shader.cpp b/src/render/Shader.cpp
index 3359de66..8a7b8ba9 100644
--- a/src/render/Shader.cpp
+++ b/src/render/Shader.cpp
@@ -126,6 +126,7 @@ void CShader::getUniformLocations() {
m_uniformLocations[SHADER_PROJ] = getUniform("proj");
m_uniformLocations[SHADER_COLOR] = getUniform("color");
+ m_uniformLocations[SHADER_COLOR_SRGB] = getUniform("colorSRGB");
m_uniformLocations[SHADER_ALPHA_MATTE] = getUniform("texMatte");
m_uniformLocations[SHADER_TEX_TYPE] = getUniform("texType");
diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp
index 84a4014c..cf15c805 100644
--- a/src/render/Shader.hpp
+++ b/src/render/Shader.hpp
@@ -7,6 +7,7 @@
enum eShaderUniform : uint8_t {
SHADER_PROJ = 0,
SHADER_COLOR,
+ SHADER_COLOR_SRGB,
SHADER_ALPHA_MATTE,
SHADER_TEX_TYPE,
SHADER_SOURCE_TF,
diff --git a/src/render/gl/GLElementRenderer.cpp b/src/render/gl/GLElementRenderer.cpp
index dbf62cb8..c20fffc0 100644
--- a/src/render/gl/GLElementRenderer.cpp
+++ b/src/render/gl/GLElementRenderer.cpp
@@ -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,
diff --git a/src/render/gl/GLFramebuffer.cpp b/src/render/gl/GLFramebuffer.cpp
index d8b198c3..196f3327 100644
--- a/src/render/gl/GLFramebuffer.cpp
+++ b/src/render/gl/GLFramebuffer.cpp
@@ -171,4 +171,15 @@ void CGLFramebuffer::invalidate(const std::vector<GLenum>& attachments) {
return;
glInvalidateFramebuffer(GL_FRAMEBUFFER, attachments.size(), attachments.data());
+ m_cleared = false;
+}
+
+void CGLFramebuffer::clearAfterInvalidation() {
+ if (m_cleared)
+ return;
+
+ m_cleared = true;
+ glClearColor(0, 0, 0, 0);
+ g_pHyprOpenGL->scissor(nullptr);
+ glClear(GL_COLOR_BUFFER_BIT);
}
diff --git a/src/render/gl/GLFramebuffer.hpp b/src/render/gl/GLFramebuffer.hpp
index 1be5d0e0..34051656 100644
--- a/src/render/gl/GLFramebuffer.hpp
+++ b/src/render/gl/GLFramebuffer.hpp
@@ -21,11 +21,15 @@ namespace Render::GL {
GLuint getFBID();
void invalidate(const std::vector<GLenum>& attachments);
+ // clear at most once per invalidate()
+ void clearAfterInvalidation();
+
protected:
bool internalAlloc(int w, int h, DRMFormat format = DRM_FORMAT_ARGB8888) override;
private:
- GLuint m_fb = -1;
+ GLuint m_fb = -1;
+ bool m_cleared = false;
friend class CGLRenderbuffer;
};
diff --git a/src/render/pass/TexPassElement.hpp b/src/render/pass/TexPassElement.hpp
index 6c0cfab1..413f9875 100644
--- a/src/render/pass/TexPassElement.hpp
+++ b/src/render/pass/TexPassElement.hpp
@@ -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;
diff --git a/src/render/shaders/glsl/blur1.glsl b/src/render/shaders/glsl/blur1.glsl
index 86a37d88..8d9e39ae 100644
--- a/src/render/shaders/glsl/blur1.glsl
+++ b/src/render/shaders/glsl/blur1.glsl
@@ -104,10 +104,10 @@ vec4 blur1(vec2 v_texcoord, sampler2D tex, float radius, vec2 halfpixel, int pas
// That garbage maps to 0.0-1.0 range with UINT8 buffer and doesn't have any significant impact on the end result.
// FP16 garbage maps to -65,504 - 65,504 and defines the end result. Clamp it here to 0.0 - 1.0 to get the same quality outcome as with UINT8.
// Rerendering an undamaged area to get some insignificant color accuracy increase on blur edges isn't worth it.
- sum += clamp(texture(tex, uv - halfpixel.xy * radius), 0.0, 1.0);
- sum += clamp(texture(tex, uv + halfpixel.xy * radius), 0.0, 1.0);
- sum += clamp(texture(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius), 0.0, 1.0);
- sum += clamp(texture(tex, uv - vec2(halfpixel.x, -halfpixel.y) * radius), 0.0, 1.0);
+ sum += texture(tex, uv - halfpixel.xy * radius);
+ sum += texture(tex, uv + halfpixel.xy * radius);
+ sum += texture(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius);
+ sum += texture(tex, uv - vec2(halfpixel.x, -halfpixel.y) * radius);
vec4 color = sum / 8.0;
diff --git a/src/render/shaders/glsl/blurFinish.glsl b/src/render/shaders/glsl/blurFinish.glsl
index e7e1f1c6..bdfe2bc8 100644
--- a/src/render/shaders/glsl/blurFinish.glsl
+++ b/src/render/shaders/glsl/blurFinish.glsl
@@ -30,7 +30,11 @@ vec4 blurFinish(vec4 pixColor, vec2 v_texcoord, float noise, float brightness
pixColor.rgb *= min(1.0, brightness);
#if USE_CM
- pixColor = doColorManagement(pixColor, sourceTF, targetTF, convertMatrix, srcTFRange, dstTFRange);
+ if (targetTF == CM_TRANSFER_FUNCTION_EXT_LINEAR) {
+ pixColor = doColorManagement(pixColor, sourceTF, targetTF, convertMatrix, srcTFRange, vec2(0.0, 203.0)); // FIXME wtf
+ } else {
+ pixColor = doColorManagement(pixColor, sourceTF, targetTF, convertMatrix, srcTFRange, dstTFRange);
+ }
#endif
return pixColor;
diff --git a/src/render/shaders/glsl/cm_helpers.glsl b/src/render/shaders/glsl/cm_helpers.glsl
index 0d8c68e9..ae4b63ae 100644
--- a/src/render/shaders/glsl/cm_helpers.glsl
+++ b/src/render/shaders/glsl/cm_helpers.glsl
@@ -127,6 +127,7 @@ vec3 tfST240(vec3 color) {
vec3 toLinearRGB(vec3 color, int tf) {
switch (tf) {
+ case CM_TRANSFER_FUNCTION_LINEAR: return color;
case CM_TRANSFER_FUNCTION_EXT_LINEAR: return color;
case CM_TRANSFER_FUNCTION_ST2084_PQ: return tfInvPQ(color);
case CM_TRANSFER_FUNCTION_GAMMA22: return pow(max(color, vec3(0.0)), vec3(2.2));
@@ -179,7 +180,7 @@ vec3 fromLinearRGB(vec3 color, int tf) {
}
vec4 fromLinear(vec4 color, int tf) {
- if (tf == CM_TRANSFER_FUNCTION_EXT_LINEAR)
+ if (tf == CM_TRANSFER_FUNCTION_EXT_LINEAR || tf == CM_TRANSFER_FUNCTION_LINEAR)
return color;
color.rgb /= max(color.a, 0.001);
@@ -189,6 +190,9 @@ vec4 fromLinear(vec4 color, int tf) {
}
vec4 fromLinearNit(vec4 color, int tf, vec2 range) {
+ if (tf == CM_TRANSFER_FUNCTION_LINEAR)
+ return color;
+
color.rgb = (color.rgb - range[0] * color.a) / (range[1] - range[0]); // @gulafaran
color.rgb /= max(color.a, 0.001);
color.rgb = fromLinearRGB(color.rgb, tf);
@@ -231,7 +235,8 @@ vec4
pixColor.rgb *= pixColor.a;
#else
pixColor.rgb = convertMatrix * pixColor.rgb;
- pixColor = toNit(pixColor, srcTFRange);
+ if (srcTF != CM_TRANSFER_FUNCTION_LINEAR)
+ pixColor = toNit(pixColor, srcTFRange);
pixColor.rgb *= pixColor.a;
#if USE_TONEMAP
pixColor = tonemap(pixColor, dstxyz, maxLuminance, dstMaxLuminance, dstRefLuminance, srcRefLuminance);
@@ -258,4 +263,4 @@ vec4
#endif
}
-#endif \ No newline at end of file
+#endif
diff --git a/src/render/shaders/glsl/constants.h b/src/render/shaders/glsl/constants.h
index bbab5284..db8b2cc1 100644
--- a/src/render/shaders/glsl/constants.h
+++ b/src/render/shaders/glsl/constants.h
@@ -1,6 +1,7 @@
#ifndef CONSTANTS_H
#define CONSTANTS_H
//enum eTransferFunction
+#define CM_TRANSFER_FUNCTION_LINEAR 0 // not normalised
#define CM_TRANSFER_FUNCTION_BT1886 1
#define CM_TRANSFER_FUNCTION_GAMMA22 2
#define CM_TRANSFER_FUNCTION_GAMMA28 3
diff --git a/src/render/shaders/glsl/inner_glow.frag b/src/render/shaders/glsl/inner_glow.frag
index 2fc405c0..63369e0a 100644
--- a/src/render/shaders/glsl/inner_glow.frag
+++ b/src/render/shaders/glsl/inner_glow.frag
@@ -8,10 +8,7 @@ precision highp float;
in vec4 v_color;
in vec2 v_texcoord;
-uniform int sourceTF; // eTransferFunction
-uniform int targetTF; // eTransferFunction
-uniform mat3 targetPrimariesXYZ;
-
+uniform vec4 colorSRGB;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
@@ -20,38 +17,22 @@ uniform float roundingPower;
uniform float range;
uniform float shadowPower;
-#if USE_CM
-#include "cm_helpers.glsl"
-#include "CM.glsl"
-#endif
-
#include "inner_glow.glsl"
layout(location = 0) out vec4 fragColor;
+#if USE_MIRROR
+layout(location = 1) out vec4 mirrorColor;
+#endif
void main() {
vec4 pixColor = v_color;
-
- fragColor = getInnerGlow(pixColor, v_texcoord, radius, roundingPower, topLeft, fullSize, range, shadowPower, bottomRight
-#if USE_CM
- ,
- sourceTF, targetTF, convertMatrix, srcTFRange, dstTFRange
-#if USE_ICC
- ,
- iccLut3D, iccLutSize
+#if USE_MIRROR
+ vec4[2] pixColors =
#else
-#if USE_TONEMAP || USE_SDR_MOD
- ,
- targetPrimariesXYZ
-#endif
-#if USE_TONEMAP
- ,
- maxLuminance, dstMaxLuminance, dstRefLuminance, srcRefLuminance
-#endif
-#if USE_SDR_MOD
- ,
- sdrSaturation, sdrBrightnessMultiplier
-#endif
+ fragColor =
#endif
+ getInnerGlow(pixColor, colorSRGB, v_texcoord, radius, roundingPower, topLeft, fullSize, range, shadowPower, bottomRight);
+#if USE_MIRROR
+ fragColor = pixColors[0];
+ mirrorColor = pixColors[1];
#endif
- );
}
diff --git a/src/render/shaders/glsl/inner_glow.glsl b/src/render/shaders/glsl/inner_glow.glsl
index b0d55b19..307c3648 100644
--- a/src/render/shaders/glsl/inner_glow.glsl
+++ b/src/render/shaders/glsl/inner_glow.glsl
@@ -5,8 +5,6 @@
#ifndef INNER_GLOW_GLSL
#define INNER_GLOW_GLSL
-#include "cm_helpers.glsl"
-
float innerGlowAlpha(float distFromEdge, float range, float glowPower) {
if (distFromEdge >= range)
return 0.0;
@@ -26,29 +24,7 @@ float innerGlowSmin(float a, float b, float k) {
return min(a, b) - h * h * h * k * (1.0 / 6.0);
}
-vec4 getInnerGlow(vec4 pixColor, vec2 v_texcoord, float radius, float roundingPower, vec2 topLeft, vec2 fullSize, float range, float glowPower, vec2 bottomRight
-#if USE_CM
- ,
- int sourceTF, int targetTF, mat3 convertMatrix, vec2 srcTFRange, vec2 dstTFRange
-#if USE_ICC
- ,
- highp sampler3D iccLut3D, float iccLutSize
-#else
-#if USE_TONEMAP || USE_SDR_MOD
- ,
- mat3 targetPrimariesXYZ
-#endif
-#if USE_TONEMAP
- ,
- float maxLuminance, float dstMaxLuminance, float dstRefLuminance, float srcRefLuminance
-#endif
-#if USE_SDR_MOD
- ,
- float sdrSaturation, float sdrBrightnessMultiplier
-#endif
-#endif
-#endif
-) {
+vec4 getInnerGlow(vec4 pixColor, vec4 colorSRGB, vec2 v_texcoord, float radius, float roundingPower, vec2 topLeft, vec2 fullSize, float range, float glowPower, vec2 bottomRight) {
vec2 pixCoord = fullSize * v_texcoord;
// clip to the rounded rectangle shape using actual SDF
@@ -79,28 +55,15 @@ vec4 getInnerGlow(vec4 pixColor, vec2 v_texcoord, float radius, float roundingPo
// premultiply
pixColor.rgb *= pixColor[3];
-#if USE_CM
- pixColor = doColorManagement(pixColor, sourceTF, targetTF, convertMatrix, srcTFRange, dstTFRange
-#if USE_ICC
- ,
- iccLut3D, iccLutSize
+#if USE_MIRROR
+ vec4[2] pixColors;
+ pixColors[0] = pixColor;
+ pixColors[1] = colorSRGB;
+ pixColors[1].a = pixColor.a;
+ pixColors[1].rgb *= pixColors[1].a;
+ return pixColors;
#else
-#if USE_TONEMAP || USE_SDR_MOD
- ,
- targetPrimariesXYZ
-#endif
-#if USE_TONEMAP
- ,
- maxLuminance, dstMaxLuminance, dstRefLuminance, srcRefLuminance
-#endif
-#if USE_SDR_MOD
- ,
- sdrSaturation, sdrBrightnessMultiplier
-#endif
-#endif
- );
-#endif
-
return pixColor;
+#endif
}
#endif
diff --git a/src/render/shaders/glsl/quad.frag b/src/render/shaders/glsl/quad.frag
index dc1945af..46d42a8c 100644
--- a/src/render/shaders/glsl/quad.frag
+++ b/src/render/shaders/glsl/quad.frag
@@ -7,6 +7,7 @@
precision highp float;
in vec4 v_color;
+uniform vec4 colorSRGB;
#if USE_ROUNDING
uniform float radius;
uniform float roundingPower;
@@ -28,6 +29,10 @@ void main() {
fragColor = pixColor;
#if USE_MIRROR
- mirrorColor = fragColor;
+#if USE_ROUNDING
+ mirrorColor = rounding(colorSRGB, radius, roundingPower, topLeft, fullSize);
+#else
+ mirrorColor = colorSRGB;
+#endif
#endif
}
diff --git a/src/render/shaders/glsl/shadow.frag b/src/render/shaders/glsl/shadow.frag
index e91e9a14..eb6f3174 100644
--- a/src/render/shaders/glsl/shadow.frag
+++ b/src/render/shaders/glsl/shadow.frag
@@ -8,10 +8,7 @@ precision highp float;
in vec4 v_color;
in vec2 v_texcoord;
-uniform int sourceTF; // eTransferFunction
-uniform int targetTF; // eTransferFunction
-uniform mat3 targetPrimariesXYZ;
-
+uniform vec4 colorSRGB;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 windowTopLeft;
@@ -23,11 +20,6 @@ uniform float range;
uniform float shadowPower;
uniform float thick;
-#if USE_CM
-#include "cm_helpers.glsl"
-#include "CM.glsl"
-#endif
-
#include "shadow.glsl"
layout(location = 0) out vec4 fragColor;
@@ -41,29 +33,7 @@ void main() {
#else
fragColor =
#endif
- getShadow(pixColor, v_texcoord, radius, roundingPower, topLeft, fullSize, range, shadowPower, bottomRight, windowTopLeft, windowBottomRight, thick
-#if USE_CM
- ,
- sourceTF, targetTF, convertMatrix, srcTFRange, dstTFRange
-#if USE_ICC
- ,
- iccLut3D, iccLutSize
-#else
-#if USE_TONEMAP || USE_SDR_MOD
- ,
- targetPrimariesXYZ
-#endif
-#if USE_TONEMAP
- ,
- maxLuminance, dstMaxLuminance, dstRefLuminance, srcRefLuminance
-#endif
-#if USE_SDR_MOD
- ,
- sdrSaturation, sdrBrightnessMultiplier
-#endif
-#endif
-#endif
- );
+ getShadow(pixColor, colorSRGB, v_texcoord, radius, roundingPower, topLeft, fullSize, range, shadowPower, bottomRight, windowTopLeft, windowBottomRight, thick);
#if USE_MIRROR
fragColor = pixColors[0];
mirrorColor = pixColors[1];
diff --git a/src/render/shaders/glsl/shadow.glsl b/src/render/shaders/glsl/shadow.glsl
index fdfa697c..ba68bc49 100644
--- a/src/render/shaders/glsl/shadow.glsl
+++ b/src/render/shaders/glsl/shadow.glsl
@@ -5,7 +5,6 @@
#ifndef SHADOW_GLSL
#define SHADOW_GLSL
-#include "cm_helpers.glsl"
#include "rounding.glsl"
float pixAlphaRoundedDistance(float distanceToCorner, float radius, float range, float shadowPower) {
@@ -54,30 +53,8 @@ vec4[2]
#else
vec4
#endif
- getShadow(vec4 pixColor, vec2 v_texcoord, float borderRadius, float roundingPower, vec2 topLeft, vec2 fullSize, float range, float shadowPower, vec2 bottomRight,
- vec2 windowTopLeft, vec2 windowBottomRight, float windowRadius
-#if USE_CM
- ,
- int sourceTF, int targetTF, mat3 convertMatrix, vec2 srcTFRange, vec2 dstTFRange
-#if USE_ICC
- ,
- highp sampler3D iccLut3D, float iccLutSize
-#else
-#if USE_TONEMAP || USE_SDR_MOD
- ,
- mat3 targetPrimariesXYZ
-#endif
-#if USE_TONEMAP
- ,
- float maxLuminance, float dstMaxLuminance, float dstRefLuminance, float srcRefLuminance
-#endif
-#if USE_SDR_MOD
- ,
- float sdrSaturation, float sdrBrightnessMultiplier
-#endif
-#endif
-#endif
- ) {
+ getShadow(vec4 pixColor, vec4 colorSRGB, vec2 v_texcoord, float borderRadius, float roundingPower, vec2 topLeft, vec2 fullSize, float range, float shadowPower, vec2 bottomRight,
+ vec2 windowTopLeft, vec2 windowBottomRight, float windowRadius) {
float radius = range + borderRadius;
float originalAlpha = pixColor[3];
@@ -144,33 +121,12 @@ vec4
// premultiply
pixColor.rgb *= pixColor[3];
-#if USE_CM
-#if USE_MIRROR
- vec4[2] pixColors =
-#else
- pixColor =
-#endif
- doColorManagement(pixColor, sourceTF, targetTF, convertMatrix, srcTFRange, dstTFRange
-#if USE_ICC
- ,
- iccLut3D, iccLutSize
-#else
-#if USE_TONEMAP || USE_SDR_MOD
- ,
- targetPrimariesXYZ
-#endif
-#if USE_TONEMAP
- ,
- maxLuminance, dstMaxLuminance, dstRefLuminance, srcRefLuminance
-#endif
-#if USE_SDR_MOD
- ,
- sdrSaturation, sdrBrightnessMultiplier
-#endif
-#endif
- );
-#endif
#if USE_MIRROR
+ vec4[2] pixColors;
+ pixColors[0] = pixColor;
+ pixColors[1] = colorSRGB;
+ pixColors[1].a = pixColor.a;
+ pixColors[1].rgb *= pixColors[1].a;
return pixColors;
#else
return pixColor;
diff --git a/src/render/shaders/glsl/tonemap.glsl b/src/render/shaders/glsl/tonemap.glsl
index dcce45a6..a2db7e6e 100644
--- a/src/render/shaders/glsl/tonemap.glsl
+++ b/src/render/shaders/glsl/tonemap.glsl
@@ -50,21 +50,16 @@ vec4 tonemap(vec4 color, mat3 dstXYZ, float maxLuminance, float dstMaxLuminance,
float E = pow(clamp(ICtCp[0], 0.0, 1.0), PQ_INV_M2);
float luminance = pow((max(E - PQ_C1, 0.0)) / (PQ_C2 - PQ_C3 * E), PQ_INV_M1) * HDR_MAX_LUMINANCE;
- float linearPart = min(luminance, dstRefLuminance);
- float luminanceAboveRef = max(luminance - dstRefLuminance, 0.0);
- float maxExcessLuminance = max(maxLuminance - dstRefLuminance, 1.0);
- float shoulder = log((luminanceAboveRef / maxExcessLuminance + 1.0) * (M_E - 1.0));
- float mappedHigh = shoulder * (dstMaxLuminance - dstRefLuminance);
- float newLum = clamp(linearPart + mappedHigh, 0.0, dstMaxLuminance);
+ float luminanceRatio = max(luminance / dstRefLuminance, 0.0);
+ float srcScale = maxLuminance / dstRefLuminance;
+ float dstScale = dstMaxLuminance / dstRefLuminance;
+ float v = (dstScale * (1.0 + srcScale) - srcScale) / pow(srcScale, 2.0);
+ float newLuminance = (luminanceRatio * (1.0 + luminanceRatio * v) / (1.0 + luminanceRatio)) * dstRefLuminance;
- // scale src to dst reference
- float refScale = dstRefLuminance / srcRefLuminance;
+ E = pow(clamp(newLuminance / HDR_MAX_LUMINANCE, 0.0, 1.0), PQ_M1);
+ ICtCp[0] = pow((PQ_C1 + PQ_C2 * E) / (1.0 + PQ_C3 * E), PQ_M2);
- // kind of works but doesn't use newLum at all
- return vec4(fromLMS * toLinear(vec4(ICtCpPQInv * ICtCp, 1.0), CM_TRANSFER_FUNCTION_ST2084_PQ).rgb * HDR_MAX_LUMINANCE * refScale, color[3]);
- // breaks with overriden monitor luminances. might be caused by incorrect imput values
- // @gulafaran
- // vec3 outRGB = fromLMS * toLinear(vec4(ICtCpPQInv * ICtCp, 1.0), CM_TRANSFER_FUNCTION_ST2084_PQ).rgb;
- // outRGB *= (newLum / max(luminance, 0.0001)); // actually apply the tone mapping
- // return vec4(clamp(outRGB * HDR_MAX_LUMINANCE * refScale, 0.0, dstMaxLuminance), color[3]);
+ color = vec4(fromLMS * toLinear(vec4(ICtCpPQInv * ICtCp, 1.0), CM_TRANSFER_FUNCTION_ST2084_PQ).rgb * HDR_MAX_LUMINANCE, color[3]);
+
+ return clamp(color, 0.0, dstMaxLuminance);
}