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

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

Merge "SF: Handle buffer scale transforms when calculating layer geometry"

parents 5e1371af c652ff88
Loading
Loading
Loading
Loading
+38 −18
Original line number Diff line number Diff line
@@ -278,14 +278,12 @@ FloatRect Layer::getBounds(const Region& activeTransparentRegion) const {
    return reduce(mBounds, activeTransparentRegion);
}

ui::Transform Layer::getTransformWithScale() const {
ui::Transform Layer::getBufferScaleTransform() const {
    // If the layer is not using NATIVE_WINDOW_SCALING_MODE_FREEZE (e.g.
    // it isFixedSize) then there may be additional scaling not accounted
    // for in the transform. We need to mirror this scaling to child surfaces
    // or we will break the contract where WM can treat child surfaces as
    // pixels in the parent surface.
    // for in the layer transform.
    if (!isFixedSize() || !mActiveBuffer) {
        return mEffectiveTransform;
        return {};
    }

    // If the layer is a buffer state layer, the active width and height
@@ -293,24 +291,40 @@ ui::Transform Layer::getTransformWithScale() const {
    const uint32_t activeWidth = getActiveWidth(getDrawingState());
    const uint32_t activeHeight = getActiveHeight(getDrawingState());
    if (activeWidth >= UINT32_MAX && activeHeight >= UINT32_MAX) {
        return mEffectiveTransform;
        return {};
    }

    int bufferWidth;
    int bufferHeight;
    if ((mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) == 0) {
        bufferWidth = mActiveBuffer->getWidth();
        bufferHeight = mActiveBuffer->getHeight();
    } else {
        bufferHeight = mActiveBuffer->getWidth();
        bufferWidth = mActiveBuffer->getHeight();
    int bufferWidth = mActiveBuffer->getWidth();
    int bufferHeight = mActiveBuffer->getHeight();

    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
        std::swap(bufferWidth, bufferHeight);
    }

    float sx = activeWidth / static_cast<float>(bufferWidth);
    float sy = activeHeight / static_cast<float>(bufferHeight);

    ui::Transform extraParentScaling;
    extraParentScaling.set(sx, 0, 0, sy);
    return mEffectiveTransform * extraParentScaling;
    return extraParentScaling;
}

ui::Transform Layer::getTransformWithScale(const ui::Transform& bufferScaleTransform) const {
    // We need to mirror this scaling to child surfaces or we will break the contract where WM can
    // treat child surfaces as pixels in the parent surface.
    if (!isFixedSize() || !mActiveBuffer) {
        return mEffectiveTransform;
    }
    return mEffectiveTransform * bufferScaleTransform;
}

FloatRect Layer::getBoundsPreScaling(const ui::Transform& bufferScaleTransform) const {
    // We need the pre scaled layer bounds when computing child bounds to make sure the child is
    // cropped to its parent layer after any buffer transform scaling is applied.
    if (!isFixedSize() || !mActiveBuffer) {
        return mBounds;
    }
    return bufferScaleTransform.inverse().transform(mBounds);
}

void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform) {
@@ -322,7 +336,7 @@ void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform)
    // Transform parent bounds to layer space
    parentBounds = getActiveTransform(s).inverse().transform(parentBounds);

    // Calculate display frame
    // Calculate source bounds
    mSourceBounds = computeSourceBounds(parentBounds);

    // Calculate bounds by croping diplay frame with layer crop and parent bounds
@@ -335,8 +349,12 @@ void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform)

    mBounds = bounds;
    mScreenBounds = mEffectiveTransform.transform(mBounds);

    // Add any buffer scaling to the layer's children.
    ui::Transform bufferScaleTransform = getBufferScaleTransform();
    for (const sp<Layer>& child : mDrawingChildren) {
        child->computeBounds(mBounds, getTransformWithScale());
        child->computeBounds(getBoundsPreScaling(bufferScaleTransform),
                             getTransformWithScale(bufferScaleTransform));
    }
}

