BufferQueueCore.cpp revision 3e96f1982fda358424b0b75f394cbf7c1794a072
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#include <gui/BufferItem.h> 24#include <gui/BufferQueueCore.h> 25#include <gui/IConsumerListener.h> 26#include <gui/IGraphicBufferAlloc.h> 27#include <gui/ISurfaceComposer.h> 28#include <private/gui/ComposerService.h> 29 30template <typename T> 31static inline T max(T a, T b) { return a > b ? a : b; } 32 33namespace android { 34 35static String8 getUniqueName() { 36 static volatile int32_t counter = 0; 37 return String8::format("unnamed-%d-%d", getpid(), 38 android_atomic_inc(&counter)); 39} 40 41BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) : 42 mAllocator(allocator), 43 mMutex(), 44 mIsAbandoned(false), 45 mConsumerControlledByApp(false), 46 mConsumerName(getUniqueName()), 47 mConsumerListener(), 48 mConsumerUsageBits(0), 49 mConnectedApi(NO_CONNECTED_API), 50 mConnectedProducerToken(), 51 mSlots(), 52 mQueue(), 53 mOverrideMaxBufferCount(0), 54 mDequeueCondition(), 55 mUseAsyncBuffer(true), 56 mDequeueBufferCannotBlock(false), 57 mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), 58 mDefaultWidth(1), 59 mDefaultHeight(1), 60 mDefaultMaxBufferCount(2), 61 mMaxAcquiredBufferCount(1), 62 mBufferHasBeenQueued(false), 63 mFrameCounter(0), 64 mTransformHint(0) 65{ 66 if (allocator == NULL) { 67 sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 68 mAllocator = composer->createGraphicBufferAlloc(); 69 if (mAllocator == NULL) { 70 BQ_LOGE("createGraphicBufferAlloc failed"); 71 } 72 } 73} 74 75BufferQueueCore::~BufferQueueCore() {} 76 77void BufferQueueCore::dump(String8& result, const char* prefix) const { 78 Mutex::Autolock lock(mMutex); 79 80 String8 fifo; 81 Fifo::const_iterator current(mQueue.begin()); 82 while (current != mQueue.end()) { 83 fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], " 84 "xform=0x%02x, time=%#llx, scale=%s\n", 85 current->mSlot, current->mGraphicBuffer.get(), 86 current->mCrop.left, current->mCrop.top, current->mCrop.right, 87 current->mCrop.bottom, current->mTransform, current->mTimestamp, 88 BufferItem::scalingModeName(current->mScalingMode)); 89 ++current; 90 } 91 92 result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, " 93 "mDequeueBufferCannotBlock=%d, default-size=[%dx%d], " 94 "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n", 95 prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, 96 mDefaultWidth, mDefaultHeight, mDefaultBufferFormat, mTransformHint, 97 mQueue.size(), fifo.string()); 98 99 // Trim the free buffers so as to not spam the dump 100 int maxBufferCount = 0; 101 for (int s = BufferQueueDefs::NUM_BUFFER_SLOTS - 1; s >= 0; --s) { 102 const BufferSlot& slot(mSlots[s]); 103 if (slot.mBufferState != BufferSlot::FREE || 104 slot.mGraphicBuffer != NULL) { 105 maxBufferCount = s + 1; 106 break; 107 } 108 } 109 110 for (int s = 0; s < maxBufferCount; ++s) { 111 const BufferSlot& slot(mSlots[s]); 112 const sp<GraphicBuffer>& buffer(slot.mGraphicBuffer); 113 result.appendFormat("%s%s[%02d:%p] state=%-8s", prefix, 114 (slot.mBufferState == BufferSlot::ACQUIRED) ? ">" : " ", 115 s, buffer.get(), 116 BufferSlot::bufferStateName(slot.mBufferState)); 117 118 if (buffer != NULL) { 119 result.appendFormat(", %p [%4ux%4u:%4u,%3X]", buffer->handle, 120 buffer->width, buffer->height, buffer->stride, 121 buffer->format); 122 } 123 124 result.append("\n"); 125 } 126} 127 128int BufferQueueCore::getMinUndequeuedBufferCountLocked(bool async) const { 129 // If dequeueBuffer is allowed to error out, we don't have to add an 130 // extra buffer. 131 if (!mUseAsyncBuffer) { 132 return mMaxAcquiredBufferCount; 133 } 134 135 if (mDequeueBufferCannotBlock || async) { 136 return mMaxAcquiredBufferCount + 1; 137 } 138 139 return mMaxAcquiredBufferCount; 140} 141 142int BufferQueueCore::getMinMaxBufferCountLocked(bool async) const { 143 return getMinUndequeuedBufferCountLocked(async) + 1; 144} 145 146int BufferQueueCore::getMaxBufferCountLocked(bool async) const { 147 int minMaxBufferCount = getMinMaxBufferCountLocked(async); 148 149 int maxBufferCount = max(mDefaultMaxBufferCount, minMaxBufferCount); 150 if (mOverrideMaxBufferCount != 0) { 151 assert(mOverrideMaxBufferCount >= minMaxBufferCount); 152 maxBufferCount = mOverrideMaxBufferCount; 153 } 154 155 // Any buffers that are dequeued by the producer or sitting in the queue 156 // waiting to be consumed need to have their slots preserved. Such buffers 157 // will temporarily keep the max buffer count up until the slots no longer 158 // need to be preserved. 159 for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 160 BufferSlot::BufferState state = mSlots[s].mBufferState; 161 if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) { 162 maxBufferCount = s + 1; 163 } 164 } 165 166 return maxBufferCount; 167} 168 169status_t BufferQueueCore::setDefaultMaxBufferCountLocked(int count) { 170 const int minBufferCount = mUseAsyncBuffer ? 2 : 1; 171 if (count < minBufferCount || count > BufferQueueDefs::NUM_BUFFER_SLOTS) { 172 BQ_LOGV("setDefaultMaxBufferCount: invalid count %d, should be in " 173 "[%d, %d]", minBufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS); 174 return BAD_VALUE; 175 } 176 177 BQ_LOGV("setDefaultMaxBufferCount: setting count to %d", count); 178 mDefaultMaxBufferCount = count; 179 mDequeueCondition.broadcast(); 180 181 return NO_ERROR; 182} 183 184void BufferQueueCore::freeBufferLocked(int slot) { 185 BQ_LOGV("freeBufferLocked: slot %d", slot); 186 mSlots[slot].mGraphicBuffer.clear(); 187 if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) { 188 mSlots[slot].mNeedsCleanupOnRelease = true; 189 } 190 mSlots[slot].mBufferState = BufferSlot::FREE; 191 mSlots[slot].mFrameNumber = 0; 192 mSlots[slot].mAcquireCalled = false; 193 194 // Destroy fence as BufferQueue now takes ownership 195 if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) { 196 eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence); 197 mSlots[slot].mEglFence = EGL_NO_SYNC_KHR; 198 } 199 mSlots[slot].mFence = Fence::NO_FENCE; 200} 201 202void BufferQueueCore::freeAllBuffersLocked() { 203 mBufferHasBeenQueued = false; 204 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 205 freeBufferLocked(s); 206 } 207} 208 209bool BufferQueueCore::stillTracking(const BufferItem* item) const { 210 const BufferSlot& slot = mSlots[item->mSlot]; 211 212 BQ_LOGV("stillTracking: item { slot=%d/%llu buffer=%p } " 213 "slot { slot=%d/%llu buffer=%p }", 214 item->mSlot, item->mFrameNumber, 215 (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0), 216 item->mSlot, slot.mFrameNumber, 217 (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0)); 218 219 // Compare item with its original buffer slot. We can check the slot as 220 // the buffer would not be moved to a different slot by the producer. 221 return (slot.mGraphicBuffer != NULL) && 222 (item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle); 223} 224 225} // namespace android 226