diff options
author | 2024-10-23 22:01:28 +0000 | |
---|---|---|
committer | 2024-10-23 22:01:28 +0000 | |
commit | b2e1d4abc635314169f2c97a7f585d9c1123c57f (patch) | |
tree | f61442951d15075522515f1f295cc00b3cd82679 | |
parent | 266ad0c9c9c0d19e2d35b77bbe0ce1aec070cac5 (diff) | |
parent | 0abc4a5897fdd556f2a618400eff4f9677649024 (diff) |
Merge "[Lut HAL backend] implementation 2nd patch" into main
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 eeea80fa82..a93fc926c2 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 22ab3d953b..bb456138d6 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; @@ -1678,6 +1681,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 1c18cd28c5..74ff12407b 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -785,17 +785,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)); @@ -822,17 +825,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)); @@ -858,17 +861,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)); @@ -896,11 +899,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, @@ -4932,12 +4935,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)); @@ -4966,17 +4969,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)); @@ -5006,17 +5009,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 f64ba9e900..a346981ae6 100644 --- a/services/surfaceflinger/LayerFE.cpp +++ b/services/surfaceflinger/LayerFE.cpp @@ -174,6 +174,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 09dbc59c69..d35a76ad4b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1656,19 +1656,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 |