mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-22 13:33:40 +00:00
[client] egl: add support to map HDR to SDR
This commit is contained in:
parent
99333a03c1
commit
ad43969c1a
@ -72,6 +72,7 @@ LG_RendererRotate;
|
||||
typedef struct LG_RendererFormat
|
||||
{
|
||||
FrameType type; // frame type
|
||||
bool hdr; // if the frame is HDR or not
|
||||
unsigned int screenWidth; // actual width of the host
|
||||
unsigned int screenHeight; // actual height of the host
|
||||
unsigned int frameWidth; // width of frame transmitted
|
||||
|
@ -50,6 +50,7 @@ struct DesktopShader
|
||||
GLint uScaleAlgo;
|
||||
GLint uNVGain;
|
||||
GLint uCBMode;
|
||||
GLint uIsHDR;
|
||||
};
|
||||
|
||||
struct EGL_Desktop
|
||||
@ -64,6 +65,7 @@ struct EGL_Desktop
|
||||
|
||||
// internals
|
||||
int width, height;
|
||||
bool hdr;
|
||||
LG_RendererRotate rotate;
|
||||
|
||||
bool useSpice;
|
||||
@ -113,6 +115,7 @@ static bool egl_initDesktopShader(
|
||||
shader->uScaleAlgo = egl_shaderGetUniform(shader->shader, "scaleAlgo" );
|
||||
shader->uNVGain = egl_shaderGetUniform(shader->shader, "nvGain" );
|
||||
shader->uCBMode = egl_shaderGetUniform(shader->shader, "cbMode" );
|
||||
shader->uIsHDR = egl_shaderGetUniform(shader->shader, "isHDR" );
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -303,6 +306,7 @@ bool egl_desktopSetup(EGL_Desktop * desktop, const LG_RendererFormat format)
|
||||
|
||||
desktop->width = format.frameWidth;
|
||||
desktop->height = format.frameHeight;
|
||||
desktop->hdr = format.hdr;
|
||||
|
||||
if (!egl_textureSetup(
|
||||
desktop->texture,
|
||||
@ -481,6 +485,11 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
.type = EGL_UNIFORM_TYPE_1I,
|
||||
.location = shader->uCBMode,
|
||||
.f = { desktop->cbMode }
|
||||
},
|
||||
{
|
||||
.type = EGL_UNIFORM_TYPE_1I,
|
||||
.location = shader->uIsHDR,
|
||||
.i = { desktop->hdr }
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,7 @@ precision highp float;
|
||||
#define EGL_SCALE_MAX 3
|
||||
|
||||
#include "color_blind.h"
|
||||
#include "hdr.h"
|
||||
|
||||
in vec2 uv;
|
||||
out vec4 color;
|
||||
@ -19,6 +20,7 @@ uniform int scaleAlgo;
|
||||
|
||||
uniform float nvGain;
|
||||
uniform int cbMode;
|
||||
uniform bool isHDR;
|
||||
|
||||
void main()
|
||||
{
|
||||
@ -38,6 +40,9 @@ void main()
|
||||
}
|
||||
}
|
||||
|
||||
if (isHDR)
|
||||
color.rgb = mapToSDR(color.rgb);
|
||||
|
||||
if (cbMode > 0)
|
||||
color = cbTransform(color, cbMode);
|
||||
|
||||
|
108
client/renderers/EGL/shader/hdr.h
Normal file
108
client/renderers/EGL/shader/hdr.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
_______ _____ __ __ ____ __
|
||||
/ ____(_)___ ___ ____ ___ ____ _ / ___// /_ ____ _____/ /__ _____ / __ \____ ______/ /__
|
||||
/ / / / __ \/ _ \/ __ `__ \/ __ `/ \__ \/ __ \/ __ `/ __ / _ \/ ___/ / /_/ / __ `/ ___/ //_/
|
||||
/ /___/ / / / / __/ / / / / / /_/ / ___/ / / / / /_/ / /_/ / __/ / / ____/ /_/ / /__/ ,<
|
||||
\____/_/_/ /_/\___/_/ /_/ /_/\__,_/ /____/_/ /_/\__,_/\__,_/\___/_/ /_/ \__,_/\___/_/|_|
|
||||
http://en.sbence.hu/ Shader: Try to get the SDR part of HDR content
|
||||
*/
|
||||
|
||||
/**
|
||||
* Translated to GLSL, original source is:
|
||||
* https://github.com/VoidXH/Cinema-Shader-Pack
|
||||
*/
|
||||
|
||||
// Configuration ---------------------------------------------------------------
|
||||
const float peakLuminance = 250.0; // Peak playback screen luminance in nits
|
||||
const float knee = 0.75; // Compressor knee position
|
||||
const float ratio = 4.0; // Compressor ratio: 1 = disabled, <1 = expander
|
||||
const float maxCLL = 10000.0; // Maximum content light level in nits
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Precalculated values
|
||||
const float gain = maxCLL / peakLuminance;
|
||||
const float compressor = 1.0 / ratio;
|
||||
|
||||
// PQ constants
|
||||
const float m1inv = 16384.0 / 2610.0;
|
||||
const float m2inv = 32.0 / 2523.0;
|
||||
const float c1 = 3424.0 / 4096.0;
|
||||
const float c2 = 2413.0 / 128.0;
|
||||
const float c3 = 2392.0 / 128.0;
|
||||
|
||||
float minGain(vec3 pixel) { return min(pixel.r, min(pixel.g, pixel.b)); }
|
||||
float maxGain(vec3 pixel) { return max(pixel.r, max(pixel.g, pixel.b)); }
|
||||
float midGain(vec3 pixel)
|
||||
{
|
||||
return pixel.r < pixel.g ?
|
||||
(pixel.r < pixel.b ?
|
||||
min(pixel.g, pixel.b) : // min = r
|
||||
min(pixel.r, pixel.g)) : // min = b
|
||||
(pixel.g < pixel.b ?
|
||||
min(pixel.r, pixel.b) : // min = g
|
||||
min(pixel.r, pixel.g)); // min = b
|
||||
}
|
||||
|
||||
vec3 compress(vec3 pixel)
|
||||
{
|
||||
float gain = maxGain(pixel);
|
||||
return pixel * (gain < knee ? gain : knee + max(gain - knee, 0.0) * compressor) / gain;
|
||||
}
|
||||
|
||||
vec3 fixClip(vec3 pixel)
|
||||
{
|
||||
// keep the (mid - min) / (max - min) ratio
|
||||
float preMin = minGain(pixel);
|
||||
float preMid = midGain(pixel);
|
||||
float preMax = maxGain(pixel);
|
||||
vec3 clip = clamp(pixel, 0.0, 1.0);
|
||||
float postMin = minGain(clip);
|
||||
float postMid = midGain(clip);
|
||||
float postMax = maxGain(clip);
|
||||
float ratio = (preMid - preMin) / (preMax - preMin);
|
||||
float newMid = ratio * (postMax - postMin) + postMin;
|
||||
return vec3(clip.r != postMid ? clip.r : newMid,
|
||||
clip.g != postMid ? clip.g : newMid,
|
||||
clip.b != postMid ? clip.b : newMid);
|
||||
}
|
||||
|
||||
// Returns luminance in nits
|
||||
vec3 pq2lin(vec3 pq)
|
||||
{
|
||||
vec3 p = pow(pq, vec3(m2inv));
|
||||
vec3 d = max(p - c1, vec3(0.0)) / (c2 - c3 * p);
|
||||
return pow(d, vec3(m1inv)) * gain;
|
||||
}
|
||||
|
||||
vec3 srgb2lin(vec3 c)
|
||||
{
|
||||
vec3 v = c / 12.92;
|
||||
vec3 v2 = pow((c + vec3(0.055)) / 1.055, vec3(2.4));
|
||||
vec3 threshold = vec3(0.04045);
|
||||
vec3 result = mix(v, v2, greaterThanEqual(c, threshold));
|
||||
return result;
|
||||
}
|
||||
|
||||
vec3 lin2srgb(vec3 c)
|
||||
{
|
||||
vec3 v = c * 12.92;
|
||||
vec3 v2 = pow(c, vec3(1.0/2.4)) * 1.055 - 0.055;
|
||||
vec3 threshold = vec3(0.0031308);
|
||||
vec3 result = mix(v, v2, greaterThanEqual(c, threshold));
|
||||
return result;
|
||||
}
|
||||
|
||||
// in linear space
|
||||
vec3 bt2020to709(vec3 bt2020)
|
||||
{
|
||||
return vec3(
|
||||
bt2020.r * 1.6605 + bt2020.g * -0.5876 + bt2020.b * -0.0728,
|
||||
bt2020.r * -0.1246 + bt2020.g * 1.1329 + bt2020.b * -0.0083,
|
||||
bt2020.r * -0.0182 + bt2020.g * -0.1006 + bt2020.b * 1.1187);
|
||||
}
|
||||
|
||||
vec3 mapToSDR(vec3 color)
|
||||
{
|
||||
vec3 lin = bt2020to709(pq2lin(color.rgb));
|
||||
return lin2srgb(compress(lin));
|
||||
}
|
@ -631,6 +631,7 @@ int main_frameThread(void * unused)
|
||||
lgrFormat.frameHeight = frame->frameHeight;
|
||||
lgrFormat.stride = frame->stride;
|
||||
lgrFormat.pitch = frame->pitch;
|
||||
lgrFormat.hdr = frame->flags & FRAME_FLAG_HDR;
|
||||
|
||||
if (frame->flags & FRAME_FLAG_TRUNCATED)
|
||||
{
|
||||
@ -695,11 +696,12 @@ int main_frameThread(void * unused)
|
||||
g_state.formatValid = true;
|
||||
formatVer = frame->formatVer;
|
||||
|
||||
DEBUG_INFO("Format: %s %ux%u stride:%u pitch:%u rotation:%d",
|
||||
DEBUG_INFO("Format: %s %ux%u stride:%u pitch:%u rotation:%d hdr:%d",
|
||||
FrameTypeStr[frame->type],
|
||||
frame->frameWidth, frame->frameHeight,
|
||||
frame->stride, frame->pitch,
|
||||
frame->rotation);
|
||||
frame->rotation,
|
||||
frame->flags & FRAME_FLAG_HDR ? 1 : 0);
|
||||
|
||||
LG_LOCK(g_state.lgrLock);
|
||||
if (!RENDERER(onFrameFormat, lgrFormat))
|
||||
|
Loading…
Reference in New Issue
Block a user