summaryrefslogtreecommitdiffstats
path: root/libs/surfaceflinger_client
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2010-05-07 15:58:44 -0700
committerMathias Agopian <mathias@google.com>2010-05-12 17:28:20 -0700
commit59751dbf7d8f12aeb5c4c07719b7dbbf1f9b5d4b (patch)
treea1f1d7119a8109d06cfc2f24b26284ff7627de7a /libs/surfaceflinger_client
parent9f2c4fd9a14ea79e4cbbd3ab8925794711a6411c (diff)
downloadframeworks_base-59751dbf7d8f12aeb5c4c07719b7dbbf1f9b5d4b.zip
frameworks_base-59751dbf7d8f12aeb5c4c07719b7dbbf1f9b5d4b.tar.gz
frameworks_base-59751dbf7d8f12aeb5c4c07719b7dbbf1f9b5d4b.tar.bz2
SharedBufferStack now can grow up to 16 buffers.
there is a new resize() api, which currently only allows growing. Change-Id: Ia37b81b73be466d2491ffed7f3a23cd8e113c6fe
Diffstat (limited to 'libs/surfaceflinger_client')
-rw-r--r--libs/surfaceflinger_client/ISurface.cpp17
-rw-r--r--libs/surfaceflinger_client/SharedBufferStack.cpp91
-rw-r--r--libs/surfaceflinger_client/Surface.cpp21
3 files changed, 123 insertions, 6 deletions
diff --git a/libs/surfaceflinger_client/ISurface.cpp b/libs/surfaceflinger_client/ISurface.cpp
index bb86199..c5d0c0e 100644
--- a/libs/surfaceflinger_client/ISurface.cpp
+++ b/libs/surfaceflinger_client/ISurface.cpp
@@ -83,6 +83,16 @@ public:
return buffer;
}
+ virtual status_t setBufferCount(int bufferCount)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+ data.writeInt32(bufferCount);
+ remote()->transact(SET_BUFFER_COUNT, data, &reply);
+ status_t err = reply.readInt32();
+ return err;
+ }
+
virtual status_t registerBuffers(const BufferHeap& buffers)
{
Parcel data, reply;
@@ -146,6 +156,13 @@ status_t BnSurface::onTransact(
return BAD_VALUE;
return reply->write(*buffer);
}
+ case SET_BUFFER_COUNT: {
+ CHECK_INTERFACE(ISurface, data, reply);
+ int bufferCount = data.readInt32();
+ status_t err = setBufferCount(bufferCount);
+ reply->writeInt32(err);
+ return NO_ERROR;
+ }
case REGISTER_BUFFERS: {
CHECK_INTERFACE(ISurface, data, reply);
BufferHeap buffer;
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index d6b2375..4a98026 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -305,7 +305,6 @@ SharedBufferServer::RetireUpdate::RetireUpdate(
: UpdateBase(sbb), numBuffers(numBuffers) {
}
ssize_t SharedBufferServer::RetireUpdate::operator()() {
- // head is only written in this function, which is single-thread.
int32_t head = stack.head;
if (uint32_t(head) >= NUM_BUFFER_MAX)
return BAD_VALUE;
@@ -322,16 +321,14 @@ ssize_t SharedBufferServer::RetireUpdate::operator()() {
}
} while (android_atomic_cmpxchg(queued, queued-1, &stack.queued));
- // update the head pointer
- head = ((head+1 >= numBuffers) ? 0 : head+1);
-
// lock the buffer before advancing head, which automatically unlocks
// the buffer we preventively locked upon entering this function
+ head = (head + 1) % numBuffers;
android_atomic_write(stack.index[head], &stack.inUse);
- // advance head
+ // head is only modified here, so we don't need to use cmpxchg
android_atomic_write(head, &stack.head);
-
+
// now that head has moved, we can increment the number of available buffers
android_atomic_inc(&stack.available);
return head;
@@ -450,6 +447,14 @@ status_t SharedBufferClient::setDirtyRegion(int buf, const Region& reg)
return stack.setDirtyRegion(buf, reg);
}
+status_t SharedBufferClient::setBufferCount(int bufferCount)
+{
+ if (uint32_t(bufferCount) >= NUM_BUFFER_MAX)
+ return BAD_VALUE;
+ mNumBuffers = bufferCount;
+ return NO_ERROR;
+}
+
// ----------------------------------------------------------------------------
SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
@@ -463,6 +468,7 @@ SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
mSharedStack->reallocMask = 0;
memset(mSharedStack->buffers, 0, sizeof(mSharedStack->buffers));
for (int i=0 ; i<num ; i++) {
+ mBufferList.add(i);
mSharedStack->index[i] = i;
}
}
@@ -525,12 +531,85 @@ Region SharedBufferServer::getDirtyRegion(int buf) const
return stack.getDirtyRegion(buf);
}
+
+/*
+ *
+ * NOTE: this is not thread-safe on the server-side, meaning
+ * 'head' cannot move during this operation. The client-side
+ * can safely operate an usual.
+ *
+ */
+status_t SharedBufferServer::resize(int newNumBuffers)
+{
+ if (uint32_t(newNumBuffers) >= NUM_BUFFER_MAX)
+ return BAD_VALUE;
+
+ // for now we're not supporting shrinking
+ const int numBuffers = mNumBuffers;
+ if (newNumBuffers < numBuffers)
+ return BAD_VALUE;
+
+ SharedBufferStack& stack( *mSharedStack );
+ const int extra = newNumBuffers - numBuffers;
+
+ // read the head, make sure it's valid
+ int32_t head = stack.head;
+ if (uint32_t(head) >= NUM_BUFFER_MAX)
+ return BAD_VALUE;
+
+ int base = numBuffers;
+ int32_t avail = stack.available;
+ int tail = head - avail + 1;
+ if (tail >= 0) {
+ int8_t* const index = const_cast<int8_t*>(stack.index);
+ const int nb = numBuffers - head;
+ memmove(&index[head + extra], &index[head], nb);
+ base = head;
+ // move head 'extra' ahead, this doesn't impact stack.index[head];
+ stack.head = head + extra;
+ }
+ stack.available += extra;
+
+ // fill the new free space with unused buffers
+ BufferList::const_iterator curr(mBufferList.free_begin());
+ for (int i=0 ; i<extra ; i++) {
+ stack.index[base+i] = *curr++;
+ mBufferList.add(stack.index[base+i]);
+ }
+
+ mNumBuffers = newNumBuffers;
+ return NO_ERROR;
+}
+
SharedBufferStack::Statistics SharedBufferServer::getStats() const
{
SharedBufferStack& stack( *mSharedStack );
return stack.stats;
}
+// ---------------------------------------------------------------------------
+status_t SharedBufferServer::BufferList::add(int value)
+{
+ if (uint32_t(value) >= mCapacity)
+ return BAD_VALUE;
+ uint32_t mask = 1<<(31-value);
+ if (mList & mask)
+ return ALREADY_EXISTS;
+ mList |= mask;
+ return NO_ERROR;
+}
+
+status_t SharedBufferServer::BufferList::remove(int value)
+{
+ if (uint32_t(value) >= mCapacity)
+ return BAD_VALUE;
+ uint32_t mask = 1<<(31-value);
+ if (!(mList & mask))
+ return NAME_NOT_FOUND;
+ mList &= ~mask;
+ return NO_ERROR;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index eee4dae..afbeafb 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -673,6 +673,27 @@ int Surface::crop(Rect const* rect)
return NO_ERROR;
}
+int Surface::setBufferCount(int bufferCount)
+{
+ sp<ISurface> s(mSurface);
+ if (s == 0) return NO_INIT;
+
+ // FIXME: this needs to be synchronized dequeue/queue
+
+ status_t err = s->setBufferCount(bufferCount);
+ LOGE_IF(err, "ISurface::setBufferCount(%d) returned %s",
+ bufferCount, strerror(-err));
+ if (err == NO_ERROR) {
+ err = mSharedBufferClient->getStatus();
+ LOGE_IF(err, "Surface (identity=%d) state = %d", mIdentity, err);
+ if (!err) {
+ // update our local copy of the buffer count
+ mSharedBufferClient->setBufferCount(bufferCount);
+ }
+ }
+ return err;
+}
+
// ----------------------------------------------------------------------------