Move crop outside of geometry state.

Prior to this CL, if Layer crop is changed while a
surface resize is pending, the crop will not be
applied until a buffer latches at the new size. This
CL makes the crop apply immediately. We can see this
is the desired behavior by looking at the two cases
where a resize is pending.

1. A resize is pending to make the surface smaller.
  In this case we need to be able to immediately update the crop so that
  we can shrink the visible region of the surface at an interactive rate
  with input. The window manager currently uses big surfaces and scaling
  modes to accomplish this.
2. A resize is pending to make the surface larger.
  In this case it doesn't matter. If we expand the crop immediately to
  the new surface size, then we have simply uncropped an area which is
  by definition transparent pixels (as we haven't latched a buffer
  at the new size yet).

This change has conceptual soundness as well. We can see that the
scaling mode will not affect properties that affect scaling (transform,
width/height) but not properties which do not (crop).

Bug: 27729195
Bug: 27687126
Change-Id: Ieafdc14aeecb23085793e3056a746d6f344781df
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 80012a6..afaba1f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -120,8 +120,8 @@
     mCurrentState.active.w = w;
     mCurrentState.active.h = h;
     mCurrentState.active.transform.set(0, 0);
-    mCurrentState.active.crop.makeInvalid();
-    mCurrentState.active.finalCrop.makeInvalid();
+    mCurrentState.crop.makeInvalid();
+    mCurrentState.finalCrop.makeInvalid();
     mCurrentState.z = 0;
 #ifdef USE_HWC2
     mCurrentState.alpha = 1.0f;
