From 4abbf33e9f1f2b8e8dba15ce08273484b93be64e Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Sun, 19 Jul 2026 17:34:40 +1000 Subject: [PATCH] [obs] hdr: correct logical and color cursor composition Keep masked-color XOR operands on the untransformed logical path rather than applying the color cursor shader. Preserve the white level delivered with cursor updates instead of replacing it with frame SDR white during format changes. This keeps inverse-destination blending intact and ensures HDR cursor brightness follows QueryHardwareCursor3. --- obs/lg.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/obs/lg.c b/obs/lg.c index 95693fb8..aa909c1c 100644 --- a/obs/lg.c +++ b/obs/lg.c @@ -949,8 +949,8 @@ static void lgFormatInit(LGPlugin * this, const KVMFRFrame * frame, this->unpack = false; this->hdr = frame->flags & FRAME_FLAG_HDR; this->hdrPQ = frame->flags & FRAME_FLAG_HDR_PQ; - atomic_store(&this->sdrWhiteLevel, frame->sdrWhiteLevel ? - frame->sdrWhiteLevel : KVMFR_SDR_WHITE_LEVEL_DEFAULT); + /* Keep the white level supplied with the cursor message. The frame value + * is only a general SDR-content level and can differ from QueryHWCursor3. */ if (this->hdr && this->hdrPQ) lgComputeColorMatrix(this); @@ -1434,13 +1434,12 @@ static void lgVideoRender(void * data, gs_effect_t * effect) if (this->cursor.type == CURSOR_TYPE_MASKED_COLOR && this->cursorXorTex) { - effect = useCursorEffect ? - this->cursorEffect : obs_get_base_effect(OBS_EFFECT_DEFAULT); - image = useCursorEffect ? - this->cursorImage : gs_effect_get_param_by_name(effect, "image"); + /* The XOR plane is a logical operand, not SDR colour. Applying the + * cursor colour transform or white-level mapping changes the mask + * before the inverse-destination blend. */ + effect = obs_get_base_effect(OBS_EFFECT_DEFAULT); + image = gs_effect_get_param_by_name(effect, "image"); gs_effect_set_texture(image, this->cursorXorTex); - if (useCursorEffect) - lgSetupCursorEffect(this, cursorOutputTransfer); gs_blend_function_separate( GS_BLEND_INVDSTCOLOR, GS_BLEND_INVSRCALPHA, GS_BLEND_ZERO , GS_BLEND_ONE);