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

Commit 87a5944e authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 10682531 from 19603058 to udc-qpr1-release

Change-Id: Ifaa5d2134281bdd6252bf9172f11cf7cb603b712
parents 3f8c57ac 19603058
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ use bitflags::bitflags;
use log::info;

#[cxx::bridge(namespace = "android::input")]
#[allow(unsafe_op_in_unsafe_fn)]
mod ffi {
    #[namespace = "android"]
    unsafe extern "C++" {
+7 −10
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ public:
    TexturePool(renderengine::RenderEngine& renderEngine)
          : mRenderEngine(renderEngine), mEnabled(false) {}

    virtual ~TexturePool();
    virtual ~TexturePool() = default;

    // Sets the display size for the texture pool.
    // This will trigger a reallocation for all remaining textures in the pool.
@@ -83,10 +83,11 @@ public:
    // be held by the pool. This is useful when the active display changes.
    void setEnabled(bool enable);

    void dump(std::string& out) const EXCLUDES(mMutex);
    void dump(std::string& out) const;

protected:
    // Proteted visibility so that they can be used for testing
    const static constexpr size_t kMinPoolSize = 3;
    const static constexpr size_t kMaxPoolSize = 4;

    struct Entry {
@@ -95,20 +96,16 @@ protected:
    };

    std::deque<Entry> mPool;
    std::future<std::shared_ptr<renderengine::ExternalTexture>> mGenTextureFuture;

private:
    std::shared_ptr<renderengine::ExternalTexture> genTexture(ui::Size size);
    std::shared_ptr<renderengine::ExternalTexture> genTexture();
    // Returns a previously borrowed texture to the pool.
    void returnTexture(std::shared_ptr<renderengine::ExternalTexture>&& texture,
                       const sp<Fence>& fence);
    void genTextureAsyncIfNeeded() REQUIRES(mMutex);
    void resetPool() REQUIRES(mMutex);
    renderengine::RenderEngine& mRenderEngine GUARDED_BY(mRenderEngineMutex);
    ui::Size mSize GUARDED_BY(mMutex);
    void allocatePool();
    renderengine::RenderEngine& mRenderEngine;
    ui::Size mSize;
    bool mEnabled;
    mutable std::mutex mMutex;
    mutable std::mutex mRenderEngineMutex;
};

} // namespace android::compositionengine::impl::planner
+14 −50
Original line number Diff line number Diff line
@@ -25,61 +25,31 @@

