mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-07-15 20:02:05 +00:00
[client] wayland: implement HDR support
This commit is contained in:
@@ -91,6 +91,7 @@ struct EGL_Desktop
|
||||
|
||||
// map HDR content to SDR
|
||||
bool mapHDRtoSDR;
|
||||
bool nativeHDR;
|
||||
int peakLuminance;
|
||||
int maxCLL;
|
||||
|
||||
@@ -548,7 +549,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
{
|
||||
.type = EGL_UNIFORM_TYPE_1I,
|
||||
.location = shader->uCBMode,
|
||||
.f = { desktop->cbMode }
|
||||
.i = { desktop->cbMode }
|
||||
},
|
||||
{
|
||||
.type = EGL_UNIFORM_TYPE_1I,
|
||||
@@ -558,7 +559,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
{
|
||||
.type = EGL_UNIFORM_TYPE_1I,
|
||||
.location = shader->uMapHDRtoSDR,
|
||||
.i = { desktop->mapHDRtoSDR }
|
||||
.i = { desktop->mapHDRtoSDR && !desktop->nativeHDR }
|
||||
},
|
||||
{
|
||||
.type = EGL_UNIFORM_TYPE_1F,
|
||||
@@ -568,7 +569,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
{
|
||||
.type = EGL_UNIFORM_TYPE_1I,
|
||||
.location = shader->uMapHDRPQ,
|
||||
.f = { desktop->hdrPQ }
|
||||
.i = { desktop->hdrPQ }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -579,6 +580,11 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
return true;
|
||||
}
|
||||
|
||||
void egl_desktopSetNativeHDR(EGL_Desktop * desktop, bool nativeHDR)
|
||||
{
|
||||
desktop->nativeHDR = nativeHDR;
|
||||
}
|
||||
|
||||
void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height)
|
||||
{
|
||||
if (!desktop->spiceTexture)
|
||||
|
||||
@@ -42,6 +42,7 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop, EGLDisplay * display,
|
||||
void egl_desktopFree(EGL_Desktop ** desktop);
|
||||
|
||||
void egl_desktopConfigUI(EGL_Desktop * desktop);
|
||||
void egl_desktopSetNativeHDR(EGL_Desktop * desktop, bool nativeHDR);
|
||||
bool egl_desktopSetup (EGL_Desktop * desktop, const LG_RendererFormat format);
|
||||
bool egl_desktopUpdate(EGL_Desktop * desktop, const FrameBuffer * frame, int dmaFd,
|
||||
const FrameDamageRect * damageRects, int damageRectsCount);
|
||||
|
||||
@@ -121,6 +121,9 @@ struct Inst
|
||||
|
||||
bool showSpice;
|
||||
int spiceWidth, spiceHeight;
|
||||
|
||||
bool configSupportsHDR; // true if we probed FP16 or 10-bit EGL config
|
||||
bool hdr; // true if current frame format is HDR
|
||||
};
|
||||
|
||||
static struct Option egl_options[] =
|
||||
@@ -607,6 +610,26 @@ static bool egl_onFrameFormat(LG_Renderer * renderer, const LG_RendererFormat fo
|
||||
egl_cursorSetScale(this->cursor, scale);
|
||||
}
|
||||
|
||||
// Track HDR state and warn if HDR frames arrive without any HDR path
|
||||
this->hdr = format.hdr;
|
||||
if (format.hdr)
|
||||
{
|
||||
bool nativeHDR = false;
|
||||
app_getProp(LG_DS_NATIVE_HDR, &nativeHDR);
|
||||
if (!this->configSupportsHDR && !nativeHDR)
|
||||
DEBUG_WARN("HDR frames being displayed on an 8-bit EGL surface "
|
||||
"without a color-managed compositor; tones may be incorrect");
|
||||
}
|
||||
|
||||
// If the display server supports native HDR (via setHDRImageDescription),
|
||||
// disable software tone-mapping to avoid double tone-mapping.
|
||||
// However, if the last call to setHDRImageDescription actually failed
|
||||
// (e.g., compositor missing required primaries), keep tone-mapping on.
|
||||
bool nativeHDR = false;
|
||||
app_getProp(LG_DS_NATIVE_HDR, &nativeHDR);
|
||||
egl_desktopSetNativeHDR(this->desktop,
|
||||
format.hdr && nativeHDR && !app_getHDRDescFailed());
|
||||
|
||||
egl_update_scale_type(this);
|
||||
egl_damageSetup(this->damage, format.frameWidth, format.frameHeight);
|
||||
|
||||
@@ -774,22 +797,51 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA)
|
||||
}
|
||||
}
|
||||
|
||||
EGLint attr[] =
|
||||
// Probe for best available color depth: FP16 → 10-bit → 8-bit
|
||||
static const struct { EGLint r, g, b, a, depth; const char * desc; } configs[] =
|
||||
{
|
||||
EGL_BUFFER_SIZE , 30,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_SAMPLE_BUFFERS , maxSamples > 0 ? 1 : 0,
|
||||
EGL_SAMPLES , maxSamples,
|
||||
EGL_NONE
|
||||
{ 16, 16, 16, 0, 48, "FP16 (RGBA16F)" },
|
||||
{ 10, 10, 10, 2, 32, "10-bit (RGBA10)" },
|
||||
{ 8, 8, 8, 0, 24, "8-bit (RGBA8)" },
|
||||
};
|
||||
EGLint num_config;
|
||||
const char * configDesc = NULL;
|
||||
int chosen = -1;
|
||||
|
||||
EGLint num_config;
|
||||
if (!eglChooseConfig(this->display, attr, &this->configs, 1, &num_config))
|
||||
for (int i = 0; i < (int)(sizeof(configs) / sizeof(configs[0])); ++i)
|
||||
{
|
||||
DEBUG_ERROR("Failed to choose config (eglError: 0x%x)", eglGetError());
|
||||
EGLint attr[] =
|
||||
{
|
||||
EGL_RED_SIZE , configs[i].r,
|
||||
EGL_GREEN_SIZE , configs[i].g,
|
||||
EGL_BLUE_SIZE , configs[i].b,
|
||||
EGL_ALPHA_SIZE , configs[i].a,
|
||||
EGL_BUFFER_SIZE , configs[i].depth,
|
||||
EGL_RENDERABLE_TYPE , EGL_OPENGL_ES2_BIT,
|
||||
EGL_SAMPLE_BUFFERS , maxSamples > 0 ? 1 : 0,
|
||||
EGL_SAMPLES , maxSamples,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
if (eglChooseConfig(this->display, attr, &this->configs, 1, &num_config) &&
|
||||
num_config > 0)
|
||||
{
|
||||
configDesc = configs[i].desc;
|
||||
chosen = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chosen < 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to choose any EGL config");
|
||||
return false;
|
||||
}
|
||||
|
||||
this->configSupportsHDR = chosen <= 1; // FP16 or 10-bit
|
||||
DEBUG_INFO("EGL config: %s%s", configDesc,
|
||||
this->configSupportsHDR ? " (HDR capable)" : "");
|
||||
|
||||
const EGLint surfattr[] =
|
||||
{
|
||||
EGL_RENDER_BUFFER, this->opt.doubleBuffer ? EGL_BACK_BUFFER : EGL_SINGLE_BUFFER,
|
||||
|
||||
Reference in New Issue
Block a user