@@ -1436,7 +1454,9 @@ bool Layer::reparentChildren(const sp<IBinder>& newParentHandle) {
void Layer::setChildrenDrawingParent(const sp<Layer>& newParent) {
    for (const sp<Layer>& child : mDrawingChildren) {
        child->mDrawingParent = newParent;
        child->computeBounds(newParent->mBounds, newParent->getTransformWithScale());
        child->computeBounds(newParent->mBounds,
                             newParent->getTransformWithScale(
                                     newParent->getBufferScaleTransform()));
    }
}

+7 −1
Original line number Diff line number Diff line
@@ -361,9 +361,15 @@ public:
    // Compute bounds for the layer and cache the results.
    void computeBounds(FloatRect parentBounds, ui::Transform parentTransform);

    // Returns the buffer scale transform if a scaling mode is set.
    ui::Transform getBufferScaleTransform() const;

    // Get effective layer transform, taking into account all its parent transform with any
    // scaling if the parent scaling more is not NATIVE_WINDOW_SCALING_MODE_FREEZE.
    ui::Transform getTransformWithScale() const;
    ui::Transform getTransformWithScale(const ui::Transform& bufferScaleTransform) const;

    // Returns the bounds of the layer without any buffer scaling.
    FloatRect getBoundsPreScaling(const ui::Transform& bufferScaleTransform) const;

    int32_t getSequence() const { return sequence; }

+145 −8
Original line number Diff line number Diff line
@@ -4307,7 +4307,7 @@ class ChildLayerTest : public LayerUpdateTest {
protected:
    void SetUp() override {
        LayerUpdateTest::SetUp();
        mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, 0,
        mChild = createSurface(mClient, "Child surface", 10, 15, PIXEL_FORMAT_RGBA_8888, 0,
                               mFGSurfaceControl.get());
        fillSurfaceRGBA8(mChild, 200, 200, 200);

@@ -4413,6 +4413,32 @@ TEST_F(ChildLayerTest, ChildLayerScaling) {
    }
}

// A child with a scale transform should be cropped by its parent bounds.
TEST_F(ChildLayerTest, ChildLayerScalingCroppedByParent) {
    asTransaction([&](Transaction& t) {
        t.setPosition(mFGSurfaceControl, 0, 0);
        t.setPosition(mChild, 0, 0);
    });

    // Find the boundary between the parent and child.
    {
        mCapture = screenshot();
        mCapture->expectChildColor(0, 0);
        mCapture->expectChildColor(9, 9);
        mCapture->expectFGColor(10, 10);
    }

    asTransaction([&](Transaction& t) { t.setMatrix(mChild, 10.0, 0, 0, 10.0); });

    // The child should fill its parent bounds and be cropped by it.
    {
        mCapture = screenshot();
        mCapture->expectChildColor(0, 0);
        mCapture->expectChildColor(63, 63);
        mCapture->expectBGColor(64, 64);
    }
}

TEST_F(ChildLayerTest, ChildLayerAlpha) {
    fillSurfaceRGBA8(mBGSurfaceControl, 0, 0, 254);
    fillSurfaceRGBA8(mFGSurfaceControl, 254, 0, 0);
@@ -4649,8 +4675,8 @@ TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
        mCapture = screenshot();
        // We've positioned the child in the top left.
        mCapture->expectChildColor(0, 0);
        // But it's only 10x10.
        mCapture->expectFGColor(10, 10);
        // But it's only 10x15.
        mCapture->expectFGColor(10, 15);
    }

    asTransaction([&](Transaction& t) {
@@ -4664,9 +4690,9 @@ TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
        // We've positioned the child in the top left.
        mCapture->expectChildColor(0, 0);
        mCapture->expectChildColor(10, 10);
        mCapture->expectChildColor(19, 19);
        // And now it should be scaled all the way to 20x20
        mCapture->expectFGColor(20, 20);
        mCapture->expectChildColor(19, 29);
        // And now it should be scaled all the way to 20x30
        mCapture->expectFGColor(20, 30);
    }
}

@@ -4682,8 +4708,9 @@ TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) {
        mCapture = screenshot();
        // We've positioned the child in the top left.
        mCapture->expectChildColor(0, 0);
        // But it's only 10x10.
        mCapture->expectFGColor(10, 10);
        mCapture->expectChildColor(9, 14);
        // But it's only 10x15.
        mCapture->expectFGColor(10, 15);
    }
    // We set things up as in b/37673612 so that there is a mismatch between the buffer size and
    // the WM specified state size.
@@ -4704,6 +4731,115 @@ TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) {
    }
}

