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