Home | History | Annotate | Download | only in gui
      1 /*
      2  * Copyright 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "BufferQueueCore"
     18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
     19 //#define LOG_NDEBUG 0
     20 
     21 #define EGL_EGLEXT_PROTOTYPES
     22 
     23 #if DEBUG_ONLY_CODE
     24 #define VALIDATE_CONSISTENCY() do { validateConsistencyLocked(); } while (0)
     25 #else
     26 #define VALIDATE_CONSISTENCY()
     27 #endif
     28 
     29 #include <inttypes.h>
     30 
     31 #include <cutils/properties.h>
     32 #include <cutils/atomic.h>
     33 
     34 #include <gui/BufferItem.h>
     35 #include <gui/BufferQueueCore.h>
     36 #include <gui/IConsumerListener.h>
     37 #include <gui/IProducerListener.h>
     38 #include <gui/ISurfaceComposer.h>
     39 #include <private/gui/ComposerService.h>
     40 
     41 #include <system/window.h>
     42 
     43 namespace android {
     44 
     45 static String8 getUniqueName() {
     46     static volatile int32_t counter = 0;
     47     return String8::format("unnamed-%d-%d", getpid(),
     48             android_atomic_inc(&counter));
     49 }
     50 
     51 static uint64_t getUniqueId() {
     52     static std::atomic<uint32_t> counter{0};
     53     static uint64_t id = static_cast<uint64_t>(getpid()) << 32;
     54     return id | counter++;
     55 }
     56 
     57 BufferQueueCore::BufferQueueCore() :
     58     mMutex(),
     59     mIsAbandoned(false),
     60     mConsumerControlledByApp(false),
     61     mConsumerName(getUniqueName()),
     62     mConsumerListener(),
     63     mConsumerUsageBits(0),
     64     mConsumerIsProtected(false),
     65     mConnectedApi(NO_CONNECTED_API),
     66     mLinkedToDeath(),
     67     mConnectedProducerListener(),
     68     mSlots(),
     69     mQueue(),
     70     mFreeSlots(),
     71     mFreeBuffers(),
     72     mUnusedSlots(),
     73     mActiveBuffers(),
     74     mDequeueCondition(),
     75     mDequeueBufferCannotBlock(false),
     76     mQueueBufferCanDrop(false),
     77     mLegacyBufferDrop(true),
     78     mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
     79     mDefaultWidth(1),
     80     mDefaultHeight(1),
     81     mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
     82     mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
     83     mMaxAcquiredBufferCount(1),
     84     mMaxDequeuedBufferCount(1),
     85     mBufferHasBeenQueued(false),
     86     mFrameCounter(0),
     87     mTransformHint(0),
     88     mIsAllocating(false),
     89     mIsAllocatingCondition(),
     90     mAllowAllocation(true),
     91     mBufferAge(0),
     92     mGenerationNumber(0),
     93     mAsyncMode(false),
     94     mSharedBufferMode(false),
     95     mAutoRefresh(false),
     96     mSharedBufferSlot(INVALID_BUFFER_SLOT),
     97     mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
     98             HAL_DATASPACE_UNKNOWN),
     99     mLastQueuedSlot(INVALID_BUFFER_SLOT),
    100     mUniqueId(getUniqueId())
    101 {
    102     int numStartingBuffers = getMaxBufferCountLocked();
    103     for (int s = 0; s < numStartingBuffers; s++) {
    104         mFreeSlots.insert(s);
    105     }
    106     for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
    107             s++) {
    108         mUnusedSlots.push_front(s);
    109     }
    110 }
    111 
    112 BufferQueueCore::~BufferQueueCore() {}
    113 
    114 void BufferQueueCore::dumpState(const String8& prefix, String8* outResult) const {
    115     std::lock_guard<std::mutex> lock(mMutex);
    116 
    117     outResult->appendFormat("%s- BufferQueue ", prefix.string());
    118     outResult->appendFormat("mMaxAcquiredBufferCount=%d mMaxDequeuedBufferCount=%d\n",
    119                             mMaxAcquiredBufferCount, mMaxDequeuedBufferCount);
    120     outResult->appendFormat("%s  mDequeueBufferCannotBlock=%d mAsyncMode=%d\n", prefix.string(),
    121                             mDequeueBufferCannotBlock, mAsyncMode);
    122     outResult->appendFormat("%s  mQueueBufferCanDrop=%d mLegacyBufferDrop=%d\n", prefix.string(),
    123                             mQueueBufferCanDrop, mLegacyBufferDrop);
    124     outResult->appendFormat("%s  default-size=[%dx%d] default-format=%d ", prefix.string(),
    125                             mDefaultWidth, mDefaultHeight, mDefaultBufferFormat);
    126     outResult->appendFormat("transform-hint=%02x frame-counter=%" PRIu64, mTransformHint,
    127                             mFrameCounter);
    128 
    129     outResult->appendFormat("\n%sFIFO(%zu):\n", prefix.string(), mQueue.size());
    130     Fifo::const_iterator current(mQueue.begin());
    131     while (current != mQueue.end()) {
    132         double timestamp = current->mTimestamp / 1e9;
    133         outResult->appendFormat("%s  %02d:%p ", prefix.string(), current->mSlot,
    134                                 current->mGraphicBuffer.get());
    135         outResult->appendFormat("crop=[%d,%d,%d,%d] ", current->mCrop.left, current->mCrop.top,
    136                                 current->mCrop.right, current->mCrop.bottom);
    137         outResult->appendFormat("xform=0x%02x time=%.4f scale=%s\n", current->mTransform, timestamp,
    138                                 BufferItem::scalingModeName(current->mScalingMode));
    139         ++current;
    140     }
    141 
    142     outResult->appendFormat("%sSlots:\n", prefix.string());
    143     for (int s : mActiveBuffers) {
    144         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
    145         // A dequeued buffer might be null if it's still being allocated
    146         if (buffer.get()) {
    147             outResult->appendFormat("%s %s[%02d:%p] ", prefix.string(),
    148                                     (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
    149                                     buffer.get());
    150             outResult->appendFormat("state=%-8s %p frame=%" PRIu64, mSlots[s].mBufferState.string(),
    151                                     buffer->handle, mSlots[s].mFrameNumber);
    152             outResult->appendFormat(" [%4ux%4u:%4u,%3X]\n", buffer->width, buffer->height,
    153                                     buffer->stride, buffer->format);
    154         } else {
    155             outResult->appendFormat("%s  [%02d:%p] ", prefix.string(), s, buffer.get());
    156             outResult->appendFormat("state=%-8s frame=%" PRIu64 "\n",
    157                                     mSlots[s].mBufferState.string(), mSlots[s].mFrameNumber);
    158         }
    159     }
    160     for (int s : mFreeBuffers) {
    161         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
    162         outResult->appendFormat("%s  [%02d:%p] ", prefix.string(), s, buffer.get());
    163         outResult->appendFormat("state=%-8s %p frame=%" PRIu64, mSlots[s].mBufferState.string(),
    164                                 buffer->handle, mSlots[s].mFrameNumber);
    165         outResult->appendFormat(" [%4ux%4u:%4u,%3X]\n", buffer->width, buffer->height,
    166                                 buffer->stride, buffer->format);
    167     }
    168 
    169     for (int s : mFreeSlots) {
    170         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
    171         outResult->appendFormat("%s  [%02d:%p] state=%-8s\n", prefix.string(), s, buffer.get(),
    172                                 mSlots[s].mBufferState.string());
    173     }
    174 }
    175 
    176 int BufferQueueCore::getMinUndequeuedBufferCountLocked() const {
    177     // If dequeueBuffer is allowed to error out, we don't have to add an
    178     // extra buffer.
    179     if (mAsyncMode || mDequeueBufferCannotBlock) {
    180         return mMaxAcquiredBufferCount + 1;
    181     }
    182 
    183     return mMaxAcquiredBufferCount;
    184 }
    185 
    186 int BufferQueueCore::getMinMaxBufferCountLocked() const {
    187     return getMinUndequeuedBufferCountLocked() + 1;
    188 }
    189 
    190 int BufferQueueCore::getMaxBufferCountLocked(bool asyncMode,
    191         bool dequeueBufferCannotBlock, int maxBufferCount) const {
    192     int maxCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
    193             ((asyncMode || dequeueBufferCannotBlock) ? 1 : 0);
    194     maxCount = std::min(maxBufferCount, maxCount);
    195     return maxCount;
    196 }
    197 
    198 int BufferQueueCore::getMaxBufferCountLocked() const {
    199     int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
    200             ((mAsyncMode || mDequeueBufferCannotBlock) ? 1 : 0);
    201 
    202     // limit maxBufferCount by mMaxBufferCount always
    203     maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);
    204 
    205     return maxBufferCount;
    206 }
    207 
    208 void BufferQueueCore::clearBufferSlotLocked(int slot) {
    209     BQ_LOGV("clearBufferSlotLocked: slot %d", slot);
    210 
    211     mSlots[slot].mGraphicBuffer.clear();
    212     mSlots[slot].mBufferState.reset();
    213     mSlots[slot].mRequestBufferCalled = false;
    214     mSlots[slot].mFrameNumber = 0;
    215     mSlots[slot].mAcquireCalled = false;
    216     mSlots[slot].mNeedsReallocation = true;
    217 
    218     // Destroy fence as BufferQueue now takes ownership
    219     if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) {
    220         eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence);
    221         mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
    222     }
    223     mSlots[slot].mFence = Fence::NO_FENCE;
    224     mSlots[slot].mEglDisplay = EGL_NO_DISPLAY;
    225 
    226     if (mLastQueuedSlot == slot) {
    227         mLastQueuedSlot = INVALID_BUFFER_SLOT;
    228     }
    229 }
    230 
    231 void BufferQueueCore::freeAllBuffersLocked() {
    232     for (int s : mFreeSlots) {
    233         clearBufferSlotLocked(s);
    234     }
    235 
    236     for (int s : mFreeBuffers) {
    237         mFreeSlots.insert(s);
    238         clearBufferSlotLocked(s);
    239     }
    240     mFreeBuffers.clear();
    241 
    242     for (int s : mActiveBuffers) {
    243         mFreeSlots.insert(s);
    244         clearBufferSlotLocked(s);
    245     }
    246     mActiveBuffers.clear();
    247 
    248     for (auto& b : mQueue) {
    249         b.mIsStale = true;
    250 
    251         // We set this to false to force the BufferQueue to resend the buffer
    252         // handle upon acquire, since if we're here due to a producer
    253         // disconnect, the consumer will have been told to purge its cache of
    254         // slot-to-buffer-handle mappings and will not be able to otherwise
    255         // obtain a valid buffer handle.
    256         b.mAcquireCalled = false;
    257     }
    258 
    259     VALIDATE_CONSISTENCY();
    260 }
    261 
    262 void BufferQueueCore::discardFreeBuffersLocked() {
    263     for (int s : mFreeBuffers) {
    264         mFreeSlots.insert(s);
    265         clearBufferSlotLocked(s);
    266     }
    267     mFreeBuffers.clear();
    268 
    269     VALIDATE_CONSISTENCY();
    270 }
    271 
    272 bool BufferQueueCore::adjustAvailableSlotsLocked(int delta) {
    273     if (delta >= 0) {
    274         // If we're going to fail, do so before modifying anything
    275         if (delta > static_cast<int>(mUnusedSlots.size())) {
    276             return false;
    277         }
    278         while (delta > 0) {
    279             if (mUnusedSlots.empty()) {
    280                 return false;
    281             }
    282             int slot = mUnusedSlots.back();
    283             mUnusedSlots.pop_back();
    284             mFreeSlots.insert(slot);
    285             delta--;
    286         }
    287     } else {
    288         // If we're going to fail, do so before modifying anything
    289         if (-delta > static_cast<int>(mFreeSlots.size() +
    290                 mFreeBuffers.size())) {
    291             return false;
    292         }
    293         while (delta < 0) {
    294             if (!mFreeSlots.empty()) {
    295                 auto slot = mFreeSlots.begin();
    296                 clearBufferSlotLocked(*slot);
    297                 mUnusedSlots.push_back(*slot);
    298                 mFreeSlots.erase(slot);
    299             } else if (!mFreeBuffers.empty()) {
    300                 int slot = mFreeBuffers.back();
    301                 clearBufferSlotLocked(slot);
    302                 mUnusedSlots.push_back(slot);
    303                 mFreeBuffers.pop_back();
    304             } else {
    305                 return false;
    306             }
    307             delta++;
    308         }
    309     }
    310     return true;
    311 }
    312 
    313 void BufferQueueCore::waitWhileAllocatingLocked(std::unique_lock<std::mutex>& lock) const {
    314     ATRACE_CALL();
    315     while (mIsAllocating) {
    316         mIsAllocatingCondition.wait(lock);
    317     }
    318 }
    319 
    320 #if DEBUG_ONLY_CODE
    321 void BufferQueueCore::validateConsistencyLocked() const {
    322     static const useconds_t PAUSE_TIME = 0;
    323     int allocatedSlots = 0;
    324     for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
    325         bool isInFreeSlots = mFreeSlots.count(slot) != 0;
    326         bool isInFreeBuffers =
    327                 std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) !=
    328                 mFreeBuffers.cend();
    329         bool isInActiveBuffers = mActiveBuffers.count(slot) != 0;
    330         bool isInUnusedSlots =
    331                 std::find(mUnusedSlots.cbegin(), mUnusedSlots.cend(), slot) !=
    332                 mUnusedSlots.cend();
    333 
    334         if (isInFreeSlots || isInFreeBuffers || isInActiveBuffers) {
    335             allocatedSlots++;
    336         }
    337 
    338         if (isInUnusedSlots) {
    339             if (isInFreeSlots) {
    340                 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeSlots", slot);
    341                 usleep(PAUSE_TIME);
    342             }
    343             if (isInFreeBuffers) {
    344                 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeBuffers", slot);
    345                 usleep(PAUSE_TIME);
    346             }
    347             if (isInActiveBuffers) {
    348                 BQ_LOGE("Slot %d is in mUnusedSlots and in mActiveBuffers",
    349                         slot);
    350                 usleep(PAUSE_TIME);
    351             }
    352             if (!mSlots[slot].mBufferState.isFree()) {
    353                 BQ_LOGE("Slot %d is in mUnusedSlots but is not FREE", slot);
    354                 usleep(PAUSE_TIME);
    355             }
    356             if (mSlots[slot].mGraphicBuffer != nullptr) {
    357                 BQ_LOGE("Slot %d is in mUnusedSluts but has an active buffer",
    358                         slot);
    359                 usleep(PAUSE_TIME);
    360             }
    361         } else if (isInFreeSlots) {
    362             if (isInUnusedSlots) {
    363                 BQ_LOGE("Slot %d is in mFreeSlots and in mUnusedSlots", slot);
    364                 usleep(PAUSE_TIME);
    365             }
    366             if (isInFreeBuffers) {
    367                 BQ_LOGE("Slot %d is in mFreeSlots and in mFreeBuffers", slot);
    368                 usleep(PAUSE_TIME);
    369             }
    370             if (isInActiveBuffers) {
    371                 BQ_LOGE("Slot %d is in mFreeSlots and in mActiveBuffers", slot);
    372                 usleep(PAUSE_TIME);
    373             }
    374             if (!mSlots[slot].mBufferState.isFree()) {
    375                 BQ_LOGE("Slot %d is in mFreeSlots but is not FREE", slot);
    376                 usleep(PAUSE_TIME);
    377             }
    378             if (mSlots[slot].mGraphicBuffer != nullptr) {
    379                 BQ_LOGE("Slot %d is in mFreeSlots but has a buffer",
    380                         slot);
    381                 usleep(PAUSE_TIME);
    382             }
    383         } else if (isInFreeBuffers) {
    384             if (isInUnusedSlots) {
    385                 BQ_LOGE("Slot %d is in mFreeBuffers and in mUnusedSlots", slot);
    386                 usleep(PAUSE_TIME);
    387             }
    388             if (isInFreeSlots) {
    389                 BQ_LOGE("Slot %d is in mFreeBuffers and in mFreeSlots", slot);
    390                 usleep(PAUSE_TIME);
    391             }
    392             if (isInActiveBuffers) {
    393                 BQ_LOGE("Slot %d is in mFreeBuffers and in mActiveBuffers",
    394                         slot);
    395                 usleep(PAUSE_TIME);
    396             }
    397             if (!mSlots[slot].mBufferState.isFree()) {
    398                 BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE", slot);
    399                 usleep(PAUSE_TIME);
    400             }
    401             if (mSlots[slot].mGraphicBuffer == nullptr) {
    402                 BQ_LOGE("Slot %d is in mFreeBuffers but has no buffer", slot);
    403                 usleep(PAUSE_TIME);
    404             }
    405         } else if (isInActiveBuffers) {
    406             if (isInUnusedSlots) {
    407                 BQ_LOGE("Slot %d is in mActiveBuffers and in mUnusedSlots",
    408                         slot);
    409                 usleep(PAUSE_TIME);
    410             }
    411             if (isInFreeSlots) {
    412                 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeSlots", slot);
    413                 usleep(PAUSE_TIME);
    414             }
    415             if (isInFreeBuffers) {
    416                 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeBuffers",
    417                         slot);
    418                 usleep(PAUSE_TIME);
    419             }
    420             if (mSlots[slot].mBufferState.isFree() &&
    421                     !mSlots[slot].mBufferState.isShared()) {
    422                 BQ_LOGE("Slot %d is in mActiveBuffers but is FREE", slot);
    423                 usleep(PAUSE_TIME);
    424             }
    425             if (mSlots[slot].mGraphicBuffer == nullptr && !mIsAllocating) {
    426                 BQ_LOGE("Slot %d is in mActiveBuffers but has no buffer", slot);
    427                 usleep(PAUSE_TIME);
    428             }
    429         } else {
    430             BQ_LOGE("Slot %d isn't in any of mUnusedSlots, mFreeSlots, "
    431                     "mFreeBuffers, or mActiveBuffers", slot);
    432             usleep(PAUSE_TIME);
    433         }
    434     }
    435 
    436     if (allocatedSlots != getMaxBufferCountLocked()) {
    437         BQ_LOGE("Number of allocated slots is incorrect. Allocated = %d, "
    438                 "Should be %d (%zu free slots, %zu free buffers, "
    439                 "%zu activeBuffers, %zu unusedSlots)", allocatedSlots,
    440                 getMaxBufferCountLocked(), mFreeSlots.size(),
    441                 mFreeBuffers.size(), mActiveBuffers.size(),
    442                 mUnusedSlots.size());
    443     }
    444 }
    445 #endif
    446 
    447 } // namespace android
    448