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");