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

Commit 97486060 authored by Alec Mouri's avatar Alec Mouri
Browse files

Add blur support in caching

Fixes some flickering issues:
* Add blur metadata into LayerState
* Only cache a layer that requires blurring if all layers below it are
part of the same CachedSet to avoid caching part of, but not all of, the
blur

This doesn't preclude caching intermediate blurs: e.g., the blur radius
of a layer does not change, everything else below the layer does not
change, but some other property of that layer changes - ideally this
layer should be cached, but is not currently supported in this patch.

Bug: 186692925
Test: Notification shade blur overlayed on Maps
Test: Notification shade blur overlayed on Wallpaper

Change-Id: I2f112927accc35cab406292486890fe41423d022
parent d1bf1b52
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -195,18 +195,6 @@ static inline bool operator==(const ShadowSettings& lhs, const ShadowSettings& r
            lhs.length == rhs.length && lhs.casterIsTranslucent == rhs.casterIsTranslucent;
}

static inline bool operator==(const BlurRegion& lhs, const BlurRegion& rhs) {
    return lhs.alpha == rhs.alpha && lhs.cornerRadiusTL == rhs.cornerRadiusTL &&
            lhs.cornerRadiusTR == rhs.cornerRadiusTR && lhs.cornerRadiusBL == rhs.cornerRadiusBL &&
            lhs.cornerRadiusBR == rhs.cornerRadiusBR && lhs.blurRadius == rhs.blurRadius &&
            lhs.left == rhs.left && lhs.top == rhs.top && lhs.right == rhs.right &&
            lhs.bottom == rhs.bottom;
}

static inline bool operator!=(const BlurRegion& lhs, const BlurRegion& rhs) {
    return !(lhs == rhs);
}

