Merge "libgui: Fix handling of rotated surface damage" into mnc-dev
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index df0661c..4b76f98 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -344,20 +344,61 @@
     if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
         input.setSurfaceDamage(Region::INVALID_REGION);
     } else {
-        // The surface damage was specified using the OpenGL ES convention of
-        // the origin being in the bottom-left corner. Here we flip to the
-        // convention that the rest of the system uses (top-left corner) by
-        // subtracting all top/bottom coordinates from the buffer height.
+        // Here we do two things:
+        // 1) The surface damage was specified using the OpenGL ES convention of
+        //    the origin being in the bottom-left corner. Here we flip to the
+        //    convention that the rest of the system uses (top-left corner) by
+        //    subtracting all top/bottom coordinates from the buffer height.
+        // 2) If the buffer is coming in rotated (for example, because the EGL
+        //    implementation is reacting to the transform hint coming back from
+        //    SurfaceFlinger), the surface damage needs to be rotated the
+        //    opposite direction, since it was generated assuming an unrotated
+        //    buffer (the app doesn't know that the EGL implementation is
+        //    reacting to the transform hint behind its back). The
+        //    transformations in the switch statement below apply those
+        //    complementary rotations (e.g., if 90 degrees, rotate 270 degrees).
+
+        int width = buffer->width;
         int height = buffer->height;
-        if ((mTransform ^ mStickyTransform) & NATIVE_WINDOW_TRANSFORM_ROT_90) {
-            height = buffer->width;
+        bool rotated90 = (mTransform ^ mStickyTransform) &
+                NATIVE_WINDOW_TRANSFORM_ROT_90;
+        if (rotated90) {
+            std::swap(width, height);
         }
+
         Region flippedRegion;
         for (auto rect : mDirtyRegion) {
-            auto top = height - rect.bottom;
-            auto bottom = height - rect.top;
-            Rect flippedRect{rect.left, top, rect.right, bottom};
-            flippedRegion.orSelf(flippedRect);
+            int left = rect.left;
+            int right = rect.right;
+            int top = height - rect.bottom; // Flip from OpenGL convention
+            int bottom = height - rect.top; // Flip from OpenGL convention
+            switch (mTransform ^ mStickyTransform) {
+                case NATIVE_WINDOW_TRANSFORM_ROT_90: {
+                    // Rotate 270 degrees
+                    Rect flippedRect{top, width - right, bottom, width - left};
+                    flippedRegion.orSelf(flippedRect);
+                    break;
+                }
+                case NATIVE_WINDOW_TRANSFORM_ROT_180: {
+                    // Rotate 180 degrees
+                    Rect flippedRect{width - right, height - bottom,
+                            width - left, height - top};
+                    flippedRegion.orSelf(flippedRect);
+                    break;
+                }
+                case NATIVE_WINDOW_TRANSFORM_ROT_270: {
+                    // Rotate 90 degrees
+                    Rect flippedRect{height - bottom, left,
+                            height - top, right};
+                    flippedRegion.orSelf(flippedRect);
+                    break;
+                }
+                default: {
+                    Rect flippedRect{left, top, right, bottom};
+                    flippedRegion.orSelf(flippedRect);
+                    break;
+                }
+            }
         }
 
         input.setSurfaceDamage(flippedRegion);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 39b80ec..91f80b6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -551,14 +551,7 @@
     const Transform& tr = hw->getTransform();
     Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
     layer.setVisibleRegionScreen(visible);
-
-    // Pass full-surface damage down untouched
-    if (surfaceDamageRegion.isRect() &&
-            surfaceDamageRegion.getBounds() == Rect::INVALID_RECT) {
-        layer.setSurfaceDamage(surfaceDamageRegion);
-    } else {
-        layer.setSurfaceDamage(tr.transform(surfaceDamageRegion));
-    }
+    layer.setSurfaceDamage(surfaceDamageRegion);
 
     if (mSidebandStream.get()) {
         layer.setSidebandStream(mSidebandStream);