Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01c77c1a authored by Lloyd Pique's avatar Lloyd Pique
Browse files

CE: Move knowledge of the OutputLayers out of Output

This separates knowledge of the type and management of OutputLayers from
the implementation of the Output class.

1) getOutputLayersOrderedByZ() is now a non-virtual function which
returns a helper object for iterating over all the layers in the Output,
with only minor code changes to the callers. Internally the helper
object uses a pair of virtual functions to get the count and access a
layer by index. The old interface fixed both the type of the layer and
the type of container it was stored in, which was problematic.

2) When rebuilding the layer stack, the implementation now uses
additional abstract interface functions that allow the layer stack to be
maniupluated without the caller having to own even temporarily instances
of the OutputLayer type.

3) The Output interface has been cleaned up to remove functions that
were no longer needed in the public interface, and to introduce a few
others such as injectOutputLayerForTest() and clearOutputLayers() for
performing special layer manipulations.

Test: atest libsurfaceflinger_unittest libcompositionengine_test
Test: go/wm-smoke
Bug: 121291683
Change-Id: I636cfaea7254c7e164837ef8b441932f364808f3
parent a38ea7e7
Loading
Loading
Loading
Loading
+79 −17
Original line number Diff line number Diff line
@@ -17,9 +17,12 @@
#pragma once

#include <cstdint>
#include <iterator>
#include <optional>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>

#include <compositionengine/LayerFE.h>
#include <renderengine/LayerSettings.h>
@@ -55,10 +58,67 @@ struct OutputCompositionState;
 */
class Output {
public:
    using OutputLayers = std::vector<std::unique_ptr<compositionengine::OutputLayer>>;
    using ReleasedLayers = std::vector<wp<LayerFE>>;
    using UniqueFELayerStateMap = std::unordered_map<LayerFE*, LayerFECompositionState*>;

    // A helper class for enumerating the output layers using a C++11 ranged-based for loop
    template <typename T>
    class OutputLayersEnumerator {
    public:
        // TODO(lpique): Consider turning this into a C++20 view when possible.
        template <bool IsConstIter>
        class IteratorImpl {
        public:
            // Required definitions to be considered an iterator
            using iterator_category = std::forward_iterator_tag;
            using value_type = decltype(std::declval<T>().getOutputLayerOrderedByZByIndex(0));
            using difference_type = std::ptrdiff_t;
            using pointer = std::conditional_t<IsConstIter, const value_type*, value_type*>;
            using reference = std::conditional_t<IsConstIter, const value_type&, value_type&>;

            IteratorImpl() = default;
            IteratorImpl(const T* output, size_t index) : mOutput(output), mIndex(index) {}

            value_type operator*() const {
                return mOutput->getOutputLayerOrderedByZByIndex(mIndex);
            }
            value_type operator->() const {
                return mOutput->getOutputLayerOrderedByZByIndex(mIndex);
            }

            bool operator==(const IteratorImpl& other) const {
                return mOutput == other.mOutput && mIndex == other.mIndex;
            }
            bool operator!=(const IteratorImpl& other) const { return !operator==(other); }

            IteratorImpl& operator++() {
                ++mIndex;
                return *this;
            }
            IteratorImpl operator++(int) {
                auto prev = *this;
                ++mIndex;
                return prev;
            }

        private:
            const T* mOutput{nullptr};
            size_t mIndex{0};
        };

        using iterator = IteratorImpl<false>;
        using const_iterator = IteratorImpl<true>;

        explicit OutputLayersEnumerator(const T& output) : mOutput(output) {}
        auto begin() const { return iterator(&mOutput, 0); }
        auto end() const { return iterator(&mOutput, mOutput.getOutputLayerCount()); }
        auto cbegin() const { return const_iterator(&mOutput, 0); }
        auto cend() const { return const_iterator(&mOutput, mOutput.getOutputLayerCount()); }

    private:
        const T& mOutput;
    };

    struct FrameFences {
        sp<Fence> presentFence{Fence::NO_FENCE};
        sp<Fence> clientTargetAcquireFence{Fence::NO_FENCE};
@@ -152,28 +212,32 @@ public:
    virtual bool belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const = 0;

    // Determines if a layer belongs to the output.
    virtual bool belongsInOutput(const compositionengine::Layer*) const = 0;
    virtual bool belongsInOutput(const Layer*) const = 0;

