Send dimming ratio to composer instead of white point nits
* Send the dimming ratio over to composer as the HWC api is changing to
not expose the notion of nits to composer, as the white point nits are
part of logical SF state that does not map as nicely to display
hardware
* Fixes an issue where scheduling a recomposite for a frame when
brightness changes is contingent on the presence of HDR layers, which
is not valid when an HDR layer exits the scene, but DisplayManager
animates the display brightness down to the SDR white point.
Bug: 217961164
Test: builds, boots
Test: HDR test videos on youtube
Change-Id: Icc07b00f60859bbd3ee078cd2bb793eda42e7781
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index 08cfaa6..2b383c1 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -153,9 +153,11 @@
// Timestamp for when the layer is queued for client composition
nsecs_t clientCompositionTimestamp{0};
- // White point of the layer, in nits.
static constexpr float kDefaultWhitePointNits = 200.f;
float whitePointNits = kDefaultWhitePointNits;
+ // Dimming ratio of the layer from [0, 1]
+ static constexpr float kDefaultDimmingRatio = 1.f;
+ float dimmingRatio = kDefaultDimmingRatio;
};
} // namespace compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 4ccf11f..3e983f3 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -324,9 +324,14 @@
// For hdr content, treat the white point as the display brightness - HDR content should not be
// boosted or dimmed.
- if (isHdrDataspace(state.dataspace)) {
+ if (isHdrDataspace(state.dataspace) ||
+ getOutput().getState().displayBrightnessNits == getOutput().getState().sdrWhitePointNits) {
+ state.dimmingRatio = 1.f;
state.whitePointNits = getOutput().getState().displayBrightnessNits;
} else {
+ state.dimmingRatio = std::clamp(getOutput().getState().sdrWhitePointNits /
+ getOutput().getState().displayBrightnessNits,
+ 0.f, 1.f);
state.whitePointNits = getOutput().getState().sdrWhitePointNits;
}
@@ -502,13 +507,12 @@
}
// Don't dim cached layers
- const auto whitePointNits = outputDependentState.overrideInfo.buffer
- ? getOutput().getState().displayBrightnessNits
- : outputDependentState.whitePointNits;
+ const auto dimmingRatio =
+ outputDependentState.overrideInfo.buffer ? 1.f : outputDependentState.dimmingRatio;
- 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));
+ if (auto error = hwcLayer->setBrightness(dimmingRatio); error != hal::Error::NONE) {
+ ALOGE("[%s] Failed to set brightness %f: %s (%d)", getLayerFE().getDebugName(),
+ dimmingRatio, to_string(error).c_str(), static_cast<int32_t>(error));
}
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
index 5185ea9..d933b94 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
@@ -74,7 +74,7 @@
MOCK_METHOD1(setColorTransform, Error(const android::mat4&));
MOCK_METHOD3(setLayerGenericMetadata,
Error(const std::string&, bool, const std::vector<uint8_t>&));
- MOCK_METHOD1(setWhitePointNits, Error(float));
+ MOCK_METHOD1(setBrightness, Error(float));
MOCK_METHOD1(setBlockingRegion, Error(const android::Region&));
};
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 82dcc66..dda0822 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -751,6 +751,8 @@
static constexpr bool kLayerGenericMetadata2Mandatory = true;
static constexpr float kWhitePointNits = 200.f;
static constexpr float kDisplayBrightnessNits = 400.f;
+ static constexpr float kLayerBrightness = kWhitePointNits / kDisplayBrightnessNits;
+ static constexpr float kFullLayerBrightness = 1.f;
static const half4 kColor;
static const Rect kDisplayFrame;
@@ -782,6 +784,7 @@
outputLayerState.outputSpaceVisibleRegion = kOutputSpaceVisibleRegion;
outputLayerState.dataspace = kDataspace;
outputLayerState.whitePointNits = kWhitePointNits;
+ outputLayerState.dimmingRatio = kLayerBrightness;
mLayerFEState.blendMode = kBlendMode;
mLayerFEState.alpha = kAlpha;
@@ -846,11 +849,11 @@
ui::Dataspace dataspace = kDataspace,
const Region& visibleRegion = kOutputSpaceVisibleRegion,
const Region& surfaceDamage = kSurfaceDamage,
- float whitePointNits = kWhitePointNits,
+ float brightness = kLayerBrightness,
const Region& blockingRegion = Region()) {
EXPECT_CALL(*mHwcLayer, setVisibleRegion(RegionEq(visibleRegion))).WillOnce(Return(kError));
EXPECT_CALL(*mHwcLayer, setDataspace(dataspace)).WillOnce(Return(kError));
- EXPECT_CALL(*mHwcLayer, setWhitePointNits(whitePointNits)).WillOnce(Return(kError));
+ EXPECT_CALL(*mHwcLayer, setBrightness(brightness)).WillOnce(Return(kError));
EXPECT_CALL(*mHwcLayer, setColorTransform(kColorTransform))
.WillOnce(Return(unsupported == SimulateUnsupported::ColorTransform
? hal::Error::UNSUPPORTED
@@ -1114,7 +1117,7 @@
expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
kOverrideBlendMode, kSkipAlpha);
expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
- kOverrideSurfaceDamage, kDisplayBrightnessNits);
+ kOverrideSurfaceDamage, kFullLayerBrightness);
expectSetHdrMetadataAndBufferCalls();
expectSetCompositionTypeCall(Composition::DEVICE);
EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
@@ -1130,7 +1133,7 @@
expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
kOverrideBlendMode, kSkipAlpha);
expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
- kOverrideSurfaceDamage, kDisplayBrightnessNits);
+ kOverrideSurfaceDamage, kFullLayerBrightness);
expectSetHdrMetadataAndBufferCalls();
expectSetCompositionTypeCall(Composition::DEVICE);
EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
@@ -1146,7 +1149,7 @@
expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
kOverrideBlendMode, kOverrideAlpha);
expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
- kOverrideSurfaceDamage, kDisplayBrightnessNits);
+ kOverrideSurfaceDamage, kFullLayerBrightness);
expectSetHdrMetadataAndBufferCalls(kOverrideHwcSlot, kOverrideBuffer, kOverrideFence);
expectSetCompositionTypeCall(Composition::DEVICE);
EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
@@ -1162,7 +1165,7 @@
expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
kOverrideBlendMode, kOverrideAlpha);
expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
- kOverrideSurfaceDamage, kDisplayBrightnessNits);
+ kOverrideSurfaceDamage, kFullLayerBrightness);
expectSetHdrMetadataAndBufferCalls(kOverrideHwcSlot, kOverrideBuffer, kOverrideFence);
expectSetCompositionTypeCall(Composition::DEVICE);
EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
@@ -1288,7 +1291,7 @@
expectGeometryCommonCalls();
expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
- kSurfaceDamage, kWhitePointNits, blockingRegion);
+ kSurfaceDamage, kLayerBrightness, blockingRegion);
expectSetHdrMetadataAndBufferCalls();
EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
expectSetCompositionTypeCall(Composition::DISPLAY_DECORATION);
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index d10468a..4e8d8c4 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -1062,9 +1062,8 @@
return Error::NONE;
}
-Error AidlComposer::setLayerWhitePointNits(Display display, Layer layer, float whitePointNits) {
- mWriter.setLayerWhitePointNits(translate<int64_t>(display), translate<int64_t>(layer),
- whitePointNits);
+Error AidlComposer::setLayerBrightness(Display display, Layer layer, float brightness) {
+ mWriter.setLayerBrightness(translate<int64_t>(display), translate<int64_t>(layer), brightness);
return Error::NONE;
}
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index a9f7606..aad09cb 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -211,7 +211,7 @@
float* outClientTargetWhitePointNits) override;
// AIDL Composer HAL
- Error setLayerWhitePointNits(Display display, Layer layer, float whitePointNits) override;
+ Error setLayerBrightness(Display display, Layer layer, float brightness) override;
Error setLayerBlockingRegion(Display display, Layer layer,
const std::vector<IComposerClient::Rect>& blocking) override;
Error setBootDisplayConfig(Display displayId, Config) override;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 5cc5a12..6e4d23b 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -261,7 +261,7 @@
float* outWhitePointNits) = 0;
// AIDL Composer
- virtual Error setLayerWhitePointNits(Display display, Layer layer, float whitePointNits) = 0;
+ virtual Error setLayerBrightness(Display display, Layer layer, float brightness) = 0;
virtual Error setLayerBlockingRegion(Display display, Layer layer,
const std::vector<IComposerClient::Rect>& blocking) = 0;
virtual Error setBootDisplayConfig(Display displayId, Config) = 0;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index b59b333..73f9468 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -940,12 +940,12 @@
}
// AIDL HAL
-Error Layer::setWhitePointNits(float whitePointNits) {
+Error Layer::setBrightness(float brightness) {
if (CC_UNLIKELY(!mDisplay)) {
return Error::BAD_DISPLAY;
}
- auto intError = mComposer.setLayerWhitePointNits(mDisplay->getId(), mId, whitePointNits);
+ auto intError = mComposer.setLayerBrightness(mDisplay->getId(), mId, brightness);
return static_cast<Error>(intError);
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index b183924..a37b8dd 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -320,7 +320,7 @@
const std::string& name, bool mandatory, const std::vector<uint8_t>& value) = 0;
// AIDL HAL
- [[clang::warn_unused_result]] virtual hal::Error setWhitePointNits(float whitePointNits) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setBrightness(float brightness) = 0;
[[clang::warn_unused_result]] virtual hal::Error setBlockingRegion(
const android::Region& region) = 0;
};
@@ -369,7 +369,7 @@
const std::vector<uint8_t>& value) override;
// AIDL HAL
- hal::Error setWhitePointNits(float whitePointNits) override;
+ hal::Error setBrightness(float brightness) override;
hal::Error setBlockingRegion(const android::Region& region) override;
private:
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index 25f03be..c6b8802 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -1303,7 +1303,7 @@
return Error::NONE;
}
-Error HidlComposer::setLayerWhitePointNits(Display, Layer, float) {
+Error HidlComposer::setLayerBrightness(Display, Layer, float) {
return Error::NONE;
}
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index 0f15598..41bf825 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -321,7 +321,7 @@
float* outWhitePointNits) override;
// AIDL Composer HAL
- Error setLayerWhitePointNits(Display display, Layer layer, float whitePointNits) override;
+ Error setLayerBrightness(Display display, Layer layer, float brightness) override;
Error setLayerBlockingRegion(Display display, Layer layer,
const std::vector<IComposerClient::Rect>& blocking) override;
Error setBootDisplayConfig(Display displayId, Config) override;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f99a2a3..df8f6e6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1733,11 +1733,15 @@
// If we support applying display brightness as a command, then we also support
// dimming SDR layers.
if (supportsDisplayBrightnessCommand) {
- display->getCompositionDisplay()
- ->setDisplayBrightness(brightness.sdrWhitePointNits,
- brightness.displayBrightnessNits);
+ auto compositionDisplay = display->getCompositionDisplay();
+ float currentDimmingRatio =
+ compositionDisplay->editState().sdrWhitePointNits /
+ compositionDisplay->editState().displayBrightnessNits;
+ compositionDisplay->setDisplayBrightness(brightness.sdrWhitePointNits,
+ brightness.displayBrightnessNits);
MAIN_THREAD_GUARD(display->stageBrightness(brightness.displayBrightness));
- if (hasVisibleHdrLayer(display)) {
+ if (brightness.sdrWhitePointNits / brightness.displayBrightnessNits !=
+ currentDimmingRatio) {
scheduleComposite(FrameHint::kNone);
} else {
scheduleCommit(FrameHint::kNone);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b95cd91..a7cd579 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1261,6 +1261,7 @@
ui::Dataspace mDefaultCompositionDataspace;
ui::Dataspace mWideColorGamutCompositionDataspace;
ui::Dataspace mColorSpaceAgnosticDataspace;
+ float mDimmingRatio = -1.f;
SurfaceFlingerBE mBE;
std::unique_ptr<compositionengine::CompositionEngine> mCompositionEngine;
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index ce9ec96..99d94f7 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -150,7 +150,7 @@
V2_4::Error(std::vector<IComposerClient::LayerGenericMetadataKey>*));
MOCK_METHOD3(getClientTargetProperty,
Error(Display, IComposerClient::ClientTargetProperty*, float*));
- MOCK_METHOD3(setLayerWhitePointNits, Error(Display, Layer, float));
+ MOCK_METHOD3(setLayerBrightness, Error(Display, Layer, float));
MOCK_METHOD3(setLayerBlockingRegion,
Error(Display, Layer, const std::vector<IComposerClient::Rect>&));
};
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
index 9015944..85c65cf 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
@@ -127,7 +127,7 @@
MOCK_METHOD(hal::Error, setColorTransform, (const android::mat4 &), (override));
MOCK_METHOD(hal::Error, setLayerGenericMetadata,
(const std::string &, bool, const std::vector<uint8_t> &), (override));
- MOCK_METHOD(hal::Error, setWhitePointNits, (float whitePointNits), (override));
+ MOCK_METHOD(hal::Error, setBrightness, (float), (override));
MOCK_METHOD(hal::Error, setBlockingRegion, (const android::Region &), (override));
};