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