refactor the crop region for hwc is calculated/set

- the crop region is now always calculated and set
  in LayerBase::setGeometry which uses new virtuals to
  access the "content" crop and transform (which are
  provided by the Layer subclass)

Change-Id: Ib7769bdec0917dd248f926600c14ddf9ea84897a
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 439acb5..c9f1eb5 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -19,7 +19,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
-#include <math.h>
 
 #include <cutils/compiler.h>
 #include <cutils/native_handle.h>
@@ -200,48 +199,27 @@
     return NO_ERROR;
 }
 
-Rect Layer::computeBufferCrop() const {
-    // Start with the SurfaceFlingerConsumer's buffer crop...
+Rect Layer::getContentCrop() const {
+    // this is the crop rectangle that applies to the buffer
+    // itself (as opposed to the window)
     Rect crop;
     if (!mCurrentCrop.isEmpty()) {
+        // if the buffer crop is defined, we use that
         crop = mCurrentCrop;
-    } else  if (mActiveBuffer != NULL){
-        crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
+    } else if (mActiveBuffer != NULL) {
+        // otherwise we use the whole buffer
+        crop = mActiveBuffer->getBounds();
     } else {
+        // if we don't have a buffer yet, we use an empty/invalid crop
         crop.makeInvalid();
-        return crop;
     }
-
-    // ... then reduce that in the same proportions as the window crop reduces
-    // the window size.
-    const State& s(drawingState());
-    if (!s.active.crop.isEmpty()) {
-        // Transform the window crop to match the buffer coordinate system,
-        // which means using the inverse of the current transform set on the
-        // SurfaceFlingerConsumer.
-        uint32_t invTransform = mCurrentTransform;
-        int winWidth = s.active.w;
-        int winHeight = s.active.h;
-        if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
-            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
-                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
-            winWidth = s.active.h;
-            winHeight = s.active.w;
-        }
-        Rect winCrop = s.active.crop.transform(invTransform,
-                s.active.w, s.active.h);
-
-        float xScale = float(crop.width()) / float(winWidth);
-        float yScale = float(crop.height()) / float(winHeight);
-        crop.left += int(ceilf(float(winCrop.left) * xScale));
-        crop.top += int(ceilf(float(winCrop.top) * yScale));
-        crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
-        crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
-    }
-
     return crop;
 }
 
+uint32_t Layer::getContentTransform() const {
+    return mCurrentTransform;
+}
+
 void Layer::setGeometry(
     const sp<const DisplayDevice>& hw,
         HWComposer::HWCLayerInterface& layer)
@@ -278,7 +256,6 @@
     } else {
         layer.setTransform(finalTransform);
     }
-    layer.setCrop(computeBufferCrop());
 }
 
 void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index a82767b..242493d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -103,6 +103,9 @@
     // the current orientation of the display device.
     virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const;
 
+    virtual Rect getContentCrop() const;
+    virtual uint32_t getContentTransform() const;
+
 protected:
     virtual void onFirstRef();
     virtual void dump(String8& result, char* scratch, size_t size) const;
@@ -115,7 +118,6 @@
 
     uint32_t getEffectiveUsage(uint32_t usage) const;
     bool isCropped() const;
-    Rect computeBufferCrop() const;
     static bool getOpacityForFormat(uint32_t format);
 
     // Interface implementation for SurfaceFlingerConsumer::FrameAvailableListener
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index ba56c23..572e7c8 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -17,6 +17,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
+#include <math.h>
 
 #include <utils/Errors.h>
 #include <utils/Log.h>
@@ -267,6 +268,61 @@
     return result;
 }
 
+
+Rect LayerBase::getContentCrop() const {
+    // regular layers just use their active area as the content crop
+    const State& s(drawingState());
+    return Rect(s.active.w, s.active.h);
+}
+
+uint32_t LayerBase::getContentTransform() const {
+    // regular layers don't have a content transform
+    return 0;
+}
+
+Rect LayerBase::computeCrop(const sp<const DisplayDevice>& hw) const {
+    // the content crop is the area of the content that gets scaled to the
+    // layer's size.
+    Rect crop(getContentCrop());
+
+    // the active.crop is the area of the window that gets cropped, but not
+    // scaled in any ways.
+    const State& s(drawingState());
+    Rect activeCrop(s.active.crop);
+    if (!activeCrop.isEmpty()) {
+        // Transform the window crop to match the buffer coordinate system,
+        // which means using the inverse of the current transform set on the
+        // SurfaceFlingerConsumer.
+        uint32_t invTransform = getContentTransform();
+        int winWidth = s.active.w;
+        int winHeight = s.active.h;
+        if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
+            winWidth = s.active.h;
+            winHeight = s.active.w;
+        }
+        const Rect winCrop = activeCrop.transform(
+                invTransform, s.active.w, s.active.h);
+
+        // the code below essentially performs a scaled intersection
+        // of crop and winCrop
+        float xScale = float(crop.width()) / float(winWidth);
+        float yScale = float(crop.height()) / float(winHeight);
+
+        int insetL = int(ceilf( winCrop.left                * xScale));
+        int insetT = int(ceilf( winCrop.top                 * yScale));
+        int insetR = int(ceilf((winWidth  - winCrop.right ) * xScale));
+        int insetB = int(ceilf((winHeight - winCrop.bottom) * yScale));
+
+        crop.left   += insetL;
+        crop.top    += insetT;
+        crop.right  -= insetR;
+        crop.bottom -= insetB;
+    }
+    return crop;
+}
+
 void LayerBase::setGeometry(
     const sp<const DisplayDevice>& hw,
         HWComposer::HWCLayerInterface& layer)
@@ -290,15 +346,13 @@
     }
 
 
-    Rect bounds(computeBounds());
-
     // apply the layer's transform, followed by the display's global transform
     // here we're guaranteed that the layer's transform preserves rects
 
-    const Transform& tr = hw->getTransform();
-    Rect frame(tr.transform(s.transform.transform(bounds)));
-    layer.setFrame(frame);
-    layer.setCrop(bounds);
+    Rect frame(s.transform.transform(computeBounds()));
+    const Transform& tr(hw->getTransform());
+    layer.setFrame(tr.transform(frame));
+    layer.setCrop(computeCrop(hw));
 }
 
 void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index c2624df..ecae2d9 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -260,6 +260,18 @@
      */
     virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const { }
 
+    /**
+     * returns the rectangle that crops the content of the layer and scales it
+     * to the layer's size.
+     */
+    virtual Rect getContentCrop() const;
+
+    /*
+     * returns the transform bits (90 rotation / h-flip / v-flip) of the
+     * layer's content
+     */
+    virtual uint32_t getContentTransform() const;
+
     /** always call base class first */
     virtual void dump(String8& result, char* scratch, size_t size) const;
     virtual void shortDump(String8& result, char* scratch, size_t size) const;
@@ -282,6 +294,9 @@
     void setFiltering(bool filtering);
     bool getFiltering() const;
 
+private:
+    Rect computeCrop(const sp<const DisplayDevice>& hw) const;
+
 protected:
           void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
                   GLclampf r, GLclampf g, GLclampf b, GLclampf alpha) const;