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