    // Returns a pointer to the output layer corresponding to the given layer on
    // this output, or nullptr if the layer does not have one
    virtual OutputLayer* getOutputLayerForLayer(Layer*) const = 0;

    // Creates an OutputLayer instance for this output
    virtual std::unique_ptr<OutputLayer> createOutputLayer(const std::shared_ptr<Layer>&,
                                                           const sp<LayerFE>&) const = 0;
    // Immediately clears all layers from the output.
    virtual void clearOutputLayers() = 0;

    // For tests use only. Creates and appends an OutputLayer into the output.
    virtual OutputLayer* injectOutputLayerForTest(const std::shared_ptr<Layer>&,
                                                  const sp<LayerFE>&) = 0;

    // Sets the new ordered set of output layers for this output
    virtual void setOutputLayersOrderedByZ(OutputLayers&&) = 0;
    // Gets the count of output layers managed by this output
    virtual size_t getOutputLayerCount() const = 0;

    // Gets the ordered set of output layers for this output
    virtual const OutputLayers& getOutputLayersOrderedByZ() const = 0;
    // Gets an output layer in Z order given its index
    virtual OutputLayer* getOutputLayerOrderedByZByIndex(size_t) const = 0;

    // A helper function for enumerating all the output layers in Z order using
    // a C++11 range-based for loop.
    auto getOutputLayersOrderedByZ() const { return OutputLayersEnumerator(*this); }

    // Sets the new set of layers being released this frame
    virtual void setReleasedLayers(ReleasedLayers&&) = 0;

    // Takes (moves) the set of layers being released this frame.
    virtual ReleasedLayers takeReleasedLayers() = 0;

    // Prepare the output, updating the OutputLayers used in the output
    virtual void prepare(const CompositionRefreshArgs&, LayerFESet&) = 0;

@@ -187,12 +251,10 @@ protected:
    virtual void setDisplayColorProfile(std::unique_ptr<DisplayColorProfile>) = 0;
    virtual void setRenderSurface(std::unique_ptr<RenderSurface>) = 0;

    virtual void rebuildLayerStacks(const compositionengine::CompositionRefreshArgs&,
                                    LayerFESet&) = 0;
    virtual void rebuildLayerStacks(const CompositionRefreshArgs&, LayerFESet&) = 0;
    virtual void collectVisibleLayers(const CompositionRefreshArgs&, CoverageState&) = 0;
    virtual std::unique_ptr<OutputLayer> getOutputLayerIfVisible(
            std::shared_ptr<compositionengine::Layer>, CoverageState&) = 0;
    virtual void setReleasedLayers(const compositionengine::CompositionRefreshArgs&) = 0;
    virtual void ensureOutputLayerIfVisible(std::shared_ptr<Layer>, CoverageState&) = 0;
    virtual void setReleasedLayers(const CompositionRefreshArgs&) = 0;

    virtual void updateAndWriteCompositionState(const CompositionRefreshArgs&) = 0;
    virtual void setColorTransform(const CompositionRefreshArgs&) = 0;
+4 −2
Original line number Diff line number Diff line
@@ -41,8 +41,6 @@ public:

    // compositionengine::Output overrides
    void dump(std::string&) const override;
    std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
            const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&) const override;
    using compositionengine::impl::Output::setReleasedLayers;
    void setReleasedLayers(const CompositionRefreshArgs&) override;
    void setColorTransform(const CompositionRefreshArgs&) override;
@@ -72,6 +70,10 @@ public:
    virtual void applyDisplayRequests(const DisplayRequests&);
    virtual void applyLayerRequestsToLayers(const LayerRequests&);

    // Internal
    std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
            const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&) const;

private:
    const bool mIsVirtual;
    std::optional<DisplayId> mId;
+71 −13
Original line number Diff line number Diff line
@@ -60,13 +60,8 @@ public:

    compositionengine::OutputLayer* getOutputLayerForLayer(
            compositionengine::Layer*) const override;
    std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
            const std::shared_ptr<Layer>&, const sp<LayerFE>&) const override;
    void setOutputLayersOrderedByZ(OutputLayers&&) override;
    const OutputLayers& getOutputLayersOrderedByZ() const override;

    void setReleasedLayers(ReleasedLayers&&) override;
    ReleasedLayers takeReleasedLayers() override;

    void prepare(const CompositionRefreshArgs&, LayerFESet&) override;
    void present(const CompositionRefreshArgs&) override;
