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
This commit is contained in:
parent
5933280430
commit
d72f233ffa
@ -170,7 +170,6 @@ public:
|
|||||||
mFrameNumber(0),
|
mFrameNumber(0),
|
||||||
mBuf(INVALID_BUFFER_SLOT) {
|
mBuf(INVALID_BUFFER_SLOT) {
|
||||||
mCrop.makeInvalid();
|
mCrop.makeInvalid();
|
||||||
mActiveRect.makeInvalid();
|
|
||||||
}
|
}
|
||||||
// mGraphicBuffer points to the buffer allocated for this slot or is NULL
|
// mGraphicBuffer points to the buffer allocated for this slot or is NULL
|
||||||
// if no buffer has been allocated.
|
// if no buffer has been allocated.
|
||||||
@ -194,11 +193,6 @@ public:
|
|||||||
|
|
||||||
// mBuf is the slot index of this buffer
|
// mBuf is the slot index of this buffer
|
||||||
int mBuf;
|
int mBuf;
|
||||||
|
|
||||||
// mActiveRect is the active rectangle for the buffer. Pixels outside
|
|
||||||
// this rectangle are considered completely transparent for the purposes
|
|
||||||
// of window composition.
|
|
||||||
Rect mActiveRect;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The following public functions is the consumer facing interface
|
// The following public functions is the consumer facing interface
|
||||||
@ -302,7 +296,6 @@ private:
|
|||||||
mAcquireCalled(false),
|
mAcquireCalled(false),
|
||||||
mNeedsCleanupOnRelease(false) {
|
mNeedsCleanupOnRelease(false) {
|
||||||
mCrop.makeInvalid();
|
mCrop.makeInvalid();
|
||||||
mActiveRect.makeInvalid();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// mGraphicBuffer points to the buffer allocated for this slot or is NULL
|
// mGraphicBuffer points to the buffer allocated for this slot or is NULL
|
||||||
@ -359,12 +352,6 @@ private:
|
|||||||
// mCrop is the current crop rectangle for this buffer slot.
|
// mCrop is the current crop rectangle for this buffer slot.
|
||||||
Rect mCrop;
|
Rect mCrop;
|
||||||
|
|
||||||
// mActiveRect is the current active rectangle for this buffer slot.
|
|
||||||
// Pixels outside of this rectangle are to be treated as completely
|
|
||||||
// transparent during window composition. The rectangle is in buffer
|
|
||||||
// pixel coordinates.
|
|
||||||
Rect mActiveRect;
|
|
||||||
|
|
||||||
// mTransform is the current transform flags for this buffer slot.
|
// mTransform is the current transform flags for this buffer slot.
|
||||||
uint32_t mTransform;
|
uint32_t mTransform;
|
||||||
|
|
||||||
|
@ -86,25 +86,21 @@ protected:
|
|||||||
// QueueBufferInput must be a POD structure
|
// QueueBufferInput must be a POD structure
|
||||||
struct QueueBufferInput {
|
struct QueueBufferInput {
|
||||||
inline QueueBufferInput(int64_t timestamp,
|
inline QueueBufferInput(int64_t timestamp,
|
||||||
const Rect& crop, int scalingMode, uint32_t transform,
|
const Rect& crop, int scalingMode, uint32_t transform)
|
||||||
const Rect& activeRect)
|
|
||||||
: timestamp(timestamp), crop(crop), scalingMode(scalingMode),
|
: timestamp(timestamp), crop(crop), scalingMode(scalingMode),
|
||||||
transform(transform), activeRect(activeRect) { }
|
transform(transform) { }
|
||||||
inline void deflate(int64_t* outTimestamp, Rect* outCrop,
|
inline void deflate(int64_t* outTimestamp, Rect* outCrop,
|
||||||
int* outScalingMode, uint32_t* outTransform,
|
int* outScalingMode, uint32_t* outTransform) const {
|
||||||
Rect* outActiveRect) const {
|
|
||||||
*outTimestamp = timestamp;
|
*outTimestamp = timestamp;
|
||||||
*outCrop = crop;
|
*outCrop = crop;
|
||||||
*outScalingMode = scalingMode;
|
*outScalingMode = scalingMode;
|
||||||
*outTransform = transform;
|
*outTransform = transform;
|
||||||
*outActiveRect = activeRect;
|
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
int64_t timestamp;
|
int64_t timestamp;
|
||||||
Rect crop;
|
Rect crop;
|
||||||
int scalingMode;
|
int scalingMode;
|
||||||
uint32_t transform;
|
uint32_t transform;
|
||||||
Rect activeRect;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// QueueBufferOutput must be a POD structure
|
// QueueBufferOutput must be a POD structure
|
||||||
|
@ -154,9 +154,6 @@ public:
|
|||||||
// getCurrentCrop returns the cropping rectangle of the current buffer.
|
// getCurrentCrop returns the cropping rectangle of the current buffer.
|
||||||
Rect getCurrentCrop() const;
|
Rect getCurrentCrop() const;
|
||||||
|
|
||||||
// getCurrentActiveRect returns the active rectangle of the current buffer.
|
|
||||||
Rect getCurrentActiveRect() const;
|
|
||||||
|
|
||||||
// getCurrentTransform returns the transform of the current buffer.
|
// getCurrentTransform returns the transform of the current buffer.
|
||||||
uint32_t getCurrentTransform() const;
|
uint32_t getCurrentTransform() const;
|
||||||
|
|
||||||
@ -273,12 +270,6 @@ private:
|
|||||||
// It gets set each time updateTexImage is called.
|
// It gets set each time updateTexImage is called.
|
||||||
Rect mCurrentCrop;
|
Rect mCurrentCrop;
|
||||||
|
|
||||||
// mCurrentActiveRect is the active rectangle that applies to the current
|
|
||||||
// texture. It gets set each time updateTexImage is called. All pixels
|
|
||||||
// outside the active rectangle are be considered completely transparent for
|
|
||||||
// the purpose of window composition.
|
|
||||||
Rect mCurrentActiveRect;
|
|
||||||
|
|
||||||
// mCurrentTransform is the transform identifier for the current texture. It
|
// mCurrentTransform is the transform identifier for the current texture. It
|
||||||
// gets set each time updateTexImage is called.
|
// gets set each time updateTexImage is called.
|
||||||
uint32_t mCurrentTransform;
|
uint32_t mCurrentTransform;
|
||||||
|
@ -80,10 +80,10 @@ private:
|
|||||||
int dispatchSetBuffersTransform(va_list args);
|
int dispatchSetBuffersTransform(va_list args);
|
||||||
int dispatchSetBuffersTimestamp(va_list args);
|
int dispatchSetBuffersTimestamp(va_list args);
|
||||||
int dispatchSetCrop(va_list args);
|
int dispatchSetCrop(va_list args);
|
||||||
|
int dispatchSetPostTransformCrop(va_list args);
|
||||||
int dispatchSetUsage(va_list args);
|
int dispatchSetUsage(va_list args);
|
||||||
int dispatchLock(va_list args);
|
int dispatchLock(va_list args);
|
||||||
int dispatchUnlockAndPost(va_list args);
|
int dispatchUnlockAndPost(va_list args);
|
||||||
int dispatchSetActiveRect(va_list args);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int cancelBuffer(ANativeWindowBuffer* buffer);
|
virtual int cancelBuffer(ANativeWindowBuffer* buffer);
|
||||||
@ -104,10 +104,10 @@ protected:
|
|||||||
virtual int setBuffersTransform(int transform);
|
virtual int setBuffersTransform(int transform);
|
||||||
virtual int setBuffersTimestamp(int64_t timestamp);
|
virtual int setBuffersTimestamp(int64_t timestamp);
|
||||||
virtual int setCrop(Rect const* rect);
|
virtual int setCrop(Rect const* rect);
|
||||||
|
virtual int setPostTransformCrop(Rect const* rect);
|
||||||
virtual int setUsage(uint32_t reqUsage);
|
virtual int setUsage(uint32_t reqUsage);
|
||||||
virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
|
virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
|
||||||
virtual int unlockAndPost();
|
virtual int unlockAndPost();
|
||||||
virtual int setActiveRect(Rect const* rect);
|
|
||||||
|
|
||||||
enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };
|
enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };
|
||||||
enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
|
enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
|
||||||
@ -159,6 +159,13 @@ private:
|
|||||||
// that gets queued. It is set by calling setCrop.
|
// that gets queued. It is set by calling setCrop.
|
||||||
Rect mCrop;
|
Rect mCrop;
|
||||||
|
|
||||||
|
// mCropNeedsTransform indicates whether mCrop is in post-transform
|
||||||
|
// coordinates and must be transformed using the inverse of mTransform
|
||||||
|
// before being queued with a buffer. Otherwise the crop is passed
|
||||||
|
// untransformed. It is initialized to false, is set to true by
|
||||||
|
// setPostTransformCrop, and set to false by setCrop.
|
||||||
|
bool mCropNeedsTransform;
|
||||||
|
|
||||||
// mScalingMode is the scaling mode that will be used for the next
|
// mScalingMode is the scaling mode that will be used for the next
|
||||||
// buffers that get queued. It is set by calling setScalingMode.
|
// buffers that get queued. It is set by calling setScalingMode.
|
||||||
int mScalingMode;
|
int mScalingMode;
|
||||||
@ -167,10 +174,6 @@ private:
|
|||||||
// buffer that gets queued. It is set by calling setTransform.
|
// buffer that gets queued. It is set by calling setTransform.
|
||||||
uint32_t mTransform;
|
uint32_t mTransform;
|
||||||
|
|
||||||
// mActiveRect is the active rectangle that will be used for the next buffer
|
|
||||||
// that gets queued. It is set by calling setActiveRect.
|
|
||||||
Rect mActiveRect;
|
|
||||||
|
|
||||||
// mDefaultWidth is default width of the buffers, regardless of the
|
// mDefaultWidth is default width of the buffers, regardless of the
|
||||||
// native_window_set_buffers_dimensions call.
|
// native_window_set_buffers_dimensions call.
|
||||||
uint32_t mDefaultWidth;
|
uint32_t mDefaultWidth;
|
||||||
|
@ -540,15 +540,11 @@ status_t BufferQueue::queueBuffer(int buf,
|
|||||||
uint32_t transform;
|
uint32_t transform;
|
||||||
int scalingMode;
|
int scalingMode;
|
||||||
int64_t timestamp;
|
int64_t timestamp;
|
||||||
Rect activeRect;
|
|
||||||
|
|
||||||
input.deflate(×tamp, &crop, &scalingMode, &transform,
|
input.deflate(×tamp, &crop, &scalingMode, &transform);
|
||||||
&activeRect);
|
|
||||||
|
|
||||||
ST_LOGV("queueBuffer: slot=%d time=%lld crop=[%d,%d,%d,%d] "
|
ST_LOGV("queueBuffer: slot=%d time=%lld crop=[%d,%d,%d,%d]",
|
||||||
"active=[%d,%d,%d,%d]", buf, timestamp, crop.left, crop.top,
|
buf, timestamp, crop.left, crop.top, crop.right, crop.bottom);
|
||||||
crop.right, crop.bottom, activeRect.left, activeRect.top,
|
|
||||||
activeRect.right, activeRect.bottom);
|
|
||||||
|
|
||||||
sp<ConsumerListener> listener;
|
sp<ConsumerListener> listener;
|
||||||
|
|
||||||
@ -572,6 +568,16 @@ status_t BufferQueue::queueBuffer(int buf,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer);
|
||||||
|
Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
|
||||||
|
Rect croppedCrop;
|
||||||
|
crop.intersect(bufferRect, &croppedCrop);
|
||||||
|
if (croppedCrop != crop) {
|
||||||
|
ST_LOGE("queueBuffer: crop rect is not contained within the "
|
||||||
|
"buffer in slot %d", buf);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (mSynchronousMode) {
|
if (mSynchronousMode) {
|
||||||
// In synchronous mode we queue all buffers in a FIFO.
|
// In synchronous mode we queue all buffers in a FIFO.
|
||||||
mQueue.push_back(buf);
|
mQueue.push_back(buf);
|
||||||
@ -600,12 +606,12 @@ status_t BufferQueue::queueBuffer(int buf,
|
|||||||
mSlots[buf].mTimestamp = timestamp;
|
mSlots[buf].mTimestamp = timestamp;
|
||||||
mSlots[buf].mCrop = crop;
|
mSlots[buf].mCrop = crop;
|
||||||
mSlots[buf].mTransform = transform;
|
mSlots[buf].mTransform = transform;
|
||||||
mSlots[buf].mActiveRect = activeRect;
|
|
||||||
|
|
||||||
switch (scalingMode) {
|
switch (scalingMode) {
|
||||||
case NATIVE_WINDOW_SCALING_MODE_FREEZE:
|
case NATIVE_WINDOW_SCALING_MODE_FREEZE:
|
||||||
case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
|
case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
|
||||||
case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
|
case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
|
||||||
|
case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode);
|
ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode);
|
||||||
@ -859,7 +865,6 @@ status_t BufferQueue::acquireBuffer(BufferItem *buffer) {
|
|||||||
buffer->mFrameNumber = mSlots[buf].mFrameNumber;
|
buffer->mFrameNumber = mSlots[buf].mFrameNumber;
|
||||||
buffer->mTimestamp = mSlots[buf].mTimestamp;
|
buffer->mTimestamp = mSlots[buf].mTimestamp;
|
||||||
buffer->mBuf = buf;
|
buffer->mBuf = buf;
|
||||||
buffer->mActiveRect = mSlots[buf].mActiveRect;
|
|
||||||
mSlots[buf].mAcquireCalled = true;
|
mSlots[buf].mAcquireCalled = true;
|
||||||
|
|
||||||
mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
|
mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
|
||||||
|
@ -294,7 +294,6 @@ status_t SurfaceTexture::updateTexImage() {
|
|||||||
mCurrentTransform = item.mTransform;
|
mCurrentTransform = item.mTransform;
|
||||||
mCurrentScalingMode = item.mScalingMode;
|
mCurrentScalingMode = item.mScalingMode;
|
||||||
mCurrentTimestamp = item.mTimestamp;
|
mCurrentTimestamp = item.mTimestamp;
|
||||||
mCurrentActiveRect = item.mActiveRect;
|
|
||||||
computeCurrentTransformMatrix();
|
computeCurrentTransformMatrix();
|
||||||
} else {
|
} else {
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
@ -534,8 +533,9 @@ void SurfaceTexture::computeCurrentTransformMatrix() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sp<GraphicBuffer>& buf(mCurrentTextureBuf);
|
sp<GraphicBuffer>& buf(mCurrentTextureBuf);
|
||||||
|
Rect cropRect = mCurrentCrop;
|
||||||
float tx, ty, sx, sy;
|
float tx, ty, sx, sy;
|
||||||
if (!mCurrentCrop.isEmpty()) {
|
if (!cropRect.isEmpty()) {
|
||||||
// In order to prevent bilinear sampling at the of the crop rectangle we
|
// In order to prevent bilinear sampling at the of the crop rectangle we
|
||||||
// may need to shrink it by 2 texels in each direction. Normally this
|
// may need to shrink it by 2 texels in each direction. Normally this
|
||||||
// would just need to take 1/2 a texel off each end, but because the
|
// would just need to take 1/2 a texel off each end, but because the
|
||||||
@ -552,14 +552,16 @@ void SurfaceTexture::computeCurrentTransformMatrix() {
|
|||||||
// correct edge behavior.
|
// correct edge behavior.
|
||||||
const float shrinkAmount = 1.0f; // the amount that each edge is shrunk
|
const float shrinkAmount = 1.0f; // the amount that each edge is shrunk
|
||||||
|
|
||||||
tx = (float(mCurrentCrop.left) + shrinkAmount) /
|
float bufferWidth = buf->getWidth();
|
||||||
float(buf->getWidth());
|
float bufferHeight = buf->getHeight();
|
||||||
ty = (float(buf->getHeight() - mCurrentCrop.bottom) +
|
|
||||||
shrinkAmount) / float(buf->getHeight());
|
tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
|
||||||
sx = (float(mCurrentCrop.width()) - (2.0f * shrinkAmount)) /
|
ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
|
||||||
float(buf->getWidth());
|
bufferHeight;
|
||||||
sy = (float(mCurrentCrop.height()) - (2.0f * shrinkAmount)) /
|
sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
|
||||||
float(buf->getHeight());
|
bufferWidth;
|
||||||
|
sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
|
||||||
|
bufferHeight;
|
||||||
} else {
|
} else {
|
||||||
tx = 0.0f;
|
tx = 0.0f;
|
||||||
ty = 0.0f;
|
ty = 0.0f;
|
||||||
@ -653,11 +655,6 @@ Rect SurfaceTexture::getCurrentCrop() const {
|
|||||||
return outCrop;
|
return outCrop;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect SurfaceTexture::getCurrentActiveRect() const {
|
|
||||||
Mutex::Autolock lock(mMutex);
|
|
||||||
return mCurrentActiveRect;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t SurfaceTexture::getCurrentTransform() const {
|
uint32_t SurfaceTexture::getCurrentTransform() const {
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
return mCurrentTransform;
|
return mCurrentTransform;
|
||||||
|
@ -76,9 +76,9 @@ void SurfaceTextureClient::init() {
|
|||||||
mReqUsage = 0;
|
mReqUsage = 0;
|
||||||
mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
|
mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
|
||||||
mCrop.clear();
|
mCrop.clear();
|
||||||
|
mCropNeedsTransform = false;
|
||||||
mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
|
mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
|
||||||
mTransform = 0;
|
mTransform = 0;
|
||||||
mActiveRect.clear();
|
|
||||||
mDefaultWidth = 0;
|
mDefaultWidth = 0;
|
||||||
mDefaultHeight = 0;
|
mDefaultHeight = 0;
|
||||||
mUserWidth = 0;
|
mUserWidth = 0;
|
||||||
@ -238,9 +238,29 @@ int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
|
|||||||
return i;
|
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::QueueBufferOutput output;
|
||||||
ISurfaceTexture::QueueBufferInput input(timestamp,
|
ISurfaceTexture::QueueBufferInput input(timestamp, crop, mScalingMode,
|
||||||
mCrop, mScalingMode, mTransform, mActiveRect);
|
mTransform);
|
||||||
status_t err = mSurfaceTexture->queueBuffer(i, input, &output);
|
status_t err = mSurfaceTexture->queueBuffer(i, input, &output);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
|
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
|
||||||
@ -321,6 +341,9 @@ int SurfaceTextureClient::perform(int operation, va_list args)
|
|||||||
case NATIVE_WINDOW_SET_CROP:
|
case NATIVE_WINDOW_SET_CROP:
|
||||||
res = dispatchSetCrop(args);
|
res = dispatchSetCrop(args);
|
||||||
break;
|
break;
|
||||||
|
case NATIVE_WINDOW_SET_POST_TRANSFORM_CROP:
|
||||||
|
res = dispatchSetPostTransformCrop(args);
|
||||||
|
break;
|
||||||
case NATIVE_WINDOW_SET_BUFFER_COUNT:
|
case NATIVE_WINDOW_SET_BUFFER_COUNT:
|
||||||
res = dispatchSetBufferCount(args);
|
res = dispatchSetBufferCount(args);
|
||||||
break;
|
break;
|
||||||
@ -357,9 +380,6 @@ int SurfaceTextureClient::perform(int operation, va_list args)
|
|||||||
case NATIVE_WINDOW_API_DISCONNECT:
|
case NATIVE_WINDOW_API_DISCONNECT:
|
||||||
res = dispatchDisconnect(args);
|
res = dispatchDisconnect(args);
|
||||||
break;
|
break;
|
||||||
case NATIVE_WINDOW_SET_ACTIVE_RECT:
|
|
||||||
res = dispatchSetActiveRect(args);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
res = NAME_NOT_FOUND;
|
res = NAME_NOT_FOUND;
|
||||||
break;
|
break;
|
||||||
@ -387,6 +407,11 @@ int SurfaceTextureClient::dispatchSetCrop(va_list args) {
|
|||||||
return setCrop(reinterpret_cast<Rect const*>(rect));
|
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) {
|
int SurfaceTextureClient::dispatchSetBufferCount(va_list args) {
|
||||||
size_t bufferCount = va_arg(args, size_t);
|
size_t bufferCount = va_arg(args, size_t);
|
||||||
return setBufferCount(bufferCount);
|
return setBufferCount(bufferCount);
|
||||||
@ -430,11 +455,6 @@ int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
|
|||||||
return setBuffersTransform(transform);
|
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) {
|
int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) {
|
||||||
int64_t timestamp = va_arg(args, int64_t);
|
int64_t timestamp = va_arg(args, int64_t);
|
||||||
return setBuffersTimestamp(timestamp);
|
return setBuffersTimestamp(timestamp);
|
||||||
@ -481,6 +501,7 @@ int SurfaceTextureClient::disconnect(int api) {
|
|||||||
mReqHeight = 0;
|
mReqHeight = 0;
|
||||||
mReqUsage = 0;
|
mReqUsage = 0;
|
||||||
mCrop.clear();
|
mCrop.clear();
|
||||||
|
mCropNeedsTransform = false;
|
||||||
mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
|
mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
|
||||||
mTransform = 0;
|
mTransform = 0;
|
||||||
if (api == NATIVE_WINDOW_API_CPU) {
|
if (api == NATIVE_WINDOW_API_CPU) {
|
||||||
@ -512,6 +533,25 @@ int SurfaceTextureClient::setCrop(Rect const* rect)
|
|||||||
|
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
mCrop = realRect;
|
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;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,7 +586,6 @@ int SurfaceTextureClient::setBuffersDimensions(int w, int h)
|
|||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
mReqWidth = w;
|
mReqWidth = w;
|
||||||
mReqHeight = h;
|
mReqHeight = h;
|
||||||
mCrop.clear();
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,7 +603,6 @@ int SurfaceTextureClient::setBuffersUserDimensions(int w, int h)
|
|||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
mUserWidth = w;
|
mUserWidth = w;
|
||||||
mUserHeight = h;
|
mUserHeight = h;
|
||||||
mCrop.clear();
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,6 +627,7 @@ int SurfaceTextureClient::setScalingMode(int mode)
|
|||||||
case NATIVE_WINDOW_SCALING_MODE_FREEZE:
|
case NATIVE_WINDOW_SCALING_MODE_FREEZE:
|
||||||
case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
|
case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
|
||||||
case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
|
case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
|
||||||
|
case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ALOGE("unknown scaling mode: %d", mode);
|
ALOGE("unknown scaling mode: %d", mode);
|
||||||
@ -609,23 +648,6 @@ int SurfaceTextureClient::setBuffersTransform(int transform)
|
|||||||
return NO_ERROR;
|
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)
|
int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp)
|
||||||
{
|
{
|
||||||
ALOGV("SurfaceTextureClient::setBuffersTimestamp");
|
ALOGV("SurfaceTextureClient::setBuffersTimestamp");
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <gui/SurfaceTextureClient.h>
|
#include <gui/SurfaceTextureClient.h>
|
||||||
|
#include <system/graphics.h>
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
#include <utils/Thread.h>
|
#include <utils/Thread.h>
|
||||||
|
|
||||||
@ -441,6 +442,68 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) {
|
|||||||
ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2]));
|
ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SurfaceTextureClientTest, SetPostTransformCropUntransforms) {
|
||||||
|
android_native_rect_t rect = {1, 5, 4, 14};
|
||||||
|
native_window_set_post_transform_crop(mANW.get(), &rect);
|
||||||
|
|
||||||
|
uint32_t xforms[] = {
|
||||||
|
HAL_TRANSFORM_FLIP_H,
|
||||||
|
HAL_TRANSFORM_FLIP_V,
|
||||||
|
HAL_TRANSFORM_ROT_90,
|
||||||
|
HAL_TRANSFORM_ROT_180,
|
||||||
|
HAL_TRANSFORM_ROT_270,
|
||||||
|
};
|
||||||
|
|
||||||
|
Rect expectedRects[] = {
|
||||||
|
Rect(4, 5, 7, 14), // HAL_TRANSFORM_FLIP_H
|
||||||
|
Rect(1, 2, 4, 11), // HAL_TRANSFORM_FLIP_V
|
||||||
|
Rect(5, 4, 14, 7), // HAL_TRANSFORM_ROT_90
|
||||||
|
Rect(4, 2, 7, 11), // HAL_TRANSFORM_ROT_180
|
||||||
|
Rect(2, 1, 11, 4), // HAL_TRANSFORM_ROT_270
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(xforms)/sizeof(xforms[0]); i++) {
|
||||||
|
SCOPED_TRACE(String8::format("xform=%#x", xforms[i]).string());
|
||||||
|
|
||||||
|
int w = 8, h = 16;
|
||||||
|
if (xforms[i] & HAL_TRANSFORM_ROT_90) {
|
||||||
|
w = 16;
|
||||||
|
h = 8;
|
||||||
|
}
|
||||||
|
ASSERT_EQ(OK, native_window_set_buffers_transform(mANW.get(), xforms[i]));
|
||||||
|
ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), w, h));
|
||||||
|
|
||||||
|
android_native_buffer_t* buf;
|
||||||
|
ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
|
||||||
|
ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf));
|
||||||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||||||
|
|
||||||
|
Rect crop = mST->getCurrentCrop();
|
||||||
|
EXPECT_EQ(expectedRects[i].left, crop.left);
|
||||||
|
EXPECT_EQ(expectedRects[i].top, crop.top);
|
||||||
|
EXPECT_EQ(expectedRects[i].right, crop.right);
|
||||||
|
EXPECT_EQ(expectedRects[i].bottom, crop.bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SurfaceTextureClientTest, SetCropCropsCrop) {
|
||||||
|
android_native_rect_t rect = {-2, -13, 40, 18};
|
||||||
|
native_window_set_crop(mANW.get(), &rect);
|
||||||
|
|
||||||
|
ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 4, 4));
|
||||||
|
|
||||||
|
android_native_buffer_t* buf;
|
||||||
|
ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
|
||||||
|
ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf));
|
||||||
|
ASSERT_EQ(OK, mST->updateTexImage());
|
||||||
|
|
||||||
|
Rect crop = mST->getCurrentCrop();
|
||||||
|
EXPECT_EQ(0, crop.left);
|
||||||
|
EXPECT_EQ(0, crop.top);
|
||||||
|
EXPECT_EQ(4, crop.right);
|
||||||
|
EXPECT_EQ(4, crop.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
// XXX: This is not expected to pass until the synchronization hacks are removed
|
// XXX: This is not expected to pass until the synchronization hacks are removed
|
||||||
// from the SurfaceTexture class.
|
// from the SurfaceTexture class.
|
||||||
TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeWaitRetire) {
|
TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeWaitRetire) {
|
||||||
|
@ -1262,28 +1262,6 @@ TEST_F(SurfaceTextureGLTest, CroppedScalingMode) {
|
|||||||
native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
|
native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SurfaceTextureGLTest, GetCurrentActiveRectWorks) {
|
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
|
|
||||||
ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
|
|
||||||
NATIVE_WINDOW_API_CPU));
|
|
||||||
|
|
||||||
ANativeWindowBuffer *anb;
|
|
||||||
|
|
||||||
android_native_rect_t odd = {23, 78, 123, 477};
|
|
||||||
ASSERT_EQ(OK, native_window_set_active_rect(mANW.get(), &odd));
|
|
||||||
EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
|
|
||||||
EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
|
|
||||||
mFW->waitForFrame();
|
|
||||||
EXPECT_EQ(OK,mST->updateTexImage());
|
|
||||||
Rect r = mST->getCurrentCrop();
|
|
||||||
assertRectEq(Rect(23, 78, 123, 477), r);
|
|
||||||
|
|
||||||
ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
|
|
||||||
NATIVE_WINDOW_API_CPU));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
|
TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
|
||||||
class ProducerThread : public Thread {
|
class ProducerThread : public Thread {
|
||||||
public:
|
public:
|
||||||
|
Loading…
Reference in New Issue
Block a user