am ff04e97f: am f4619308: Merge "fix [2835280] Add support for cancelling buffers to ANativeWindow" into gingerbread

Merge commit 'ff04e97faf75c435e453d4c1caf7eeac8b9c1ceb'

* commit 'ff04e97faf75c435e453d4c1caf7eeac8b9c1ceb':
  fix [2835280] Add support for cancelling buffers to ANativeWindow
This commit is contained in:
Mathias Agopian 2010-10-06 17:07:39 -07:00 committed by Android Git Automerger
commit e1c290b97d
5 changed files with 72 additions and 16 deletions

View File

@ -114,8 +114,9 @@ public:
int32_t identity; // surface's identity (const)
int32_t token; // surface's token (for debugging)
int32_t reserved32[1];
Statistics stats;
int8_t headBuf; // last retired buffer
uint8_t reservedBytes[3];
int32_t reserved;
BufferData buffers[NUM_BUFFER_MAX]; // 1024 bytes
};
@ -201,6 +202,7 @@ public:
status_t undoDequeue(int buf);
status_t lock(int buf);
status_t cancel(int buf);
status_t queue(int buf);
bool needNewBuffer(int buffer) const;
status_t setDirtyRegion(int buffer, const Region& reg);
@ -230,8 +232,9 @@ private:
inline ssize_t operator()();
};
struct UndoDequeueUpdate : public UpdateBase {
inline UndoDequeueUpdate(SharedBufferBase* sbb);
struct CancelUpdate : public UpdateBase {
int tail, buf;
inline CancelUpdate(SharedBufferBase* sbb, int tail, int buf);
inline ssize_t operator()();
};
@ -256,7 +259,6 @@ private:
int mNumBuffers;
int32_t tail;
int32_t undoDequeueTail;
int32_t queued_head;
// statistics...
nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX];

View File

@ -200,6 +200,7 @@ private:
*/
static int setSwapInterval(ANativeWindow* window, int interval);
static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer);
static int cancelBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
static int lockBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
static int query(ANativeWindow* window, int what, int* value);
@ -208,6 +209,7 @@ private:
int dequeueBuffer(android_native_buffer_t** buffer);
int lockBuffer(android_native_buffer_t* buffer);
int queueBuffer(android_native_buffer_t* buffer);
int cancelBuffer(android_native_buffer_t* buffer);
int query(int what, int* value);
int perform(int operation, va_list args);

View File

@ -218,7 +218,17 @@ struct ANativeWindow
int (*perform)(struct ANativeWindow* window,
int operation, ... );
void* reserved_proc[3];
/*
* hook used to cancel a buffer that has been dequeued.
* No synchronization is performed between dequeue() and cancel(), so
* either external synchronization is needed, or these functions must be
* called from the same thread.
*/
int (*cancelBuffer)(struct ANativeWindow* window,
struct android_native_buffer_t* buffer);
void* reserved_proc[2];
};
// Backwards compatibility... please switch to ANativeWindow.

View File

@ -285,10 +285,12 @@ ssize_t SharedBufferClient::DequeueUpdate::operator()() {
return NO_ERROR;
}
SharedBufferClient::UndoDequeueUpdate::UndoDequeueUpdate(SharedBufferBase* sbb)
: UpdateBase(sbb) {
SharedBufferClient::CancelUpdate::CancelUpdate(SharedBufferBase* sbb,
int tail, int buf)
: UpdateBase(sbb), tail(tail), buf(buf) {
}
ssize_t SharedBufferClient::UndoDequeueUpdate::operator()() {
ssize_t SharedBufferClient::CancelUpdate::operator()() {
stack.index[tail] = buf;
android_atomic_inc(&stack.available);
return NO_ERROR;
}
@ -319,7 +321,7 @@ ssize_t SharedBufferServer::RetireUpdate::operator()() {
return BAD_VALUE;
// Preventively lock the current buffer before updating queued.
android_atomic_write(stack.index[head], &stack.inUse);
android_atomic_write(stack.headBuf, &stack.inUse);
// Decrement the number of queued buffers
int32_t queued;
@ -334,7 +336,9 @@ ssize_t SharedBufferServer::RetireUpdate::operator()() {
// the buffer we preventively locked upon entering this function
head = (head + 1) % numBuffers;
android_atomic_write(stack.index[head], &stack.inUse);
const int8_t headBuf = stack.index[head];
stack.headBuf = headBuf;
android_atomic_write(headBuf, &stack.inUse);
// head is only modified here, so we don't need to use cmpxchg
android_atomic_write(head, &stack.head);
@ -359,7 +363,7 @@ ssize_t SharedBufferServer::StatusUpdate::operator()() {
SharedBufferClient::SharedBufferClient(SharedClient* sharedClient,
int surface, int num, int32_t identity)
: SharedBufferBase(sharedClient, surface, identity),
mNumBuffers(num), tail(0), undoDequeueTail(0)
mNumBuffers(num), tail(0)
{
SharedBufferStack& stack( *mSharedStack );
tail = computeTail();
@ -390,7 +394,6 @@ ssize_t SharedBufferClient::dequeue()
DequeueUpdate update(this);
updateCondition( update );
undoDequeueTail = tail;
int dequeued = stack.index[tail];
tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1);
LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail++=%d, %s",
@ -402,15 +405,20 @@ ssize_t SharedBufferClient::dequeue()
}
status_t SharedBufferClient::undoDequeue(int buf)
{
return cancel(buf);
}
status_t SharedBufferClient::cancel(int buf)
{
RWLock::AutoRLock _rd(mLock);
// TODO: we can only undo the previous dequeue, we should
// enforce that in the api
UndoDequeueUpdate update(this);
// calculate the new position of the tail index (essentially tail--)
int localTail = (tail + mNumBuffers - 1) % mNumBuffers;
CancelUpdate update(this, localTail, buf);
status_t err = updateCondition( update );
if (err == NO_ERROR) {
tail = undoDequeueTail;
tail = localTail;
}
return err;
}

View File

@ -416,6 +416,7 @@ void Surface::init()
{
ANativeWindow::setSwapInterval = setSwapInterval;
ANativeWindow::dequeueBuffer = dequeueBuffer;
ANativeWindow::cancelBuffer = cancelBuffer;
ANativeWindow::lockBuffer = lockBuffer;
ANativeWindow::queueBuffer = queueBuffer;
ANativeWindow::query = query;
@ -527,6 +528,12 @@ int Surface::dequeueBuffer(ANativeWindow* window,
return self->dequeueBuffer(buffer);
}
int Surface::cancelBuffer(ANativeWindow* window,
android_native_buffer_t* buffer) {
Surface* self = getSelf(window);
return self->cancelBuffer(buffer);
}
int Surface::lockBuffer(ANativeWindow* window,
android_native_buffer_t* buffer) {
Surface* self = getSelf(window);
@ -627,6 +634,33 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)
return err;
}
int Surface::cancelBuffer(android_native_buffer_t* buffer)
{
status_t err = validate();
switch (err) {
case NO_ERROR:
// no error, common case
break;
case INVALID_OPERATION:
// legitimate errors here
return err;
default:
// other errors happen because the surface is now invalid,
// for instance because it has been destroyed. In this case,
// we just fail silently (canceling a buffer is not technically
// an error at this point)
return NO_ERROR;
}
int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
err = mSharedBufferClient->cancel(bufIdx);
LOGE_IF(err, "error canceling buffer %d (%s)", bufIdx, strerror(-err));
return err;
}
int Surface::lockBuffer(android_native_buffer_t* buffer)
{
status_t err = validate();