@@ -74,8 +69,7 @@ public:
    void rebuildLayerStacks(const CompositionRefreshArgs&, LayerFESet&) override;
    void collectVisibleLayers(const CompositionRefreshArgs&,
                              compositionengine::Output::CoverageState&) override;
    std::unique_ptr<compositionengine::OutputLayer> getOutputLayerIfVisible(
            std::shared_ptr<compositionengine::Layer>,
    void ensureOutputLayerIfVisible(std::shared_ptr<compositionengine::Layer>,
                                    compositionengine::Output::CoverageState&) override;
    void setReleasedLayers(const compositionengine::CompositionRefreshArgs&) override;

@@ -95,9 +89,9 @@ public:
    void setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface>);

protected:
    virtual const CompositionEngine& getCompositionEngine() const = 0;
    std::unique_ptr<compositionengine::OutputLayer> takeOutputLayerForLayer(
            compositionengine::Layer*);
    std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
            const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&) const;
    std::optional<size_t> findCurrentOutputLayerForLayer(compositionengine::Layer*) const;
    void chooseCompositionStrategy() override;
    bool getSkipColorTransform() const override;
    compositionengine::Output::FrameFences presentAndGetFrameFences() override;
@@ -109,7 +103,14 @@ protected:
    void dumpBase(std::string&) const;

    // Implemented by the final implementation for the final state it uses.
    virtual void dumpState(std::string&) const = 0;
    virtual compositionengine::OutputLayer* ensureOutputLayer(
            std::optional<size_t>, const std::shared_ptr<compositionengine::Layer>&,
            const sp<LayerFE>&) = 0;
    virtual compositionengine::OutputLayer* injectOutputLayerForTest(
            const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&) = 0;
    virtual void finalizePendingOutputLayers() = 0;
    virtual const compositionengine::CompositionEngine& getCompositionEngine() const = 0;
    virtual void dumpState(std::string& out) const = 0;

private:
    void dirtyEntireOutput();
@@ -122,7 +123,6 @@ private:
    std::unique_ptr<compositionengine::DisplayColorProfile> mDisplayColorProfile;
    std::unique_ptr<compositionengine::RenderSurface> mRenderSurface;

    OutputLayers mOutputLayersOrderedByZ;
    ReleasedLayers mReleasedLayers;
};

