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#if DEBUG_ONLY_CODE 24#define VALIDATE_CONSISTENCY() do { validateConsistencyLocked(); } while (0) 25#else 26#define VALIDATE_CONSISTENCY() 27#endif 28 29#include <inttypes.h> 30 31#include <gui/BufferItem.h> 32#include <gui/BufferQueueCore.h> 33#include <gui/IConsumerListener.h> 34#include <gui/IGraphicBufferAlloc.h> 35#include <gui/IProducerListener.h> 36#include <gui/ISurfaceComposer.h> 37#include <private/gui/ComposerService.h> 38 39namespace android { 40 41static String8 getUniqueName() { 42 static volatile int32_t counter = 0; 43 return String8::format("unnamed-%d-%d", getpid(), 44 android_atomic_inc(&counter)); 45} 46 47static uint64_t getUniqueId() { 48 static std::atomic<uint32_t> counter{0}; 49 static uint64_t id = static_cast<uint64_t>(getpid()) << 32; 50 return id | counter++; 51} 52 53BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) : 54 mAllocator(allocator), 55 mMutex(), 56 mIsAbandoned(false), 57 mConsumerControlledByApp(false), 58 mConsumerName(getUniqueName()), 59 mConsumerListener(), 60 mConsumerUsageBits(0), 61 mConnectedApi(NO_CONNECTED_API), 62 mConnectedProducerListener(), 63 mSlots(), 64 mQueue(), 65 mFreeSlots(), 66 mFreeBuffers(), 67 mUnusedSlots(), 68 mActiveBuffers(), 69 mDequeueCondition(), 70 mDequeueBufferCannotBlock(false), 71 mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), 72 mDefaultWidth(1), 73 mDefaultHeight(1), 74 mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN), 75 mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS), 76 mMaxAcquiredBufferCount(1), 77 mMaxDequeuedBufferCount(1), 78 mBufferHasBeenQueued(false), 79 mFrameCounter(0), 80 mTransformHint(0), 81 mIsAllocating(false), 82 mIsAllocatingCondition(), 83 mAllowAllocation(true), 84 mBufferAge(0), 85 mGenerationNumber(0), 86 mAsyncMode(false), 87 mSharedBufferMode(false), 88 mAutoRefresh(false), 89 mSharedBufferSlot(INVALID_BUFFER_SLOT), 90 mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE, 91 HAL_DATASPACE_UNKNOWN), 92 mUniqueId(getUniqueId()) 93{ 94 if (allocator == NULL) { 95 sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 96 mAllocator = composer->createGraphicBufferAlloc(); 97 if (mAllocator == NULL) { 98 BQ_LOGE("createGraphicBufferAlloc failed"); 99 } 100 } 101 102 int numStartingBuffers = getMaxBufferCountLocked(); 103 for (int s = 0; s < numStartingBuffers; s++) { 104 mFreeSlots.insert(s); 105 } 106 for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS; 107 s++) { 108 mUnusedSlots.push_front(s); 109 } 110} 111 112BufferQueueCore::~BufferQueueCore() {} 113 114void BufferQueueCore::dump(String8& result, const char* prefix) const { 115 Mutex::Autolock lock(mMutex); 116 117 String8 fifo; 118 Fifo::const_iterator current(mQueue.begin()); 119 while (current != mQueue.end()) { 120 fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], " 121 "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n", 122 current->mSlot, current->mGraphicBuffer.get(), 123 current->mCrop.left, current->mCrop.top, current->mCrop.right, 124 current->mCrop.bottom, current->mTransform, current->mTimestamp, 125 BufferItem::scalingModeName(current->mScalingMode)); 126 ++current; 127 } 128 129 result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, " 130 "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d " 131 "mAsyncMode=%d, default-size=[%dx%d], default-format=%d, " 132 "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix, 133 mMaxAcquiredBufferCount, mMaxDequeuedBufferCount, 134 mDequeueBufferCannotBlock, mAsyncMode, mDefaultWidth, 135 mDefaultHeight, mDefaultBufferFormat, mTransformHint, mQueue.size(), 136 fifo.string()); 137 138 for (int s : mActiveBuffers) { 139 const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer); 140 // A dequeued buffer might be null if it's still being allocated 141 if (buffer.get()) { 142 result.appendFormat("%s%s[%02d:%p] state=%-8s, %p " 143 "[%4ux%4u:%4u,%3X]\n", prefix, 144 (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s, 145 buffer.get(), mSlots[s].mBufferState.string(), 146 buffer->handle, buffer->width, buffer->height, 147 buffer->stride, buffer->format); 148 } else { 149 result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s, 150 buffer.get(), mSlots[s].mBufferState.string()); 151 } 152 } 153 for (int s : mFreeBuffers) { 154 const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer); 155 result.appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n", 156 prefix, s, buffer.get(), mSlots[s].mBufferState.string(), 157 buffer->handle, buffer->width, buffer->height, buffer->stride, 158 buffer->format); 159 } 160 161 for (int s : mFreeSlots) { 162 const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer); 163 result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s, 164 buffer.get(), mSlots[s].mBufferState.string()); 165 } 166} 167 168int BufferQueueCore::getMinUndequeuedBufferCountLocked() const { 169 // If dequeueBuffer is allowed to error out, we don't have to add an 170 // extra buffer. 171 if (mAsyncMode || mDequeueBufferCannotBlock) { 172 return mMaxAcquiredBufferCount + 1; 173 } 174 175 return mMaxAcquiredBufferCount; 176} 177 178int BufferQueueCore::getMinMaxBufferCountLocked() const { 179 return getMinUndequeuedBufferCountLocked() + 1; 180} 181 182int BufferQueueCore::getMaxBufferCountLocked(bool asyncMode, 183 bool dequeueBufferCannotBlock, int maxBufferCount) const { 184 int maxCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount + 185 ((asyncMode || dequeueBufferCannotBlock) ? 1 : 0); 186 maxCount = std::min(maxBufferCount, maxCount); 187 return maxCount; 188} 189 190int BufferQueueCore::getMaxBufferCountLocked() const { 191 int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount + 192 ((mAsyncMode || mDequeueBufferCannotBlock) ? 1 : 0); 193 194 // limit maxBufferCount by mMaxBufferCount always 195 maxBufferCount = std::min(mMaxBufferCount, maxBufferCount); 196 197 return maxBufferCount; 198} 199 200void BufferQueueCore::clearBufferSlotLocked(int slot) { 201 BQ_LOGV("clearBufferSlotLocked: slot %d", slot); 202 203 mSlots[slot].mGraphicBuffer.clear(); 204 mSlots[slot].mBufferState.reset(); 205 mSlots[slot].mRequestBufferCalled = false; 206 mSlots[slot].mFrameNumber = 0; 207 mSlots[slot].mAcquireCalled = false; 208 mSlots[slot].mNeedsReallocation = true; 209 210 // Destroy fence as BufferQueue now takes ownership 211 if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) { 212 eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence); 213 mSlots[slot].mEglFence = EGL_NO_SYNC_KHR; 214 } 215 mSlots[slot].mFence = Fence::NO_FENCE; 216 mSlots[slot].mEglDisplay = EGL_NO_DISPLAY; 217 218 if (mLastQueuedSlot == slot) { 219 mLastQueuedSlot = INVALID_BUFFER_SLOT; 220 } 221} 222 223void BufferQueueCore::freeAllBuffersLocked() { 224 for (int s : mFreeSlots) { 225 clearBufferSlotLocked(s); 226 } 227 228 for (int s : mFreeBuffers) { 229 mFreeSlots.insert(s); 230 clearBufferSlotLocked(s); 231 } 232 mFreeBuffers.clear(); 233 234 for (int s : mActiveBuffers) { 235 mFreeSlots.insert(s); 236 clearBufferSlotLocked(s); 237 } 238 mActiveBuffers.clear(); 239 240 for (auto& b : mQueue) { 241 b.mIsStale = true; 242 } 243 244 VALIDATE_CONSISTENCY(); 245} 246 247bool BufferQueueCore::adjustAvailableSlotsLocked(int delta) { 248 if (delta >= 0) { 249 // If we're going to fail, do so before modifying anything 250 if (delta > static_cast<int>(mUnusedSlots.size())) { 251 return false; 252 } 253 while (delta > 0) { 254 if (mUnusedSlots.empty()) { 255 return false; 256 } 257 int slot = mUnusedSlots.back(); 258 mUnusedSlots.pop_back(); 259 mFreeSlots.insert(slot); 260 delta--; 261 } 262 } else { 263 // If we're going to fail, do so before modifying anything 264 if (-delta > static_cast<int>(mFreeSlots.size() + 265 mFreeBuffers.size())) { 266 return false; 267 } 268 while (delta < 0) { 269 if (!mFreeSlots.empty()) { 270 auto slot = mFreeSlots.begin(); 271 clearBufferSlotLocked(*slot); 272 mUnusedSlots.push_back(*slot); 273 mFreeSlots.erase(slot); 274 } else if (!mFreeBuffers.empty()) { 275 int slot = mFreeBuffers.back(); 276 clearBufferSlotLocked(slot); 277 mUnusedSlots.push_back(slot); 278 mFreeBuffers.pop_back(); 279 } else { 280 return false; 281 } 282 delta++; 283 } 284 } 285 return true; 286} 287 288void BufferQueueCore::waitWhileAllocatingLocked() const { 289 ATRACE_CALL(); 290 while (mIsAllocating) { 291 mIsAllocatingCondition.wait(mMutex); 292 } 293} 294 295#if DEBUG_ONLY_CODE 296void BufferQueueCore::validateConsistencyLocked() const { 297 static const useconds_t PAUSE_TIME = 0; 298 int allocatedSlots = 0; 299 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { 300 bool isInFreeSlots = mFreeSlots.count(slot) != 0; 301 bool isInFreeBuffers = 302 std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) != 303 mFreeBuffers.cend(); 304 bool isInActiveBuffers = mActiveBuffers.count(slot) != 0; 305 bool isInUnusedSlots = 306 std::find(mUnusedSlots.cbegin(), mUnusedSlots.cend(), slot) != 307 mUnusedSlots.cend(); 308 309 if (isInFreeSlots || isInFreeBuffers || isInActiveBuffers) { 310 allocatedSlots++; 311 } 312 313 if (isInUnusedSlots) { 314 if (isInFreeSlots) { 315 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeSlots", slot); 316 usleep(PAUSE_TIME); 317 } 318 if (isInFreeBuffers) { 319 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeBuffers", slot); 320 usleep(PAUSE_TIME); 321 } 322 if (isInActiveBuffers) { 323 BQ_LOGE("Slot %d is in mUnusedSlots and in mActiveBuffers", 324 slot); 325 usleep(PAUSE_TIME); 326 } 327 if (!mSlots[slot].mBufferState.isFree()) { 328 BQ_LOGE("Slot %d is in mUnusedSlots but is not FREE", slot); 329 usleep(PAUSE_TIME); 330 } 331 if (mSlots[slot].mGraphicBuffer != NULL) { 332 BQ_LOGE("Slot %d is in mUnusedSluts but has an active buffer", 333 slot); 334 usleep(PAUSE_TIME); 335 } 336 } else if (isInFreeSlots) { 337 if (isInUnusedSlots) { 338 BQ_LOGE("Slot %d is in mFreeSlots and in mUnusedSlots", slot); 339 usleep(PAUSE_TIME); 340 } 341 if (isInFreeBuffers) { 342 BQ_LOGE("Slot %d is in mFreeSlots and in mFreeBuffers", slot); 343 usleep(PAUSE_TIME); 344 } 345 if (isInActiveBuffers) { 346 BQ_LOGE("Slot %d is in mFreeSlots and in mActiveBuffers", slot); 347 usleep(PAUSE_TIME); 348 } 349 if (!mSlots[slot].mBufferState.isFree()) { 350 BQ_LOGE("Slot %d is in mFreeSlots but is not FREE", slot); 351 usleep(PAUSE_TIME); 352 } 353 if (mSlots[slot].mGraphicBuffer != NULL) { 354 BQ_LOGE("Slot %d is in mFreeSlots but has a buffer", 355 slot); 356 usleep(PAUSE_TIME); 357 } 358 } else if (isInFreeBuffers) { 359 if (isInUnusedSlots) { 360 BQ_LOGE("Slot %d is in mFreeBuffers and in mUnusedSlots", slot); 361 usleep(PAUSE_TIME); 362 } 363 if (isInFreeSlots) { 364 BQ_LOGE("Slot %d is in mFreeBuffers and in mFreeSlots", slot); 365 usleep(PAUSE_TIME); 366 } 367 if (isInActiveBuffers) { 368 BQ_LOGE("Slot %d is in mFreeBuffers and in mActiveBuffers", 369 slot); 370 usleep(PAUSE_TIME); 371 } 372 if (!mSlots[slot].mBufferState.isFree()) { 373 BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE", slot); 374 usleep(PAUSE_TIME); 375 } 376 if (mSlots[slot].mGraphicBuffer == NULL) { 377 BQ_LOGE("Slot %d is in mFreeBuffers but has no buffer", slot); 378 usleep(PAUSE_TIME); 379 } 380 } else if (isInActiveBuffers) { 381 if (isInUnusedSlots) { 382 BQ_LOGE("Slot %d is in mActiveBuffers and in mUnusedSlots", 383 slot); 384 usleep(PAUSE_TIME); 385 } 386 if (isInFreeSlots) { 387 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeSlots", slot); 388 usleep(PAUSE_TIME); 389 } 390 if (isInFreeBuffers) { 391 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeBuffers", 392 slot); 393 usleep(PAUSE_TIME); 394 } 395 if (mSlots[slot].mBufferState.isFree() && 396 !mSlots[slot].mBufferState.isShared()) { 397 BQ_LOGE("Slot %d is in mActiveBuffers but is FREE", slot); 398 usleep(PAUSE_TIME); 399 } 400 if (mSlots[slot].mGraphicBuffer == NULL && !mIsAllocating) { 401 BQ_LOGE("Slot %d is in mActiveBuffers but has no buffer", slot); 402 usleep(PAUSE_TIME); 403 } 404 } else { 405 BQ_LOGE("Slot %d isn't in any of mUnusedSlots, mFreeSlots, " 406 "mFreeBuffers, or mActiveBuffers", slot); 407 usleep(PAUSE_TIME); 408 } 409 } 410 411 if (allocatedSlots != getMaxBufferCountLocked()) { 412 BQ_LOGE("Number of allocated slots is incorrect. Allocated = %d, " 413 "Should be %d (%zu free slots, %zu free buffers, " 414 "%zu activeBuffers, %zu unusedSlots)", allocatedSlots, 415 getMaxBufferCountLocked(), mFreeSlots.size(), 416 mFreeBuffers.size(), mActiveBuffers.size(), 417 mUnusedSlots.size()); 418 } 419} 420#endif 421 422} // namespace android 423