diff options
author | 2024-02-12 22:27:19 +0000 | |
---|---|---|
committer | 2024-02-15 06:11:12 +0000 | |
commit | 1b0d4e16530a4feb99eafbfdfce2aeb39c5e23e3 (patch) | |
tree | 3b8836d60ef68835b1e4a2ce20a0972003da421f | |
parent | 9892aac629682352986492133b3d2ca40b2767bf (diff) |
Add support for restricting HDR headroom for video
This is needed for allowing apps to vote for HDR headroom restrictions
for SurfaceView and SurfaceControl
Bug: 323964760
Test: manually poking at test app
Test: SurfaceViewTests
Test: SurfaceControlTest
Test: ASurfaceControlTest
Change-Id: Ie886e67879525462d49fdedc535aea659d69321a
-rw-r--r-- | include/android/surface_control.h | 50 | ||||
-rw-r--r-- | libs/gui/LayerState.cpp | 5 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 14 | ||||
-rw-r--r-- | libs/gui/include/gui/LayerState.h | 5 | ||||
-rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 1 | ||||
-rw-r--r-- | services/surfaceflinger/FrontEnd/LayerSnapshot.cpp | 3 | ||||
-rw-r--r-- | services/surfaceflinger/FrontEnd/RequestedLayerState.cpp | 5 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 15 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 13 |
10 files changed, 106 insertions, 10 deletions
diff --git a/include/android/surface_control.h b/include/android/surface_control.h index cce2e46471..321737e226 100644 --- a/include/android/surface_control.h +++ b/include/android/surface_control.h @@ -528,9 +528,8 @@ void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transactio /** * Sets the desired extended range brightness for the layer. This only applies for layers whose - * dataspace has RANGE_EXTENDED set on it. - * - * Available since API level 34. + * dataspace has RANGE_EXTENDED set on it. See: ASurfaceTransaction_setDesiredHdrHeadroom, prefer + * using this API for formats that encode an HDR/SDR ratio as part of generating the buffer. * * @param surface_control The layer whose extended range brightness is being specified * @param currentBufferRatio The current hdr/sdr ratio of the current buffer as represented as @@ -564,6 +563,12 @@ void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transactio * determined entirely by the dataspace being used (ie, typically SDR * however PQ or HLG transfer functions will still result in HDR) * + * When called after ASurfaceTransaction_setDesiredHdrHeadroom, the + * desiredRatio will override the desiredHeadroom provided by + * ASurfaceTransaction_setDesiredHdrHeadroom. Conversely, when called before + * ASurfaceTransaction_setDesiredHdrHeadroom, the desiredHeadroom provided by + *. ASurfaceTransaction_setDesiredHdrHeadroom will override the desiredRatio. + * * Must be finite && >= 1.0f * * Available since API level 34. @@ -574,6 +579,45 @@ void ASurfaceTransaction_setExtendedRangeBrightness(ASurfaceTransaction* transac float desiredRatio) __INTRODUCED_IN(__ANDROID_API_U__); /** + * Sets the desired hdr headroom for the layer. See: ASurfaceTransaction_setExtendedRangeBrightness, + * prefer using this API for formats that conform to HDR standards like HLG or HDR10, that do not + * communicate a HDR/SDR ratio as part of generating the buffer. + * + * @param surface_control The layer whose desired hdr headroom is being specified + * + * @param desiredHeadroom The desired hdr/sdr ratio as represented as peakHdrBrightnessInNits / + * targetSdrWhitePointInNits. This can be used to communicate the max + * desired brightness range of the panel. The system may not be able to, or + * may choose not to, deliver the requested range. + * + * While requesting a large desired ratio will result in the most + * dynamic range, voluntarily reducing the requested range can help + * improve battery life as well as can improve quality by ensuring + * greater bit depth is allocated to the luminance range in use. + * + * Default value is 0.0f and indicates that the system will choose the best + * headroom for this surface control's content. Typically, this means that + * HLG/PQ encoded content will be displayed with some HDR headroom greater + * than 1.0. + * + * When called after ASurfaceTransaction_setExtendedRangeBrightness, the + * desiredHeadroom will override the desiredRatio provided by + * ASurfaceTransaction_setExtendedRangeBrightness. Conversely, when called + * before ASurfaceTransaction_setExtendedRangeBrightness, the desiredRatio + * provided by ASurfaceTransaction_setExtendedRangeBrightness will override + * the desiredHeadroom. + * + * Must be finite && >= 1.0f or 0.0f to indicate there is no desired + * headroom. + * + * Available since API level 35. + */ +void ASurfaceTransaction_setDesiredHdrHeadroom(ASurfaceTransaction* transaction, + ASurfaceControl* surface_control, + float desiredHeadroom) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** * Same as ASurfaceTransaction_setFrameRateWithChangeStrategy(transaction, surface_control, * frameRate, compatibility, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS). * diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 38fab9cdaa..9d7d304afb 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -605,6 +605,10 @@ void layer_state_t::merge(const layer_state_t& other) { desiredHdrSdrRatio = other.desiredHdrSdrRatio; currentHdrSdrRatio = other.currentHdrSdrRatio; } + if (other.what & eDesiredHdrHeadroomChanged) { + what |= eDesiredHdrHeadroomChanged; + desiredHdrSdrRatio = other.desiredHdrSdrRatio; + } if (other.what & eCachingHintChanged) { what |= eCachingHintChanged; cachingHint = other.cachingHint; @@ -768,6 +772,7 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { CHECK_DIFF(diff, eDataspaceChanged, other, dataspace); CHECK_DIFF2(diff, eExtendedRangeBrightnessChanged, other, currentHdrSdrRatio, desiredHdrSdrRatio); + CHECK_DIFF(diff, eDesiredHdrHeadroomChanged, other, desiredHdrSdrRatio); CHECK_DIFF(diff, eCachingHintChanged, other, cachingHint); CHECK_DIFF(diff, eHdrMetadataChanged, other, hdrMetadata); if (other.what & eSurfaceDamageRegionChanged && diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 8d18551b69..3a02c644bf 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1807,6 +1807,20 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setExten return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDesiredHdrHeadroom( + const sp<SurfaceControl>& sc, float desiredRatio) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eDesiredHdrHeadroomChanged; + s->desiredHdrSdrRatio = desiredRatio; + + registerSurfaceControlForCallback(sc); + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCachingHint( const sp<SurfaceControl>& sc, gui::CachingHint cachingHint) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 6b8e8248b8..9350c95178 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -206,7 +206,7 @@ struct layer_state_t { eBackgroundBlurRadiusChanged = 0x80'00000000, eProducerDisconnect = 0x100'00000000, eFixedTransformHintChanged = 0x200'00000000, - /* unused 0x400'00000000, */ + eDesiredHdrHeadroomChanged = 0x400'00000000, eBlurRegionsChanged = 0x800'00000000, eAutoRefreshChanged = 0x1000'00000000, eStretchChanged = 0x2000'00000000, @@ -245,7 +245,8 @@ struct layer_state_t { layer_state_t::eSidebandStreamChanged | layer_state_t::eSurfaceDamageRegionChanged | layer_state_t::eTransformToDisplayInverseChanged | layer_state_t::eTransparentRegionChanged | - layer_state_t::eExtendedRangeBrightnessChanged; + layer_state_t::eExtendedRangeBrightnessChanged | + layer_state_t::eDesiredHdrHeadroomChanged; // Content updates. static constexpr uint64_t CONTENT_CHANGES = layer_state_t::BUFFER_CHANGES | diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 14e3dd583e..7118883411 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -594,6 +594,7 @@ public: Transaction& setDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace); Transaction& setExtendedRangeBrightness(const sp<SurfaceControl>& sc, float currentBufferRatio, float desiredRatio); + Transaction& setDesiredHdrHeadroom(const sp<SurfaceControl>& sc, float desiredRatio); Transaction& setCachingHint(const sp<SurfaceControl>& sc, gui::CachingHint cachingHint); Transaction& setHdrMetadata(const sp<SurfaceControl>& sc, const HdrMetadata& hdrMetadata); Transaction& setSurfaceDamageRegion(const sp<SurfaceControl>& sc, diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index 38974a2f58..8b200a2cf8 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -380,6 +380,9 @@ void LayerSnapshot::merge(const RequestedLayerState& requested, bool forceUpdate currentHdrSdrRatio = requested.currentHdrSdrRatio; desiredHdrSdrRatio = requested.desiredHdrSdrRatio; } + if (forceUpdate || requested.what & layer_state_t::eDesiredHdrHeadroomChanged) { + desiredHdrSdrRatio = requested.desiredHdrSdrRatio; + } if (forceUpdate || requested.what & layer_state_t::eCachingHintChanged) { cachingHint = requested.cachingHint; } diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index 209df79f8e..b72588ab47 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -98,7 +98,7 @@ RequestedLayerState::RequestedLayerState(const LayerCreationArgs& args) z = 0; layerStack = ui::DEFAULT_LAYER_STACK; transformToDisplayInverse = false; - desiredHdrSdrRatio = 1.f; + desiredHdrSdrRatio = -1.f; currentHdrSdrRatio = 1.f; dataspaceRequested = false; hdrMetadata.validTypes = 0; @@ -603,7 +603,8 @@ bool RequestedLayerState::isSimpleBufferUpdate(const layer_state_t& s) const { layer_state_t::eShadowRadiusChanged | layer_state_t::eFixedTransformHintChanged | layer_state_t::eTrustedOverlayChanged | layer_state_t::eStretchChanged | layer_state_t::eBufferCropChanged | layer_state_t::eDestinationFrameChanged | - layer_state_t::eDimmingEnabledChanged | layer_state_t::eExtendedRangeBrightnessChanged; + layer_state_t::eDimmingEnabledChanged | layer_state_t::eExtendedRangeBrightnessChanged | + layer_state_t::eDesiredHdrHeadroomChanged; if (changedFlags & deniedChanges) { ATRACE_FORMAT_INSTANT("%s: false [has denied changes flags 0x%" PRIx64 "]", __func__, s.what & deniedChanges); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 219a8e20a4..736fec6fb2 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -3395,6 +3395,14 @@ bool Layer::setExtendedRangeBrightness(float currentBufferRatio, float desiredRa return true; } +bool Layer::setDesiredHdrHeadroom(float desiredRatio) { + if (mDrawingState.desiredHdrSdrRatio == desiredRatio) return false; + mDrawingState.desiredHdrSdrRatio = desiredRatio; + mDrawingState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + bool Layer::setCachingHint(gui::CachingHint cachingHint) { if (mDrawingState.cachingHint == cachingHint) return false; mDrawingState.cachingHint = cachingHint; @@ -3991,6 +3999,13 @@ bool Layer::isSimpleBufferUpdate(const layer_state_t& s) const { } } + if (s.what & layer_state_t::eDesiredHdrHeadroomChanged) { + if (mDrawingState.desiredHdrSdrRatio != s.desiredHdrSdrRatio) { + ATRACE_FORMAT_INSTANT("%s: false [eDesiredHdrHeadroomChanged changed]", __func__); + return false; + } + } + return true; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index dfd57c65e3..0ceecec7ec 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -233,7 +233,7 @@ public: bool autoRefresh = false; bool dimmingEnabled = true; float currentHdrSdrRatio = 1.f; - float desiredHdrSdrRatio = 1.f; + float desiredHdrSdrRatio = -1.f; gui::CachingHint cachingHint = gui::CachingHint::Enabled; int64_t latchedVsyncId = 0; bool useVsyncIdForRefreshRateSelection = false; @@ -317,6 +317,7 @@ public: void setDesiredPresentTime(nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/); bool setDataspace(ui::Dataspace /*dataspace*/); bool setExtendedRangeBrightness(float currentBufferRatio, float desiredRatio); + bool setDesiredHdrHeadroom(float desiredRatio); bool setCachingHint(gui::CachingHint cachingHint); bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/); bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/); @@ -546,7 +547,7 @@ public: sp<IBinder> mReleaseBufferEndpoint; bool mFrameLatencyNeeded{false}; - float mDesiredHdrSdrRatio = 1.f; + float mDesiredHdrSdrRatio = -1.f; }; BufferInfo mBufferInfo; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7626fe73e9..1a40bc241f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3119,6 +3119,7 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, for (auto& [compositionDisplay, listener] : hdrInfoListeners) { HdrLayerInfoReporter::HdrLayerInfo info; int32_t maxArea = 0; + auto updateInfoFn = [&](const std::shared_ptr<compositionengine::Display>& compositionDisplay, const frontend::LayerSnapshot& snapshot, const sp<LayerFE>& layerFe) { @@ -3129,7 +3130,7 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, compositionDisplay->getOutputLayerForLayer(layerFe); if (outputLayer) { const float desiredHdrSdrRatio = - snapshot.desiredHdrSdrRatio <= 1.f + snapshot.desiredHdrSdrRatio < 1.f ? std::numeric_limits<float>::infinity() : snapshot.desiredHdrSdrRatio; info.mergeDesiredRatio(desiredHdrSdrRatio); @@ -5415,6 +5416,11 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime flags |= eTraversalNeeded; } } + if (what & layer_state_t::eDesiredHdrHeadroomChanged) { + if (layer->setDesiredHdrHeadroom(s.desiredHdrSdrRatio)) { + flags |= eTraversalNeeded; + } + } if (what & layer_state_t::eCachingHintChanged) { if (layer->setCachingHint(s.cachingHint)) { flags |= eTraversalNeeded; @@ -5600,6 +5606,11 @@ uint32_t SurfaceFlinger::updateLayerCallbacksAndStats(const FrameTimelineInfo& f flags |= eTraversalNeeded; } } + if (what & layer_state_t::eDesiredHdrHeadroomChanged) { + if (layer->setDesiredHdrHeadroom(s.desiredHdrSdrRatio)) { + flags |= eTraversalNeeded; + } + } if (what & layer_state_t::eBufferChanged) { std::optional<ui::Transform::RotationFlags> transformHint = std::nullopt; frontend::LayerSnapshot* snapshot = mLayerSnapshotBuilder.getSnapshot(layer->sequence); |