backends/drm: support arbitrary input transfer functions in the icc shader

This commit is contained in:
Xaver Hugl 2024-07-04 19:12:56 +02:00
parent 50717a2f9a
commit 5b86dba6bf
7 changed files with 28 additions and 6 deletions

View file

@ -183,7 +183,7 @@ bool EglGbmLayerSurface::endRendering(const QRegion &damagedRegion, OutputFrame
GLFramebuffer::pushFramebuffer(fbo);
ShaderBinder binder = m_surface->iccShader ? ShaderBinder(m_surface->iccShader->shader()) : ShaderBinder(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace);
if (m_surface->iccShader) {
m_surface->iccShader->setUniforms(m_surface->iccProfile, m_surface->intermediaryColorDescription.referenceLuminance(), m_surface->channelFactors);
m_surface->iccShader->setUniforms(m_surface->iccProfile, m_surface->intermediaryColorDescription, m_surface->channelFactors);
} else {
QMatrix4x4 ctm;
ctm(0, 0) = m_surface->channelFactors.x();

View file

@ -1,5 +1,6 @@
// SPDX-FileCopyrightText: 2023 Xaver Hugl <xaver.hugl@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "colormanagement.glsl"
precision highp float;
precision highp sampler2D;
precision highp sampler3D;
@ -7,7 +8,6 @@ precision highp sampler3D;
in vec2 texcoord0;
uniform sampler2D src;
uniform float referenceLuminance;
uniform mat4 toXYZD50;
@ -37,6 +37,7 @@ vec3 sample1DLut(vec3 input, sampler2D lut, int lutSize) {
void main()
{
vec4 tex = texture2D(src, texcoord0);
tex = encodingToNits(tex, sourceNamedTransferFunction);
tex.rgb /= max(tex.a, 0.001);
tex.rgb /= referenceLuminance;
tex.rgb = (toXYZD50 * vec4(tex.rgb, 1.0)).rgb;

View file

@ -1,6 +1,7 @@
#version 140
// SPDX-FileCopyrightText: 2023 Xaver Hugl <xaver.hugl@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "colormanagement.glsl"
precision highp float;
precision highp sampler2D;
precision highp sampler3D;
@ -10,7 +11,6 @@ in vec2 texcoord0;
out vec4 fragColor;
uniform sampler2D src;
uniform float referenceLuminance;
uniform mat4 toXYZD50;
@ -40,6 +40,7 @@ vec3 sample1DLut(in vec3 srcColor, in sampler2D lut, in int lutSize) {
void main()
{
vec4 tex = texture(src, texcoord0);
tex = encodingToNits(tex, sourceNamedTransferFunction);
tex.rgb /= max(tex.a, 0.001);
tex.rgb /= referenceLuminance;
tex.rgb = (toXYZD50 * vec4(tex.rgb, 1.0)).rgb;

View file

@ -22,6 +22,7 @@ IccShader::IccShader()
{
m_locations = {
.src = m_shader->uniformLocation("src"),
.sourceNamedTransferFunction = m_shader->uniformLocation("sourceNamedTransferFunction"),
.referenceLuminance = m_shader->uniformLocation("referenceLuminance"),
.toXYZD50 = m_shader->uniformLocation("toXYZD50"),
.bsize = m_shader->uniformLocation("Bsize"),
@ -145,7 +146,7 @@ GLShader *IccShader::shader() const
return m_shader.get();
}
void IccShader::setUniforms(const std::shared_ptr<IccProfile> &profile, float referenceLuminance, const QVector3D &channelFactors)
void IccShader::setUniforms(const std::shared_ptr<IccProfile> &profile, const ColorDescription &inputColor, const QVector3D &channelFactors)
{
// this failing can be silently ignored, it should only happen with GPU resets and gets corrected later
setProfile(profile);
@ -155,7 +156,8 @@ void IccShader::setUniforms(const std::shared_ptr<IccProfile> &profile, float re
nightColor(1, 1) = channelFactors.y();
nightColor(2, 2) = channelFactors.z();
m_shader->setUniform(m_locations.toXYZD50, m_toXYZD50 * nightColor);
m_shader->setUniform(m_locations.referenceLuminance, referenceLuminance);
m_shader->setUniform(m_locations.sourceNamedTransferFunction, inputColor.transferFunction().type);
m_shader->setUniform(m_locations.referenceLuminance, inputColor.referenceLuminance());
glActiveTexture(GL_TEXTURE1);
if (m_B) {

View file

@ -4,6 +4,7 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "core/colorspace.h"
#include <QMatrix4x4>
#include <QSizeF>
@ -25,7 +26,7 @@ public:
~IccShader();
GLShader *shader() const;
void setUniforms(const std::shared_ptr<IccProfile> &profile, float referenceLuminance, const QVector3D &channelFactors);
void setUniforms(const std::shared_ptr<IccProfile> &profile, const ColorDescription &inputColor, const QVector3D &channelFactors);
private:
bool setProfile(const std::shared_ptr<IccProfile> &profile);
@ -42,6 +43,7 @@ private:
struct Locations
{
int src;
int sourceNamedTransferFunction;
int referenceLuminance;
int toXYZD50;
int bsize;

View file

@ -307,6 +307,12 @@ bool GLShader::setUniform(const char *name, float value)
return setUniform(location, value);
}
bool GLShader::setUniform(const char *name, double value)
{
const int location = uniformLocation(name);
return setUniform(location, value);
}
bool GLShader::setUniform(const char *name, int value)
{
const int location = uniformLocation(name);
@ -357,6 +363,14 @@ bool GLShader::setUniform(int location, float value)
return (location >= 0);
}
bool GLShader::setUniform(int location, double value)
{
if (location >= 0) {
glUniform1f(location, value);
}
return (location >= 0);
}
bool GLShader::setUniform(int location, int value)
{
if (location >= 0) {

View file

@ -46,6 +46,7 @@ public:
int uniformLocation(const char *name);
bool setUniform(const char *name, float value);
bool setUniform(const char *name, double value);
bool setUniform(const char *name, int value);
bool setUniform(const char *name, const QVector2D &value);
bool setUniform(const char *name, const QVector3D &value);
@ -55,6 +56,7 @@ public:
bool setUniform(const char *name, const QColor &color);
bool setUniform(int location, float value);
bool setUniform(int location, double value);
bool setUniform(int location, int value);
bool setUniform(int location, int xValue, int yValue, int zValue);
bool setUniform(int location, const QVector2D &value);