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