libgui: Add support for post-xform crops.

This change adds support for specifying a crop rectangle to a
SurfaceTextureClient that is in post-transformed coordinate space.

Change-Id: I247901de343e71b32850f7ae3bac62dfa612ad3d
Bug: 6299171
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index fdd14c8..9c3e28d 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -76,9 +76,9 @@
     mReqUsage = 0;
     mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
     mCrop.clear();
+    mCropNeedsTransform = false;
     mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
     mTransform = 0;
-    mActiveRect.clear();
     mDefaultWidth = 0;
     mDefaultHeight = 0;
     mUserWidth = 0;
@@ -238,9 +238,29 @@
         return i;
     }
 
+    Rect crop(mCrop);
+    if (mCropNeedsTransform) {
+        // The crop rect was specified in the post-transform coordinate space,
+        // so we need to transform that rect by the inverse of mTransform to
+        // put it into the buffer pixel space before queuing it.
+        uint32_t invTransform = mTransform;
+        int32_t width = buffer->width;
+        int32_t height = buffer->height;
+        if (mTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
+            width = buffer->height;
+            height = buffer->width;
+        }
+        crop = mCrop.transform(invTransform, width, height);
+    }
+
+    // Make sure the crop rectangle is entirely inside the buffer.
+    crop.intersect(Rect(buffer->width, buffer->height), &crop);
+
     ISurfaceTexture::QueueBufferOutput output;
-    ISurfaceTexture::QueueBufferInput input(timestamp,
-            mCrop, mScalingMode, mTransform, mActiveRect);
+    ISurfaceTexture::QueueBufferInput input(timestamp, crop, mScalingMode,
+            mTransform);
     status_t err = mSurfaceTexture->queueBuffer(i, input, &output);
     if (err != OK)  {
         ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
@@ -321,6 +341,9 @@
     case NATIVE_WINDOW_SET_CROP:
         res = dispatchSetCrop(args);
         break;
+    case NATIVE_WINDOW_SET_POST_TRANSFORM_CROP:
+        res = dispatchSetPostTransformCrop(args);
+        break;
     case NATIVE_WINDOW_SET_BUFFER_COUNT:
         res = dispatchSetBufferCount(args);
         break;
@@ -357,9 +380,6 @@
     case NATIVE_WINDOW_API_DISCONNECT:
         res = dispatchDisconnect(args);
         break;
-    case NATIVE_WINDOW_SET_ACTIVE_RECT:
-        res = dispatchSetActiveRect(args);
-        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -387,6 +407,11 @@
     return setCrop(reinterpret_cast<Rect const*>(rect));
 }
 
+int SurfaceTextureClient::dispatchSetPostTransformCrop(va_list args) {
+    android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
+    return setPostTransformCrop(reinterpret_cast<Rect const*>(rect));
+}
+
 int SurfaceTextureClient::dispatchSetBufferCount(va_list args) {
     size_t bufferCount = va_arg(args, size_t);
     return setBufferCount(bufferCount);
@@ -430,11 +455,6 @@
     return setBuffersTransform(transform);
 }
 
-int SurfaceTextureClient::dispatchSetActiveRect(va_list args) {
-    android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
-    return setActiveRect(reinterpret_cast<Rect const*>(rect));
-}
-
 int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) {
     int64_t timestamp = va_arg(args, int64_t);
     return setBuffersTimestamp(timestamp);
@@ -481,6 +501,7 @@
         mReqHeight = 0;
         mReqUsage = 0;
         mCrop.clear();
+        mCropNeedsTransform = false;
         mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
         mTransform = 0;
         if (api == NATIVE_WINDOW_API_CPU) {
@@ -512,6 +533,25 @@
 
     Mutex::Autolock lock(mMutex);
     mCrop = realRect;
+    mCropNeedsTransform = false;
+    return NO_ERROR;
+}
+
+int SurfaceTextureClient::setPostTransformCrop(Rect const* rect)
+{
+    ATRACE_CALL();
+    ALOGV("SurfaceTextureClient::setPostTransformCrop");
+
+    Rect realRect;
+    if (rect == NULL || rect->isEmpty()) {
+        realRect.clear();
+    } else {
+        realRect = *rect;
+    }
+
+    Mutex::Autolock lock(mMutex);
+    mCrop = realRect;
+    mCropNeedsTransform = true;
     return NO_ERROR;
 }
 
@@ -546,7 +586,6 @@
     Mutex::Autolock lock(mMutex);
     mReqWidth = w;
     mReqHeight = h;
-    mCrop.clear();
     return NO_ERROR;
 }
 
@@ -564,7 +603,6 @@
     Mutex::Autolock lock(mMutex);
     mUserWidth = w;
     mUserHeight = h;
-    mCrop.clear();
     return NO_ERROR;
 }
 
@@ -589,6 +627,7 @@
         case NATIVE_WINDOW_SCALING_MODE_FREEZE:
         case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
         case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
+        case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
             break;
         default:
             ALOGE("unknown scaling mode: %d", mode);
@@ -609,23 +648,6 @@
     return NO_ERROR;
 }
 
-int SurfaceTextureClient::setActiveRect(Rect const* rect)
-{
-    ATRACE_CALL();
-    ALOGV("SurfaceTextureClient::setActiveRect");
-
-    Rect realRect;
-    if (rect == NULL || rect->isEmpty()) {
-        realRect.clear();
-    } else {
-        realRect = *rect;
-    }
-
-    Mutex::Autolock lock(mMutex);
-    mActiveRect = realRect;
-    return NO_ERROR;
-}
-
 int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp)
 {
     ALOGV("SurfaceTextureClient::setBuffersTimestamp");