Latch transform with geometry state.

WindowManager would like this feature for animating
windows between sizes. For example, if we are animating
from a smaller to larger window, we need to complete the resize
at the beginning of the animation to avoid up-scaling. However
to avoid artifacts we need the window to appear at its old size
following this resize, so we use the transform to scale down. However
as the transform is latched immediately, we result in a frame where
the window is too small, until the resize is complete. This is
a change in behavior but it's hard to understand how it could
cause errors. Previously if someone wished to set the transform
and resize a window in the same transaction, then the results
would be undefined (depending on the state of the window buffer),
and there would be no avenue for synchronization.

Bug: 26454664
Change-Id: I4e8475967e0a19aa5879af965a5716eb173f9700
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 04256e1..77d9d0f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -116,6 +116,7 @@
 
     mCurrentState.active.w = w;
     mCurrentState.active.h = h;
+    mCurrentState.active.transform.set(0, 0);
     mCurrentState.active.crop.makeInvalid();
     mCurrentState.z = 0;
 #ifdef USE_HWC2
@@ -126,7 +127,6 @@
     mCurrentState.layerStack = 0;
     mCurrentState.flags = layerFlags;
     mCurrentState.sequence = 0;
-    mCurrentState.transform.set(0, 0);
     mCurrentState.requested = mCurrentState.active;
 
     // drawing state & current state are identical
@@ -399,9 +399,9 @@
         activeCrop = s.active.crop;
     }
 
-    activeCrop = s.transform.transform(activeCrop);
+    activeCrop = s.active.transform.transform(activeCrop);
     activeCrop.intersect(hw->getViewport(), &activeCrop);
-    activeCrop = s.transform.inverse().transform(activeCrop);
+    activeCrop = s.active.transform.inverse().transform(activeCrop);
 
     // This needs to be here as transform.transform(Rect) computes the
     // transformed rect and then takes the bounding box of the result before
@@ -534,13 +534,13 @@
     Region activeTransparentRegion(s.activeTransparentRegion);
     if (!s.active.crop.isEmpty()) {
         Rect activeCrop(s.active.crop);
-        activeCrop = s.transform.transform(activeCrop);
+        activeCrop = s.active.transform.transform(activeCrop);
 #ifdef USE_HWC2
         activeCrop.intersect(displayDevice->getViewport(), &activeCrop);
 #else
         activeCrop.intersect(hw->getViewport(), &activeCrop);
 #endif
-        activeCrop = s.transform.inverse().transform(activeCrop);
+        activeCrop = s.active.transform.inverse().transform(activeCrop);
         // This needs to be here as transform.transform(Rect) computes the
         // transformed rect and then takes the bounding box of the result before
         // returning. This means
@@ -557,7 +557,7 @@
         activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top,
                 s.active.w, activeCrop.bottom));
     }
-    Rect frame(s.transform.transform(computeBounds(activeTransparentRegion)));
+    Rect frame(s.active.transform.transform(computeBounds(activeTransparentRegion)));
 #ifdef USE_HWC2
     frame.intersect(displayDevice->getViewport(), &frame);
     const Transform& tr(displayDevice->getTransform());
@@ -603,7 +603,7 @@
      */
 
     const Transform bufferOrientation(mCurrentTransform);
