summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/surfaceflinger_client/SharedBufferStack.cpp30
-rw-r--r--libs/surfaceflinger_client/Surface.cpp34
2 files changed, 53 insertions, 11 deletions
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 38b2fae..4bc5d9e 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -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();
@@ -395,7 +399,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",
@@ -408,14 +411,19 @@ 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;
}
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 560ea67..d44aab9 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -409,6 +409,7 @@ void Surface::init()
{
ANativeWindow::setSwapInterval = setSwapInterval;
ANativeWindow::dequeueBuffer = dequeueBuffer;
+ ANativeWindow::cancelBuffer = cancelBuffer;
ANativeWindow::lockBuffer = lockBuffer;
ANativeWindow::queueBuffer = queueBuffer;
ANativeWindow::query = query;
@@ -517,6 +518,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);
@@ -617,6 +624,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();