@@ -341,9 +341,9 @@ status_t BufferQueueConsumer::detachBuffer(int slot) {
341341 return BAD_VALUE;
342342 }
343343
344- if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
345- BQ_LOGE ( " detachBuffer: slot index %d out of range [0, %d) " ,
346- slot, BufferQueueDefs::NUM_BUFFER_SLOTS );
344+ const int totalSlotCount = mCore -> getTotalSlotCountLocked ();
345+ if ( slot < 0 || slot >= totalSlotCount) {
346+ BQ_LOGE ( " detachBuffer: slot index %d out of range [0, %d) " , slot, totalSlotCount );
347347 return BAD_VALUE;
348348 } else if (!mSlots [slot].mBufferState .isAcquired ()) {
349349 BQ_LOGE (" detachBuffer: slot %d is not owned by the consumer "
@@ -483,10 +483,13 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
483483 ATRACE_CALL ();
484484 ATRACE_BUFFER_INDEX (slot);
485485
486- if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS ||
487- releaseFence == nullptr ) {
488- BQ_LOGE (" releaseBuffer: slot %d out of range or fence %p NULL" , slot,
489- releaseFence.get ());
486+ const int totalSlotCount = mCore ->getTotalSlotCountLocked ();
487+ if (slot < 0 || slot >= totalSlotCount) {
488+ BQ_LOGE (" releaseBuffer: slot index %d out of range [0, %d)" , slot, totalSlotCount);
489+ return BAD_VALUE;
490+ }
491+ if (releaseFence == nullptr ) {
492+ BQ_LOGE (" releaseBuffer: slot %d fence %p NULL" , slot, releaseFence.get ());
490493 return BAD_VALUE;
491494 }
492495
@@ -515,6 +518,13 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
515518 { // Autolock scope
516519 std::lock_guard<std::mutex> lock (mCore ->mMutex );
517520
521+ const int totalSlotCount = mCore ->getTotalSlotCountLocked ();
522+ if (slot < 0 || slot >= totalSlotCount || releaseFence == nullptr ) {
523+ BQ_LOGE (" releaseBuffer: slot %d out of range [0, %d) or fence %p NULL" , slot,
524+ totalSlotCount, releaseFence.get ());
525+ return BAD_VALUE;
526+ }
527+
518528 // If the frame number has changed because the buffer has been reallocated,
519529 // we can ignore this releaseBuffer for the old buffer.
520530 // Ignore this for the shared buffer where the frame number can easily
@@ -661,6 +671,43 @@ status_t BufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) {
661671 return NO_ERROR;
662672}
663673
674+ #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
675+ status_t BufferQueueConsumer::getReleasedBuffersExtended (std::vector<bool >* outSlotMask) {
676+ ATRACE_CALL ();
677+
678+ if (outSlotMask == nullptr ) {
679+ BQ_LOGE (" getReleasedBuffersExtended: outSlotMask may not be NULL" );
680+ return BAD_VALUE;
681+ }
682+
683+ std::lock_guard<std::mutex> lock (mCore ->mMutex );
684+
685+ if (mCore ->mIsAbandoned ) {
686+ BQ_LOGE (" getReleasedBuffersExtended: BufferQueue has been abandoned" );
687+ return NO_INIT;
688+ }
689+
690+ const int totalSlotCount = mCore ->getTotalSlotCountLocked ();
691+ outSlotMask->resize (totalSlotCount);
692+ for (int s = 0 ; s < totalSlotCount; ++s) {
693+ (*outSlotMask)[s] = !mSlots [s].mAcquireCalled ;
694+ }
695+
696+ // Remove from the mask queued buffers for which acquire has been called,
697+ // since the consumer will not receive their buffer addresses and so must
698+ // retain their cached information
699+ BufferQueueCore::Fifo::iterator current (mCore ->mQueue .begin ());
700+ while (current != mCore ->mQueue .end ()) {
701+ if (current->mAcquireCalled ) {
702+ (*outSlotMask)[current->mSlot ] = false ;
703+ }
704+ ++current;
705+ }
706+
707+ return NO_ERROR;
708+ }
709+ #endif
710+
664711status_t BufferQueueConsumer::setDefaultBufferSize (uint32_t width,
665712 uint32_t height) {
666713 ATRACE_CALL ();
@@ -679,6 +726,28 @@ status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width,
679726 return NO_ERROR;
680727}
681728
729+ #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
730+ status_t BufferQueueConsumer::allowUnlimitedSlots (bool allowUnlimitedSlots) {
731+ ATRACE_CALL ();
732+ BQ_LOGV (" allowUnlimitedSlots: %d" , allowUnlimitedSlots);
733+ std::lock_guard<std::mutex> lock (mCore ->mMutex );
734+
735+ if (mCore ->mIsAbandoned ) {
736+ BQ_LOGE (" allowUnlimitedSlots: BufferQueue has been abandoned" );
737+ return NO_INIT;
738+ }
739+
740+ if (mCore ->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
741+ BQ_LOGE (" allowUnlimitedSlots: BufferQueue already connected" );
742+ return INVALID_OPERATION;
743+ }
744+
745+ mCore ->mAllowExtendedSlotCount = allowUnlimitedSlots;
746+
747+ return OK;
748+ }
749+ #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
750+
682751status_t BufferQueueConsumer::setMaxBufferCount (int bufferCount) {
683752 ATRACE_CALL ();
684753
@@ -718,16 +787,23 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
718787 int maxAcquiredBuffers) {
719788 ATRACE_FORMAT (" %s(%d)" , __func__, maxAcquiredBuffers);
720789
721- if (maxAcquiredBuffers < 1 ||
722- maxAcquiredBuffers > BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) {
723- BQ_LOGE (" setMaxAcquiredBufferCount: invalid count %d" ,
724- maxAcquiredBuffers);
725- return BAD_VALUE;
726- }
727-
728790 sp<IConsumerListener> listener;
729791 { // Autolock scope
730792 std::unique_lock<std::mutex> lock (mCore ->mMutex );
793+
794+ // We reserve two slots in order to guarantee that the producer and
795+ // consumer can run asynchronously.
796+ int maxMaxAcquiredBuffers =
797+ #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
798+ mCore ->getTotalSlotCountLocked () - 2 ;
799+ #else
800+ BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS;
801+ #endif
802+ if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > maxMaxAcquiredBuffers) {
803+ BQ_LOGE (" setMaxAcquiredBufferCount: invalid count %d" , maxAcquiredBuffers);
804+ return BAD_VALUE;
805+ }
806+
731807 mCore ->waitWhileAllocatingLocked (lock);
732808
733809 if (mCore ->mIsAbandoned ) {
0 commit comments