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