diff options
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 56 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.h | 8 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/Transaction_test.cpp | 153 |
3 files changed, 190 insertions, 27 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 16e69b9b26..512a0b4f10 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -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())); } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index aba3ff2ff3..89063da251 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -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; } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index bc5642ecd3..d62afa5ec2 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -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; |