Add sticky transform to surfaceflinger.

Bug: 15116722

- Adds a sticky transform field that can be set from a
  SurfaceFlinger client Surface.  This transform is
  added to any transform applied to the Surface.

Change-Id: Idaa4311dfd027b2d2b8ea5e2c6cba2da5779d753
This commit is contained in:
Ruben Brunk 2014-06-27 15:51:55 -07:00
parent f3381cf1a6
commit 1681d95989
8 changed files with 94 additions and 16 deletions

View File

@ -195,6 +195,8 @@ private:
// most updates). // most updates).
String8 mConsumerName; String8 mConsumerName;
uint32_t mStickyTransform;
}; // class BufferQueueProducer }; // class BufferQueueProducer
} // namespace android } // namespace android

View File

@ -273,15 +273,18 @@ public:
// async - if the buffer is queued in asynchronous mode // async - if the buffer is queued in asynchronous mode
// fence - a fence that the consumer must wait on before reading the buffer, // fence - a fence that the consumer must wait on before reading the buffer,
// set this to Fence::NO_FENCE if the buffer is ready immediately // set this to Fence::NO_FENCE if the buffer is ready immediately
// sticky - the sticky transform set in Surface (only used by the LEGACY
// camera mode).
inline QueueBufferInput(int64_t timestamp, bool isAutoTimestamp, inline QueueBufferInput(int64_t timestamp, bool isAutoTimestamp,
const Rect& crop, int scalingMode, uint32_t transform, bool async, const Rect& crop, int scalingMode, uint32_t transform, bool async,
const sp<Fence>& fence) const sp<Fence>& fence, uint32_t sticky = 0)
: timestamp(timestamp), isAutoTimestamp(isAutoTimestamp), crop(crop), : timestamp(timestamp), isAutoTimestamp(isAutoTimestamp), crop(crop),
scalingMode(scalingMode), transform(transform), async(async), scalingMode(scalingMode), transform(transform), stickyTransform(sticky),
fence(fence) { } async(async), fence(fence) { }
inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp, inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
Rect* outCrop, int* outScalingMode, uint32_t* outTransform, Rect* outCrop, int* outScalingMode, uint32_t* outTransform,
bool* outAsync, sp<Fence>* outFence) const { bool* outAsync, sp<Fence>* outFence,
uint32_t* outStickyTransform = NULL) const {
*outTimestamp = timestamp; *outTimestamp = timestamp;
*outIsAutoTimestamp = bool(isAutoTimestamp); *outIsAutoTimestamp = bool(isAutoTimestamp);
*outCrop = crop; *outCrop = crop;
@ -289,6 +292,9 @@ public:
*outTransform = transform; *outTransform = transform;
*outAsync = bool(async); *outAsync = bool(async);
*outFence = fence; *outFence = fence;
if (outStickyTransform != NULL) {
*outStickyTransform = stickyTransform;
}
} }
// Flattenable protocol // Flattenable protocol
@ -303,6 +309,7 @@ public:
Rect crop; Rect crop;
int scalingMode; int scalingMode;
uint32_t transform; uint32_t transform;
uint32_t stickyTransform;
int async; int async;
sp<Fence> fence; sp<Fence> fence;
}; };

View File