namespace android::compositionengine::impl::planner {

TexturePool::~TexturePool() {
    if (mGenTextureFuture.valid()) {
        mGenTextureFuture.get();
    }
}

void TexturePool::resetPool() {
    if (mGenTextureFuture.valid()) {
        mGenTextureFuture.get();
    }
void TexturePool::allocatePool() {
    mPool.clear();
    genTextureAsyncIfNeeded();
}

// Generate a new texture asynchronously so it will not require allocation on the main
// thread.
void TexturePool::genTextureAsyncIfNeeded() {
    if (mEnabled && mSize.isValid() && !mGenTextureFuture.valid()) {
        mGenTextureFuture = std::async(
                std::launch::async, [&](ui::Size size) { return genTexture(size); }, mSize);
    if (mEnabled && mSize.isValid()) {
        mPool.resize(kMinPoolSize);
        std::generate_n(mPool.begin(), kMinPoolSize, [&]() {
            return Entry{genTexture(), nullptr};
        });
    }
}

void TexturePool::setDisplaySize(ui::Size size) {
    std::lock_guard lock(mMutex);
    if (mSize == size) {
        return;
    }
    mSize = size;
    resetPool();
    allocatePool();
}

std::shared_ptr<TexturePool::AutoTexture> TexturePool::borrowTexture() {
    if (mPool.empty()) {
        std::lock_guard lock(mMutex);
        std::shared_ptr<TexturePool::AutoTexture> tex;
        if (mGenTextureFuture.valid()) {
            tex = std::make_shared<AutoTexture>(*this, mGenTextureFuture.get(), nullptr);
        } else {
            tex = std::make_shared<AutoTexture>(*this, genTexture(mSize), nullptr);
        }
        // Speculatively generate a new texture, so that the next call does not need
        // to wait for allocation.
        genTextureAsyncIfNeeded();
        return tex;
        return std::make_shared<AutoTexture>(*this, genTexture(), nullptr);
    }

    const auto entry = mPool.front();
    mPool.pop_front();
    if (mPool.empty()) {
        std::lock_guard lock(mMutex);
        // Similiarly generate a new texture when lending out the last entry, so that
        // the next call does not need to wait for allocation.
        genTextureAsyncIfNeeded();
    }
    return std::make_shared<AutoTexture>(*this, entry.texture, entry.fence);
}

@@ -90,8 +60,6 @@ void TexturePool::returnTexture(std::shared_ptr<renderengine::ExternalTexture>&&
        return;
    }

    std::lock_guard lock(mMutex);

    // Or the texture on the floor if the pool is no longer tracking textures of the same size.
    if (static_cast<int32_t>(texture->getBuffer()->getWidth()) != mSize.getWidth() ||
        static_cast<int32_t>(texture->getBuffer()->getHeight()) != mSize.getHeight()) {
@@ -112,14 +80,13 @@ void TexturePool::returnTexture(std::shared_ptr<renderengine::ExternalTexture>&&
    mPool.push_back({std::move(texture), fence});
}

std::shared_ptr<renderengine::ExternalTexture> TexturePool::genTexture(ui::Size size) {
    std::lock_guard lock(mRenderEngineMutex);
    LOG_ALWAYS_FATAL_IF(!size.isValid(), "Attempted to generate texture with invalid size");
std::shared_ptr<renderengine::ExternalTexture> TexturePool::genTexture() {
    LOG_ALWAYS_FATAL_IF(!mSize.isValid(), "Attempted to generate texture with invalid size");
    return std::make_shared<
            renderengine::impl::
                    ExternalTexture>(sp<GraphicBuffer>::
                                             make(static_cast<uint32_t>(size.getWidth()),
                                                  static_cast<uint32_t>(size.getHeight()),
                                             make(static_cast<uint32_t>(mSize.getWidth()),
                                                  static_cast<uint32_t>(mSize.getHeight()),
                                                  HAL_PIXEL_FORMAT_RGBA_8888, 1U,
                                                  static_cast<uint64_t>(
                                                          GraphicBuffer::USAGE_HW_RENDER |
@@ -133,13 +100,10 @@ std::shared_ptr<renderengine::ExternalTexture> TexturePool::genTexture(ui::Size

void TexturePool::setEnabled(bool enabled) {
    mEnabled = enabled;

    std::lock_guard lock(mMutex);
    resetPool();
    allocatePool();
}

void TexturePool::dump(std::string& out) const {
    std::lock_guard lock(mMutex);
    base::StringAppendF(&out,
                        "TexturePool (%s) has %zu buffers of size [%" PRId32 ", %" PRId32 "]\n",
                        mEnabled ? "enabled" : "disabled", mPool.size(), mSize.width, mSize.height);
+22 −11
Original line number Diff line number Diff line
@@ -32,9 +32,9 @@ class TestableTexturePool : public TexturePool {
public:
    TestableTexturePool(renderengine::RenderEngine& renderEngine) : TexturePool(renderEngine) {}

    size_t getMinPoolSize() const { return kMinPoolSize; }
    size_t getMaxPoolSize() const { return kMaxPoolSize; }
    size_t getPoolSize() const { return mPool.size(); }
    size_t isGenTextureFutureValid() const { return mGenTextureFuture.valid(); }
};

struct TexturePoolTest : public testing::Test {
@@ -56,8 +56,16 @@ struct TexturePoolTest : public testing::Test {
    TestableTexturePool mTexturePool = TestableTexturePool(mRenderEngine);
};

TEST_F(TexturePoolTest, preallocatesZeroSizePool) {
    EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
TEST_F(TexturePoolTest, preallocatesMinPool) {
    EXPECT_EQ(mTexturePool.getMinPoolSize(), mTexturePool.getPoolSize());
}

TEST_F(TexturePoolTest, doesNotAllocateBeyondMinPool) {
    for (size_t i = 0; i < mTexturePool.getMinPoolSize() + 1; i++) {
        auto texture = mTexturePool.borrowTexture();
    }

    EXPECT_EQ(mTexturePool.getMinPoolSize(), mTexturePool.getPoolSize());
}

TEST_F(TexturePoolTest, cyclesUpToMaxPoolSize) {
@@ -111,10 +119,10 @@ TEST_F(TexturePoolTest, reallocatesWhenDisplaySizeChanges) {
              static_cast<int32_t>(texture->get()->getBuffer()->getHeight()));
    mTexturePool.setDisplaySize(kDisplaySizeTwo);

    EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
    EXPECT_EQ(mTexturePool.getMinPoolSize(), mTexturePool.getPoolSize());
    texture.reset();
    // When the texture is returned to the pool, the pool now destroys it.
    EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
    EXPECT_EQ(mTexturePool.getMinPoolSize(), mTexturePool.getPoolSize());

    texture = mTexturePool.borrowTexture();
    EXPECT_EQ(kDisplaySizeTwo.getWidth(),
@@ -124,11 +132,14 @@ TEST_F(TexturePoolTest, reallocatesWhenDisplaySizeChanges) {
}

TEST_F(TexturePoolTest, freesBuffersWhenDisabled) {
    EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize());

    std::deque<std::shared_ptr<TexturePool::AutoTexture>> textures;
    for (size_t i = 0; i < 2; i++) {
    for (size_t i = 0; i < mTexturePool.getMinPoolSize() - 1; i++) {
        textures.emplace_back(mTexturePool.borrowTexture());
    }

    EXPECT_EQ(mTexturePool.getPoolSize(), 1u);
    mTexturePool.setEnabled(false);
    EXPECT_EQ(mTexturePool.getPoolSize(), 0u);

@@ -137,11 +148,12 @@ TEST_F(TexturePoolTest, freesBuffersWhenDisabled) {
}

TEST_F(TexturePoolTest, doesNotHoldBuffersWhenDisabled) {
    EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize());
    mTexturePool.setEnabled(false);
    EXPECT_EQ(mTexturePool.getPoolSize(), 0u);

    std::deque<std::shared_ptr<TexturePool::AutoTexture>> textures;
    for (size_t i = 0; i < 2; i++) {
    for (size_t i = 0; i < mTexturePool.getMinPoolSize() - 1; i++) {
        textures.emplace_back(mTexturePool.borrowTexture());
    }

@@ -150,13 +162,12 @@ TEST_F(TexturePoolTest, doesNotHoldBuffersWhenDisabled) {
    EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
}

TEST_F(TexturePoolTest, genFutureWhenReEnabled) {
TEST_F(TexturePoolTest, reallocatesWhenReEnabled) {
    EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize());
    mTexturePool.setEnabled(false);
    EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
    EXPECT_FALSE(mTexturePool.isGenTextureFutureValid());
    mTexturePool.setEnabled(true);
    EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
    EXPECT_TRUE(mTexturePool.isGenTextureFutureValid());
    EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize());
}

} // namespace
+30 −15
Original line number Diff line number Diff line
@@ -148,8 +148,8 @@ std::string toString(const RefreshRateSelector::PolicyVariant& policy) {
} // namespace

auto RefreshRateSelector::createFrameRateModes(
        std::function<bool(const DisplayMode&)>&& filterModes, const FpsRange& renderRange) const
        -> std::vector<FrameRateMode> {
        const Policy& policy, std::function<bool(const DisplayMode&)>&& filterModes,
        const FpsRange& renderRange) const -> std::vector<FrameRateMode> {
    struct Key {
        Fps fps;
        int32_t group;
@@ -202,11 +202,25 @@ auto RefreshRateSelector::createFrameRateModes(
                ALOGV("%s: including %s (%s)", __func__, to_string(fps).c_str(),
                      to_string(mode->getFps()).c_str());
            } else {
                // If the primary physical range is a single rate, prefer to stay in that rate
                // even if there is a lower physical refresh rate available. This would cause more
                // cases to stay within the primary physical range
                const Fps existingModeFps = existingIter->second->second->getFps();
                const bool existingModeIsPrimaryRange = policy.primaryRangeIsSingleRate() &&
                        policy.primaryRanges.physical.includes(existingModeFps);
                const bool newModeIsPrimaryRange = policy.primaryRangeIsSingleRate() &&
                        policy.primaryRanges.physical.includes(mode->getFps());
                if (newModeIsPrimaryRange == existingModeIsPrimaryRange) {
                    // We might need to update the map as we found a lower refresh rate
                if (isStrictlyLess(mode->getFps(), existingIter->second->second->getFps())) {
                    if (isStrictlyLess(mode->getFps(), existingModeFps)) {
                        existingIter->second = it;
                    ALOGV("%s: changing %s (%s)", __func__, to_string(fps).c_str(),
                          to_string(mode->getFps()).c_str());
                        ALOGV("%s: changing %s (%s) as we found a lower physical rate", __func__,
                              to_string(fps).c_str(), to_string(mode->getFps()).c_str());
                    }
                } else if (newModeIsPrimaryRange) {
                    existingIter->second = it;
                    ALOGV("%s: changing %s (%s) to stay in the primary range", __func__,
                          to_string(fps).c_str(), to_string(mode->getFps()).c_str());
                }
            }
        }
@@ -500,10 +514,8 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
    // If the primary range consists of a single refresh rate then we can only
    // move out the of range if layers explicitly request a different refresh
    // rate.
    const bool primaryRangeIsSingleRate =
            isApproxEqual(policy->primaryRanges.physical.min, policy->primaryRanges.physical.max);

    if (!signals.touch && signals.idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) {
    if (!signals.touch && signals.idle &&
        !(policy->primaryRangeIsSingleRate() && hasExplicitVoteLayers)) {
        ALOGV("Idle");
        const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending);
        ATRACE_FORMAT_INSTANT("%s (Idle)", to_string(ranking.front().frameRateMode.fps).c_str());
@@ -577,8 +589,11 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
                continue;
            }

            const bool inPrimaryRange = policy->primaryRanges.render.includes(fps);
            if ((primaryRangeIsSingleRate || !inPrimaryRange) &&
            const bool inPrimaryPhysicalRange =
                    policy->primaryRanges.physical.includes(modePtr->getFps());
            const bool inPrimaryRenderRange = policy->primaryRanges.render.includes(fps);
            if (((policy->primaryRangeIsSingleRate() && !inPrimaryPhysicalRange) ||
                 !inPrimaryRenderRange) &&
                !(layer.focused &&
                  (layer.vote == LayerVoteType::ExplicitDefault ||
                   layer.vote == LayerVoteType::ExplicitExact))) {
@@ -689,7 +704,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
        return score.overallScore == 0;
    });

    if (primaryRangeIsSingleRate) {
    if (policy->primaryRangeIsSingleRate()) {
        // If we never scored any layers, then choose the rate from the primary
        // range instead of picking a random score from the app range.
        if (noLayerScore) {
@@ -1234,14 +1249,14 @@ void RefreshRateSelector::constructAvailableRefreshRates() {
                    (supportsFrameRateOverride() || ranges.render.includes(mode.getFps()));
        };

        auto frameRateModes = createFrameRateModes(filterModes, ranges.render);
        auto frameRateModes = createFrameRateModes(*policy, filterModes, ranges.render);
        if (frameRateModes.empty()) {
            ALOGW("No matching frame rate modes for %s range. policy: %s", rangeName,
                  policy->toString().c_str());
            // TODO(b/292105422): Ideally DisplayManager should not send render ranges smaller than
            // the min supported. See b/292047939.
            //  For not we just ignore the render ranges.
            frameRateModes = createFrameRateModes(filterModes, {});
            frameRateModes = createFrameRateModes(*policy, filterModes, {});
        }
        LOG_ALWAYS_FATAL_IF(frameRateModes.empty(),
                            "No matching frame rate modes for %s range even after ignoring the "
Loading