diff options
author | 2024-09-26 16:13:06 -0700 | |
---|---|---|
committer | 2024-10-22 14:02:53 -0700 | |
commit | 0abc4a5897fdd556f2a618400eff4f9677649024 (patch) | |
tree | 120065fc11ee066fd215e42eb308fdb8df70e303 | |
parent | 8ea4421c67405c42e670d219e097d290b77a4416 (diff) |
[Lut HAL backend] implementation 2nd patch
1. add gui/DisplayLuts.h structure. Mimic DisplayLuts.java.
2. add Lut parameter into Layer side. When SurfaceControl#setLuts is
called, in native code, the lut information is passed to
SurfaceFlinger and RenderEngine side via LayerState::eLutsChanged.
3. in OutputLayer::updateCompositionState, we compare the Lut
requested from the app and the Lut from the HWC to decide GPU
composition or not.
4. DPU or GPU composition? If the Lut from the app exactly matches the
Lut from the hwc, do DPU. Otherwise, GPU composition instead.
Bug: 329472856
Test: libcompositionengine_test
Flag: NONE HAL backend interface change
Change-Id: I8295fe419c6237d90b7ff9f02f62bafd6cd2cecf
33 files changed, 320 insertions, 115 deletions
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 422c57bc87..4b531345b0 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -664,6 +664,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eShadowRadiusChanged; shadowRadius = other.shadowRadius; } + if (other.what & eLutsChanged) { + what |= eLutsChanged; + luts = other.luts; + } if (other.what & eDefaultFrameRateCompatibilityChanged) { what |= eDefaultFrameRateCompatibilityChanged; defaultFrameRateCompatibility = other.defaultFrameRateCompatibility; @@ -821,6 +825,8 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { CHECK_DIFF(diff, eColorSpaceAgnosticChanged, other, colorSpaceAgnostic); CHECK_DIFF(diff, eDimmingEnabledChanged, other, dimmingEnabled); if (other.what & eBufferReleaseChannelChanged) diff |= eBufferReleaseChannelChanged; + if (other.what & eLutsChanged) diff |= eLutsChanged; + return diff; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 063aabbdef..ebad069602 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -29,6 +29,7 @@ #include <android/gui/IWindowInfosListener.h> #include <android/gui/TrustedPresentationThresholds.h> #include <android/os/IInputConstants.h> +#include <gui/DisplayLuts.h> #include <gui/FrameRateUtils.h> #include <gui/TraceUtils.h> #include <utils/Errors.h> @@ -1940,15 +1941,19 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDesir } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLuts( - const sp<SurfaceControl>& sc, const base::unique_fd& /*lutFd*/, - const std::vector<int32_t>& /*offsets*/, const std::vector<int32_t>& /*dimensions*/, - const std::vector<int32_t>& /*sizes*/, const std::vector<int32_t>& /*samplingKeys*/) { + const sp<SurfaceControl>& sc, const base::unique_fd& lutFd, + const std::vector<int32_t>& offsets, const std::vector<int32_t>& dimensions, + const std::vector<int32_t>& sizes, const std::vector<int32_t>& samplingKeys) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - // TODO (b/329472856): update layer_state_t for lut(s) + + s->luts = std::make_shared<gui::DisplayLuts>(base::unique_fd(dup(lutFd.get())), offsets, + dimensions, sizes, samplingKeys); + s->what |= layer_state_t::eLutsChanged; + registerSurfaceControlForCallback(sc); return *this; } diff --git a/libs/gui/aidl/android/gui/Lut.aidl b/libs/gui/aidl/android/gui/Lut.aidl deleted file mode 100644 index a06e521789..0000000000 --- a/libs/gui/aidl/android/gui/Lut.aidl +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.gui; - -import android.gui.LutProperties; -import android.os.ParcelFileDescriptor; - -/** - * This mirrors aidl::android::hardware::graphics::composer3::Lut definition - * @hide - */ -parcelable Lut { - @nullable ParcelFileDescriptor pfd; - - LutProperties lutProperties; -}
\ No newline at end of file diff --git a/libs/gui/aidl/android/gui/LutProperties.aidl b/libs/gui/aidl/android/gui/LutProperties.aidl index 561e0c069c..87b878c1ca 100644 --- a/libs/gui/aidl/android/gui/LutProperties.aidl +++ b/libs/gui/aidl/android/gui/LutProperties.aidl @@ -25,7 +25,7 @@ parcelable LutProperties { enum Dimension { ONE_D = 1, THREE_D = 3 } Dimension dimension; - long size; + int size; @Backing(type="int") enum SamplingKey { RGB, MAX_RGB } SamplingKey[] samplingKeys; diff --git a/libs/gui/include/gui/DisplayLuts.h b/libs/gui/include/gui/DisplayLuts.h new file mode 100644 index 0000000000..16a360dcee --- /dev/null +++ b/libs/gui/include/gui/DisplayLuts.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <android-base/unique_fd.h> +#include <vector> + +namespace android::gui { + +struct DisplayLuts { +public: + struct Entry { + int32_t dimension; + int32_t size; + int32_t samplingKey; + }; + + DisplayLuts() {} + + DisplayLuts(base::unique_fd lutfd, std::vector<int32_t> lutoffsets, + std::vector<int32_t> lutdimensions, std::vector<int32_t> lutsizes, + std::vector<int32_t> lutsamplingKeys) { + fd = std::move(lutfd); + offsets = lutoffsets; + lutProperties.reserve(offsets.size()); + for (size_t i = 0; i < lutoffsets.size(); i++) { + Entry entry{lutdimensions[i], lutsizes[i], lutsamplingKeys[i]}; + lutProperties.emplace_back(entry); + } + } + + base::unique_fd& getLutFileDescriptor() { return fd; } + + std::vector<Entry> lutProperties; + std::vector<int32_t> offsets; + +private: + base::unique_fd fd; +}; // struct DisplayLuts + +} // namespace android::gui
\ No newline at end of file diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 00065c81d8..6bfeaec26a 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -26,6 +26,7 @@ #include <android/gui/LayerCaptureArgs.h> #include <android/gui/TrustedPresentationThresholds.h> #include <android/native_window.h> +#include <gui/DisplayLuts.h> #include <gui/IGraphicBufferProducer.h> #include <gui/ITransactionCompletedListener.h> #include <math/mat4.h> @@ -184,6 +185,7 @@ struct layer_state_t { eCachingHintChanged = 0x00000200, eDimmingEnabledChanged = 0x00000400, eShadowRadiusChanged = 0x00000800, + eLutsChanged = 0x00001000, eBufferCropChanged = 0x00002000, eRelativeLayerChanged = 0x00004000, eReparent = 0x00008000, @@ -255,7 +257,7 @@ struct layer_state_t { layer_state_t::eTransformToDisplayInverseChanged | layer_state_t::eTransparentRegionChanged | layer_state_t::eExtendedRangeBrightnessChanged | - layer_state_t::eDesiredHdrHeadroomChanged; + layer_state_t::eDesiredHdrHeadroomChanged | layer_state_t::eLutsChanged; // Content updates. static constexpr uint64_t CONTENT_CHANGES = layer_state_t::BUFFER_CHANGES | @@ -416,6 +418,8 @@ struct layer_state_t { TrustedPresentationListener trustedPresentationListener; std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> bufferReleaseChannel; + + std::shared_ptr<gui::DisplayLuts> luts; }; class ComposerState { diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index 859ae8b6e2..ac43da8dcf 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -16,6 +16,7 @@ #pragma once +#include <gui/DisplayLuts.h> #include <math/mat4.h> #include <math/vec3.h> #include <renderengine/ExternalTexture.h> @@ -145,6 +146,8 @@ struct LayerSettings { // If white point nits are unknown, then this layer is assumed to have the // same luminance as the brightest layer in the scene. float whitePointNits = -1.f; + + std::shared_ptr<gui::DisplayLuts> luts; }; // Keep in sync with custom comparison function in @@ -187,7 +190,7 @@ static inline bool operator==(const LayerSettings& lhs, const LayerSettings& rhs lhs.blurRegionTransform == rhs.blurRegionTransform && lhs.stretchEffect == rhs.stretchEffect && lhs.edgeExtensionEffect == rhs.edgeExtensionEffect && - lhs.whitePointNits == rhs.whitePointNits; + lhs.whitePointNits == rhs.whitePointNits && lhs.luts == rhs.luts; } static inline void PrintTo(const Buffer& settings, ::std::ostream* os) { diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 14a8fd6ad7..8a91a07115 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -19,6 +19,7 @@ #include <cstdint> #include <android/gui/CachingHint.h> +#include <gui/DisplayLuts.h> #include <gui/HdrMetadata.h> #include <math/mat4.h> #include <ui/BlurRegion.h> @@ -219,6 +220,9 @@ struct LayerFECompositionState { float desiredHdrSdrRatio = 1.f; gui::CachingHint cachingHint = gui::CachingHint::Enabled; + + std::shared_ptr<gui::DisplayLuts> luts; + virtual ~LayerFECompositionState(); // Debugging diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index 191d475e5d..556aa249a3 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -329,6 +329,8 @@ protected: virtual bool isPowerHintSessionGpuReportingEnabled() = 0; virtual void cacheClientCompositionRequests(uint32_t cacheSize) = 0; virtual bool canPredictCompositionStrategy(const CompositionRefreshArgs&) = 0; + virtual const aidl::android::hardware::graphics::composer3::OverlayProperties* + getOverlaySupport() = 0; }; } // namespace compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h index dcfe21a849..80c5124c76 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h @@ -93,7 +93,10 @@ public: // transform, if needed. virtual void updateCompositionState( bool includeGeometry, bool forceClientComposition, - ui::Transform::RotationFlags internalDisplayRotationFlags) = 0; + ui::Transform::RotationFlags internalDisplayRotationFlags, + const std::optional<std::vector< + std::optional<aidl::android::hardware::graphics::composer3::LutProperties>>> + properties) = 0; // Writes the geometry state to the HWC, or does nothing if this layer does // not use the HWC. If includeGeometry is false, the geometry state can be @@ -129,8 +132,10 @@ public: virtual void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) = 0; // Applies a HWC device layer lut - virtual void applyDeviceLayerLut(aidl::android::hardware::graphics::composer3::LutProperties, - ndk::ScopedFileDescriptor) = 0; + virtual void applyDeviceLayerLut( + ndk::ScopedFileDescriptor, + std::vector<std::pair< + int, aidl::android::hardware::graphics::composer3::LutProperties>>) = 0; // Returns true if the composition settings scale pixels virtual bool needsFiltering() const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index a39abb40d2..d8466ffdff 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -103,6 +103,8 @@ private: DisplayId mId; bool mIsDisconnected = false; Hwc2::PowerAdvisor* mPowerAdvisor = nullptr; + const aidl::android::hardware::graphics::composer3::OverlayProperties* getOverlaySupport() + override; }; // This template factory function standardizes the implementation details of the diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index 9990a742db..69e1efc4a7 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -164,6 +164,8 @@ protected: bool mustRecompose() const; const std::string& getNamePlusId() const { return mNamePlusId; } + const aidl::android::hardware::graphics::composer3::OverlayProperties* getOverlaySupport() + override; private: void dirtyEntireOutput(); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h index 354a4416f2..0c7e4dd071 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h @@ -31,6 +31,8 @@ #include <aidl/android/hardware/graphics/composer3/Composition.h> +using aidl::android::hardware::graphics::composer3::LutProperties; + namespace android::compositionengine { struct LayerFECompositionState; @@ -48,7 +50,9 @@ public: void uncacheBuffers(const std::vector<uint64_t>& bufferIdsToUncache) override; void updateCompositionState(bool includeGeometry, bool forceClientComposition, - ui::Transform::RotationFlags) override; + ui::Transform::RotationFlags, + const std::optional<std::vector<std::optional<LutProperties>>> + properties = std::nullopt) override; void writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t z, bool zIsOverridden, bool isPeekingThrough) override; void writeCursorPositionToHWC() const override; @@ -60,8 +64,8 @@ public: aidl::android::hardware::graphics::composer3::Composition) override; void prepareForDeviceLayerRequests() override; void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) override; - void applyDeviceLayerLut(aidl::android::hardware::graphics::composer3::LutProperties, - ndk::ScopedFileDescriptor) override; + void applyDeviceLayerLut(ndk::ScopedFileDescriptor, + std::vector<std::pair<int, LutProperties>>) override; bool needsFiltering() const override; std::optional<LayerFE::LayerSettings> getOverrideCompositionSettings() const override; @@ -92,10 +96,13 @@ private: void writeCompositionTypeToHWC(HWC2::Layer*, aidl::android::hardware::graphics::composer3::Composition, bool isPeekingThrough, bool skipLayer); + void writeLutToHWC(HWC2::Layer*, const LayerFECompositionState&); void detectDisallowedCompositionTypeChange( aidl::android::hardware::graphics::composer3::Composition from, aidl::android::hardware::graphics::composer3::Composition to) const; bool isClientCompositionForced(bool isPeekingThrough) const; + void updateLuts(std::shared_ptr<gui::DisplayLuts> luts, + const std::optional<std::vector<std::optional<LutProperties>>>& properties); }; // This template factory function standardizes the implementation details of the diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index 6c419da716..28216a475c 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -18,6 +18,7 @@ #include <compositionengine/ProjectionSpace.h> #include <compositionengine/impl/HwcBufferCache.h> +#include <gui/DisplayLuts.h> #include <renderengine/ExternalTexture.h> #include <ui/FloatRect.h> #include <ui/GraphicTypes.h> @@ -151,6 +152,9 @@ struct OutputLayerCompositionState { // True when this layer was skipped as part of SF-side layer caching. bool layerSkipped = false; + + // lut information + std::shared_ptr<gui::DisplayLuts> luts; }; // The HWC state is optional, and is only set up if there is any potential diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index d5bf2b5090..33cdc54b90 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -140,6 +140,8 @@ public: MOCK_METHOD(void, setHintSessionRequiresRenderEngine, (bool requiresRenderEngine)); MOCK_METHOD(bool, isPowerHintSessionEnabled, ()); MOCK_METHOD(bool, isPowerHintSessionGpuReportingEnabled, ()); + MOCK_METHOD((const aidl::android::hardware::graphics::composer3::OverlayProperties*), + getOverlaySupport, ()); }; } // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h index 48c2f9c483..12f20942cb 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h @@ -43,7 +43,10 @@ public: MOCK_CONST_METHOD0(getState, const impl::OutputLayerCompositionState&()); MOCK_METHOD0(editState, impl::OutputLayerCompositionState&()); - MOCK_METHOD3(updateCompositionState, void(bool, bool, ui::Transform::RotationFlags)); + MOCK_METHOD(void, updateCompositionState, + (bool, bool, ui::Transform::RotationFlags, + (const std::optional<std::vector<std::optional< + aidl::android::hardware::graphics::composer3::LutProperties>>>))); MOCK_METHOD5(writeStateToHWC, void(bool, bool, uint32_t, bool, bool)); MOCK_CONST_METHOD0(writeCursorPositionToHWC, void()); @@ -57,8 +60,9 @@ public: MOCK_CONST_METHOD0(needsFiltering, bool()); MOCK_CONST_METHOD0(getOverrideCompositionSettings, std::optional<LayerFE::LayerSettings>()); MOCK_METHOD(void, applyDeviceLayerLut, - (aidl::android::hardware::graphics::composer3::LutProperties, - ndk::ScopedFileDescriptor)); + (ndk::ScopedFileDescriptor, + (std::vector<std::pair< + int, aidl::android::hardware::graphics::composer3::LutProperties>>))); MOCK_CONST_METHOD1(dump, void(std::string&)); }; diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index b0164b7c33..1825065c8f 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -370,8 +370,8 @@ void Display::applyLayerLutsToLayers(const LayerLuts& layerLuts) { if (auto lutsIt = layerLuts.find(hwcLayer); lutsIt != layerLuts.end()) { if (auto mapperIt = mapper.find(hwcLayer); mapperIt != mapper.end()) { - layer->applyDeviceLayerLut(lutsIt->second, - ndk::ScopedFileDescriptor(mapperIt->second.release())); + layer->applyDeviceLayerLut(ndk::ScopedFileDescriptor(mapperIt->second.release()), + lutsIt->second); } } } @@ -457,6 +457,11 @@ void Display::setHintSessionRequiresRenderEngine(bool requiresRenderEngine) { mPowerAdvisor->setRequiresRenderEngine(mId, requiresRenderEngine); } +const aidl::android::hardware::graphics::composer3::OverlayProperties* +Display::getOverlaySupport() { + return &getCompositionEngine().getHwComposer().getOverlaySupport(); +} + void Display::finishFrame(GpuCompositionResult&& result) { // We only need to actually compose the display if: // 1) It is being handled by hardware composer, which may need this to diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 2d8f98f2a4..58c82db0bd 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -813,11 +813,14 @@ void Output::updateCompositionState(const compositionengine::CompositionRefreshA mLayerRequestingBackgroundBlur = findLayerRequestingBackgroundComposition(); bool forceClientComposition = mLayerRequestingBackgroundBlur != nullptr; + auto* properties = getOverlaySupport(); + for (auto* layer : getOutputLayersOrderedByZ()) { layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame, refreshArgs.devOptForceClientComposition || forceClientComposition, - refreshArgs.internalDisplayRotationFlags); + refreshArgs.internalDisplayRotationFlags, + properties ? properties->lutProperties : std::nullopt); if (mLayerRequestingBackgroundBlur == layer) { forceClientComposition = false; @@ -1689,6 +1692,10 @@ void Output::setTreat170mAsSrgb(bool enable) { editState().treat170mAsSrgb = enable; } +const aidl::android::hardware::graphics::composer3::OverlayProperties* Output::getOverlaySupport() { + return nullptr; +} + bool Output::canPredictCompositionStrategy(const CompositionRefreshArgs& refreshArgs) { uint64_t lastOutputLayerHash = getState().lastOutputLayerHash; uint64_t outputLayerHash = getState().outputLayerHash; diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 2d46dc0702..934909d066 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -38,7 +38,7 @@ #pragma clang diagnostic pop // ignored "-Wconversion" using aidl::android::hardware::graphics::composer3::Composition; -using aidl::android::hardware::graphics::composer3::LutProperties; +using aidl::android::hardware::graphics::composer3::Luts; namespace android::compositionengine { @@ -285,9 +285,50 @@ uint32_t OutputLayer::calculateOutputRelativeBufferTransform( return transform.getOrientation(); } +void OutputLayer::updateLuts( + std::shared_ptr<gui::DisplayLuts> layerFEStateLut, + const std::optional<std::vector<std::optional<LutProperties>>>& properties) { + auto& state = editState(); + + if (!properties) { + // GPU composition if no Hwc Luts + state.forceClientComposition = true; + return; + } + + std::vector<LutProperties> hwcLutProperties; + for (auto& p : *properties) { + if (p) { + hwcLutProperties.emplace_back(*p); + } + } + + for (const auto& inputLut : layerFEStateLut->lutProperties) { + bool foundInHwcLuts = false; + for (const auto& hwcLut : hwcLutProperties) { + if (static_cast<int32_t>(hwcLut.dimension) == + static_cast<int32_t>(inputLut.dimension) && + hwcLut.size == inputLut.size && + std::find(hwcLut.samplingKeys.begin(), hwcLut.samplingKeys.end(), + static_cast<LutProperties::SamplingKey>(inputLut.samplingKey)) != + hwcLut.samplingKeys.end()) { + foundInHwcLuts = true; + break; + } + } + // if any lut properties of layerFEStateLut can not be found in hwcLutProperties, + // GPU composition instead + if (!foundInHwcLuts) { + state.forceClientComposition = true; + return; + } + } +} + void OutputLayer::updateCompositionState( bool includeGeometry, bool forceClientComposition, - ui::Transform::RotationFlags internalDisplayRotationFlags) { + ui::Transform::RotationFlags internalDisplayRotationFlags, + const std::optional<std::vector<std::optional<LutProperties>>> properties) { const auto* layerFEState = getLayerFE().getCompositionState(); if (!layerFEState) { return; @@ -368,6 +409,11 @@ void OutputLayer::updateCompositionState( state.whitePointNits = layerBrightnessNits; } + const auto& layerFEStateLut = layerFEState->luts; + if (layerFEStateLut) { + updateLuts(layerFEStateLut, properties); + } + // These are evaluated every frame as they can potentially change at any // time. if (layerFEState->forceClientComposition || !profile.isDataspaceSupported(state.dataspace) || @@ -420,6 +466,8 @@ void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough, skipLayer); + writeLutToHWC(hwcLayer.get(), *outputIndependentState); + if (requestedCompositionType == Composition::SOLID_COLOR) { writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState); } @@ -513,6 +561,40 @@ void OutputLayer::writeOutputIndependentGeometryStateToHWC( } } +void OutputLayer::writeLutToHWC(HWC2::Layer* hwcLayer, + const LayerFECompositionState& outputIndependentState) { + if (!outputIndependentState.luts) { + return; + } + auto& lutFileDescriptor = outputIndependentState.luts->getLutFileDescriptor(); + auto lutOffsets = outputIndependentState.luts->offsets; + auto& lutProperties = outputIndependentState.luts->lutProperties; + + std::vector<LutProperties> aidlProperties; + aidlProperties.reserve(lutProperties.size()); + for (size_t i = 0; i < lutOffsets.size(); i++) { + LutProperties properties; + properties.dimension = static_cast<LutProperties::Dimension>(lutProperties[i].dimension); + properties.size = lutProperties[i].size; + properties.samplingKeys = { + static_cast<LutProperties::SamplingKey>(lutProperties[i].samplingKey)}; + aidlProperties.emplace_back(properties); + } + + Luts luts; + luts.pfd = ndk::ScopedFileDescriptor(dup(lutFileDescriptor.get())); + luts.offsets = lutOffsets; + luts.lutProperties = std::move(aidlProperties); + + switch (auto error = hwcLayer->setLuts(luts)) { + case hal::Error::NONE: + break; + default: + ALOGE("[%s] Failed to set Luts: %s (%d)", getLayerFE().getDebugName(), + to_string(error).c_str(), static_cast<int32_t>(error)); + } +} + void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) { const auto& outputDependentState = getState(); @@ -849,10 +931,29 @@ void OutputLayer::applyDeviceLayerRequest(hal::LayerRequest request) { } } -void OutputLayer::applyDeviceLayerLut(LutProperties /*lutProperties*/, - ndk::ScopedFileDescriptor /*lutPfd*/) { - // TODO(b/329472856): decode the shared memory of the pfd, and store the lut data into - // OutputLayerCompositionState#hwc struct +void OutputLayer::applyDeviceLayerLut( + ndk::ScopedFileDescriptor lutFileDescriptor, + std::vector<std::pair<int, LutProperties>> lutOffsetsAndProperties) { + auto& state = editState(); + LOG_FATAL_IF(!state.hwc); + auto& hwcState = *state.hwc; + std::vector<int32_t> offsets; + std::vector<int32_t> dimensions; + std::vector<int32_t> sizes; + std::vector<int32_t> samplingKeys; + for (const auto& [offset, properties] : lutOffsetsAndProperties) { + // The Lut(s) that comes back through CommandResultPayload should be + // only one sampling key. + if (properties.samplingKeys.size() == 1) { + offsets.emplace_back(offset); + dimensions.emplace_back(static_cast<int32_t>(properties.dimension)); + sizes.emplace_back(static_cast<int32_t>(properties.size)); + samplingKeys.emplace_back(static_cast<int32_t>(properties.samplingKeys[0])); + } + } + hwcState.luts = std::make_shared<gui::DisplayLuts>(base::unique_fd(lutFileDescriptor.release()), + std::move(offsets), std::move(dimensions), + std::move(sizes), std::move(samplingKeys)); } bool OutputLayer::needsFiltering() const { diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h index eb6e677117..26b5f4aaed 100644 --- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h +++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h @@ -33,7 +33,7 @@ #include "DisplayHardware/HWC2.h" #include <aidl/android/hardware/graphics/composer3/Composition.h> -#include <aidl/android/hardware/graphics/composer3/Lut.h> +#include <aidl/android/hardware/graphics/composer3/Luts.h> // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" @@ -78,7 +78,7 @@ public: Error(const std::string&, bool, const std::vector<uint8_t>&)); MOCK_METHOD1(setBrightness, Error(float)); MOCK_METHOD1(setBlockingRegion, Error(const android::Region&)); - MOCK_METHOD(Error, setLuts, (std::vector<aidl::android::hardware::graphics::composer3::Lut>&)); + MOCK_METHOD(Error, setLuts, (aidl::android::hardware::graphics::composer3::Luts&)); }; } // namespace mock diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index c34168d025..e3a799ce03 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -786,17 +786,20 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerContentForAllLayers InjectedLayer layer3; uint32_t z = 0; - EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180)); + EXPECT_CALL(*layer1.outputLayer, + updateCompositionState(false, false, ui::Transform::ROT_180, _)); EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180)); + EXPECT_CALL(*layer2.outputLayer, + updateCompositionState(false, false, ui::Transform::ROT_180, _)); EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180)); + EXPECT_CALL(*layer3.outputLayer, + updateCompositionState(false, false, ui::Transform::ROT_180, _)); EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); @@ -823,17 +826,17 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerGeometryAndContentF InjectedLayer layer3; uint32_t z = 0; - EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0)); + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0)); + EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); @@ -859,17 +862,17 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, forcesClientCompositionForAllLa InjectedLayer layer3; uint32_t z = 0; - EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); + EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); @@ -897,11 +900,11 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, peekThroughLayerChangesOrder) { InjectedLayer layer3; InSequence seq; - EXPECT_CALL(*layer0.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0)); - EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0)); + EXPECT_CALL(*layer0.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _)); + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0)); - EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _)); + EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _)); uint32_t z = 0; EXPECT_CALL(*layer0.outputLayer, @@ -5066,12 +5069,12 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, noBackgroundBlurWhenOpaque) { uint32_t z = 0; // Layer requesting blur, or below, should request client composition, unless opaque. - EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0)); + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); @@ -5100,17 +5103,17 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, handlesBackgroundBlurRequests) uint32_t z = 0; // Layer requesting blur, or below, should request client composition. - EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0)); + EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); @@ -5140,17 +5143,17 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, handlesBlurRegionRequests) { uint32_t z = 0; // Layer requesting blur, or below, should request client composition. - EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0)); + EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0, _)); EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++, /*zIsOverridden*/ false, /*isPeekingThrough*/ false)); diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp index 77bd8040c5..5814aa4354 100644 --- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp @@ -44,7 +44,7 @@ using hardware::Return; using aidl::android::hardware::graphics::composer3::BnComposerCallback; using aidl::android::hardware::graphics::composer3::Capability; using aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrightness; -using aidl::android::hardware::graphics::composer3::Lut; +using aidl::android::hardware::graphics::composer3::Luts; using aidl::android::hardware::graphics::composer3::PowerMode; using aidl::android::hardware::graphics::composer3::VirtualDisplay; @@ -1565,7 +1565,7 @@ Error AidlComposer::getRequestedLuts(Display display, std::vector<Layer>* outLay return error; } -Error AidlComposer::setLayerLuts(Display display, Layer layer, std::vector<Lut>& luts) { +Error AidlComposer::setLayerLuts(Display display, Layer layer, Luts& luts) { Error error = Error::NONE; mMutex.lock_shared(); if (auto writer = getWriter(display)) { diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h index cdb67e4e5c..d724b218c0 100644 --- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h @@ -53,6 +53,7 @@ using aidl::android::hardware::graphics::common::HdrConversionCapability; using aidl::android::hardware::graphics::common::HdrConversionStrategy; using aidl::android::hardware::graphics::composer3::ComposerClientReader; using aidl::android::hardware::graphics::composer3::ComposerClientWriter; +using aidl::android::hardware::graphics::composer3::Luts; using aidl::android::hardware::graphics::composer3::OverlayProperties; class AidlIComposerCallbackWrapper; @@ -248,9 +249,7 @@ public: Display display, std::vector<Layer>* outLayers, std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>* outLuts) override; - Error setLayerLuts( - Display display, Layer layer, - std::vector<aidl::android::hardware::graphics::composer3::Lut>& luts) override; + Error setLayerLuts(Display display, Layer layer, Luts& luts) override; private: // Many public functions above simply write a command into the command diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 09056631d0..42ddcd18c8 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -42,7 +42,6 @@ #include <aidl/android/hardware/graphics/composer3/DisplayConfiguration.h> #include <aidl/android/hardware/graphics/composer3/DisplayLuts.h> #include <aidl/android/hardware/graphics/composer3/IComposerCallback.h> -#include <aidl/android/hardware/graphics/composer3/Lut.h> #include <aidl/android/hardware/graphics/composer3/OverlayProperties.h> #include <aidl/android/hardware/graphics/common/Transform.h> @@ -307,7 +306,7 @@ public: int32_t frameIntervalNs) = 0; virtual Error getRequestedLuts(Display display, std::vector<Layer>* outLayers, std::vector<V3_0::DisplayLuts::LayerLut>* outLuts) = 0; - virtual Error setLayerLuts(Display display, Layer layer, std::vector<V3_0::Lut>& luts) = 0; + virtual Error setLayerLuts(Display display, Layer layer, V3_0::Luts& luts) = 0; }; } // namespace Hwc2 diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 1df2ab12ce..5355a12cda 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -42,7 +42,8 @@ using aidl::android::hardware::graphics::composer3::Composition; using AidlCapability = aidl::android::hardware::graphics::composer3::Capability; using aidl::android::hardware::graphics::composer3::DisplayCapability; using aidl::android::hardware::graphics::composer3::DisplayLuts; -using aidl::android::hardware::graphics::composer3::Lut; +using aidl::android::hardware::graphics::composer3::LutProperties; +using aidl::android::hardware::graphics::composer3::Luts; using aidl::android::hardware::graphics::composer3::OverlayProperties; namespace android { @@ -624,10 +625,18 @@ Error Display::getRequestedLuts(LayerLuts* outLuts, auto layer = getLayerById(layerIds[i]); if (layer) { auto& layerLut = tmpLuts[i]; - outLuts->emplace_or_replace(layer.get(), layerLut.lut.lutProperties); - lutFileDescriptorMapper.emplace_or_replace(layer.get(), - ndk::ScopedFileDescriptor( - layerLut.lut.pfd.release())); + if (layerLut.luts.pfd.get() > 0 && layerLut.luts.offsets.has_value()) { + const auto& offsets = layerLut.luts.offsets.value(); + std::vector<std::pair<int32_t, LutProperties>> lutOffsetsAndProperties; + lutOffsetsAndProperties.reserve(offsets.size()); + std::transform(offsets.begin(), offsets.end(), layerLut.luts.lutProperties.begin(), + std::back_inserter(lutOffsetsAndProperties), + [](int32_t i, LutProperties j) { return std::make_pair(i, j); }); + outLuts->emplace_or_replace(layer.get(), lutOffsetsAndProperties); + lutFileDescriptorMapper.emplace_or_replace(layer.get(), + ndk::ScopedFileDescriptor( + layerLut.luts.pfd.release())); + } } } @@ -1069,7 +1078,7 @@ Error Layer::setBlockingRegion(const Region& region) { return static_cast<Error>(intError); } -Error Layer::setLuts(std::vector<Lut>& luts) { +Error Layer::setLuts(aidl::android::hardware::graphics::composer3::Luts& luts) { if (CC_UNLIKELY(!mDisplay)) { return Error::BAD_DISPLAY; } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 61f92f4d74..799fd02586 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -46,7 +46,7 @@ #include <aidl/android/hardware/graphics/composer3/Color.h> #include <aidl/android/hardware/graphics/composer3/Composition.h> #include <aidl/android/hardware/graphics/composer3/DisplayCapability.h> -#include <aidl/android/hardware/graphics/composer3/Lut.h> +#include <aidl/android/hardware/graphics/composer3/Luts.h> #include <aidl/android/hardware/graphics/composer3/OverlayProperties.h> #include <aidl/android/hardware/graphics/composer3/RefreshRateChangedDebugData.h> @@ -109,9 +109,10 @@ public: virtual std::optional<ui::Size> getPhysicalSizeInMm() const = 0; static const int kLutFileDescriptorMapperSize = 20; + using LutOffsetAndProperties = std::vector< + std::pair<int32_t, aidl::android::hardware::graphics::composer3::LutProperties>>; using LayerLuts = - ftl::SmallMap<HWC2::Layer*, aidl::android::hardware::graphics::composer3::LutProperties, - kLutFileDescriptorMapperSize>; + ftl::SmallMap<HWC2::Layer*, LutOffsetAndProperties, kLutFileDescriptorMapperSize>; using LutFileDescriptorMapper = ftl::SmallMap<HWC2::Layer*, ndk::ScopedFileDescriptor, kLutFileDescriptorMapperSize>; @@ -375,7 +376,7 @@ public: [[nodiscard]] virtual hal::Error setBrightness(float brightness) = 0; [[nodiscard]] virtual hal::Error setBlockingRegion(const android::Region& region) = 0; [[nodiscard]] virtual hal::Error setLuts( - std::vector<aidl::android::hardware::graphics::composer3::Lut>& luts) = 0; + aidl::android::hardware::graphics::composer3::Luts& luts) = 0; }; namespace impl { @@ -426,8 +427,7 @@ public: // AIDL HAL hal::Error setBrightness(float brightness) override; hal::Error setBlockingRegion(const android::Region& region) override; - hal::Error setLuts( - std::vector<aidl::android::hardware::graphics::composer3::Lut>& luts) override; + hal::Error setLuts(aidl::android::hardware::graphics::composer3::Luts&) override; private: // These are references to data owned by HWComposer, which will outlive diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp index 056ecd78f4..6a7a09b5ae 100644 --- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp @@ -47,7 +47,7 @@ using aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrig using aidl::android::hardware::graphics::composer3::DimmingStage; using aidl::android::hardware::graphics::composer3::DisplayCapability; using aidl::android::hardware::graphics::composer3::DisplayLuts; -using aidl::android::hardware::graphics::composer3::Lut; +using aidl::android::hardware::graphics::composer3::Luts; using aidl::android::hardware::graphics::composer3::OverlayProperties; namespace android { @@ -1415,7 +1415,7 @@ Error HidlComposer::getRequestedLuts(Display, std::vector<Layer>*, return Error::NONE; } -Error HidlComposer::setLayerLuts(Display, Layer, std::vector<Lut>&) { +Error HidlComposer::setLayerLuts(Display, Layer, Luts&) { return Error::NONE; } diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h index 1cc23d1409..a3d1f7f291 100644 --- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h @@ -356,7 +356,7 @@ public: std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*) override; Error setLayerLuts(Display, Layer, - std::vector<aidl::android::hardware::graphics::composer3::Lut>&) override; + aidl::android::hardware::graphics::composer3::Luts&) override; private: class CommandWriter : public CommandWriterBase { diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index e5f6b7bcd1..11b674b846 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -513,6 +513,10 @@ void LayerSnapshot::merge(const RequestedLayerState& requested, bool forceUpdate isOpaque = contentOpaque && !roundedCorner.hasRoundedCorners() && color.a == 1.f; blendMode = getBlendMode(requested); } + + if (forceUpdate || requested.what & layer_state_t::eLutsChanged) { + luts = requested.luts; + } } } // namespace android::surfaceflinger::frontend diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp index b05f0eecc4..2458614818 100644 --- a/services/surfaceflinger/LayerFE.cpp +++ b/services/surfaceflinger/LayerFE.cpp @@ -176,6 +176,7 @@ std::optional<compositionengine::LayerFE::LayerSettings> LayerFE::prepareClientC layerSettings.edgeExtensionEffect = mSnapshot->edgeExtensionEffect; // Record the name of the layer for debugging further down the stack. layerSettings.name = mSnapshot->name; + layerSettings.luts = mSnapshot->luts; if (hasEffect() && !hasBufferOrSidebandStream()) { prepareEffectsClientComposition(layerSettings, targetSettings); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a821e3d494..9b7766ff9a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1654,19 +1654,22 @@ status_t SurfaceFlinger::getOverlaySupport(gui::OverlayProperties* outProperties outProperties->combinations.emplace_back(outCombination); } outProperties->supportMixedColorSpaces = aidlProperties.supportMixedColorSpaces; - if (aidlProperties.lutProperties.has_value()) { + if (aidlProperties.lutProperties) { std::vector<gui::LutProperties> outLutProperties; - for (const auto& properties : aidlProperties.lutProperties.value()) { - gui::LutProperties currentProperties; - currentProperties.dimension = - static_cast<gui::LutProperties::Dimension>(properties->dimension); - currentProperties.size = properties->size; - currentProperties.samplingKeys.reserve(properties->samplingKeys.size()); - std::transform(properties->samplingKeys.cbegin(), properties->samplingKeys.cend(), - std::back_inserter(currentProperties.samplingKeys), [](const auto& val) { - return static_cast<gui::LutProperties::SamplingKey>(val); - }); - outLutProperties.push_back(std::move(currentProperties)); + for (auto properties : *aidlProperties.lutProperties) { + if (!properties) { + gui::LutProperties currentProperties; + currentProperties.dimension = + static_cast<gui::LutProperties::Dimension>(properties->dimension); + currentProperties.size = properties->size; + currentProperties.samplingKeys.reserve(properties->samplingKeys.size()); + std::transform(properties->samplingKeys.cbegin(), properties->samplingKeys.cend(), + std::back_inserter(currentProperties.samplingKeys), + [](const auto& val) { + return static_cast<gui::LutProperties::SamplingKey>(val); + }); + outLutProperties.push_back(std::move(currentProperties)); + } } outProperties->lutProperties.emplace(outLutProperties.begin(), outLutProperties.end()); } diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h index 615cc948ed..3e6a768db8 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h @@ -185,7 +185,7 @@ public: (Display, std::vector<Layer>*, std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*)); MOCK_METHOD(Error, setLayerLuts, - (Display, Layer, std::vector<aidl::android::hardware::graphics::composer3::Lut>&)); + (Display, Layer, aidl::android::hardware::graphics::composer3::Luts&)); }; } // namespace Hwc2::mock diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h index 53ed2e1f20..384b908624 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h @@ -147,8 +147,8 @@ public: (const std::string &, bool, const std::vector<uint8_t> &), (override)); MOCK_METHOD(hal::Error, setBrightness, (float), (override)); MOCK_METHOD(hal::Error, setBlockingRegion, (const android::Region &), (override)); - MOCK_METHOD(hal::Error, setLuts, - (std::vector<aidl::android::hardware::graphics::composer3::Lut>&), (override)); + MOCK_METHOD(hal::Error, setLuts, (aidl::android::hardware::graphics::composer3::Luts&), + (override)); }; } // namespace android::HWC2::mock |