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

Commit 8d795707 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Allow single inactive layers to be cached if they would be used for a hole punch."

parents eed5ed29 1e69253c
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -98,8 +98,8 @@ private:
                             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
    // CachedSet. Because it is wasteful to flatten 1 CachedSet, a run must contain more than
    // 1 CachedSet or be used for a hole punch.
    class Run {
    public:
        // A builder for a Run, to aid in construction
@@ -133,7 +133,13 @@ private:

            // Builds a Run instance, if a valid Run may be built.
            std::optional<Run> validateAndBuild() {
                if (mLengths.size() <= 1) {
                if (mLengths.size() == 0) {
                    return std::nullopt;
                }
                // Runs of length 1 which are hole punch candidates are allowed if the candidate is
                // going to be used.
                if (mLengths.size() == 1 &&
                    (!mHolePunchCandidate || !(mHolePunchCandidate->requiresHolePunch()))) {
                    return std::nullopt;
                }

+67 −0
Original line number Diff line number Diff line
@@ -659,6 +659,73 @@ TEST_F(FlattenerTest, flattenLayers_pip) {
    EXPECT_EQ(peekThroughLayer1, peekThroughLayer2);
}

// A test that verifies the hole puch optimization can be done on a single layer.
TEST_F(FlattenerTest, flattenLayers_holePunchSingleLayer) {
    mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);

    // An opaque static background
    auto& layerState0 = mTestLayers[0]->layerState;
    const auto& overrideBuffer0 = layerState0->getOutputLayer()->getState().overrideInfo.buffer;

    // a rounded updating layer
    auto& layerState1 = mTestLayers[1]->layerState;
    const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;

    EXPECT_CALL(*mTestLayers[1]->layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));

    std::vector<LayerFE::LayerSettings> clientCompositionList = {
            LayerFE::LayerSettings{},
    };
    clientCompositionList[0].source.buffer.buffer = std::make_shared<
            renderengine::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer,
                                           mRenderEngine,
                                           renderengine::ExternalTexture::Usage::READABLE);
    EXPECT_CALL(*mTestLayers[1]->layerFE, prepareClientCompositionList(_))
            .WillOnce(Return(clientCompositionList));

    const std::vector<const LayerState*> layers = {
            layerState0.get(),
            layerState1.get(),
    };

    initializeFlattener(layers);

    // layer 1 satisfies every condition in CachedSet::requiresHolePunch()
    mTime += 200ms;
    layerState1->resetFramesSinceBufferUpdate(); // it is updating

    initializeOverrideBuffer(layers);
    // Expect no cache invalidation the first time (there's no cache yet)
    EXPECT_EQ(getNonBufferHash(layers),
              mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));

    // This will render a CachedSet of layer 0. Though it is just one layer, it satisfies the
    // exception that there would be a hole punch above it.
    EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Return(NO_ERROR));
    mFlattener->renderCachedSets(mOutputState, std::nullopt);

    // We've rendered a CachedSet, but we haven't merged it in.
    EXPECT_EQ(nullptr, overrideBuffer0);

    // This time we merge the CachedSet in and we should still have only two sets.
    EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).Times(0);
    initializeOverrideBuffer(layers);
    EXPECT_EQ(getNonBufferHash(layers),
              mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
    mFlattener->renderCachedSets(mOutputState, std::nullopt);

    EXPECT_NE(nullptr, overrideBuffer0); // got overridden
    EXPECT_EQ(nullptr, overrideBuffer1); // did not

    // expect 0's peek though layer to be 1's output layer
    const auto* peekThroughLayer0 =
            layerState0->getOutputLayer()->getState().overrideInfo.peekThroughLayer;
    const auto* peekThroughLayer1 =
            layerState1->getOutputLayer()->getState().overrideInfo.peekThroughLayer;
    EXPECT_EQ(&mTestLayers[1]->outputLayer, peekThroughLayer0);
    EXPECT_EQ(nullptr, peekThroughLayer1);
}

TEST_F(FlattenerTest, flattenLayers_flattensBlurBehindRunIfFirstRun) {
    auto& layerState1 = mTestLayers[0]->layerState;