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

Commit 73e09c3a authored by Alec Mouri's avatar Alec Mouri
Browse files

ProjectionSpace fixes for caching:

* When feeding back into client composition, feed back the framebuffer
projection space instead of a projection space using mBounds as the
content rectangle. Otherwise, this tries to project the entire cached
set onto the entirety of the display, which is incorrect. Instead, the
cached set needs to be projected onto the displayFrame for the
overridden layer.
* When rendering the cached set and computing the physicalDisplay
rectangle, instead of passing in the framebuffer space bounds offset by
mBounds, pass in the framebuffer space content offset by mBounds.
Otherwise, this breaks simulated secondary displays: simulated secondary
displays works by projecting the layer stack onto a rectangle in the
middle of surface that is much narrower than the surface bounds. If the
framebuffer bounds are used to compute the physicalDisplay rectangle and
the cached set covers the entire secondary display, then when offset by
mBounds the cached set goes offscreen. The correct rectangle to use is
the framebuffer content rectangle.

Bug: 185398025
Test: libcompositionengine_test
Test: Simulated secondary displays
Test: Wallpaper picker doesn't suddenly resize when pulling down the
notification shade

Change-Id: Ie7119bc42db4887b448673c0ab11fee24db664c5
parent 9d533913
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -96,6 +96,11 @@ struct ProjectionSpace {
        // physical translation and finally rotate to the physical orientation.
        return rotationTransform * destTranslation * scale * sourceTranslation;
    }

    bool operator==(const ProjectionSpace& other) const {
        return bounds == other.bounds && content == other.content &&
                orientation == other.orientation;
    }
};

} // namespace compositionengine
+6 −7
Original line number Diff line number Diff line
@@ -158,11 +158,12 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine,
    const ui::Dataspace& outputDataspace = outputState.dataspace;
    const ui::Transform::RotationFlags orientation =
            ui::Transform::toRotationFlags(outputState.framebufferSpace.orientation);

    renderengine::DisplaySettings displaySettings{
            .physicalDisplay =
                    Rect(-mBounds.left, -mBounds.top,
                         -mBounds.left + outputState.framebufferSpace.content.getWidth(),
                         -mBounds.top + outputState.framebufferSpace.content.getHeight()),
            .physicalDisplay = Rect(-mBounds.left + outputState.framebufferSpace.content.left,
                                    -mBounds.top + outputState.framebufferSpace.content.top,
                                    -mBounds.left + outputState.framebufferSpace.content.right,
                                    -mBounds.top + outputState.framebufferSpace.content.bottom),
            .clip = viewport,
            .outputDataspace = outputDataspace,
            .orientation = orientation,
@@ -249,9 +250,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine,

    if (result == NO_ERROR) {
        mDrawFence = new Fence(drawFence.release());
        mOutputSpace = ProjectionSpace(ui::Size(outputState.framebufferSpace.bounds.getWidth(),
                                                outputState.framebufferSpace.bounds.getHeight()),
                                       mBounds);
        mOutputSpace = outputState.framebufferSpace;
        mTexture = std::move(texture);
        mOutputSpace.orientation = outputState.framebufferSpace.orientation;
        mOutputDataspace = outputDataspace;
+49 −4
Original line number Diff line number Diff line
@@ -325,10 +325,55 @@ TEST_F(CachedSetTest, render) {
    cachedSet.render(mRenderEngine, mOutputState);
    expectReadyBuffer(cachedSet);

    EXPECT_EQ(Rect(1, 1, 3, 3), cachedSet.getOutputSpace().content);
    EXPECT_EQ(Rect(mOutputState.framebufferSpace.bounds.getWidth(),
                   mOutputState.framebufferSpace.bounds.getHeight()),
              cachedSet.getOutputSpace().bounds);
    EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());

    // Now check that appending a new cached set properly cleans up RenderEngine resources.
    CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
    cachedSet.append(CachedSet(layer3));
}

TEST_F(CachedSetTest, rendersWithOffsetFramebufferContent) {
    // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
    CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
    sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE;
    CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get();
    sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE;

    CachedSet cachedSet(layer1);
    cachedSet.append(CachedSet(layer2));

    std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1;
    clientCompList1.push_back({});
    clientCompList1[0].alpha = 0.5f;

    std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2;
    clientCompList2.push_back({});
    clientCompList2[0].alpha = 0.75f;

    mOutputState.framebufferSpace = ProjectionSpace(ui::Size(10, 20), Rect(2, 3, 10, 5));

    const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings,
                                const std::vector<const renderengine::LayerSettings*>& layers,
                                const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
                                base::unique_fd&&, base::unique_fd*) -> size_t {
        EXPECT_EQ(Rect(1, 2, 9, 4), displaySettings.physicalDisplay);
        EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip);
        EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation),
                  displaySettings.orientation);
        EXPECT_EQ(0.5f, layers[0]->alpha);
        EXPECT_EQ(0.75f, layers[1]->alpha);
        EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace);

        return NO_ERROR;
    };

    EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1));
    EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2));
    EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
    cachedSet.render(mRenderEngine, mOutputState);
    expectReadyBuffer(cachedSet);

    EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());

    // Now check that appending a new cached set properly cleans up RenderEngine resources.
    CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
+1 −5
Original line number Diff line number Diff line
@@ -275,11 +275,7 @@ TEST_F(FlattenerTest, flattenLayers_FlattenedLayersSetsProjectionSpace) {
    mTime += 200ms;
    expectAllLayersFlattened(layers);

    EXPECT_EQ(overrideDisplaySpace.bounds,
              Rect(mOutputState.framebufferSpace.bounds.getWidth(),
                   mOutputState.framebufferSpace.bounds.getHeight()));
    EXPECT_EQ(overrideDisplaySpace.content, Rect(0, 0, 2, 2));
    EXPECT_EQ(overrideDisplaySpace.orientation, mOutputState.framebufferSpace.orientation);
    EXPECT_EQ(overrideDisplaySpace, mOutputState.framebufferSpace);
}

TEST_F(FlattenerTest, flattenLayers_FlattenedLayersSetsDamageRegions) {