@ -138,6 +138,7 @@ private:
int dispatchSetBuffersFormat(va_list args); int dispatchSetBuffersFormat(va_list args);
int dispatchSetScalingMode(va_list args); int dispatchSetScalingMode(va_list args);
int dispatchSetBuffersTransform(va_list args); int dispatchSetBuffersTransform(va_list args);
int dispatchSetBuffersStickyTransform(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 dispatchSetPostTransformCrop(va_list args);
@ -163,6 +164,7 @@ protected:
virtual int setBuffersFormat(int format); virtual int setBuffersFormat(int format);
virtual int setScalingMode(int mode); virtual int setScalingMode(int mode);
virtual int setBuffersTransform(int transform); virtual int setBuffersTransform(int transform);
virtual int setBuffersStickyTransform(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 setUsage(uint32_t reqUsage); virtual int setUsage(uint32_t reqUsage);
@ -231,6 +233,12 @@ 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;
// mStickyTransform is a transform that is applied on top of mTransform
// in each buffer that is queued. This is typically used to force the
// compositor to apply a transform, and will prevent the transform hint
// from being set by the compositor.
uint32_t mStickyTransform;
// 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;

View File

@ -37,7 +37,8 @@ namespace android {
BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) : BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
mCore(core), mCore(core),
mSlots(core->mSlots), mSlots(core->mSlots),
mConsumerName() {} mConsumerName(),
mStickyTransform(0) {}
BufferQueueProducer::~BufferQueueProducer() {} BufferQueueProducer::~BufferQueueProducer() {}
@ -509,10 +510,11 @@ status_t BufferQueueProducer::queueBuffer(int slot,
Rect crop; Rect crop;
int scalingMode; int scalingMode;
uint32_t transform; uint32_t transform;
uint32_t stickyTransform;
bool async; bool async;
sp<Fence> fence; sp<Fence> fence;
input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform, input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
&async, &fence); &async, &fence, &stickyTransform);
if (fence == NULL) { if (fence == NULL) {
BQ_LOGE("queueBuffer: fence is NULL"); BQ_LOGE("queueBuffer: fence is NULL");
@ -601,6 +603,8 @@ status_t BufferQueueProducer::queueBuffer(int slot,
item.mFence = fence; item.mFence = fence;
item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async; item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
mStickyTransform = stickyTransform;
if (mCore->mQueue.empty()) { if (mCore->mQueue.empty()) {
// When the queue is empty, we can ignore mDequeueBufferCannotBlock // When the queue is empty, we can ignore mDequeueBufferCannotBlock
// and simply queue this buffer // and simply queue this buffer
@ -701,6 +705,9 @@ int BufferQueueProducer::query(int what, int *outValue) {
case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
value = mCore->getMinUndequeuedBufferCountLocked(false); value = mCore->getMinUndequeuedBufferCountLocked(false);
break; break;
case NATIVE_WINDOW_STICKY_TRANSFORM:
value = static_cast<int>(mStickyTransform);
break;
case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
value = (mCore->mQueue.size() > 1); value = (mCore->mQueue.size() > 1);
break; break;

View File

@ -435,6 +435,7 @@ size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
+ sizeof(crop) + sizeof(crop)
+ sizeof(scalingMode) + sizeof(scalingMode)
+ sizeof(transform) + sizeof(transform)
+ sizeof(stickyTransform)
+ sizeof(async) + sizeof(async)
+ fence->getFlattenedSize(); + fence->getFlattenedSize();
} }
@ -454,6 +455,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::flatten(
FlattenableUtils::write(buffer, size, crop); FlattenableUtils::write(buffer, size, crop);
FlattenableUtils::write(buffer, size, scalingMode); FlattenableUtils::write(buffer, size, scalingMode);
FlattenableUtils::write(buffer, size, transform); FlattenableUtils::write(buffer, size, transform);
FlattenableUtils::write(buffer, size, stickyTransform);
FlattenableUtils::write(buffer, size, async); FlattenableUtils::write(buffer, size, async);
return fence->flatten(buffer, size, fds, count); return fence->flatten(buffer, size, fds, count);
} }
@ -467,6 +469,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
+ sizeof(crop) + sizeof(crop)
+ sizeof(scalingMode) + sizeof(scalingMode)
+ sizeof(transform) + sizeof(transform)
+ sizeof(stickyTransform)
+ sizeof(async); + sizeof(async);
if (size < minNeeded) { if (size < minNeeded) {
@ -478,6 +481,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
FlattenableUtils::read(buffer, size, crop); FlattenableUtils::read(buffer, size, crop);
FlattenableUtils::read(buffer, size, scalingMode); FlattenableUtils::read(buffer, size, scalingMode);
FlattenableUtils::read(buffer, size, transform); FlattenableUtils::read(buffer, size, transform);
FlattenableUtils::read(buffer, size, stickyTransform);
FlattenableUtils::read(buffer, size, async); FlattenableUtils::read(buffer, size, async);
fence = new Fence(); fence = new Fence();

View File

@ -66,6 +66,7 @@ Surface::Surface(
mCrop.clear(); mCrop.clear();
mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
mTransform = 0; mTransform = 0;
mStickyTransform = 0;
mDefaultWidth = 0; mDefaultWidth = 0;
mDefaultHeight = 0; mDefaultHeight = 0;
mUserWidth = 0; mUserWidth = 0;
@ -315,15 +316,22 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE); sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
IGraphicBufferProducer::QueueBufferOutput output; IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp, IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
crop, mScalingMode, mTransform, mSwapIntervalZero, fence); crop, mScalingMode, mTransform ^ mStickyTransform, mSwapIntervalZero,
fence, mStickyTransform);
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output); status_t err = mGraphicBufferProducer->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);
} }
uint32_t numPendingBuffers = 0; uint32_t numPendingBuffers = 0;
output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint, uint32_t hint = 0;
output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
&numPendingBuffers); &numPendingBuffers);
// Disable transform hint if sticky transform is set.
if (mStickyTransform == 0) {
mTransformHint = hint;
}
mConsumerRunningBehind = (numPendingBuffers >= 2); mConsumerRunningBehind = (numPendingBuffers >= 2);
return err; return err;
@ -405,6 +413,9 @@ int Surface::perform(int operation, va_list args)
case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
res = dispatchSetBuffersTransform(args); res = dispatchSetBuffersTransform(args);
break; break;
case NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM:
res = dispatchSetBuffersStickyTransform(args);
break;
case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
res = dispatchSetBuffersTimestamp(args); res = dispatchSetBuffersTimestamp(args);
break; break;
@ -502,6 +513,11 @@ int Surface::dispatchSetBuffersTransform(va_list args) {
return setBuffersTransform(transform); return setBuffersTransform(transform);
} }
int Surface::dispatchSetBuffersStickyTransform(va_list args) {
int transform = va_arg(args, int);
return setBuffersStickyTransform(transform);
}
int Surface::dispatchSetBuffersTimestamp(va_list args) { int Surface::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);
@ -527,8 +543,15 @@ int Surface::connect(int api) {
int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output); int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
if (err == NO_ERROR) { if (err == NO_ERROR) {
uint32_t numPendingBuffers = 0; uint32_t numPendingBuffers = 0;
output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint, uint32_t hint = 0;
output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
&numPendingBuffers); &numPendingBuffers);
// Disable transform hint if sticky transform is set.
if (mStickyTransform == 0) {
mTransformHint = hint;
}
mConsumerRunningBehind = (numPendingBuffers >= 2); mConsumerRunningBehind = (numPendingBuffers >= 2);
} }
if (!err && api == NATIVE_WINDOW_API_CPU) { if (!err && api == NATIVE_WINDOW_API_CPU) {
@ -552,6 +575,8 @@ int Surface::disconnect(int api) {
mCrop.clear(); mCrop.clear();
mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
mTransform = 0; mTransform = 0;
mStickyTransform = 0;
if (api == NATIVE_WINDOW_API_CPU) { if (api == NATIVE_WINDOW_API_CPU) {
mConnectedToCpu = false; mConnectedToCpu = false;
} }
@ -678,6 +703,15 @@ int Surface::setBuffersTransform(int transform)
return NO_ERROR; return NO_ERROR;
} }
int Surface::setBuffersStickyTransform(int transform)
{
ATRACE_CALL();
ALOGV("Surface::setBuffersStickyTransform");
Mutex::Autolock lock(mMutex);
mStickyTransform = transform;
return NO_ERROR;
}
int Surface::setBuffersTimestamp(int64_t timestamp) int Surface::setBuffersTimestamp(int64_t timestamp)
{ {
ALOGV("Surface::setBuffersTimestamp"); ALOGV("Surface::setBuffersTimestamp");

View File

@ -624,6 +624,17 @@ void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
engine.disableBlending(); engine.disableBlending();
} }
uint32_t Layer::getProducerStickyTransform() const {
int producerStickyTransform = 0;
int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform);
if (ret != OK) {
ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__,
strerror(-ret), ret);
return 0;
}
return static_cast<uint32_t>(producerStickyTransform);
}
void Layer::setFiltering(bool filtering) { void Layer::setFiltering(bool filtering) {
mFiltering = filtering; mFiltering = filtering;
} }
@ -992,10 +1003,12 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
Layer::State& front; Layer::State& front;
Layer::State& current; Layer::State& current;
bool& recomputeVisibleRegions; bool& recomputeVisibleRegions;
bool stickyTransformSet;
Reject(Layer::State& front, Layer::State& current, Reject(Layer::State& front, Layer::State& current,
bool& recomputeVisibleRegions) bool& recomputeVisibleRegions, bool stickySet)
: front(front), current(current), : front(front), current(current),
recomputeVisibleRegions(recomputeVisibleRegions) { recomputeVisibleRegions(recomputeVisibleRegions),
stickyTransformSet(stickySet) {
} }
virtual bool reject(const sp<GraphicBuffer>& buf, virtual bool reject(const sp<GraphicBuffer>& buf,
@ -1058,12 +1071,12 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
front.requested.crop.getHeight()); front.requested.crop.getHeight());
} }
if (!isFixedSize) { if (!isFixedSize && !stickyTransformSet) {
if (front.active.w != bufWidth || if (front.active.w != bufWidth ||
front.active.h != bufHeight) { front.active.h != bufHeight) {
// reject this buffer // reject this buffer
//ALOGD("rejecting buffer: bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}", ALOGE("rejecting buffer: bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
// bufWidth, bufHeight, front.active.w, front.active.h); bufWidth, bufHeight, front.active.w, front.active.h);
return true; return true;
} }
} }
@ -1092,8 +1105,8 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
} }
}; };
Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions); getProducerStickyTransform() != 0);
status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r, status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
mFlinger->mPrimaryDispSync); mFlinger->mPrimaryDispSync);

View File

@ -339,6 +339,9 @@ private:
void drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip, void drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
bool useIdentityTransform) const; bool useIdentityTransform) const;
// Temporary - Used only for LEGACY camera mode.
uint32_t getProducerStickyTransform() const;
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------