SurfaceFlinger: setGeometryAppliesWithResize crop latching fixes.
The same sort of thing we had with setPosition...not sure why I didn't
realize we would need the fixes here too! In particular we need to ensure
the following scenarios work:
1. Additional calls to set(Final)Crop while in the setGeometryAppliesWithResize
state are eventually applied.
2. Additional calls to set(Final)Crop while in the setGeometryAppliesWithResize
state are not immediately applied.
3. In LayerRejector.cpp we have to be sure we are not just latching a buffer
at the old size, which we still allow. This is the correct time to latch
the transparentRegion as it is content dependent, but doesn't represent
a size changing.
The difference between this and the original CL which was reverted has to do with
point 3. The original CL tried to solve point 3 by moving the latching logic from
the LayerRejecter in to Layer::doTransaction. However, in general doTransaction
will not be called in between Latching the buffer and drawing the frame, so this
introduced errors. The new test "FinalCropLatchingBufferOldSize" encapsulates this.
Bug: 37621737
Bug: 37531386
Test: Included in Transaction_test.cpp
Change-Id: I14bd09d01ac6b85895caa1b707d6fa7dac962074
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 1b17e55..68519a1 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -33,7 +33,7 @@
// Fill an RGBA_8888 formatted surface with a single color.
static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc,
- uint8_t r, uint8_t g, uint8_t b) {
+ uint8_t r, uint8_t g, uint8_t b, bool unlock=true) {
ANativeWindow_Buffer outBuffer;
sp<Surface> s = sc->getSurface();
ASSERT_TRUE(s != NULL);
@@ -48,7 +48,9 @@
pixel[3] = 255;
}
}
- ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+ if (unlock) {
+ ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+ }
}
// A ScreenCapture is a screenshot from SurfaceFlinger that can be used to check
@@ -479,6 +481,17 @@
sc->expectFGColor(127, 127);
sc->expectBGColor(128, 128);
}
+
+ void lockAndFillFGBuffer() {
+ fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false);
+ }
+
+ void unlockFGBuffer() {
+ sp<Surface> s = mFGSurfaceControl->getSurface();
+ ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+ waitForPostedBuffers();
+ }
+
void completeFGResize() {
fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
waitForPostedBuffers();
@@ -605,6 +618,65 @@
EXPECT_CROPPED_STATE("after the resize finishes");
}
+// In this test we ensure that setGeometryAppliesWithResize actually demands
+// a buffer of the new size, and not just any size.
+TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) {
+ EXPECT_INITIAL_STATE("before anything");
+ // Normally the crop applies immediately even while a resize is pending.
+ SurfaceComposerClient::openGlobalTransaction();
+ mFGSurfaceControl->setSize(128, 128);
+ mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)");
+
+ restoreInitialState();
+
+ // In order to prepare to submit a buffer at the wrong size, we acquire it prior to
+ // initiating the resize.
+ lockAndFillFGBuffer();
+
+ SurfaceComposerClient::openGlobalTransaction();
+ mFGSurfaceControl->setSize(128, 128);
+ mFGSurfaceControl->setGeometryAppliesWithResize();
+ mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
+
+ // We now submit our old buffer, at the old size, and ensure it doesn't
+ // trigger geometry latching.
+ unlockFGBuffer();
+
+ EXPECT_INITIAL_STATE("after unlocking FG buffer (with geometryAppliesWithResize)");
+
+ completeFGResize();
+
+ EXPECT_CROPPED_STATE("after the resize finishes");
+}
+
+TEST_F(CropLatchingTest, FinalCropLatchingRegressionForb37531386) {
+ EXPECT_INITIAL_STATE("before anything");
+ // In this scenario, we attempt to set the final crop a second time while the resize
+ // is still pending, and ensure we are successful. Success meaning the second crop
+ // is the one which eventually latches and not the first.
+ SurfaceComposerClient::openGlobalTransaction();
+ mFGSurfaceControl->setSize(128, 128);
+ mFGSurfaceControl->setGeometryAppliesWithResize();
+ mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ SurfaceComposerClient::openGlobalTransaction();
+ mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ EXPECT_INITIAL_STATE("after setting crops with geometryAppliesWithResize");
+
+ completeFGResize();
+
+ EXPECT_INITIAL_STATE("after the resize finishes");
+}
+
TEST_F(LayerUpdateTest, DeferredTransactionTest) {
sp<ScreenCapture> sc;
{