@@ -141,6 +141,8 @@ std::shared_ptr<BaseOutput> createOutputTemplated(const CompositionEngine& compo

        using OutputCompositionState = std::remove_const_t<
                std::remove_reference_t<decltype(std::declval<BaseOutput>().getState())>>;
        using OutputLayer = std::remove_pointer_t<decltype(
                std::declval<BaseOutput>().getOutputLayerOrderedByZByIndex(0))>;

#pragma clang diagnostic pop

@@ -151,16 +153,72 @@ std::shared_ptr<BaseOutput> createOutputTemplated(const CompositionEngine& compo
    private:
        // compositionengine::Output overrides
        const OutputCompositionState& getState() const override { return mState; }

        OutputCompositionState& editState() override { return mState; }

        size_t getOutputLayerCount() const override {
            return mCurrentOutputLayersOrderedByZ.size();
        }

        OutputLayer* getOutputLayerOrderedByZByIndex(size_t index) const override {
            if (index >= mCurrentOutputLayersOrderedByZ.size()) {
                return nullptr;
            }
            return mCurrentOutputLayersOrderedByZ[index].get();
        }

        // compositionengine::impl::Output overrides
        const CompositionEngine& getCompositionEngine() const override {
            return mCompositionEngine;
        };

        OutputLayer* ensureOutputLayer(std::optional<size_t> prevIndex,
                                       const std::shared_ptr<compositionengine::Layer>& layer,
                                       const sp<LayerFE>& layerFE) {
            auto outputLayer = (prevIndex && *prevIndex <= mCurrentOutputLayersOrderedByZ.size())
                    ? std::move(mCurrentOutputLayersOrderedByZ[*prevIndex])
                    : BaseOutput::createOutputLayer(layer, layerFE);
            auto result = outputLayer.get();
            mPendingOutputLayersOrderedByZ.emplace_back(std::move(outputLayer));
            return result;
        }

        void finalizePendingOutputLayers() override {
            // The pending layers are added in reverse order. Reverse them to
            // get the back-to-front ordered list of layers.
            std::reverse(mPendingOutputLayersOrderedByZ.begin(),
                         mPendingOutputLayersOrderedByZ.end());

            mCurrentOutputLayersOrderedByZ = std::move(mPendingOutputLayersOrderedByZ);
        }

        void dumpState(std::string& out) const override { mState.dump(out); }

        OutputLayer* injectOutputLayerForTest(
                const std::shared_ptr<compositionengine::Layer>& layer,
                const sp<LayerFE>& layerFE) override {
            auto outputLayer = BaseOutput::createOutputLayer(layer, layerFE);
            auto result = outputLayer.get();
            mCurrentOutputLayersOrderedByZ.emplace_back(std::move(outputLayer));
            return result;
        }

        // Note: This is declared as a private virtual non-override so it can be
        // an override implementation in the unit tests, but otherwise is not an
        // accessible override for the normal implementation.
        virtual void injectOutputLayerForTest(std::unique_ptr<OutputLayer> outputLayer) {
            mCurrentOutputLayersOrderedByZ.emplace_back(std::move(outputLayer));
        }

        void clearOutputLayers() override {
            mCurrentOutputLayersOrderedByZ.clear();
            mPendingOutputLayersOrderedByZ.clear();
        }

        const CompositionEngine& mCompositionEngine;
        OutputCompositionState mState;
        std::vector<std::unique_ptr<OutputLayer>> mCurrentOutputLayersOrderedByZ;
        std::vector<std::unique_ptr<OutputLayer>> mPendingOutputLayersOrderedByZ;
    };

    return std::make_shared<Output>(compositionEngine, std::forward<Args>(args)...);
+9 −16
Original line number Diff line number Diff line
@@ -64,20 +64,14 @@ public:

    MOCK_CONST_METHOD1(getOutputLayerForLayer,
                       compositionengine::OutputLayer*(compositionengine::Layer*));
    MOCK_CONST_METHOD2(createOutputLayer,
                       std::unique_ptr<compositionengine::OutputLayer>(
                               const std::shared_ptr<compositionengine::Layer>&,
    MOCK_METHOD0(clearOutputLayers, void());
    MOCK_METHOD2(injectOutputLayerForTest,
                 compositionengine::OutputLayer*(const std::shared_ptr<compositionengine::Layer>&,
                                                 const sp<compositionengine::LayerFE>&));
    MOCK_METHOD2(getOrCreateOutputLayer,
                 std::unique_ptr<compositionengine::OutputLayer>(
                         std::shared_ptr<compositionengine::Layer>,
                         sp<compositionengine::LayerFE>));

    MOCK_METHOD1(setOutputLayersOrderedByZ, void(OutputLayers&&));
    MOCK_CONST_METHOD0(getOutputLayersOrderedByZ, OutputLayers&());
    MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
    MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, OutputLayer*(size_t));

    MOCK_METHOD1(setReleasedLayers, void(ReleasedLayers&&));
    MOCK_METHOD0(takeReleasedLayers, ReleasedLayers());

    MOCK_METHOD2(prepare, void(const compositionengine::CompositionRefreshArgs&, LayerFESet&));
    MOCK_METHOD1(present, void(const compositionengine::CompositionRefreshArgs&));
@@ -87,9 +81,8 @@ public:
    MOCK_METHOD2(collectVisibleLayers,
                 void(const compositionengine::CompositionRefreshArgs&,
                      compositionengine::Output::CoverageState&));
    MOCK_METHOD2(getOutputLayerIfVisible,
                 std::unique_ptr<compositionengine::OutputLayer>(
                         std::shared_ptr<compositionengine::Layer>,
    MOCK_METHOD2(ensureOutputLayerIfVisible,
                 void(std::shared_ptr<compositionengine::Layer>,
                      compositionengine::Output::CoverageState&));
    MOCK_METHOD1(setReleasedLayers, void(const compositionengine::CompositionRefreshArgs&));

+1 −1
Original line number Diff line number Diff line
@@ -101,7 +101,7 @@ void CompositionEngine::updateCursorAsync(CompositionRefreshArgs& args) {
            uniqueVisibleLayers;

    for (const auto& output : args.outputs) {
        for (auto& layer : output->getOutputLayersOrderedByZ()) {
        for (auto* layer : output->getOutputLayersOrderedByZ()) {
            if (layer->isHardwareCursor()) {
                // Latch the cursor composition state from each front-end layer.
                layer->getLayerFE().latchCursorCompositionState(layer->getLayer().editFEState());
Loading