Loading services/surfaceflinger/Layer.cpp +38 −18 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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) { Loading @@ -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 Loading @@ -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)); } } Loading Loading @@ -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())); } } Loading services/surfaceflinger/Layer.h +7 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading services/surfaceflinger/tests/Transaction_test.cpp +145 −8 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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) { Loading @@ -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); } } Loading @@ -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. Loading @@ -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(); Loading Loading @@ -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; Loading Loading
services/surfaceflinger/Layer.cpp +38 −18 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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) { Loading @@ -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 Loading @@ -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)); } } Loading Loading @@ -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())); } } Loading
services/surfaceflinger/Layer.h +7 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading
services/surfaceflinger/tests/Transaction_test.cpp +145 −8 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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) { Loading @@ -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); } } Loading @@ -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. Loading @@ -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(); Loading Loading @@ -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; Loading