// A child with a buffer transform from its parents should be cropped by its parent bounds.
TEST_F(ChildLayerTest, ChildCroppedByParentWithBufferTransform) {
    asTransaction([&](Transaction& t) {
        t.show(mChild);
        t.setPosition(mChild, 0, 0);
        t.setPosition(mFGSurfaceControl, 0, 0);
        t.setSize(mChild, 100, 100);
    });
    fillSurfaceRGBA8(mChild, 200, 200, 200);

    {
        mCapture = screenshot();

        mCapture->expectChildColor(0, 0);
        mCapture->expectChildColor(63, 63);
        mCapture->expectBGColor(64, 64);
    }

    asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 64); });
    sp<Surface> s = mFGSurfaceControl->getSurface();
    auto anw = static_cast<ANativeWindow*>(s.get());
    // Apply a 90 transform on the buffer.
    native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
    native_window_set_buffers_dimensions(anw, 64, 128);
    fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
    waitForPostedBuffers();

    // The child should be cropped by the new parent bounds.
    {
        mCapture = screenshot();
        mCapture->expectChildColor(0, 0);
        mCapture->expectChildColor(99, 63);
        mCapture->expectFGColor(100, 63);
        mCapture->expectBGColor(128, 64);
    }
}

// A child with a scale transform from its parents should be cropped by its parent bounds.
TEST_F(ChildLayerTest, ChildCroppedByParentWithBufferScale) {
    asTransaction([&](Transaction& t) {
        t.show(mChild);
        t.setPosition(mChild, 0, 0);
        t.setPosition(mFGSurfaceControl, 0, 0);
        t.setSize(mChild, 200, 200);
    });
    fillSurfaceRGBA8(mChild, 200, 200, 200);

    {
        mCapture = screenshot();

        mCapture->expectChildColor(0, 0);
        mCapture->expectChildColor(63, 63);
        mCapture->expectBGColor(64, 64);
    }

    asTransaction([&](Transaction& t) {
        t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
        // Set a scaling by 2.
        t.setSize(mFGSurfaceControl, 128, 128);
    });

    // Child should inherit its parents scale but should be cropped by its parent bounds.
    {
        mCapture = screenshot();
        mCapture->expectChildColor(0, 0);
        mCapture->expectChildColor(127, 127);
        mCapture->expectBGColor(128, 128);
    }
}

// Regression test for b/127368943
// Child should ignore the buffer transform but apply parent scale transform.
TEST_F(ChildLayerTest, ChildrenWithParentBufferTransformAndScale) {
    asTransaction([&](Transaction& t) {
        t.show(mChild);
        t.setPosition(mChild, 0, 0);
        t.setPosition(mFGSurfaceControl, 0, 0);
    });

    {
        mCapture = screenshot();
        mCapture->expectChildColor(0, 0);
        mCapture->expectChildColor(9, 14);
        mCapture->expectFGColor(10, 15);
    }

    // Change the size of the foreground to 128 * 64 so we can test rotation as well.
    asTransaction([&](Transaction& t) {
        t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
        t.setSize(mFGSurfaceControl, 128, 64);
    });
    sp<Surface> s = mFGSurfaceControl->getSurface();
    auto anw = static_cast<ANativeWindow*>(s.get());
    // Apply a 90 transform on the buffer and submit a buffer half the expected size so that we
    // have an effective scale of 2.0 applied to the buffer along with a rotation transform.
    native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
    native_window_set_buffers_dimensions(anw, 32, 64);
    fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
    waitForPostedBuffers();

    // The child should ignore the buffer transform but apply the 2.0 scale from parent.
    {
        mCapture = screenshot();
        mCapture->expectChildColor(0, 0);
        mCapture->expectChildColor(19, 29);
        mCapture->expectFGColor(20, 30);
    }
}

TEST_F(ChildLayerTest, Bug36858924) {
    // Destroy the child layer
    mChild.clear();
@@ -4857,6 +4993,7 @@ TEST_F(ChildLayerTest, ChildLayerRelativeLayer) {
        mCapture->checkPixel(10, 10, 255, 255, 255);
    }
}

class BoundlessLayerTest : public LayerUpdateTest {
protected:
    std::unique_ptr<ScreenCapture> mCapture;