End-to-end plumbing for dimming SDR layers
Model here is:
* HDR luminance is set to the current display brightness
* SDR luminance is set to the current SDR white point reported by
DisplayManager
Ideally we use scene-referred white points instead, so:
* PQ is always 10k nits
* HLG is always 1k nits
* Everything else is 150-200 nits
So relative dimming thresholds are fixed. But right now this is visually
less jarring (otherwise youtube UI will suddenly dim when autoplaying
HDR video).
Bug: 200310158
Test: Verified that plumbing sdr white point is sent to renderengine
Test: librenderengine_test
Test: libcompositionengine_test
Test: DataspaceUtils_test
Change-Id: I5bcea7941935c43e57cd5434e1ec69b41d31f2b4
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 02fa49f..4603e6b 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -237,7 +237,8 @@
applyChangedTypesToLayers(changes->changedTypes);
applyDisplayRequests(changes->displayRequests);
applyLayerRequestsToLayers(changes->layerRequests);
- applyClientTargetRequests(changes->clientTargetProperty);
+ applyClientTargetRequests(changes->clientTargetProperty,
+ changes->clientTargetWhitePointNits);
}
// Determine what type of composition we are doing from the final state
@@ -309,12 +310,14 @@
}
}
-void Display::applyClientTargetRequests(const ClientTargetProperty& clientTargetProperty) {
+void Display::applyClientTargetRequests(const ClientTargetProperty& clientTargetProperty,
+ float whitePointNits) {
if (clientTargetProperty.dataspace == ui::Dataspace::UNKNOWN) {
return;
}
editState().dataspace = clientTargetProperty.dataspace;
+ editState().clientTargetWhitePointNits = whitePointNits;
getRenderSurface()->setBufferDataspace(clientTargetProperty.dataspace);
getRenderSurface()->setBufferPixelFormat(clientTargetProperty.pixelFormat);
}
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 6800004..d503153 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -1057,7 +1057,7 @@
clientCompositionDisplay.maxLuminance = outputState.displayBrightnessNits > 0.f
? outputState.displayBrightnessNits
: mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
- clientCompositionDisplay.sdrWhitePointNits = outputState.sdrWhitePointNits;
+ clientCompositionDisplay.targetLuminanceNits = outputState.clientTargetWhitePointNits;
// Compute the global color transform matrix.
if (!outputState.usesDeviceComposition && !getSkipColorTransform()) {
@@ -1217,7 +1217,8 @@
.dataspace = outputDataspace,
.realContentIsVisible = realContentIsVisible,
.clearContent = !clientComposition,
- .blurSetting = blurSetting};
+ .blurSetting = blurSetting,
+ .whitePointNits = layerState.whitePointNits};
results = layerFE.prepareClientCompositionList(targetSettings);
if (realContentIsVisible && !results.empty()) {
layer->editState().clientCompositionTimestamp = systemTime();
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index cf76183..b010d9f 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -24,6 +24,9 @@
#include <compositionengine/impl/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <cstdint>
+#include "system/graphics-base-v1.0.h"
+
+#include <ui/DataspaceUtils.h>
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
@@ -317,6 +320,14 @@
? outputState.targetDataspace
: layerFEState->dataspace;
+ // For hdr content, treat the white point as the display brightness - HDR content should not be
+ // boosted or dimmed.
+ if (isHdrDataspace(state.dataspace)) {
+ state.whitePointNits = getOutput().getState().displayBrightnessNits;
+ } else {
+ state.whitePointNits = getOutput().getState().sdrWhitePointNits;
+ }
+
// These are evaluated every frame as they can potentially change at any
// time.
if (layerFEState->forceClientComposition || !profile.isDataspaceSupported(state.dataspace) ||
@@ -479,6 +490,16 @@
ALOGE("[%s] Failed to set dataspace %d: %s (%d)", getLayerFE().getDebugName(), dataspace,
to_string(error).c_str(), static_cast<int32_t>(error));
}
+
+ // Don't dim cached layers
+ const auto whitePointNits = outputDependentState.overrideInfo.buffer
+ ? getOutput().getState().displayBrightnessNits
+ : outputDependentState.whitePointNits;
+
+ if (auto error = hwcLayer->setWhitePointNits(whitePointNits); error != hal::Error::NONE) {
+ ALOGE("[%s] Failed to set white point %f: %s (%d)", getLayerFE().getDebugName(),
+ whitePointNits, to_string(error).c_str(), static_cast<int32_t>(error));
+ }
}
void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
index ff96d94..2203f22 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -170,6 +170,7 @@
.clip = viewport,
.outputDataspace = outputDataspace,
.orientation = orientation,
+ .targetLuminanceNits = outputState.displayBrightnessNits,
};
LayerFE::ClientCompositionTargetSettings targetSettings{
@@ -182,6 +183,7 @@
.realContentIsVisible = true,
.clearContent = false,
.blurSetting = LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
+ .whitePointNits = outputState.displayBrightnessNits,
};
std::vector<renderengine::LayerSettings> layerSettings;