mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 05:27:20 +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
|
typedef struct LG_RendererFormat
|
||||||
{
|
{
|
||||||
FrameType type; // frame type
|
FrameType type; // frame type
|
||||||
|
bool hdr; // if the frame is HDR or not
|
||||||
unsigned int screenWidth; // actual width of the host
|
unsigned int screenWidth; // actual width of the host
|
||||||
unsigned int screenHeight; // actual height of the host
|
unsigned int screenHeight; // actual height of the host
|
||||||
unsigned int frameWidth; // width of frame transmitted
|
unsigned int frameWidth; // width of frame transmitted
|
||||||
|
@ -50,6 +50,7 @@ struct DesktopShader
|
|||||||
GLint uScaleAlgo;
|
GLint uScaleAlgo;
|
||||||
GLint uNVGain;
|
GLint uNVGain;
|
||||||
GLint uCBMode;
|
GLint uCBMode;
|
||||||
|
GLint uIsHDR;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EGL_Desktop
|
struct EGL_Desktop
|
||||||
@ -64,6 +65,7 @@ struct EGL_Desktop
|
|||||||
|
|
||||||
// internals
|
// internals
|
||||||
int width, height;
|
int width, height;
|
||||||
|
bool hdr;
|
||||||
LG_RendererRotate rotate;
|
LG_RendererRotate rotate;
|
||||||
|
|
||||||
bool useSpice;
|
bool useSpice;
|
||||||
@ -113,6 +115,7 @@ static bool egl_initDesktopShader(
|
|||||||
shader->uScaleAlgo = egl_shaderGetUniform(shader->shader, "scaleAlgo" );
|
shader->uScaleAlgo = egl_shaderGetUniform(shader->shader, "scaleAlgo" );
|
||||||
shader->uNVGain = egl_shaderGetUniform(shader->shader, "nvGain" );
|
shader->uNVGain = egl_shaderGetUniform(shader->shader, "nvGain" );
|
||||||
shader->uCBMode = egl_shaderGetUniform(shader->shader, "cbMode" );
|
shader->uCBMode = egl_shaderGetUniform(shader->shader, "cbMode" );
|
||||||
|
shader->uIsHDR = egl_shaderGetUniform(shader->shader, "isHDR" );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -303,6 +306,7 @@ bool egl_desktopSetup(EGL_Desktop * desktop, const LG_RendererFormat format)
|
|||||||
|
|
||||||
desktop->width = format.frameWidth;
|
desktop->width = format.frameWidth;
|
||||||
desktop->height = format.frameHeight;
|
desktop->height = format.frameHeight;
|
||||||
|
desktop->hdr = format.hdr;
|
||||||
|
|
||||||
if (!egl_textureSetup(
|
if (!egl_textureSetup(
|
||||||
desktop->texture,
|
desktop->texture,
|
||||||
@ -481,6 +485,11 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
.type = EGL_UNIFORM_TYPE_1I,
|
.type = EGL_UNIFORM_TYPE_1I,
|
||||||
.location = shader->uCBMode,
|
.location = shader->uCBMode,
|
||||||
.f = { desktop->cbMode }
|
.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
|
#define EGL_SCALE_MAX 3
|
||||||
|
|
||||||
#include "color_blind.h"
|
#include "color_blind.h"
|
||||||
|
#include "hdr.h"
|
||||||
|
|
||||||
in vec2 uv;
|
in vec2 uv;
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
@ -19,6 +20,7 @@ uniform int scaleAlgo;
|
|||||||
|
|
||||||
uniform float nvGain;
|
uniform float nvGain;
|
||||||
uniform int cbMode;
|
uniform int cbMode;
|
||||||
|
uniform bool isHDR;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
@ -38,6 +40,9 @@ void main()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isHDR)
|
||||||
|
color.rgb = mapToSDR(color.rgb);
|
||||||
|
|
||||||
if (cbMode > 0)
|
if (cbMode > 0)
|
||||||
color = cbTransform(color, cbMode);
|
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.frameHeight = frame->frameHeight;
|
||||||
lgrFormat.stride = frame->stride;
|
lgrFormat.stride = frame->stride;
|
||||||
lgrFormat.pitch = frame->pitch;
|
lgrFormat.pitch = frame->pitch;
|
||||||
|
lgrFormat.hdr = frame->flags & FRAME_FLAG_HDR;
|
||||||
|
|
||||||
if (frame->flags & FRAME_FLAG_TRUNCATED)
|
if (frame->flags & FRAME_FLAG_TRUNCATED)
|
||||||
{
|
{
|
||||||
@ -695,11 +696,12 @@ int main_frameThread(void * unused)
|
|||||||
g_state.formatValid = true;
|
g_state.formatValid = true;
|
||||||
formatVer = frame->formatVer;
|
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],
|
FrameTypeStr[frame->type],
|
||||||
frame->frameWidth, frame->frameHeight,
|
frame->frameWidth, frame->frameHeight,
|
||||||
frame->stride, frame->pitch,
|
frame->stride, frame->pitch,
|
||||||
frame->rotation);
|
frame->rotation,
|
||||||
|
frame->flags & FRAME_FLAG_HDR ? 1 : 0);
|
||||||
|
|
||||||
LG_LOCK(g_state.lgrLock);
|
LG_LOCK(g_state.lgrLock);
|
||||||
if (!RENDERER(onFrameFormat, lgrFormat))
|
if (!RENDERER(onFrameFormat, lgrFormat))
|
||||||
|
Loading…
Reference in New Issue
Block a user