-    Transform transform(tr * s.transform * bufferOrientation);
+    Transform transform(tr * s.active.transform * bufferOrientation);
 
     if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
         /*
@@ -825,7 +825,7 @@
     }
     // subtract the transparent region and snap to the bounds
     Rect bounds = reduce(win, s.activeTransparentRegion);
-    Rect frame(s.transform.transform(bounds));
+    Rect frame(s.active.transform.transform(bounds));
     frame.intersect(hw->getViewport(), &frame);
     const Transform& tr(hw->getTransform());
     return Rect(tr.transform(frame));
@@ -1120,7 +1120,7 @@
 {
     const Layer::State& s(getDrawingState());
     const Transform tr(useIdentityTransform ?
-            hw->getTransform() : hw->getTransform() * s.transform);
+            hw->getTransform() : hw->getTransform() * s.active.transform);
     const uint32_t hw_h = hw->getHeight();
     Rect win(s.active.w, s.active.h);
     if (!s.active.crop.isEmpty()) {
@@ -1403,8 +1403,8 @@
         this->contentDirty = true;
 
         // we may use linear filtering, if the matrix scales us
-        const uint8_t type = c.transform.getType();
-        mNeedsFiltering = (!c.transform.preserveRects() ||
+        const uint8_t type = c.active.transform.getType();
+        mNeedsFiltering = (!c.active.transform.preserveRects() ||
                 (type >= Transform::SCALE));
     }
 
@@ -1426,10 +1426,10 @@
 }
 
 bool Layer::setPosition(float x, float y) {
-    if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
+    if (mCurrentState.requested.transform.tx() == x && mCurrentState.requested.transform.ty() == y)
         return false;
     mCurrentState.sequence++;
-    mCurrentState.transform.set(x, y);
+    mCurrentState.requested.transform.set(x, y);
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
@@ -1467,7 +1467,7 @@
 }
 bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
     mCurrentState.sequence++;
-    mCurrentState.transform.set(
+    mCurrentState.requested.transform.set(
             matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
@@ -1632,7 +1632,7 @@
         recomputeVisibleRegions = true;
 
         const State& s(getDrawingState());
-        return s.transform.transform(Region(Rect(s.active.w, s.active.h)));
+        return s.active.transform.transform(Region(Rect(s.active.w, s.active.h)));
     }
 
     Region outDirtyRegion;
@@ -1938,7 +1938,7 @@
         Region dirtyRegion(Rect(s.active.w, s.active.h));
 
         // transform the dirty region to window-manager space
-        outDirtyRegion = (s.transform.transform(dirtyRegion));
+        outDirtyRegion = (s.active.transform.transform(dirtyRegion));
     }
     return outDirtyRegion;
 }
@@ -2000,13 +2000,13 @@
             "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
 #endif
             "      client=%p\n",
-            s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
+            s.layerStack, s.z, s.active.transform.tx(), s.active.transform.ty(), s.active.w, s.active.h,
             s.active.crop.left, s.active.crop.top,
             s.active.crop.right, s.active.crop.bottom,
             isOpaque(s), contentDirty,
             s.alpha, s.flags,
-            s.transform[0][0], s.transform[0][1],
-            s.transform[1][0], s.transform[1][1],
+            s.active.transform[0][0], s.active.transform[0][1],
+            s.active.transform[1][0], s.active.transform[1][1],
             client.get());
 
     sp<const GraphicBuffer> buf0(mActiveBuffer);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 26e1adb..b0088e6 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -94,6 +94,8 @@
         uint32_t w;
         uint32_t h;
         Rect crop;
+        Transform transform;
+
         inline bool operator ==(const Geometry& rhs) const {
             return (w == rhs.w && h == rhs.h && crop == rhs.crop);
         }
@@ -116,7 +118,6 @@
         uint8_t mask;
         uint8_t reserved[2];
         int32_t sequence; // changes when visible regions can change
-        Transform transform;
         bool modified;
 
         // If set, defers this state update until the Layer identified by handle
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0a3534f..db03c23 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1563,7 +1563,7 @@
                 //       compute the actual visible region
                 // TODO: we could cache the transformed region
                 const Layer::State& s(layer->getDrawingState());
-                Region visibleReg = s.transform.transform(
+                Region visibleReg = s.active.transform.transform(
                         Region(Rect(s.active.w, s.active.h)));
                 invalidateLayerStack(s.layerStack, visibleReg);
             }
@@ -1666,12 +1666,12 @@
         // handle hidden surfaces by setting the visible region to empty
         if (CC_LIKELY(layer->isVisible())) {
             const bool translucent = !layer->isOpaque(s);
-            Rect bounds(s.transform.transform(layer->computeBounds()));
+            Rect bounds(s.active.transform.transform(layer->computeBounds()));
             visibleRegion.set(bounds);
             if (!visibleRegion.isEmpty()) {
                 // Remove the transparent area from the visible region
                 if (translucent) {
-                    const Transform tr(s.transform);
+                    const Transform tr(s.active.transform);
                     if (tr.transformed()) {
                         if (tr.preserveRects()) {
                             // transform the transparent region
@@ -1687,7 +1687,7 @@
                 }
 
                 // compute the opaque region
-                const int32_t layerOrientation = s.transform.getOrientation();
+                const int32_t layerOrientation = s.active.transform.getOrientation();
                 if (s.alpha == 1.0f && !translucent &&
                         ((layerOrientation & Transform::ROT_INVALID) == false)) {
                     // the opaque region is the layer's footprint
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 737cc82..16332f3 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -1593,7 +1593,7 @@
                 //       compute the actual visible region
                 // TODO: we could cache the transformed region
                 const Layer::State& s(layer->getDrawingState());
-                Region visibleReg = s.transform.transform(
+                Region visibleReg = s.active.transform.transform(
                         Region(Rect(s.active.w, s.active.h)));
                 invalidateLayerStack(s.layerStack, visibleReg);
             }
@@ -1707,12 +1707,12 @@
         // handle hidden surfaces by setting the visible region to empty
         if (CC_LIKELY(layer->isVisible())) {
             const bool translucent = !layer->isOpaque(s);
-            Rect bounds(s.transform.transform(layer->computeBounds()));
+            Rect bounds(s.active.transform.transform(layer->computeBounds()));
             visibleRegion.set(bounds);
             if (!visibleRegion.isEmpty()) {
                 // Remove the transparent area from the visible region
                 if (translucent) {
-                    const Transform tr(s.transform);
+                    const Transform tr(s.active.transform);
                     if (tr.transformed()) {
                         if (tr.preserveRects()) {
                             // transform the transparent region
@@ -1728,7 +1728,7 @@
                 }
 
                 // compute the opaque region
-                const int32_t layerOrientation = s.transform.getOrientation();
+                const int32_t layerOrientation = s.active.transform.getOrientation();
                 if (s.alpha==255 && !translucent &&
                         ((layerOrientation & Transform::ROT_INVALID) == false)) {
                     // the opaque region is the layer's footprint