mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-07-21 06:42:02 +00:00
[obs] hdr: apply the complete HDR cursor transform
Keep transform-only cursor messages independent from visibility and use the cursor-specific SDR white level reported by IddCx. Apply the Windows XYZ matrix, scalar, and transfer-domain LUT before compositing colour and masked-colour cursors into OBS scRGB. Preserve premultiplied alpha and leave monochrome logical masks unchanged.
This commit is contained in:
@@ -1,6 +1,15 @@
|
|||||||
uniform float4x4 ViewProj;
|
uniform float4x4 ViewProj;
|
||||||
uniform texture2d image;
|
uniform texture2d image;
|
||||||
|
uniform texture2d colorLUT;
|
||||||
uniform float multiplier;
|
uniform float multiplier;
|
||||||
|
uniform float sdrWhiteLevel;
|
||||||
|
uniform int outputTransfer; /* 0: sRGB, 1: scRGB, 2: PQ decoded to scRGB */
|
||||||
|
uniform bool matrixEnabled;
|
||||||
|
uniform bool lutEnabled;
|
||||||
|
uniform float4 colorMatrix0;
|
||||||
|
uniform float4 colorMatrix1;
|
||||||
|
uniform float4 colorMatrix2;
|
||||||
|
uniform float colorScalar;
|
||||||
|
|
||||||
sampler_state def_sampler
|
sampler_state def_sampler
|
||||||
{
|
{
|
||||||
@@ -9,6 +18,13 @@ sampler_state def_sampler
|
|||||||
AddressV = Clamp;
|
AddressV = Clamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sampler_state lut_sampler
|
||||||
|
{
|
||||||
|
Filter = Point;
|
||||||
|
AddressU = Clamp;
|
||||||
|
AddressV = Clamp;
|
||||||
|
};
|
||||||
|
|
||||||
struct VertData
|
struct VertData
|
||||||
{
|
{
|
||||||
float4 pos : POSITION;
|
float4 pos : POSITION;
|
||||||
@@ -37,6 +53,99 @@ float3 srgbToLinear(float3 color)
|
|||||||
srgbToLinearChannel(color.b));
|
srgbToLinearChannel(color.b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float3 pow3(float3 value, float exponent)
|
||||||
|
{
|
||||||
|
return pow(value, float3(exponent, exponent, exponent));
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 linearToSrgb(float3 value)
|
||||||
|
{
|
||||||
|
float3 low = value * 12.92;
|
||||||
|
float3 high = 1.055 * pow3(max(value, 0.0), 1.0 / 2.4) - 0.055;
|
||||||
|
return lerp(low, high, step(0.0031308, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 bt709ToXYZ(float3 rgb)
|
||||||
|
{
|
||||||
|
return float3(
|
||||||
|
dot(rgb, float3(0.4123908, 0.3575843, 0.1804808)),
|
||||||
|
dot(rgb, float3(0.2126390, 0.7151687, 0.0721923)),
|
||||||
|
dot(rgb, float3(0.0193308, 0.1191948, 0.9505322)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 xyzToBT709(float3 xyz)
|
||||||
|
{
|
||||||
|
return float3(
|
||||||
|
dot(xyz, float3( 3.2409699, -1.5373832, -0.4986108)),
|
||||||
|
dot(xyz, float3(-0.9692436, 1.8759675, 0.0415551)),
|
||||||
|
dot(xyz, float3( 0.0556301, -0.2039770, 1.0569715)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 xyzToBT2020(float3 xyz)
|
||||||
|
{
|
||||||
|
return float3(
|
||||||
|
dot(xyz, float3( 1.7166512, -0.3556708, -0.2533663)),
|
||||||
|
dot(xyz, float3(-0.6666844, 1.6164812, 0.0157685)),
|
||||||
|
dot(xyz, float3( 0.0176399, -0.0427706, 0.9421031)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 bt709ToBT2020(float3 rgb)
|
||||||
|
{
|
||||||
|
return xyzToBT2020(bt709ToXYZ(rgb));
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 bt2020ToBT709(float3 rgb)
|
||||||
|
{
|
||||||
|
return float3(
|
||||||
|
dot(rgb, float3( 1.6604910, -0.5876411, -0.0728499)),
|
||||||
|
dot(rgb, float3(-0.1245505, 1.1328999, -0.0083494)),
|
||||||
|
dot(rgb, float3(-0.0181508, -0.1005789, 1.1187297)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 linearToPQ(float3 value)
|
||||||
|
{
|
||||||
|
const float m1 = 0.1593017578125;
|
||||||
|
const float m2 = 78.84375;
|
||||||
|
const float c1 = 0.8359375;
|
||||||
|
const float c2 = 18.8515625;
|
||||||
|
const float c3 = 18.6875;
|
||||||
|
float3 p = pow3(max(value, 0.0), m1);
|
||||||
|
return pow3((c1 + c2 * p) / (1.0 + c3 * p), m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 pqToLinear(float3 value)
|
||||||
|
{
|
||||||
|
const float m1 = 0.1593017578125;
|
||||||
|
const float m2 = 78.84375;
|
||||||
|
const float c1 = 0.8359375;
|
||||||
|
const float c2 = 18.8515625;
|
||||||
|
const float c3 = 18.6875;
|
||||||
|
float3 p = pow3(max(value, 0.0), 1.0 / m2);
|
||||||
|
return pow3(max(p - c1, 0.0) / max(c2 - c3 * p, 0.000001),
|
||||||
|
1.0 / m1);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 applyLUT(float3 value)
|
||||||
|
{
|
||||||
|
float3 pos = clamp(value, 0.0, 1.0) * 4095.0;
|
||||||
|
float3 lo = floor(pos);
|
||||||
|
float3 hi = min(lo + 1.0, 4095.0);
|
||||||
|
float3 f = frac(pos);
|
||||||
|
float2 rlo = float2((lo.r + 0.5) / 4096.0, 0.5);
|
||||||
|
float2 rhi = float2((hi.r + 0.5) / 4096.0, 0.5);
|
||||||
|
float2 glo = float2((lo.g + 0.5) / 4096.0, 0.5);
|
||||||
|
float2 ghi = float2((hi.g + 0.5) / 4096.0, 0.5);
|
||||||
|
float2 blo = float2((lo.b + 0.5) / 4096.0, 0.5);
|
||||||
|
float2 bhi = float2((hi.b + 0.5) / 4096.0, 0.5);
|
||||||
|
return float3(
|
||||||
|
lerp(colorLUT.Sample(lut_sampler, rlo).r,
|
||||||
|
colorLUT.Sample(lut_sampler, rhi).r, f.r),
|
||||||
|
lerp(colorLUT.Sample(lut_sampler, glo).g,
|
||||||
|
colorLUT.Sample(lut_sampler, ghi).g, f.g),
|
||||||
|
lerp(colorLUT.Sample(lut_sampler, blo).b,
|
||||||
|
colorLUT.Sample(lut_sampler, bhi).b, f.b));
|
||||||
|
}
|
||||||
|
|
||||||
float4 PSCursor(VertData vert_in) : TARGET
|
float4 PSCursor(VertData vert_in) : TARGET
|
||||||
{
|
{
|
||||||
float4 pixel = image.Sample(def_sampler, vert_in.uv);
|
float4 pixel = image.Sample(def_sampler, vert_in.uv);
|
||||||
@@ -46,7 +155,40 @@ float4 PSCursor(VertData vert_in) : TARGET
|
|||||||
/* Cursor RGB is premultiplied in nonlinear sRGB. Recover the straight
|
/* Cursor RGB is premultiplied in nonlinear sRGB. Recover the straight
|
||||||
* color before decoding it, then premultiply again in linear light. */
|
* color before decoding it, then premultiply again in linear light. */
|
||||||
float3 srgb = clamp(pixel.rgb / pixel.a, 0.0, 1.0);
|
float3 srgb = clamp(pixel.rgb / pixel.a, 0.0, 1.0);
|
||||||
pixel.rgb = srgbToLinear(srgb) * pixel.a * multiplier;
|
float3 value = srgbToLinear(srgb);
|
||||||
|
if (matrixEnabled)
|
||||||
|
{
|
||||||
|
float3 xyz = bt709ToXYZ(value);
|
||||||
|
xyz = float3(
|
||||||
|
dot(float4(xyz, 1.0), colorMatrix0),
|
||||||
|
dot(float4(xyz, 1.0), colorMatrix1),
|
||||||
|
dot(float4(xyz, 1.0), colorMatrix2)) * colorScalar;
|
||||||
|
value = outputTransfer == 2 ? xyzToBT2020(xyz) : xyzToBT709(xyz);
|
||||||
|
}
|
||||||
|
else if (outputTransfer == 2)
|
||||||
|
value = bt709ToBT2020(value);
|
||||||
|
|
||||||
|
if (outputTransfer == 2)
|
||||||
|
{
|
||||||
|
value = linearToPQ(value * (sdrWhiteLevel / 10000.0));
|
||||||
|
if (lutEnabled)
|
||||||
|
value = applyLUT(value);
|
||||||
|
value = bt2020ToBT709(pqToLinear(value)) * 125.0;
|
||||||
|
}
|
||||||
|
else if (outputTransfer == 1)
|
||||||
|
{
|
||||||
|
value *= multiplier;
|
||||||
|
if (lutEnabled)
|
||||||
|
value = applyLUT(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = linearToSrgb(value);
|
||||||
|
if (lutEnabled)
|
||||||
|
value = applyLUT(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel.rgb = value * pixel.a;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pixel.rgb = float3(0.0, 0.0, 0.0);
|
pixel.rgb = float3(0.0, 0.0, 0.0);
|
||||||
|
|||||||
156
obs/lg.c
156
obs/lg.c
@@ -105,7 +105,7 @@ typedef struct
|
|||||||
bool hideMouse;
|
bool hideMouse;
|
||||||
bool hdr;
|
bool hdr;
|
||||||
bool hdrPQ;
|
bool hdrPQ;
|
||||||
float sdrWhiteLevel; // source SDR white level in nits
|
_Atomic(float) sdrWhiteLevel; // source cursor white level in nits
|
||||||
struct vec3 colorMatrix[3]; // source primaries -> BT.709 (linear)
|
struct vec3 colorMatrix[3]; // source primaries -> BT.709 (linear)
|
||||||
float hdrScale; // scRGB reference white scaling
|
float hdrScale; // scRGB reference white scaling
|
||||||
#if LIBOBS_API_MAJOR_VER >= 27
|
#if LIBOBS_API_MAJOR_VER >= 27
|
||||||
@@ -132,6 +132,11 @@ typedef struct
|
|||||||
os_sem_t * cursorSem;
|
os_sem_t * cursorSem;
|
||||||
atomic_uint cursorVer;
|
atomic_uint cursorVer;
|
||||||
unsigned int cursorCurVer;
|
unsigned int cursorCurVer;
|
||||||
|
KVMFRColorTransform pendingCursorTransform;
|
||||||
|
KVMFRColorTransform activeCursorTransform;
|
||||||
|
atomic_uint cursorTransformVer;
|
||||||
|
unsigned int cursorTransformCurVer;
|
||||||
|
gs_texture_t * cursorLUT;
|
||||||
uint32_t cursorSize;
|
uint32_t cursorSize;
|
||||||
uint32_t * cursorData;
|
uint32_t * cursorData;
|
||||||
|
|
||||||
@@ -149,6 +154,13 @@ typedef struct
|
|||||||
gs_effect_t * cursorEffect;
|
gs_effect_t * cursorEffect;
|
||||||
gs_eparam_t * cursorImage;
|
gs_eparam_t * cursorImage;
|
||||||
gs_eparam_t * cursorMultiplier;
|
gs_eparam_t * cursorMultiplier;
|
||||||
|
gs_eparam_t * cursorSDRWhiteLevel;
|
||||||
|
gs_eparam_t * cursorOutputTransfer;
|
||||||
|
gs_eparam_t * cursorMatrixEnabled;
|
||||||
|
gs_eparam_t * cursorLUTEnabled;
|
||||||
|
gs_eparam_t * cursorColorMatrix[3];
|
||||||
|
gs_eparam_t * cursorColorScalar;
|
||||||
|
gs_eparam_t * cursorColorLUT;
|
||||||
}
|
}
|
||||||
LGPlugin;
|
LGPlugin;
|
||||||
|
|
||||||
@@ -231,11 +243,31 @@ static void * lgCreate(obs_data_t * settings, obs_source_t * context)
|
|||||||
this->cursorEffect, "image" );
|
this->cursorEffect, "image" );
|
||||||
this->cursorMultiplier = gs_effect_get_param_by_name(
|
this->cursorMultiplier = gs_effect_get_param_by_name(
|
||||||
this->cursorEffect, "multiplier");
|
this->cursorEffect, "multiplier");
|
||||||
|
this->cursorSDRWhiteLevel = gs_effect_get_param_by_name(
|
||||||
|
this->cursorEffect, "sdrWhiteLevel");
|
||||||
|
this->cursorOutputTransfer = gs_effect_get_param_by_name(
|
||||||
|
this->cursorEffect, "outputTransfer");
|
||||||
|
this->cursorMatrixEnabled = gs_effect_get_param_by_name(
|
||||||
|
this->cursorEffect, "matrixEnabled");
|
||||||
|
this->cursorLUTEnabled = gs_effect_get_param_by_name(
|
||||||
|
this->cursorEffect, "lutEnabled");
|
||||||
|
this->cursorColorMatrix[0] = gs_effect_get_param_by_name(
|
||||||
|
this->cursorEffect, "colorMatrix0");
|
||||||
|
this->cursorColorMatrix[1] = gs_effect_get_param_by_name(
|
||||||
|
this->cursorEffect, "colorMatrix1");
|
||||||
|
this->cursorColorMatrix[2] = gs_effect_get_param_by_name(
|
||||||
|
this->cursorEffect, "colorMatrix2");
|
||||||
|
this->cursorColorScalar = gs_effect_get_param_by_name(
|
||||||
|
this->cursorEffect, "colorScalar");
|
||||||
|
this->cursorColorLUT = gs_effect_get_param_by_name(
|
||||||
|
this->cursorEffect, "colorLUT");
|
||||||
obs_leave_graphics();
|
obs_leave_graphics();
|
||||||
|
|
||||||
os_sem_init (&this->frameSem , 0);
|
os_sem_init (&this->frameSem , 0);
|
||||||
os_sem_init (&this->cursorSem, 1);
|
os_sem_init (&this->cursorSem, 1);
|
||||||
atomic_store(&this->cursorVer, 0);
|
atomic_store(&this->cursorVer, 0);
|
||||||
|
atomic_store(&this->cursorTransformVer, 0);
|
||||||
|
atomic_store(&this->sdrWhiteLevel, KVMFR_SDR_WHITE_LEVEL_DEFAULT);
|
||||||
lgUpdate(this, settings);
|
lgUpdate(this, settings);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -353,6 +385,21 @@ static void deinit(LGPlugin * this)
|
|||||||
this->cursorXorTex = NULL;
|
this->cursorXorTex = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->cursorLUT)
|
||||||
|
{
|
||||||
|
gs_effect_set_texture(this->cursorColorLUT, NULL);
|
||||||
|
gs_texture_destroy(this->cursorLUT);
|
||||||
|
this->cursorLUT = NULL;
|
||||||
|
}
|
||||||
|
memset(&this->pendingCursorTransform, 0,
|
||||||
|
sizeof(this->pendingCursorTransform));
|
||||||
|
memset(&this->activeCursorTransform, 0,
|
||||||
|
sizeof(this->activeCursorTransform));
|
||||||
|
this->pendingCursorTransform.scalar = 1.0f;
|
||||||
|
this->activeCursorTransform.scalar = 1.0f;
|
||||||
|
atomic_store(&this->cursorTransformVer, 0);
|
||||||
|
this->cursorTransformCurVer = 0;
|
||||||
|
|
||||||
#if LIBOBS_API_MAJOR_VER >= 27
|
#if LIBOBS_API_MAJOR_VER >= 27
|
||||||
dmabufReset(this);
|
dmabufReset(this);
|
||||||
#endif
|
#endif
|
||||||
@@ -488,8 +535,13 @@ static void * pointerThread(void * data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const KVMFRCursor * const cursor = (const KVMFRCursor * const)msg.mem;
|
const KVMFRCursor * const cursor = (const KVMFRCursor * const)msg.mem;
|
||||||
this->cursorVisible = this->hideMouse ?
|
if (msg.udata & CURSOR_FLAG_VISIBLE_VALID)
|
||||||
0 : msg.udata & CURSOR_FLAG_VISIBLE;
|
{
|
||||||
|
this->cursorVisible = this->hideMouse ?
|
||||||
|
0 : msg.udata & CURSOR_FLAG_VISIBLE;
|
||||||
|
if (cursor->sdrWhiteLevel)
|
||||||
|
atomic_store(&this->sdrWhiteLevel, cursor->sdrWhiteLevel);
|
||||||
|
}
|
||||||
|
|
||||||
if (msg.udata & CURSOR_FLAG_SHAPE)
|
if (msg.udata & CURSOR_FLAG_SHAPE)
|
||||||
{
|
{
|
||||||
@@ -576,6 +628,21 @@ static void * pointerThread(void * data)
|
|||||||
os_sem_post(this->cursorSem);
|
os_sem_post(this->cursorSem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (msg.udata & CURSOR_FLAG_COLOR_TRANSFORM)
|
||||||
|
{
|
||||||
|
const size_t shapeSize = msg.udata & CURSOR_FLAG_SHAPE ?
|
||||||
|
(size_t)cursor->height * cursor->pitch : 0;
|
||||||
|
const KVMFRColorTransform * transform =
|
||||||
|
(const KVMFRColorTransform *)((const uint8_t *)(cursor + 1) +
|
||||||
|
shapeSize);
|
||||||
|
|
||||||
|
os_sem_wait(this->cursorSem);
|
||||||
|
this->pendingCursorTransform = *transform;
|
||||||
|
atomic_fetch_add_explicit(
|
||||||
|
&this->cursorTransformVer, 1, memory_order_release);
|
||||||
|
os_sem_post(this->cursorSem);
|
||||||
|
}
|
||||||
|
|
||||||
if (msg.udata & CURSOR_FLAG_POSITION)
|
if (msg.udata & CURSOR_FLAG_POSITION)
|
||||||
{
|
{
|
||||||
this->cursor.x = cursor->x;
|
this->cursor.x = cursor->x;
|
||||||
@@ -882,8 +949,8 @@ static void lgFormatInit(LGPlugin * this, const KVMFRFrame * frame,
|
|||||||
this->unpack = false;
|
this->unpack = false;
|
||||||
this->hdr = frame->flags & FRAME_FLAG_HDR;
|
this->hdr = frame->flags & FRAME_FLAG_HDR;
|
||||||
this->hdrPQ = frame->flags & FRAME_FLAG_HDR_PQ;
|
this->hdrPQ = frame->flags & FRAME_FLAG_HDR_PQ;
|
||||||
this->sdrWhiteLevel = frame->sdrWhiteLevel ?
|
atomic_store(&this->sdrWhiteLevel, frame->sdrWhiteLevel ?
|
||||||
frame->sdrWhiteLevel : KVMFR_SDR_WHITE_LEVEL_DEFAULT;
|
frame->sdrWhiteLevel : KVMFR_SDR_WHITE_LEVEL_DEFAULT);
|
||||||
|
|
||||||
if (this->hdr && this->hdrPQ)
|
if (this->hdr && this->hdrPQ)
|
||||||
lgComputeColorMatrix(this);
|
lgComputeColorMatrix(this);
|
||||||
@@ -1113,6 +1180,36 @@ static void lgVideoTick(void * data, float seconds)
|
|||||||
os_sem_post(this->cursorSem);
|
os_sem_post(this->cursorSem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const unsigned int cursorTransformVer = atomic_load_explicit(
|
||||||
|
&this->cursorTransformVer, memory_order_acquire);
|
||||||
|
if (cursorTransformVer != this->cursorTransformCurVer)
|
||||||
|
{
|
||||||
|
os_sem_wait(this->cursorSem);
|
||||||
|
this->activeCursorTransform = this->pendingCursorTransform;
|
||||||
|
|
||||||
|
obs_enter_graphics();
|
||||||
|
if (this->cursorLUT)
|
||||||
|
{
|
||||||
|
gs_effect_set_texture(this->cursorColorLUT, NULL);
|
||||||
|
gs_texture_destroy(this->cursorLUT);
|
||||||
|
this->cursorLUT = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->activeCursorTransform.flags & KVMFR_COLOR_TRANSFORM_LUT)
|
||||||
|
{
|
||||||
|
const uint8_t * lut =
|
||||||
|
(const uint8_t *)this->activeCursorTransform.lut;
|
||||||
|
this->cursorLUT = gs_texture_create(
|
||||||
|
4096, 1, GS_RGBA32F, 1, &lut, GS_DYNAMIC);
|
||||||
|
if (!this->cursorLUT)
|
||||||
|
blog(LOG_ERROR, "Failed to create cursor colour-transform LUT");
|
||||||
|
}
|
||||||
|
obs_leave_graphics();
|
||||||
|
|
||||||
|
this->cursorTransformCurVer = cursorTransformVer;
|
||||||
|
os_sem_post(this->cursorSem);
|
||||||
|
}
|
||||||
|
|
||||||
if ((status = lgmpClientAdvanceToLast(this->frameQueue)) != LGMP_OK)
|
if ((status = lgmpClientAdvanceToLast(this->frameQueue)) != LGMP_OK)
|
||||||
{
|
{
|
||||||
if (status != LGMP_ERR_QUEUE_EMPTY)
|
if (status != LGMP_ERR_QUEUE_EMPTY)
|
||||||
@@ -1206,6 +1303,29 @@ static void lgVideoTick(void * data, float seconds)
|
|||||||
obs_leave_graphics();
|
obs_leave_graphics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lgSetupCursorEffect(LGPlugin * this, int outputTransfer)
|
||||||
|
{
|
||||||
|
const KVMFRColorTransform * transform = &this->activeCursorTransform;
|
||||||
|
const bool matrixEnabled =
|
||||||
|
transform->flags & KVMFR_COLOR_TRANSFORM_MATRIX;
|
||||||
|
const bool lutEnabled =
|
||||||
|
(transform->flags & KVMFR_COLOR_TRANSFORM_LUT) && this->cursorLUT;
|
||||||
|
const float whiteLevel = atomic_load(&this->sdrWhiteLevel);
|
||||||
|
|
||||||
|
gs_effect_set_float(this->cursorMultiplier,
|
||||||
|
whiteLevel / LG_SCRGB_REFERENCE_WHITE);
|
||||||
|
gs_effect_set_float(this->cursorSDRWhiteLevel, whiteLevel);
|
||||||
|
gs_effect_set_int(this->cursorOutputTransfer, outputTransfer);
|
||||||
|
gs_effect_set_bool(this->cursorMatrixEnabled, matrixEnabled);
|
||||||
|
gs_effect_set_bool(this->cursorLUTEnabled, lutEnabled);
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
gs_effect_set_val(this->cursorColorMatrix[i],
|
||||||
|
transform->matrix[i], sizeof(transform->matrix[i]));
|
||||||
|
gs_effect_set_float(this->cursorColorScalar, transform->scalar);
|
||||||
|
if (lutEnabled)
|
||||||
|
gs_effect_set_texture(this->cursorColorLUT, this->cursorLUT);
|
||||||
|
}
|
||||||
|
|
||||||
static void lgVideoRender(void * data, gs_effect_t * effect)
|
static void lgVideoRender(void * data, gs_effect_t * effect)
|
||||||
{
|
{
|
||||||
LGPlugin * this = (LGPlugin *)data;
|
LGPlugin * this = (LGPlugin *)data;
|
||||||
@@ -1275,20 +1395,24 @@ static void lgVideoRender(void * data, gs_effect_t * effect)
|
|||||||
* linear scRGB space, decode them and reproduce the source display's SDR
|
* linear scRGB space, decode them and reproduce the source display's SDR
|
||||||
* white level reported by the IDD. */
|
* white level reported by the IDD. */
|
||||||
bool mapCursorToScRGB = false;
|
bool mapCursorToScRGB = false;
|
||||||
float cursorScale = 1.0f;
|
|
||||||
#if LIBOBS_API_MAJOR_VER >= 28
|
#if LIBOBS_API_MAJOR_VER >= 28
|
||||||
mapCursorToScRGB = this->colorSpace == GS_CS_709_SCRGB;
|
mapCursorToScRGB = this->colorSpace == GS_CS_709_SCRGB;
|
||||||
if (mapCursorToScRGB)
|
|
||||||
cursorScale = this->sdrWhiteLevel / LG_SCRGB_REFERENCE_WHITE;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
effect = mapCursorToScRGB && !this->cursorMono ?
|
const bool hasCursorTransform =
|
||||||
|
this->activeCursorTransform.flags != 0;
|
||||||
|
const bool useCursorEffect = !this->cursorMono &&
|
||||||
|
(mapCursorToScRGB || hasCursorTransform);
|
||||||
|
const int cursorOutputTransfer = !mapCursorToScRGB ? 0 :
|
||||||
|
(this->hdrPQ ? 2 : 1);
|
||||||
|
|
||||||
|
effect = useCursorEffect ?
|
||||||
this->cursorEffect : obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
this->cursorEffect : obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
||||||
gs_eparam_t * image = mapCursorToScRGB && !this->cursorMono ?
|
gs_eparam_t * image = useCursorEffect ?
|
||||||
this->cursorImage : gs_effect_get_param_by_name(effect, "image");
|
this->cursorImage : gs_effect_get_param_by_name(effect, "image");
|
||||||
gs_effect_set_texture(image, this->cursorTex);
|
gs_effect_set_texture(image, this->cursorTex);
|
||||||
if (mapCursorToScRGB && !this->cursorMono)
|
if (useCursorEffect)
|
||||||
gs_effect_set_float(this->cursorMultiplier, cursorScale);
|
lgSetupCursorEffect(this, cursorOutputTransfer);
|
||||||
|
|
||||||
gs_matrix_push();
|
gs_matrix_push();
|
||||||
gs_matrix_translate3f(
|
gs_matrix_translate3f(
|
||||||
@@ -1310,13 +1434,13 @@ static void lgVideoRender(void * data, gs_effect_t * effect)
|
|||||||
if (this->cursor.type == CURSOR_TYPE_MASKED_COLOR &&
|
if (this->cursor.type == CURSOR_TYPE_MASKED_COLOR &&
|
||||||
this->cursorXorTex)
|
this->cursorXorTex)
|
||||||
{
|
{
|
||||||
effect = mapCursorToScRGB ?
|
effect = useCursorEffect ?
|
||||||
this->cursorEffect : obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
this->cursorEffect : obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
||||||
image = mapCursorToScRGB ?
|
image = useCursorEffect ?
|
||||||
this->cursorImage : gs_effect_get_param_by_name(effect, "image");
|
this->cursorImage : gs_effect_get_param_by_name(effect, "image");
|
||||||
gs_effect_set_texture(image, this->cursorXorTex);
|
gs_effect_set_texture(image, this->cursorXorTex);
|
||||||
if (mapCursorToScRGB)
|
if (useCursorEffect)
|
||||||
gs_effect_set_float(this->cursorMultiplier, cursorScale);
|
lgSetupCursorEffect(this, cursorOutputTransfer);
|
||||||
gs_blend_function_separate(
|
gs_blend_function_separate(
|
||||||
GS_BLEND_INVDSTCOLOR, GS_BLEND_INVSRCALPHA,
|
GS_BLEND_INVDSTCOLOR, GS_BLEND_INVSRCALPHA,
|
||||||
GS_BLEND_ZERO , GS_BLEND_ONE);
|
GS_BLEND_ZERO , GS_BLEND_ONE);
|
||||||
|
|||||||
Reference in New Issue
Block a user