summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorDan Stoza2015-04-24 10:48:37 -0500
committerGerrit Code Review2015-04-24 10:48:38 -0500
commitfb6d43ff44bb2b708494749a7f6037505ccd7bf6 (patch)
tree0787fd87be87ee92762753f107ebf61b120f61d7 /libs
parent56f1f16c7b01a53282d483259ae80d035cc6496b (diff)
parent0de7ea752900b5da29ad19c2799040235477f3c5 (diff)
downloadframeworks-native-fb6d43ff44bb2b708494749a7f6037505ccd7bf6.tar.gz
frameworks-native-fb6d43ff44bb2b708494749a7f6037505ccd7bf6.tar.xz
frameworks-native-fb6d43ff44bb2b708494749a7f6037505ccd7bf6.zip
Merge "libgui: Change BufferQueue to use free lists"
Diffstat (limited to 'libs')
-rw-r--r--libs/gui/BufferQueueConsumer.cpp28
-rw-r--r--libs/gui/BufferQueueCore.cpp60
-rw-r--r--libs/gui/BufferQueueProducer.cpp67
3 files changed, 116 insertions, 39 deletions
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 526c3b729..c7d5e0032 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -120,6 +120,7 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
120 if (mCore->stillTracking(front)) { 120 if (mCore->stillTracking(front)) {
121 // Front buffer is still in mSlots, so mark the slot as free 121 // Front buffer is still in mSlots, so mark the slot as free
122 mSlots[front->mSlot].mBufferState = BufferSlot::FREE; 122 mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
123 mCore->mFreeBuffers.push_back(front->mSlot);
123 } 124 }
124 mCore->mQueue.erase(front); 125 mCore->mQueue.erase(front);
125 front = mCore->mQueue.begin(); 126 front = mCore->mQueue.begin();
@@ -173,6 +174,8 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
173 174
174 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); 175 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
175 176
177 mCore->validateConsistencyLocked();
178
176 return NO_ERROR; 179 return NO_ERROR;
177} 180}
178 181
@@ -199,6 +202,7 @@ status_t BufferQueueConsumer::detachBuffer(int slot) {
199 202
200 mCore->freeBufferLocked(slot); 203 mCore->freeBufferLocked(slot);
201 mCore->mDequeueCondition.broadcast(); 204 mCore->mDequeueCondition.broadcast();
205 mCore->validateConsistencyLocked();
202 206
203 return NO_ERROR; 207 return NO_ERROR;
204} 208}
@@ -217,18 +221,11 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot,
217 221
218 Mutex::Autolock lock(mCore->mMutex); 222 Mutex::Autolock lock(mCore->mMutex);
219 223
220 // Make sure we don't have too many acquired buffers and find a free slot 224 // Make sure we don't have too many acquired buffers
221 // to put the buffer into (the oldest if there are multiple).
222 int numAcquiredBuffers = 0; 225 int numAcquiredBuffers = 0;
223 int found = BufferQueueCore::INVALID_BUFFER_SLOT;
224 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 226 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
225 if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) { 227 if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
226 ++numAcquiredBuffers; 228 ++numAcquiredBuffers;
227 } else if (mSlots[s].mBufferState == BufferSlot::FREE) {
228 if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
229 mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
230 found = s;
231 }
232 } 229 }
233 } 230 }
234 231
@@ -238,6 +235,17 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot,
238 mCore->mMaxAcquiredBufferCount); 235 mCore->mMaxAcquiredBufferCount);
239 return INVALID_OPERATION; 236 return INVALID_OPERATION;
240 } 237 }
238
239 // Find a free slot to put the buffer into
240 int found = BufferQueueCore::INVALID_BUFFER_SLOT;
241 if (!mCore->mFreeSlots.empty()) {
242 auto slot = mCore->mFreeSlots.begin();
243 found = *slot;
244 mCore->mFreeSlots.erase(slot);
245 } else if (!mCore->mFreeBuffers.empty()) {
246 found = mCore->mFreeBuffers.front();
247 mCore->mFreeBuffers.remove(found);
248 }
241 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 249 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
242 BQ_LOGE("attachBuffer(P): could not find free buffer slot"); 250 BQ_LOGE("attachBuffer(P): could not find free buffer slot");
243 return NO_MEMORY; 251 return NO_MEMORY;
@@ -271,6 +279,8 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot,
271 // for attached buffers. 279 // for attached buffers.
272 mSlots[*outSlot].mAcquireCalled = false; 280 mSlots[*outSlot].mAcquireCalled = false;
273 281
282 mCore->validateConsistencyLocked();
283
274 return NO_ERROR; 284 return NO_ERROR;
275} 285}
276 286
@@ -311,6 +321,7 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
311 mSlots[slot].mEglFence = eglFence; 321 mSlots[slot].mEglFence = eglFence;
312 mSlots[slot].mFence = releaseFence; 322 mSlots[slot].mFence = releaseFence;
313 mSlots[slot].mBufferState = BufferSlot::FREE; 323 mSlots[slot].mBufferState = BufferSlot::FREE;
324 mCore->mFreeBuffers.push_back(slot);
314 listener = mCore->mConnectedProducerListener; 325 listener = mCore->mConnectedProducerListener;
315 BQ_LOGV("releaseBuffer: releasing slot %d", slot); 326 BQ_LOGV("releaseBuffer: releasing slot %d", slot);
316 } else if (mSlots[slot].mNeedsCleanupOnRelease) { 327 } else if (mSlots[slot].mNeedsCleanupOnRelease) {
@@ -325,6 +336,7 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
325 } 336 }
326 337
327 mCore->mDequeueCondition.broadcast(); 338 mCore->mDequeueCondition.broadcast();
339 mCore->validateConsistencyLocked();
328 } // Autolock scope 340 } // Autolock scope
329 341
330 // Call back without lock held 342 // Call back without lock held
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index edebc4553..29415c94c 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -53,6 +53,8 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
53 mConnectedProducerListener(), 53 mConnectedProducerListener(),
54 mSlots(), 54 mSlots(),
55 mQueue(), 55 mQueue(),
56 mFreeSlots(),
57 mFreeBuffers(),
56 mOverrideMaxBufferCount(0), 58 mOverrideMaxBufferCount(0),
57 mDequeueCondition(), 59 mDequeueCondition(),
58 mUseAsyncBuffer(true), 60 mUseAsyncBuffer(true),
@@ -76,6 +78,9 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
76 BQ_LOGE("createGraphicBufferAlloc failed"); 78 BQ_LOGE("createGraphicBufferAlloc failed");
77 } 79 }
78 } 80 }
81 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
82 mFreeSlots.insert(slot);
83 }
79} 84}
80 85
81BufferQueueCore::~BufferQueueCore() {} 86BufferQueueCore::~BufferQueueCore() {}
@@ -190,12 +195,20 @@ status_t BufferQueueCore::setDefaultMaxBufferCountLocked(int count) {
190 195
191void BufferQueueCore::freeBufferLocked(int slot) { 196void BufferQueueCore::freeBufferLocked(int slot) {
192 BQ_LOGV("freeBufferLocked: slot %d", slot); 197 BQ_LOGV("freeBufferLocked: slot %d", slot);
198 bool hadBuffer = mSlots[slot].mGraphicBuffer != NULL;
193 mSlots[slot].mGraphicBuffer.clear(); 199 mSlots[slot].mGraphicBuffer.clear();
194 if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) { 200 if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) {
195 mSlots[slot].mNeedsCleanupOnRelease = true; 201 mSlots[slot].mNeedsCleanupOnRelease = true;
196 } 202 }
203 if (mSlots[slot].mBufferState != BufferSlot::FREE) {
204 mFreeSlots.insert(slot);
205 } else if (hadBuffer) {
206 // If the slot was FREE, but we had a buffer, we need to move this slot
207 // from the free buffers list to the the free slots list
208 mFreeBuffers.remove(slot);
209 mFreeSlots.insert(slot);
210 }
197 mSlots[slot].mBufferState = BufferSlot::FREE; 211 mSlots[slot].mBufferState = BufferSlot::FREE;
198 mSlots[slot].mFrameNumber = UINT32_MAX;
199 mSlots[slot].mAcquireCalled = false; 212 mSlots[slot].mAcquireCalled = false;
200 213
201 // Destroy fence as BufferQueue now takes ownership 214 // Destroy fence as BufferQueue now takes ownership
@@ -204,6 +217,7 @@ void BufferQueueCore::freeBufferLocked(int slot) {
204 mSlots[slot].mEglFence = EGL_NO_SYNC_KHR; 217 mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
205 } 218 }
206 mSlots[slot].mFence = Fence::NO_FENCE; 219 mSlots[slot].mFence = Fence::NO_FENCE;
220 validateConsistencyLocked();
207} 221}
208 222
209void BufferQueueCore::freeAllBuffersLocked() { 223void BufferQueueCore::freeAllBuffersLocked() {
@@ -236,4 +250,48 @@ void BufferQueueCore::waitWhileAllocatingLocked() const {
236 } 250 }
237} 251}
238 252
253void BufferQueueCore::validateConsistencyLocked() const {
254 static const useconds_t PAUSE_TIME = 0;
255 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
256 bool isInFreeSlots = mFreeSlots.count(slot) != 0;
257 bool isInFreeBuffers =
258 std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) !=
259 mFreeBuffers.cend();
260 if (mSlots[slot].mBufferState == BufferSlot::FREE) {
261 if (mSlots[slot].mGraphicBuffer == NULL) {
262 if (!isInFreeSlots) {
263 BQ_LOGE("Slot %d is FREE but is not in mFreeSlots", slot);
264 usleep(PAUSE_TIME);
265 }
266 if (isInFreeBuffers) {
267 BQ_LOGE("Slot %d is in mFreeSlots "
268 "but is also in mFreeBuffers", slot);
269 usleep(PAUSE_TIME);
270 }
271 } else {
272 if (!isInFreeBuffers) {
273 BQ_LOGE("Slot %d is FREE but is not in mFreeBuffers", slot);
274 usleep(PAUSE_TIME);
275 }
276 if (isInFreeSlots) {
277 BQ_LOGE("Slot %d is in mFreeBuffers "
278 "but is also in mFreeSlots", slot);
279 usleep(PAUSE_TIME);
280 }
281 }
282 } else {
283 if (isInFreeSlots) {
284 BQ_LOGE("Slot %d is in mFreeSlots but is not FREE (%d)",
285 slot, mSlots[slot].mBufferState);
286 usleep(PAUSE_TIME);
287 }
288 if (isInFreeBuffers) {
289 BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE (%d)",
290 slot, mSlots[slot].mBufferState);
291 usleep(PAUSE_TIME);
292 }
293 }
294 }
295}
296
239} // namespace android 297} // namespace android
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 6452cddcf..a27d5f033 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -161,8 +161,6 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
161 } 161 }
162 } 162 }
163 163
164 // Look for a free buffer to give to the client
165 *found = BufferQueueCore::INVALID_BUFFER_SLOT;
166 int dequeuedCount = 0; 164 int dequeuedCount = 0;
167 int acquiredCount = 0; 165 int acquiredCount = 0;
168 for (int s = 0; s < maxBufferCount; ++s) { 166 for (int s = 0; s < maxBufferCount; ++s) {
@@ -173,15 +171,6 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
173 case BufferSlot::ACQUIRED: 171 case BufferSlot::ACQUIRED:
174 ++acquiredCount; 172 ++acquiredCount;
175 break; 173 break;
176 case BufferSlot::FREE:
177 // We return the oldest of the free buffers to avoid
178 // stalling the producer if possible, since the consumer
179 // may still have pending reads of in-flight buffers
180 if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||
181 mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
182 *found = s;
183 }
184 break;
185 default: 174 default:
186 break; 175 break;
187 } 176 }
@@ -214,6 +203,8 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
214 } 203 }
215 } 204 }
216 205
206 *found = BufferQueueCore::INVALID_BUFFER_SLOT;
207
217 // If we disconnect and reconnect quickly, we can be in a state where 208 // If we disconnect and reconnect quickly, we can be in a state where
218 // our slots are empty but we have many buffers in the queue. This can 209 // our slots are empty but we have many buffers in the queue. This can
219 // cause us to run out of memory if we outrun the consumer. Wait here if 210 // cause us to run out of memory if we outrun the consumer. Wait here if
@@ -223,6 +214,19 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
223 if (tooManyBuffers) { 214 if (tooManyBuffers) {
224 BQ_LOGV("%s: queue size is %zu, waiting", caller, 215 BQ_LOGV("%s: queue size is %zu, waiting", caller,
225 mCore->mQueue.size()); 216 mCore->mQueue.size());
217 } else {
218 if (!mCore->mFreeBuffers.empty()) {
219 auto slot = mCore->mFreeBuffers.begin();
220 *found = *slot;
221 mCore->mFreeBuffers.erase(slot);
222 } else if (!mCore->mFreeSlots.empty()) {
223 auto slot = mCore->mFreeSlots.begin();
224 // Only return free slots up to the max buffer count
225 if (*slot < maxBufferCount) {
226 *found = *slot;
227 mCore->mFreeSlots.erase(slot);
228 }
229 }
226 } 230 }
227 231
228 // If no buffer is found, or if the queue has too many buffers 232 // If no buffer is found, or if the queue has too many buffers
@@ -335,6 +339,8 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
335 *outFence = mSlots[found].mFence; 339 *outFence = mSlots[found].mFence;
336 mSlots[found].mEglFence = EGL_NO_SYNC_KHR; 340 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
337 mSlots[found].mFence = Fence::NO_FENCE; 341 mSlots[found].mFence = Fence::NO_FENCE;
342
343 mCore->validateConsistencyLocked();
338 } // Autolock scope 344 } // Autolock scope
339 345
340 if (returnFlags & BUFFER_NEEDS_REALLOCATION) { 346 if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
@@ -355,7 +361,6 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
355 return NO_INIT; 361 return NO_INIT;
356 } 362 }
357 363
358 mSlots[*outSlot].mFrameNumber = UINT32_MAX;
359 mSlots[*outSlot].mGraphicBuffer = graphicBuffer; 364 mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
360 } // Autolock scope 365 } // Autolock scope
361 } 366 }
@@ -414,6 +419,7 @@ status_t BufferQueueProducer::detachBuffer(int slot) {
414 419
415 mCore->freeBufferLocked(slot); 420 mCore->freeBufferLocked(slot);
416 mCore->mDequeueCondition.broadcast(); 421 mCore->mDequeueCondition.broadcast();
422 mCore->validateConsistencyLocked();
417 423
418 return NO_ERROR; 424 return NO_ERROR;
419} 425}
@@ -438,27 +444,19 @@ status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
438 return NO_INIT; 444 return NO_INIT;
439 } 445 }
440 446
441 // Find the oldest valid slot 447 if (mCore->mFreeBuffers.empty()) {
442 int found = BufferQueueCore::INVALID_BUFFER_SLOT;
443 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
444 if (mSlots[s].mBufferState == BufferSlot::FREE &&
445 mSlots[s].mGraphicBuffer != NULL) {
446 if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
447 mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
448 found = s;
449 }
450 }
451 }
452
453 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
454 return NO_MEMORY; 448 return NO_MEMORY;
455 } 449 }
456 450
451 int found = mCore->mFreeBuffers.front();
452 mCore->mFreeBuffers.remove(found);
453
457 BQ_LOGV("detachNextBuffer detached slot %d", found); 454 BQ_LOGV("detachNextBuffer detached slot %d", found);
458 455
459 *outBuffer = mSlots[found].mGraphicBuffer; 456 *outBuffer = mSlots[found].mGraphicBuffer;
460 *outFence = mSlots[found].mFence; 457 *outFence = mSlots[found].mFence;
461 mCore->freeBufferLocked(found); 458 mCore->freeBufferLocked(found);
459 mCore->validateConsistencyLocked();
462 460
463 return NO_ERROR; 461 return NO_ERROR;
464} 462}
@@ -506,6 +504,8 @@ status_t BufferQueueProducer::attachBuffer(int* outSlot,
506 mSlots[*outSlot].mFence = Fence::NO_FENCE; 504 mSlots[*outSlot].mFence = Fence::NO_FENCE;
507 mSlots[*outSlot].mRequestBufferCalled = true; 505 mSlots[*outSlot].mRequestBufferCalled = true;
508 506
507 mCore->validateConsistencyLocked();
508
509 return returnFlags; 509 return returnFlags;
510} 510}
511 511
@@ -640,9 +640,7 @@ status_t BufferQueueProducer::queueBuffer(int slot,
640 // mark it as freed 640 // mark it as freed
641 if (mCore->stillTracking(front)) { 641 if (mCore->stillTracking(front)) {
642 mSlots[front->mSlot].mBufferState = BufferSlot::FREE; 642 mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
643 // Reset the frame number of the freed buffer so that it is 643 mCore->mFreeBuffers.push_front(front->mSlot);
644 // the first in line to be dequeued again
645 mSlots[front->mSlot].mFrameNumber = 0;
646 } 644 }
647 // Overwrite the droppable buffer with the incoming one 645 // Overwrite the droppable buffer with the incoming one
648 *front = item; 646 *front = item;
@@ -664,6 +662,8 @@ status_t BufferQueueProducer::queueBuffer(int slot,
664 662
665 // Take a ticket for the callback functions 663 // Take a ticket for the callback functions
666 callbackTicket = mNextCallbackTicket++; 664 callbackTicket = mNextCallbackTicket++;
665
666 mCore->validateConsistencyLocked();
667 } // Autolock scope 667 } // Autolock scope
668 668
669 // Wait without lock held 669 // Wait without lock held
@@ -724,10 +724,11 @@ void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
724 return; 724 return;
725 } 725 }
726 726
727 mCore->mFreeBuffers.push_front(slot);
727 mSlots[slot].mBufferState = BufferSlot::FREE; 728 mSlots[slot].mBufferState = BufferSlot::FREE;
728 mSlots[slot].mFrameNumber = 0;
729 mSlots[slot].mFence = fence; 729 mSlots[slot].mFence = fence;
730 mCore->mDequeueCondition.broadcast(); 730 mCore->mDequeueCondition.broadcast();
731 mCore->validateConsistencyLocked();
731} 732}
732 733
733int BufferQueueProducer::query(int what, int *outValue) { 734int BufferQueueProducer::query(int what, int *outValue) {
@@ -1009,13 +1010,19 @@ void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
1009 } 1010 }
1010 mCore->freeBufferLocked(slot); // Clean up the slot first 1011 mCore->freeBufferLocked(slot); // Clean up the slot first
1011 mSlots[slot].mGraphicBuffer = buffers[i]; 1012 mSlots[slot].mGraphicBuffer = buffers[i];
1012 mSlots[slot].mFrameNumber = 0;
1013 mSlots[slot].mFence = Fence::NO_FENCE; 1013 mSlots[slot].mFence = Fence::NO_FENCE;
1014
1015 // freeBufferLocked puts this slot on the free slots list. Since
1016 // we then attached a buffer, move the slot to free buffer list.
1017 mCore->mFreeSlots.erase(slot);
1018 mCore->mFreeBuffers.push_front(slot);
1019
1014 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot); 1020 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
1015 } 1021 }
1016 1022
1017 mCore->mIsAllocating = false; 1023 mCore->mIsAllocating = false;
1018 mCore->mIsAllocatingCondition.broadcast(); 1024 mCore->mIsAllocatingCondition.broadcast();
1025 mCore->validateConsistencyLocked();
1019 } // Autolock scope 1026 } // Autolock scope
1020 } 1027 }
1021} 1028}