Skip to content

Commit c282e18

Browse files
committed
Set right dimmingRatio for fp16 input layers without metadata
...since 1.0 == SDR white, we can program these layers by sending SDR/HDR as the dimmingRatio to map the degamma'd value at HDR/SDR to the max panel lux. It's a little counter-intuitive at first glance, because we're sending a dimming ratio < 1.0 for an HDR layer which looks like we're intending to dim the layer. But it makes sense just from the math: layer_luminance = panel_luminance * srgb_EOTF(layer_input) * (SDR_white / panel_luminance) = srgb_EOTF(layer_input) * SDR_white. For an entirely SDR layer, then the layer luminance is capped by SDR_white as desired, and for a layer that was rendered with an HDR/SDR ratio then the layer luminance cancels out to HDR_white == panel_luminance. And, we *are* dimming the layer: since for a full range layer 1.0 before this infrastructure was in place would have mapped to the max panel luminance. Now, the HDR/SDR ratio may have differed by the time we hit the panel (the layer is slightly in the past), but assuming the ratio changed slowly: * If HDR/SDR increased, then we dim the layer a bit more than the application intended, but the user does not notice because the SDR white point stayed the same; the application just used less headroom than it could have. * If HDR/SDR decreased, then we dim the layer less than the application intended, but the panel can just clip Bug: 236745178 Flag: com.android.graphics.surfaceflinger.flags.fp16_client_target Test: builds Test: courage Change-Id: I85a0d978f994d495e34dfbdd9dc7b03bd64f293c
1 parent f74bfe1 commit c282e18

2 files changed

Lines changed: 19 additions & 7 deletions

File tree

libs/ui/include_types/ui/HdrRenderTypeUtils.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ enum class HdrRenderType {
3636
*/
3737
inline HdrRenderType getHdrRenderType(ui::Dataspace dataspace,
3838
std::optional<ui::PixelFormat> pixelFormat,
39-
float hdrSdrRatio = 1.f) {
39+
float hdrSdrRatio = 1.f, bool hasHdrMetadata = false) {
4040
const auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK;
4141
const auto range = dataspace & HAL_DATASPACE_RANGE_MASK;
4242

@@ -49,7 +49,8 @@ inline HdrRenderType getHdrRenderType(ui::Dataspace dataspace,
4949
HAL_DATASPACE_RANGE_EXTENDED);
5050

5151
if ((dataspace == BT2020_LINEAR_EXT || dataspace == ui::Dataspace::V0_SCRGB) &&
52-
pixelFormat.has_value() && pixelFormat.value() == ui::PixelFormat::RGBA_FP16) {
52+
pixelFormat.has_value() && pixelFormat.value() == ui::PixelFormat::RGBA_FP16 &&
53+
hasHdrMetadata) {
5354
return HdrRenderType::GENERIC_HDR;
5455
}
5556

services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,11 @@ void OutputLayer::updateCompositionState(
315315
layerFEState->buffer->getPixelFormat()))
316316
: std::nullopt;
317317

318-
auto hdrRenderType =
319-
getHdrRenderType(outputState.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio);
318+
// prefer querying this from gralloc instead to catch 2094-10 metadata
319+
const bool hasHdrMetadata = layerFEState->hdrMetadata.validTypes != 0;
320+
321+
auto hdrRenderType = getHdrRenderType(outputState.dataspace, pixelFormat,
322+
layerFEState->desiredHdrSdrRatio, hasHdrMetadata);
320323

321324
// Determine the output dependent dataspace for this layer. If it is
322325
// colorspace agnostic, it just uses the dataspace chosen for the output to
@@ -339,8 +342,8 @@ void OutputLayer::updateCompositionState(
339342
}
340343

341344
// re-get HdrRenderType after the dataspace gets changed.
342-
hdrRenderType =
343-
getHdrRenderType(state.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio);
345+
hdrRenderType = getHdrRenderType(state.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio,
346+
hasHdrMetadata);
344347

345348
// For hdr content, treat the white point as the display brightness - HDR content should not be
346349
// boosted or dimmed.
@@ -351,12 +354,20 @@ void OutputLayer::updateCompositionState(
351354
state.dimmingRatio = 1.f;
352355
state.whitePointNits = getOutput().getState().displayBrightnessNits;
353356
} else {
357+
const bool isLayerFp16 = pixelFormat && *pixelFormat == ui::PixelFormat::RGBA_FP16;
354358
float layerBrightnessNits = getOutput().getState().sdrWhitePointNits;
355359
// RANGE_EXTENDED can "self-promote" to HDR, but is still rendered for a particular
356360
// range that we may need to re-adjust to the current display conditions
361+
// Do NOT do this when we may render fp16 to an fp16 client target, to avoid applying
362+
// and additional gain to the layer. This is because the fp16 client target should
363+
// already be adapted to remap 1.0 to the SDR white point in the panel's luminance
364+
// space.
357365
if (hdrRenderType == HdrRenderType::DISPLAY_HDR) {
358-
layerBrightnessNits *= layerFEState->currentHdrSdrRatio;
366+
if (!FlagManager::getInstance().fp16_client_target() || !isLayerFp16) {
367+
layerBrightnessNits *= layerFEState->currentHdrSdrRatio;
368+
}
359369
}
370+
360371
state.dimmingRatio =
361372
std::clamp(layerBrightnessNits / getOutput().getState().displayBrightnessNits, 0.f,
362373
1.f);

0 commit comments

Comments
 (0)