summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorJamie Gennis <jgennis@google.com>2010-11-02 11:51:32 -0700
committerJamie Gennis <jgennis@google.com>2010-11-11 14:06:38 -0800
commit6c925d00e131e40811897e0ddc332d6f5bc83178 (patch)
tree813fca5b0cff6cdc7e2a6c15a12b3ae777b12d3d /libs
parent0b440fc34da7f53fcec24cc8c907b959218b957d (diff)
downloadframeworks_base-6c925d00e131e40811897e0ddc332d6f5bc83178.zip
frameworks_base-6c925d00e131e40811897e0ddc332d6f5bc83178.tar.gz
frameworks_base-6c925d00e131e40811897e0ddc332d6f5bc83178.tar.bz2
Implement reducing the buffer count of a Surface.
Change-Id: I7f979c60c06d654aa8265002836277434bc1a64f Bug: 3095167
Diffstat (limited to 'libs')
-rw-r--r--libs/surfaceflinger_client/SharedBufferStack.cpp75
-rw-r--r--libs/surfaceflinger_client/Surface.cpp6
-rw-r--r--libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp7
3 files changed, 82 insertions, 6 deletions
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 8f583f0..3b2ef84 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -265,6 +265,14 @@ bool SharedBufferClient::LockCondition::operator()() const {
(stack.queued > 0 && stack.inUse != buf));
}
+SharedBufferServer::BuffersAvailableCondition::BuffersAvailableCondition(
+ SharedBufferServer* sbs, int numBuffers) : ConditionBase(sbs),
+ mNumBuffers(numBuffers) {
+}
+bool SharedBufferServer::BuffersAvailableCondition::operator()() const {
+ return stack.available == mNumBuffers;
+}
+
// ----------------------------------------------------------------------------
SharedBufferClient::QueueUpdate::QueueUpdate(SharedBufferBase* sbb)
@@ -448,6 +456,7 @@ status_t SharedBufferClient::queue(int buf)
const nsecs_t now = systemTime(SYSTEM_TIME_THREAD);
stack.stats.totalTime = ns2us(now - mDequeueTime[buf]);
+
return err;
}
@@ -492,6 +501,7 @@ status_t SharedBufferClient::setBufferCount(
if (err == NO_ERROR) {
mNumBuffers = bufferCount;
queued_head = (stack.head + stack.queued) % mNumBuffers;
+ tail = computeTail();
}
return err;
}
@@ -606,17 +616,24 @@ uint32_t SharedBufferServer::getTransform(int buf) const
*/
status_t SharedBufferServer::resize(int newNumBuffers)
{
- if (uint32_t(newNumBuffers) >= SharedBufferStack::NUM_BUFFER_MAX)
+ if ((unsigned int)(newNumBuffers) < SharedBufferStack::NUM_BUFFER_MIN ||
+ (unsigned int)(newNumBuffers) > SharedBufferStack::NUM_BUFFER_MAX) {
return BAD_VALUE;
+ }
RWLock::AutoWLock _l(mLock);
- // for now we're not supporting shrinking
- const int numBuffers = mNumBuffers;
- if (newNumBuffers < numBuffers)
- return BAD_VALUE;
+ if (newNumBuffers < mNumBuffers) {
+ return shrink(newNumBuffers);
+ } else {
+ return grow(newNumBuffers);
+ }
+}
+status_t SharedBufferServer::grow(int newNumBuffers)
+{
SharedBufferStack& stack( *mSharedStack );
+ const int numBuffers = mNumBuffers;
const int extra = newNumBuffers - numBuffers;
// read the head, make sure it's valid
@@ -650,6 +667,54 @@ status_t SharedBufferServer::resize(int newNumBuffers)
return NO_ERROR;
}
+status_t SharedBufferServer::shrink(int newNumBuffers)
+{
+ SharedBufferStack& stack( *mSharedStack );
+
+ // Shrinking is only supported if there are no buffers currently dequeued.
+ int32_t avail = stack.available;
+ int32_t queued = stack.queued;
+ if (avail + queued != mNumBuffers) {
+ return INVALID_OPERATION;
+ }
+
+ // Wait for any queued buffers to be displayed.
+ BuffersAvailableCondition condition(this, mNumBuffers);
+ status_t err = waitForCondition(condition);
+ if (err < 0) {
+ return err;
+ }
+
+ // Reset head to index 0 and make it refer to buffer 0. The same renaming
+ // (head -> 0) is done in the BufferManager.
+ int32_t head = stack.head;
+ int8_t* index = const_cast<int8_t*>(stack.index);
+ for (int8_t i = 0; i < newNumBuffers; i++) {
+ index[i] = i;
+ }
+ stack.head = 0;
+ stack.headBuf = 0;
+
+ // If one of the buffers is in use it must be the head buffer, which we are
+ // renaming to buffer 0.
+ if (stack.inUse > 0) {
+ stack.inUse = 0;
+ }
+
+ // Free the buffers from the end of the list that are no longer needed.
+ for (int i = newNumBuffers; i < mNumBuffers; i++) {
+ mBufferList.remove(i);
+ }
+
+ // Tell the client to reallocate all the buffers.
+ reallocateAll();
+
+ mNumBuffers = newNumBuffers;
+ stack.available = newNumBuffers;
+
+ return NO_ERROR;
+}
+
SharedBufferStack::Statistics SharedBufferServer::getStats() const
{
SharedBufferStack& stack( *mSharedStack );
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index c1e00ca..9467a4c 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -855,6 +855,12 @@ int Surface::setBufferCount(int bufferCount)
status_t err = mSharedBufferClient->setBufferCount(bufferCount, ipc);
LOGE_IF(err, "ISurface::setBufferCount(%d) returned %s",
bufferCount, strerror(-err));
+
+ if (err == NO_ERROR) {
+ // Clear out any references to the old buffers.
+ mBuffers.clear();
+ }
+
return err;
}
diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
index f409f48..7ef5926 100644
--- a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
+++ b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
@@ -32,7 +32,8 @@ void test0(SharedBufferServer& s, SharedBufferClient& c, size_t num, int* list);
int main(int argc, char** argv)
{
SharedClient client;
- SharedBufferServer s(&client, 0, 4, 0);
+ sp<SharedBufferServer> ps(new SharedBufferServer(&client, 0, 4, 0));
+ SharedBufferServer& s(*ps);
SharedBufferClient c(&client, 0, 4, 0);
printf("basic test 0\n");
@@ -67,6 +68,10 @@ int main(int argc, char** argv)
int list3[6] = {3, 2, 1, 4, 5, 0};
test0(s, c, 6, list3);
+ c.setBufferCount(4, resize);
+ int list4[4] = {1, 2, 3, 0};
+ test0(s, c, 4, list4);
+
return 0;
}