static inline bool operator==(const LayerSettings& lhs, const LayerSettings& rhs) {
    if (lhs.blurRegions.size() != rhs.blurRegions.size()) {
        return false;
+24 −1
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#include <iosfwd>
#include <iostream>

#include <math/HashCombine.h>

namespace android {

struct BlurRegion {
@@ -33,6 +35,16 @@ struct BlurRegion {
    int top;
    int right;
    int bottom;

    inline bool operator==(const BlurRegion& other) const {
        return blurRadius == other.blurRadius && cornerRadiusTL == other.cornerRadiusTL &&
                cornerRadiusTR == other.cornerRadiusTR && cornerRadiusBL == other.cornerRadiusBL &&
                cornerRadiusBR == other.cornerRadiusBR && alpha == other.alpha &&
                left == other.left && top == other.top && right == other.right &&
                bottom == other.bottom;
    }

    inline bool operator!=(const BlurRegion& other) const { return !(*this == other); }
};

static inline void PrintTo(const BlurRegion& blurRegion, ::std::ostream* os) {
@@ -51,3 +63,14 @@ static inline void PrintTo(const BlurRegion& blurRegion, ::std::ostream* os) {
}

} // namespace android

namespace std {
template <>
struct hash<android::BlurRegion> {
    size_t operator()(const android::BlurRegion& region) const {
        return android::hashCombine(region.blurRadius, region.cornerRadiusTL, region.cornerRadiusTR,
                                    region.cornerRadiusBL, region.cornerRadiusBR, region.alpha,
                                    region.left, region.top, region.right, region.bottom);
    }
};
} // namespace std
 No newline at end of file
+3 −0
Original line number Diff line number Diff line
@@ -110,6 +110,9 @@ public:
    // CachedSet and punching a hole.
    bool requiresHolePunch() const;

    // True if any constituent layer is configured to blur any layers behind.
    bool hasBlurBehind() const;

    // Add a layer that will be drawn behind this one. ::render() will render a
    // hole in this CachedSet's buffer, allowing the supplied layer to peek
    // through. Must be called before ::render().
+68 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <compositionengine/impl/planner/CachedSet.h>
#include <compositionengine/impl/planner/LayerState.h>

#include <numeric>
#include <vector>

namespace android {
@@ -60,6 +61,73 @@ private:
    bool mergeWithCachedSets(const std::vector<const LayerState*>& layers,
                             std::chrono::steady_clock::time_point now);

    // A Run is a sequence of CachedSets, which is a candidate for flattening into a single
    // CachedSet. Because it is wasteful to flatten 1 CachedSet, a Run must contain more than 1
    // CachedSet
    class Run {
    public:
        // A builder for a Run, to aid in construction
        class Builder {
        private:
            std::vector<CachedSet>::const_iterator mStart;
            std::vector<size_t> mLengths;
            const CachedSet* mHolePunchCandidate = nullptr;

        public:
            // Initializes a Builder a CachedSet to start from.
            // This start iterator must be an iterator for mLayers
            void init(const std::vector<CachedSet>::const_iterator& start) {
                mStart = start;
                mLengths.push_back(start->getLayerCount());
            }

            // Appends a new CachedSet to the end of the run
            // The provided length must be the size of the next sequential CachedSet in layers
            void append(size_t length) { mLengths.push_back(length); }

            // Sets the hole punch candidate for the Run.
            void setHolePunchCandidate(const CachedSet* holePunchCandidate) {
                mHolePunchCandidate = holePunchCandidate;
            }

            // Builds a Run instance, if a valid Run may be built.
            std::optional<Run> validateAndBuild() {
                if (mLengths.size() <= 1) {
                    return std::nullopt;
                }

                return Run(mStart,
                           std::reduce(mLengths.cbegin(), mLengths.cend(), 0u,
                                       [](size_t left, size_t right) { return left + right; }),
                           mHolePunchCandidate);
            }

            void reset() { *this = {}; }
        };

        // Gets the starting CachedSet of this run.
        // This is an iterator into mLayers
        const std::vector<CachedSet>::const_iterator& getStart() const { return mStart; }
        // Gets the total number of layers encompassing this Run.
        size_t getLayerLength() const { return mLength; }
        // Gets the hole punch candidate for this Run.
        const CachedSet* getHolePunchCandidate() const { return mHolePunchCandidate; }

    private:
        Run(std::vector<CachedSet>::const_iterator start, size_t length,
            const CachedSet* holePunchCandidate)
              : mStart(start), mLength(length), mHolePunchCandidate(holePunchCandidate) {}
        const std::vector<CachedSet>::const_iterator mStart;
        const size_t mLength;
        const CachedSet* const mHolePunchCandidate;

        friend class Builder;
    };

    std::vector<Run> findCandidateRuns(std::chrono::steady_clock::time_point now) const;

    std::optional<Run> findBestRun(std::vector<Run>& runs) const;

    void buildCachedSets(std::chrono::steady_clock::time_point now);

    const bool mEnableHolePunch;
+67 −23
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <string>

#include "DisplayHardware/Hal.h"
#include "math/HashCombine.h"

namespace std {
template <typename T>
@@ -66,6 +67,8 @@ enum class LayerStateField : uint32_t {
    SidebandStream        = 1u << 14,
    Buffer                = 1u << 15,
    SolidColor            = 1u << 16,
    BackgroundBlurRadius  = 1u << 17,
    BlurRegions           = 1u << 18,
};
// clang-format on

@@ -225,6 +228,9 @@ public:
    const std::string& getName() const { return mName.get(); }
    Rect getDisplayFrame() const { return mDisplayFrame.get(); }
    const Region& getVisibleRegion() const { return mVisibleRegion.get(); }
    bool hasBlurBehind() const {
        return mBackgroundBlurRadius.get() > 0 || !mBlurRegions.get().empty();
    }
    hardware::graphics::composer::hal::Composition getCompositionType() const {
        return mCompositionType.get();
    }
@@ -398,7 +404,45 @@ private:
                            return std::vector<std::string>{stream.str()};
                        }};

    static const constexpr size_t kNumNonUniqueFields = 14;
    OutputLayerState<int32_t, LayerStateField::BackgroundBlurRadius> mBackgroundBlurRadius{
            [](auto layer) {
                return layer->getLayerFE().getCompositionState()->backgroundBlurRadius;
            }};

    using BlurRegionsState =
            OutputLayerState<std::vector<BlurRegion>, LayerStateField::BlurRegions>;
    BlurRegionsState mBlurRegions{[](auto layer) {
                                      return layer->getLayerFE().getCompositionState()->blurRegions;
                                  },
                                  [](const std::vector<BlurRegion>& regions) {
                                      std::vector<std::string> result;
                                      for (const auto region : regions) {
                                          std::string str;
                                          base::StringAppendF(&str,
                                                              "{radius=%du, cornerRadii=[%f, %f, "
                                                              "%f, %f], alpha=%f, rect=[%d, "
                                                              "%d, %d, %d]",
                                                              region.blurRadius,
                                                              region.cornerRadiusTL,
                                                              region.cornerRadiusTR,
                                                              region.cornerRadiusBL,
                                                              region.cornerRadiusBR, region.alpha,
                                                              region.left, region.top, region.right,
                                                              region.bottom);
                                          result.push_back(str);
                                      }
                                      return result;
                                  },
                                  BlurRegionsState::getDefaultEquals(),
                                  [](const std::vector<BlurRegion>& regions) {
                                      size_t hash = 0;
                                      for (const auto& region : regions) {
                                          android::hashCombineSingle(hash, region);
                                      }
                                      return hash;
                                  }};

    static const constexpr size_t kNumNonUniqueFields = 16;

    std::array<StateInterface*, kNumNonUniqueFields> getNonUniqueFields() {
        std::array<const StateInterface*, kNumNonUniqueFields> constFields =
@@ -416,7 +460,7 @@ private:
                &mDisplayFrame, &mSourceCrop,     &mBufferTransform,      &mBlendMode,
                &mAlpha,        &mLayerMetadata,  &mVisibleRegion,        &mOutputDataspace,
                &mPixelFormat,  &mColorTransform, &mCompositionType,      &mSidebandStream,
                &mBuffer,       &mSolidColor,
                &mBuffer,       &mSolidColor,     &mBackgroundBlurRadius, &mBlurRegions,
        };
    }
};
Loading