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 <gui/BufferItem.h>
     32 #include <gui/BufferQueueCore.h>
     33 #include <gui/IConsumerListener.h>
     34 #include <gui/IGraphicBufferAlloc.h>
     35 #include <gui/IProducerListener.h>
     36 #include <gui/ISurfaceComposer.h>
     37 #include <private/gui/ComposerService.h>
     38 
     39 namespace android {
     40 
     41 static String8 getUniqueName() {
     42     static volatile int32_t counter = 0;
     43     return String8::format("unnamed-%d-%d", getpid(),
     44             android_atomic_inc(&counter));
     45 }
     46 
     47 static uint64_t getUniqueId() {
     48     static std::atomic<uint32_t> counter{0};
     49     static uint64_t id = static_cast<uint64_t>(getpid()) << 32;
     50     return id | counter++;
     51 }
     52 
     53 BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
     54     mAllocator(allocator),
     55     mMutex(),
     56     mIsAbandoned(false),
     57     mConsumerControlledByApp(false),
     58     mConsumerName(getUniqueName()),
     59     mConsumerListener(),
     60     mConsumerUsageBits(0),
     61     mConnectedApi(NO_CONNECTED_API),
     62     mConnectedProducerListener(),
     63     mSlots(),
     64     mQueue(),
     65     mFreeSlots(),
     66     mFreeBuffers(),
     67     mUnusedSlots(),
     68     mActiveBuffers(),
     69     mDequeueCondition(),
     70     mDequeueBufferCannotBlock(false),
     71     mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
     72     mDefaultWidth(1),
     73     mDefaultHeight(1),
     74     mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
     75     mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
     76     mMaxAcquiredBufferCount(1),
     77     mMaxDequeuedBufferCount(1),
     78     mBufferHasBeenQueued(false),
     79     mFrameCounter(0),
     80     mTransformHint(0),
     81     mIsAllocating(false),
     82     mIsAllocatingCondition(),
     83     mAllowAllocation(true),
     84     mBufferAge(0),
     85     mGenerationNumber(0),
     86     mAsyncMode(false),
     87     mSharedBufferMode(false),
     88     mAutoRefresh(false),
     89     mSharedBufferSlot(INVALID_BUFFER_SLOT),
     90     mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
     91             HAL_DATASPACE_UNKNOWN),
     92     mUniqueId(getUniqueId())
     93 {
     94     if (allocator == NULL) {
     95         sp<ISurfaceComposer> composer(ComposerService::getComposerService());
     96         mAllocator = composer->createGraphicBufferAlloc();
     97         if (mAllocator == NULL) {
     98             BQ_LOGE("createGraphicBufferAlloc failed");
     99         }
    100     }
    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::dump(String8& result, const char* prefix) const {
    115     Mutex::Autolock lock(mMutex);
    116 
    117     String8 fifo;
    118     Fifo::const_iterator current(mQueue.begin());
    119     while (current != mQueue.end()) {
    120         fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
    121                 "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n",
    122                 current->mSlot, current->mGraphicBuffer.get(),
    123                 current->mCrop.left, current->mCrop.top, current->mCrop.right,
    124                 current->mCrop.bottom, current->mTransform, current->mTimestamp,
    125                 BufferItem::scalingModeName(current->mScalingMode));
    126         ++current;
    127     }
    128 
    129     result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
    130             "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d "
    131             "mAsyncMode=%d, default-size=[%dx%d], default-format=%d, "
    132             "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix,
    133             mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
    134             mDequeueBufferCannotBlock, mAsyncMode, mDefaultWidth,
    135             mDefaultHeight, mDefaultBufferFormat, mTransformHint, mQueue.size(),
    136             fifo.string());
    137 
    138     for (int s : mActiveBuffers) {
    139         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
    140         // A dequeued buffer might be null if it's still being allocated
    141         if (buffer.get()) {
    142             result.appendFormat("%s%s[%02d:%p] state=%-8s, %p "
    143                     "[%4ux%4u:%4u,%3X]\n", prefix,
    144                     (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
    145                     buffer.get(), mSlots[s].mBufferState.string(),
    146                     buffer->handle, buffer->width, buffer->height,
    147                     buffer->stride, buffer->format);
    148         } else {
    149             result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
    150                     buffer.get(), mSlots[s].mBufferState.string());
    151         }
    152     }
    153     for (int s : mFreeBuffers) {
    154         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
    155         result.appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
    156                 prefix, s, buffer.get(), mSlots[s].mBufferState.string(),
    157                 buffer->handle, buffer->width, buffer->height, buffer->stride,
    158                 buffer->format);
    159     }
    160 
    161     for (int s : mFreeSlots) {
    162         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
    163         result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
    164                 buffer.get(), mSlots[s].mBufferState.string());
    165     }
    166 }
    167 
    168 int BufferQueueCore::getMinUndequeuedBufferCountLocked() const {
    169     // If dequeueBuffer is allowed to error out, we don't have to add an
    170     // extra buffer.
    171     if (mAsyncMode || mDequeueBufferCannotBlock) {
    172         return mMaxAcquiredBufferCount + 1;
    173     }
    174 
    175     return mMaxAcquiredBufferCount;
    176 }
    177 
    178 int BufferQueueCore::getMinMaxBufferCountLocked() const {
    179     return getMinUndequeuedBufferCountLocked() + 1;
    180 }
    181 
    182 int BufferQueueCore::getMaxBufferCountLocked(bool asyncMode,
    183         bool dequeueBufferCannotBlock, int maxBufferCount) const {
    184     int maxCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
    185             ((asyncMode || dequeueBufferCannotBlock) ? 1 : 0);
    186     maxCount = std::min(maxBufferCount, maxCount);
    187     return maxCount;
    188 }
    189 
    190 int BufferQueueCore::getMaxBufferCountLocked() const {
    191     int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
    192             ((mAsyncMode || mDequeueBufferCannotBlock) ? 1 : 0);
    193 
    194     // limit maxBufferCount by mMaxBufferCount always
    195     maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);
    196 
    197     return maxBufferCount;
    198 }
    199 
    200 void BufferQueueCore::clearBufferSlotLocked(int slot) {
    201     BQ_LOGV("clearBufferSlotLocked: slot %d", slot);
    202 
    203     mSlots[slot].mGraphicBuffer.clear();
    204     mSlots[slot].mBufferState.reset();
    205     mSlots[slot].mRequestBufferCalled = false;
    206     mSlots[slot].mFrameNumber = 0;
    207     mSlots[slot].mAcquireCalled = false;
    208     mSlots[slot].mNeedsReallocation = true;
    209 
    210     // Destroy fence as BufferQueue now takes ownership
    211     if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) {
    212         eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence);
    213         mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
    214     }
    215     mSlots[slot].mFence = Fence::NO_FENCE;
    216     mSlots[slot].mEglDisplay = EGL_NO_DISPLAY;
    217 
    218     if (mLastQueuedSlot == slot) {
    219         mLastQueuedSlot = INVALID_BUFFER_SLOT;
    220     }
    221 }
    222 
    223 void BufferQueueCore::freeAllBuffersLocked() {
    224     for (int s : mFreeSlots) {
    225         clearBufferSlotLocked(s);
    226     }
    227 
    228     for (int s : mFreeBuffers) {
    229         mFreeSlots.insert(s);
    230         clearBufferSlotLocked(s);
    231     }
    232     mFreeBuffers.clear();
    233 
    234     for (int s : mActiveBuffers) {
    235         mFreeSlots.insert(s);
    236         clearBufferSlotLocked(s);
    237     }
    238     mActiveBuffers.clear();
    239 
    240     for (auto& b : mQueue) {
    241         b.mIsStale = true;
    242     }
    243 
    244     VALIDATE_CONSISTENCY();
    245 }
    246 
    247 void BufferQueueCore::discardFreeBuffersLocked() {
    248     for (int s : mFreeBuffers) {
    249         mFreeSlots.insert(s);
    250         clearBufferSlotLocked(s);
    251     }
    252     mFreeBuffers.clear();
    253 
    254     VALIDATE_CONSISTENCY();
    255 }
    256 
    257 bool BufferQueueCore::adjustAvailableSlotsLocked(int delta) {
    258     if (delta >= 0) {
    259         // If we're going to fail, do so before modifying anything
    260         if (delta > static_cast<int>(mUnusedSlots.size())) {
    261             return false;
    262         }
    263         while (delta > 0) {
    264             if (mUnusedSlots.empty()) {
    265                 return false;
    266             }
    267             int slot = mUnusedSlots.back();
    268             mUnusedSlots.pop_back();
    269             mFreeSlots.insert(slot);
    270             delta--;
    271         }
    272     } else {
    273         // If we're going to fail, do so before modifying anything
    274         if (-delta > static_cast<int>(mFreeSlots.size() +
    275                 mFreeBuffers.size())) {
    276             return false;
    277         }
    278         while (delta < 0) {
    279             if (!mFreeSlots.empty()) {
    280                 auto slot = mFreeSlots.begin();
    281                 clearBufferSlotLocked(*slot);
    282                 mUnusedSlots.push_back(*slot);
    283                 mFreeSlots.erase(slot);
    284             } else if (!mFreeBuffers.empty()) {
    285                 int slot = mFreeBuffers.back();
    286                 clearBufferSlotLocked(slot);
    287                 mUnusedSlots.push_back(slot);
    288                 mFreeBuffers.pop_back();
    289             } else {
    290                 return false;
    291             }
    292             delta++;
    293         }
    294     }
    295     return true;
    296 }
    297 
    298 void BufferQueueCore::waitWhileAllocatingLocked() const {
    299     ATRACE_CALL();
    300     while (mIsAllocating) {
    301         mIsAllocatingCondition.wait(mMutex);
    302     }
    303 }
    304 
    305 #if DEBUG_ONLY_CODE
    306 void BufferQueueCore::validateConsistencyLocked() const {
    307     static const useconds_t PAUSE_TIME = 0;
    308     int allocatedSlots = 0;
    309     for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
    310         bool isInFreeSlots = mFreeSlots.count(slot) != 0;
    311         bool isInFreeBuffers =
    312                 std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) !=
    313                 mFreeBuffers.cend();
    314         bool isInActiveBuffers = mActiveBuffers.count(slot) != 0;
    315         bool isInUnusedSlots =
    316                 std::find(mUnusedSlots.cbegin(), mUnusedSlots.cend(), slot) !=
    317                 mUnusedSlots.cend();
    318 
    319         if (isInFreeSlots || isInFreeBuffers || isInActiveBuffers) {
    320             allocatedSlots++;
    321         }
    322 
    323         if (isInUnusedSlots) {
    324             if (isInFreeSlots) {
    325                 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeSlots", slot);
    326                 usleep(PAUSE_TIME);
    327             }
    328             if (isInFreeBuffers) {
    329                 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeBuffers", slot);
    330                 usleep(PAUSE_TIME);
    331             }
    332             if (isInActiveBuffers) {
    333                 BQ_LOGE("Slot %d is in mUnusedSlots and in mActiveBuffers",
    334                         slot);
    335                 usleep(PAUSE_TIME);
    336             }
    337             if (!mSlots[slot].mBufferState.isFree()) {
    338                 BQ_LOGE("Slot %d is in mUnusedSlots but is not FREE", slot);
    339                 usleep(PAUSE_TIME);
    340             }
    341             if (mSlots[slot].mGraphicBuffer != NULL) {
    342                 BQ_LOGE("Slot %d is in mUnusedSluts but has an active buffer",
    343                         slot);
    344                 usleep(PAUSE_TIME);
    345             }
    346         } else if (isInFreeSlots) {
    347             if (isInUnusedSlots) {
    348                 BQ_LOGE("Slot %d is in mFreeSlots and in mUnusedSlots", slot);
    349                 usleep(PAUSE_TIME);
    350             }
    351             if (isInFreeBuffers) {
    352                 BQ_LOGE("Slot %d is in mFreeSlots and in mFreeBuffers", slot);
    353                 usleep(PAUSE_TIME);
    354             }
    355             if (isInActiveBuffers) {
    356                 BQ_LOGE("Slot %d is in mFreeSlots and in mActiveBuffers", slot);
    357                 usleep(PAUSE_TIME);
    358             }
    359             if (!mSlots[slot].mBufferState.isFree()) {
    360                 BQ_LOGE("Slot %d is in mFreeSlots but is not FREE", slot);
    361                 usleep(PAUSE_TIME);
    362             }
    363             if (mSlots[slot].mGraphicBuffer != NULL) {
    364                 BQ_LOGE("Slot %d is in mFreeSlots but has a buffer",
    365                         slot);
    366                 usleep(PAUSE_TIME);
    367             }
    368         } else if (isInFreeBuffers) {
    369             if (isInUnusedSlots) {
    370                 BQ_LOGE("Slot %d is in mFreeBuffers and in mUnusedSlots", slot);
    371                 usleep(PAUSE_TIME);
    372             }
    373             if (isInFreeSlots) {
    374                 BQ_LOGE("Slot %d is in mFreeBuffers and in mFreeSlots", slot);
    375                 usleep(PAUSE_TIME);
    376             }
    377             if (isInActiveBuffers) {
    378                 BQ_LOGE("Slot %d is in mFreeBuffers and in mActiveBuffers",
    379                         slot);
    380                 usleep(PAUSE_TIME);
    381             }
    382             if (!mSlots[slot].mBufferState.isFree()) {
    383                 BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE", slot);
    384                 usleep(PAUSE_TIME);
    385             }
    386             if (mSlots[slot].mGraphicBuffer == NULL) {
    387                 BQ_LOGE("Slot %d is in mFreeBuffers but has no buffer", slot);
    388                 usleep(PAUSE_TIME);
    389             }
    390         } else if (isInActiveBuffers) {
    391             if (isInUnusedSlots) {
    392                 BQ_LOGE("Slot %d is in mActiveBuffers and in mUnusedSlots",
    393                         slot);
    394                 usleep(PAUSE_TIME);
    395             }
    396             if (isInFreeSlots) {
    397                 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeSlots", slot);
    398                 usleep(PAUSE_TIME);
    399             }
    400             if (isInFreeBuffers) {
    401                 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeBuffers",
    402                         slot);
    403                 usleep(PAUSE_TIME);
    404             }
    405             if (mSlots[slot].mBufferState.isFree() &&
    406                     !mSlots[slot].mBufferState.isShared()) {
    407                 BQ_LOGE("Slot %d is in mActiveBuffers but is FREE", slot);
    408                 usleep(PAUSE_TIME);
    409             }
    410             if (mSlots[slot].mGraphicBuffer == NULL && !mIsAllocating) {
    411                 BQ_LOGE("Slot %d is in mActiveBuffers but has no buffer", slot);
    412                 usleep(PAUSE_TIME);
    413             }
    414         } else {
    415             BQ_LOGE("Slot %d isn't in any of mUnusedSlots, mFreeSlots, "
    416                     "mFreeBuffers, or mActiveBuffers", slot);
    417             usleep(PAUSE_TIME);
    418         }
    419     }
    420 
    421     if (allocatedSlots != getMaxBufferCountLocked()) {
    422         BQ_LOGE("Number of allocated slots is incorrect. Allocated = %d, "
    423                 "Should be %d (%zu free slots, %zu free buffers, "
    424                 "%zu activeBuffers, %zu unusedSlots)", allocatedSlots,
    425                 getMaxBufferCountLocked(), mFreeSlots.size(),
    426                 mFreeBuffers.size(), mActiveBuffers.size(),
    427                 mUnusedSlots.size());
    428     }
    429 }
    430 #endif
    431 
    432 } // namespace android
    433