@@ -376,8 +376,9 @@
 Rect Layer::computeBounds(const Region& activeTransparentRegion) const {
     const Layer::State& s(getDrawingState());
     Rect win(s.active.w, s.active.h);
-    if (!s.active.crop.isEmpty()) {
-        win.intersect(s.active.crop, &win);
+
+    if (!s.crop.isEmpty()) {
+        win.intersect(s.crop, &win);
     }
     // subtract the transparent region and snap to the bounds
     return reduce(win, activeTransparentRegion);
@@ -388,7 +389,7 @@
     // layer's size.
     FloatRect crop(getContentCrop());
 
-    // the active.crop is the area of the window that gets cropped, but not
+    // the crop is the area of the window that gets cropped, but not
     // scaled in any ways.
     const State& s(getDrawingState());
 
@@ -400,16 +401,16 @@
     // a viewport clipping and a window transform. we should use floating point to fix this.
 
     Rect activeCrop(s.active.w, s.active.h);
-    if (!s.active.crop.isEmpty()) {
-        activeCrop = s.active.crop;
+    if (!s.crop.isEmpty()) {
+        activeCrop = s.crop;
     }
 
     activeCrop = s.active.transform.transform(activeCrop);
     if (!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
         activeCrop.clear();
     }
-    if (!s.active.finalCrop.isEmpty()) {
-        if(!activeCrop.intersect(s.active.finalCrop, &activeCrop)) {
+    if (!s.finalCrop.isEmpty()) {
+        if(!activeCrop.intersect(s.finalCrop, &activeCrop)) {
             activeCrop.clear();
         }
     }
@@ -545,8 +546,8 @@
     // apply the layer's transform, followed by the display's global transform
     // here we're guaranteed that the layer's transform preserves rects
     Region activeTransparentRegion(s.activeTransparentRegion);
-    if (!s.active.crop.isEmpty()) {
-        Rect activeCrop(s.active.crop);
+    if (!s.crop.isEmpty()) {
+        Rect activeCrop(s.crop);
         activeCrop = s.active.transform.transform(activeCrop);
 #ifdef USE_HWC2
         if(!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) {
@@ -575,8 +576,8 @@
                 s.active.w, activeCrop.bottom));
     }
     Rect frame(s.active.transform.transform(computeBounds(activeTransparentRegion)));
-    if (!s.active.finalCrop.isEmpty()) {
-        if(!frame.intersect(s.active.finalCrop, &frame)) {
+    if (!s.finalCrop.isEmpty()) {
+        if(!frame.intersect(s.finalCrop, &frame)) {
             frame.clear();
         }
     }
@@ -801,15 +802,15 @@
     // Apply the layer's transform, followed by the display's global transform
     // Here we're guaranteed that the layer's transform preserves rects
     Rect win(s.active.w, s.active.h);
-    if (!s.active.crop.isEmpty()) {
-        win.intersect(s.active.crop, &win);
+    if (!s.crop.isEmpty()) {
+        win.intersect(s.crop, &win);
     }
     // Subtract the transparent region and snap to the bounds
     Rect bounds = reduce(win, s.activeTransparentRegion);
     Rect frame(s.active.transform.transform(bounds));
     frame.intersect(displayDevice->getViewport(), &frame);
-    if (!s.active.finalCrop.isEmpty()) {
-        frame.intersect(s.active.finalCrop, &frame);
+    if (!s.finalCrop.isEmpty()) {
+        frame.intersect(s.finalCrop, &frame);
     }
     auto& displayTransform(displayDevice->getTransform());
     auto position = displayTransform.transform(frame);
@@ -850,15 +851,15 @@
     // apply the layer's transform, followed by the display's global transform
     // here we're guaranteed that the layer's transform preserves rects
     Rect win(s.active.w, s.active.h);
-    if (!s.active.crop.isEmpty()) {
-        win.intersect(s.active.crop, &win);
+    if (!s.crop.isEmpty()) {
+        win.intersect(s.crop, &win);
     }
     // subtract the transparent region and snap to the bounds
     Rect bounds = reduce(win, s.activeTransparentRegion);
     Rect frame(s.active.transform.transform(bounds));
     frame.intersect(hw->getViewport(), &frame);
-    if (!s.active.finalCrop.isEmpty()) {
-        frame.intersect(s.active.finalCrop, &frame);
+    if (!s.finalCrop.isEmpty()) {
+        frame.intersect(s.finalCrop, &frame);
     }
     const Transform& tr(hw->getTransform());
     return Rect(tr.transform(frame));
@@ -1016,9 +1017,9 @@
      */
     Rect win(computeBounds());
 
-    if (!s.active.finalCrop.isEmpty()) {
+    if (!s.finalCrop.isEmpty()) {
         win = s.active.transform.transform(win);
-        if (!win.intersect(s.active.finalCrop, &win)) {
+        if (!win.intersect(s.finalCrop, &win)) {
             win.clear();
         }
         win = s.active.transform.inverse().transform(win);
@@ -1181,8 +1182,8 @@
     const Transform tr(hw->getTransform());
     const uint32_t hw_h = hw->getHeight();
     Rect win(s.active.w, s.active.h);
-    if (!s.active.crop.isEmpty()) {
-        win.intersect(s.active.crop, &win);
+    if (!s.crop.isEmpty()) {
+        win.intersect(s.crop, &win);
     }
     // subtract the transparent region and snap to the bounds
     win = reduce(win, s.activeTransparentRegion);
@@ -1199,11 +1200,11 @@
         rt = s.active.transform.transform(rt);
     }
 
-    if (!s.active.finalCrop.isEmpty()) {
-        boundPoint(&lt, s.active.finalCrop);
-        boundPoint(&lb, s.active.finalCrop);
-        boundPoint(&rb, s.active.finalCrop);
-        boundPoint(&rt, s.active.finalCrop);
+    if (!s.finalCrop.isEmpty()) {
+        boundPoint(&lt, s.finalCrop);
+        boundPoint(&lb, s.finalCrop);
+        boundPoint(&rb, s.finalCrop);
+        boundPoint(&rt, s.finalCrop);
     }
 
     Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
@@ -1399,38 +1400,26 @@
         ALOGD_IF(DEBUG_RESIZE,
                 "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
                 "  current={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
-                "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
+                "            requested={ wh={%4u,%4u} }}\n"
                 "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
-                "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
+                "            requested={ wh={%4u,%4u} }}\n",
                 this, getName().string(), mCurrentTransform, mCurrentScalingMode,
                 c.active.w, c.active.h,
-                c.active.crop.left,
-                c.active.crop.top,
-                c.active.crop.right,
-                c.active.crop.bottom,
-                c.active.crop.getWidth(),
-                c.active.crop.getHeight(),
+                c.crop.left,
+                c.crop.top,
+                c.crop.right,
+                c.crop.bottom,
+                c.crop.getWidth(),
+                c.crop.getHeight(),
                 c.requested.w, c.requested.h,
-                c.requested.crop.left,
-                c.requested.crop.top,
-                c.requested.crop.right,
-                c.requested.crop.bottom,
-                c.requested.crop.getWidth(),
-                c.requested.crop.getHeight(),
                 s.active.w, s.active.h,
-                s.active.crop.left,
-                s.active.crop.top,
-                s.active.crop.right,
-                s.active.crop.bottom,
-                s.active.crop.getWidth(),
-                s.active.crop.getHeight(),
-                s.requested.w, s.requested.h,
-                s.requested.crop.left,
-                s.requested.crop.top,
-                s.requested.crop.right,
-                s.requested.crop.bottom,
-                s.requested.crop.getWidth(),
-                s.requested.crop.getHeight());
+                s.crop.left,
+                s.crop.top,
+                s.crop.right,
+                s.crop.bottom,
+                s.crop.getWidth(),
+                s.crop.getHeight(),
+                s.requested.w, s.requested.h);
 
         // record the new size, form this point on, when the client request
         // a buffer, it'll get the new size.
@@ -1568,19 +1557,19 @@
     return true;
 }
 bool Layer::setCrop(const Rect& crop) {
-    if (mCurrentState.requested.crop == crop)
+    if (mCurrentState.crop == crop)
         return false;
     mCurrentState.sequence++;
-    mCurrentState.requested.crop = crop;
+    mCurrentState.crop = crop;
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 bool Layer::setFinalCrop(const Rect& crop) {
-    if (mCurrentState.requested.finalCrop == crop)
+    if (mCurrentState.finalCrop == crop)
         return false;
     mCurrentState.sequence++;
-    mCurrentState.requested.finalCrop = crop;
+    mCurrentState.finalCrop = crop;
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
@@ -1743,11 +1732,15 @@
             Layer::State& current;
             bool& recomputeVisibleRegions;
             bool stickyTransformSet;
+            const char* name;
+
             Reject(Layer::State& front, Layer::State& current,
-                    bool& recomputeVisibleRegions, bool stickySet)
+                    bool& recomputeVisibleRegions, bool stickySet,
+                    const char* name)
                 : front(front), current(current),
                   recomputeVisibleRegions(recomputeVisibleRegions),
-                  stickyTransformSet(stickySet) {
+                  stickyTransformSet(stickySet),
+                  name(name) {
             }
 
             virtual bool reject(const sp<GraphicBuffer>& buf,
@@ -1790,32 +1783,28 @@
                     }
 
                     ALOGD_IF(DEBUG_RESIZE,
-                            "latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
+                            "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
                             "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
-                            "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
+                            "            requested={ wh={%4u,%4u} }}\n",
+                            name,
                             bufWidth, bufHeight, item.mTransform, item.mScalingMode,
                             front.active.w, front.active.h,
-                            front.active.crop.left,
-                            front.active.crop.top,
-                            front.active.crop.right,
-                            front.active.crop.bottom,
-                            front.active.crop.getWidth(),
-                            front.active.crop.getHeight(),
-                            front.requested.w, front.requested.h,
-                            front.requested.crop.left,
-                            front.requested.crop.top,
-                            front.requested.crop.right,
-                            front.requested.crop.bottom,
-                            front.requested.crop.getWidth(),
-                            front.requested.crop.getHeight());
+                            front.crop.left,
+                            front.crop.top,
+                            front.crop.right,
+                            front.crop.bottom,
+                            front.crop.getWidth(),
+                            front.crop.getHeight(),
+                            front.requested.w, front.requested.h);
                 }
 
                 if (!isFixedSize && !stickyTransformSet) {
                     if (front.active.w != bufWidth ||
                         front.active.h != bufHeight) {
                         // reject this buffer
-                        ALOGE("rejecting buffer: bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
-                                bufWidth, bufHeight, front.active.w, front.active.h);
+                        ALOGE("[%s] rejecting buffer: "
+                                "bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
+                                name, bufWidth, bufHeight, front.active.w, front.active.h);
                         return true;
                     }
                 }
@@ -1845,7 +1834,7 @@
         };
 
         Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
-                getProducerStickyTransform() != 0);
+                getProducerStickyTransform() != 0, mName.string());
 
 
         // Check all of our local sync points to ensure that all transactions
@@ -2088,10 +2077,10 @@
 #endif
             "      client=%p\n",
             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,
-            s.active.finalCrop.left, s.active.finalCrop.top,
-            s.active.finalCrop.right, s.active.finalCrop.bottom,
+            s.crop.left, s.crop.top,
+            s.crop.right, s.crop.bottom,
+            s.finalCrop.left, s.finalCrop.top,
+            s.finalCrop.right, s.finalCrop.bottom,
             isOpaque(s), contentDirty,
             s.alpha, s.flags,
             s.active.transform[0][0], s.active.transform[0][1],
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 34857c2..1d73b43 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -93,12 +93,10 @@
     struct Geometry {
         uint32_t w;
         uint32_t h;
-        Rect crop;
-        Rect finalCrop;
         Transform transform;
 
         inline bool operator ==(const Geometry& rhs) const {
-            return (w == rhs.w && h == rhs.h && crop == rhs.crop);
+          return (w == rhs.w && h == rhs.h);
         }
         inline bool operator !=(const Geometry& rhs) const {
             return !operator ==(rhs);
@@ -121,6 +119,9 @@
         int32_t sequence; // changes when visible regions can change
         bool modified;
 
+        Rect crop;
+        Rect finalCrop;
+
         // If set, defers this state update until the Layer identified by handle
         // receives a frame with the given frameNumber
         sp<IBinder> handle;