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 mFreeSlots(), 57 mFreeBuffers(), 58 mOverrideMaxBufferCount(0), 59 mDequeueCondition(), 60 mUseAsyncBuffer(true), 61 mDequeueBufferCannotBlock(false), 62 mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), 63 mDefaultWidth(1), 64 mDefaultHeight(1), 65 mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN), 66 mDefaultMaxBufferCount(2), 67 mMaxAcquiredBufferCount(1), 68 mBufferHasBeenQueued(false), 69 mFrameCounter(0), 70 mTransformHint(0), 71 mIsAllocating(false), 72 mIsAllocatingCondition(), 73 mAllowAllocation(true), 74 mBufferAge(0), 75 mGenerationNumber(0) 76 { 77 if (allocator == NULL) { 78 sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 79 mAllocator = composer->createGraphicBufferAlloc(); 80 if (mAllocator == NULL) { 81 BQ_LOGE("createGraphicBufferAlloc failed"); 82 } 83 } 84 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { 85 mFreeSlots.insert(slot); 86 } 87 } 88 89 BufferQueueCore::~BufferQueueCore() {} 90 91 void BufferQueueCore::dump(String8& result, const char* prefix) const { 92 Mutex::Autolock lock(mMutex); 93 94 String8 fifo; 95 Fifo::const_iterator current(mQueue.begin()); 96 while (current != mQueue.end()) { 97 fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], " 98 "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n", 99 current->mSlot, current->mGraphicBuffer.get(), 100 current->mCrop.left, current->mCrop.top, current->mCrop.right, 101 current->mCrop.bottom, current->mTransform, current->mTimestamp, 102 BufferItem::scalingModeName(current->mScalingMode)); 103 ++current; 104 } 105 106 result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, " 107 "mDequeueBufferCannotBlock=%d, default-size=[%dx%d], " 108 "default-format=%d, transform-hint=%02x, FIFO(%zu)={%s}\n", 109 prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, 110 mDefaultWidth, mDefaultHeight, mDefaultBufferFormat, mTransformHint, 111 mQueue.size(), fifo.string()); 112 113 // Trim the free buffers so as to not spam the dump 114 int maxBufferCount = 0; 115 for (int s = BufferQueueDefs::NUM_BUFFER_SLOTS - 1; s >= 0; --s) { 116 const BufferSlot& slot(mSlots[s]); 117 if (slot.mBufferState != BufferSlot::FREE || 118 slot.mGraphicBuffer != NULL) { 119 maxBufferCount = s + 1; 120 break; 121 } 122 } 123 124 for (int s = 0; s < maxBufferCount; ++s) { 125 const BufferSlot& slot(mSlots[s]); 126 const sp<GraphicBuffer>& buffer(slot.mGraphicBuffer); 127 result.appendFormat("%s%s[%02d:%p] state=%-8s", prefix, 128 (slot.mBufferState == BufferSlot::ACQUIRED) ? ">" : " ", 129 s, buffer.get(), 130 BufferSlot::bufferStateName(slot.mBufferState)); 131 132 if (buffer != NULL) { 133 result.appendFormat(", %p [%4ux%4u:%4u,%3X]", buffer->handle, 134 buffer->width, buffer->height, buffer->stride, 135 buffer->format); 136 } 137 138 result.append("\n"); 139 } 140 } 141 142 int BufferQueueCore::getMinUndequeuedBufferCountLocked(bool async) const { 143 // If dequeueBuffer is allowed to error out, we don't have to add an 144 // extra buffer. 145 if (!mUseAsyncBuffer) { 146 return mMaxAcquiredBufferCount; 147 } 148 149 if (mDequeueBufferCannotBlock || async) { 150 return mMaxAcquiredBufferCount + 1; 151 } 152 153 return mMaxAcquiredBufferCount; 154 } 155 156 int BufferQueueCore::getMinMaxBufferCountLocked(bool async) const { 157 return getMinUndequeuedBufferCountLocked(async) + 1; 158 } 159 160 int BufferQueueCore::getMaxBufferCountLocked(bool async) const { 161 int minMaxBufferCount = getMinMaxBufferCountLocked(async); 162 163 int maxBufferCount = max(mDefaultMaxBufferCount, minMaxBufferCount); 164 if (mOverrideMaxBufferCount != 0) { 165 assert(mOverrideMaxBufferCount >= minMaxBufferCount); 166 maxBufferCount = mOverrideMaxBufferCount; 167 } 168 169 // Any buffers that are dequeued by the producer or sitting in the queue 170 // waiting to be consumed need to have their slots preserved. Such buffers 171 // will temporarily keep the max buffer count up until the slots no longer 172 // need to be preserved. 173 for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 174 BufferSlot::BufferState state = mSlots[s].mBufferState; 175 if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) { 176 maxBufferCount = s + 1; 177 } 178 } 179 180 return maxBufferCount; 181 } 182 183 status_t BufferQueueCore::setDefaultMaxBufferCountLocked(int count) { 184 const int minBufferCount = mUseAsyncBuffer ? 2 : 1; 185 if (count < minBufferCount || count > BufferQueueDefs::NUM_BUFFER_SLOTS) { 186 BQ_LOGV("setDefaultMaxBufferCount: invalid count %d, should be in " 187 "[%d, %d]", 188 count, minBufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS); 189 return BAD_VALUE; 190 } 191 192 BQ_LOGV("setDefaultMaxBufferCount: setting count to %d", count); 193 mDefaultMaxBufferCount = count; 194 mDequeueCondition.broadcast(); 195 196 return NO_ERROR; 197 } 198 199 void BufferQueueCore::freeBufferLocked(int slot) { 200 BQ_LOGV("freeBufferLocked: slot %d", slot); 201 bool hadBuffer = mSlots[slot].mGraphicBuffer != NULL; 202 mSlots[slot].mGraphicBuffer.clear(); 203 if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) { 204 mSlots[slot].mNeedsCleanupOnRelease = true; 205 } 206 if (mSlots[slot].mBufferState != BufferSlot::FREE) { 207 mFreeSlots.insert(slot); 208 } else if (hadBuffer) { 209 // If the slot was FREE, but we had a buffer, we need to move this slot 210 // from the free buffers list to the the free slots list 211 mFreeBuffers.remove(slot); 212 mFreeSlots.insert(slot); 213 } 214 mSlots[slot].mBufferState = BufferSlot::FREE; 215 mSlots[slot].mAcquireCalled = false; 216 mSlots[slot].mFrameNumber = 0; 217 218 // Destroy fence as BufferQueue now takes ownership 219 if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) { 220 eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence); 221 mSlots[slot].mEglFence = EGL_NO_SYNC_KHR; 222 } 223 mSlots[slot].mFence = Fence::NO_FENCE; 224 validateConsistencyLocked(); 225 } 226 227 void BufferQueueCore::freeAllBuffersLocked() { 228 mBufferHasBeenQueued = false; 229 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 230 freeBufferLocked(s); 231 } 232 } 233 234 bool BufferQueueCore::stillTracking(const BufferItem* item) const { 235 const BufferSlot& slot = mSlots[item->mSlot]; 236 237 BQ_LOGV("stillTracking: item { slot=%d/%" PRIu64 " buffer=%p } " 238 "slot { slot=%d/%" PRIu64 " buffer=%p }", 239 item->mSlot, item->mFrameNumber, 240 (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0), 241 item->mSlot, slot.mFrameNumber, 242 (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0)); 243 244 // Compare item with its original buffer slot. We can check the slot as 245 // the buffer would not be moved to a different slot by the producer. 246 return (slot.mGraphicBuffer != NULL) && 247 (item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle); 248 } 249 250 void BufferQueueCore::waitWhileAllocatingLocked() const { 251 ATRACE_CALL(); 252 while (mIsAllocating) { 253 mIsAllocatingCondition.wait(mMutex); 254 } 255 } 256 257 void BufferQueueCore::validateConsistencyLocked() const { 258 static const useconds_t PAUSE_TIME = 0; 259 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { 260 bool isInFreeSlots = mFreeSlots.count(slot) != 0; 261 bool isInFreeBuffers = 262 std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) != 263 mFreeBuffers.cend(); 264 if (mSlots[slot].mBufferState == BufferSlot::FREE) { 265 if (mSlots[slot].mGraphicBuffer == NULL) { 266 if (!isInFreeSlots) { 267 BQ_LOGE("Slot %d is FREE but is not in mFreeSlots", slot); 268 usleep(PAUSE_TIME); 269 } 270 if (isInFreeBuffers) { 271 BQ_LOGE("Slot %d is in mFreeSlots " 272 "but is also in mFreeBuffers", slot); 273 usleep(PAUSE_TIME); 274 } 275 } else { 276 if (!isInFreeBuffers) { 277 BQ_LOGE("Slot %d is FREE but is not in mFreeBuffers", slot); 278 usleep(PAUSE_TIME); 279 } 280 if (isInFreeSlots) { 281 BQ_LOGE("Slot %d is in mFreeBuffers " 282 "but is also in mFreeSlots", slot); 283 usleep(PAUSE_TIME); 284 } 285 } 286 } else { 287 if (isInFreeSlots) { 288 BQ_LOGE("Slot %d is in mFreeSlots but is not FREE (%d)", 289 slot, mSlots[slot].mBufferState); 290 usleep(PAUSE_TIME); 291 } 292 if (isInFreeBuffers) { 293 BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE (%d)", 294 slot, mSlots[slot].mBufferState); 295 usleep(PAUSE_TIME); 296 } 297 } 298 } 299 } 300 301 } // namespace android 302