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