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 39 namespace android { 40 41 static String8 getUniqueName() { 42 static volatile int32_t counter = 0; 43 return String8::format("unnamed-%d-%d", getpid(), 44 android_atomic_inc(&counter)); 45 } 46 47 static 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 53 BufferQueueCore::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 112 BufferQueueCore::~BufferQueueCore() {} 113 114 void 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 168 int 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 178 int BufferQueueCore::getMinMaxBufferCountLocked() const { 179 return getMinUndequeuedBufferCountLocked() + 1; 180 } 181 182 int 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 190 int 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 200 void 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 223 void 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 247 void BufferQueueCore::discardFreeBuffersLocked() { 248 for (int s : mFreeBuffers) { 249 mFreeSlots.insert(s); 250 clearBufferSlotLocked(s); 251 } 252 mFreeBuffers.clear(); 253 254 VALIDATE_CONSISTENCY(); 255 } 256 257 bool BufferQueueCore::adjustAvailableSlotsLocked(int delta) { 258 if (delta >= 0) { 259 // If we're going to fail, do so before modifying anything 260 if (delta > static_cast<int>(mUnusedSlots.size())) { 261 return false; 262 } 263 while (delta > 0) { 264 if (mUnusedSlots.empty()) { 265 return false; 266 } 267 int slot = mUnusedSlots.back(); 268 mUnusedSlots.pop_back(); 269 mFreeSlots.insert(slot); 270 delta--; 271 } 272 } else { 273 // If we're going to fail, do so before modifying anything 274 if (-delta > static_cast<int>(mFreeSlots.size() + 275 mFreeBuffers.size())) { 276 return false; 277 } 278 while (delta < 0) { 279 if (!mFreeSlots.empty()) { 280 auto slot = mFreeSlots.begin(); 281 clearBufferSlotLocked(*slot); 282 mUnusedSlots.push_back(*slot); 283 mFreeSlots.erase(slot); 284 } else if (!mFreeBuffers.empty()) { 285 int slot = mFreeBuffers.back(); 286 clearBufferSlotLocked(slot); 287 mUnusedSlots.push_back(slot); 288 mFreeBuffers.pop_back(); 289 } else { 290 return false; 291 } 292 delta++; 293 } 294 } 295 return true; 296 } 297 298 void BufferQueueCore::waitWhileAllocatingLocked() const { 299 ATRACE_CALL(); 300 while (mIsAllocating) { 301 mIsAllocatingCondition.wait(mMutex); 302 } 303 } 304 305 #if DEBUG_ONLY_CODE 306 void BufferQueueCore::validateConsistencyLocked() const { 307 static const useconds_t PAUSE_TIME = 0; 308 int allocatedSlots = 0; 309 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { 310 bool isInFreeSlots = mFreeSlots.count(slot) != 0; 311 bool isInFreeBuffers = 312 std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) != 313 mFreeBuffers.cend(); 314 bool isInActiveBuffers = mActiveBuffers.count(slot) != 0; 315 bool isInUnusedSlots = 316 std::find(mUnusedSlots.cbegin(), mUnusedSlots.cend(), slot) != 317 mUnusedSlots.cend(); 318 319 if (isInFreeSlots || isInFreeBuffers || isInActiveBuffers) { 320 allocatedSlots++; 321 } 322 323 if (isInUnusedSlots) { 324 if (isInFreeSlots) { 325 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeSlots", slot); 326 usleep(PAUSE_TIME); 327 } 328 if (isInFreeBuffers) { 329 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeBuffers", slot); 330 usleep(PAUSE_TIME); 331 } 332 if (isInActiveBuffers) { 333 BQ_LOGE("Slot %d is in mUnusedSlots and in mActiveBuffers", 334 slot); 335 usleep(PAUSE_TIME); 336 } 337 if (!mSlots[slot].mBufferState.isFree()) { 338 BQ_LOGE("Slot %d is in mUnusedSlots but is not FREE", slot); 339 usleep(PAUSE_TIME); 340 } 341 if (mSlots[slot].mGraphicBuffer != NULL) { 342 BQ_LOGE("Slot %d is in mUnusedSluts but has an active buffer", 343 slot); 344 usleep(PAUSE_TIME); 345 } 346 } else if (isInFreeSlots) { 347 if (isInUnusedSlots) { 348 BQ_LOGE("Slot %d is in mFreeSlots and in mUnusedSlots", slot); 349 usleep(PAUSE_TIME); 350 } 351 if (isInFreeBuffers) { 352 BQ_LOGE("Slot %d is in mFreeSlots and in mFreeBuffers", slot); 353 usleep(PAUSE_TIME); 354 } 355 if (isInActiveBuffers) { 356 BQ_LOGE("Slot %d is in mFreeSlots and in mActiveBuffers", slot); 357 usleep(PAUSE_TIME); 358 } 359 if (!mSlots[slot].mBufferState.isFree()) { 360 BQ_LOGE("Slot %d is in mFreeSlots but is not FREE", slot); 361 usleep(PAUSE_TIME); 362 } 363 if (mSlots[slot].mGraphicBuffer != NULL) { 364 BQ_LOGE("Slot %d is in mFreeSlots but has a buffer", 365 slot); 366 usleep(PAUSE_TIME); 367 } 368 } else if (isInFreeBuffers) { 369 if (isInUnusedSlots) { 370 BQ_LOGE("Slot %d is in mFreeBuffers and in mUnusedSlots", slot); 371 usleep(PAUSE_TIME); 372 } 373 if (isInFreeSlots) { 374 BQ_LOGE("Slot %d is in mFreeBuffers and in mFreeSlots", slot); 375 usleep(PAUSE_TIME); 376 } 377 if (isInActiveBuffers) { 378 BQ_LOGE("Slot %d is in mFreeBuffers and in mActiveBuffers", 379 slot); 380 usleep(PAUSE_TIME); 381 } 382 if (!mSlots[slot].mBufferState.isFree()) { 383 BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE", slot); 384 usleep(PAUSE_TIME); 385 } 386 if (mSlots[slot].mGraphicBuffer == NULL) { 387 BQ_LOGE("Slot %d is in mFreeBuffers but has no buffer", slot); 388 usleep(PAUSE_TIME); 389 } 390 } else if (isInActiveBuffers) { 391 if (isInUnusedSlots) { 392 BQ_LOGE("Slot %d is in mActiveBuffers and in mUnusedSlots", 393 slot); 394 usleep(PAUSE_TIME); 395 } 396 if (isInFreeSlots) { 397 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeSlots", slot); 398 usleep(PAUSE_TIME); 399 } 400 if (isInFreeBuffers) { 401 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeBuffers", 402 slot); 403 usleep(PAUSE_TIME); 404 } 405 if (mSlots[slot].mBufferState.isFree() && 406 !mSlots[slot].mBufferState.isShared()) { 407 BQ_LOGE("Slot %d is in mActiveBuffers but is FREE", slot); 408 usleep(PAUSE_TIME); 409 } 410 if (mSlots[slot].mGraphicBuffer == NULL && !mIsAllocating) { 411 BQ_LOGE("Slot %d is in mActiveBuffers but has no buffer", slot); 412 usleep(PAUSE_TIME); 413 } 414 } else { 415 BQ_LOGE("Slot %d isn't in any of mUnusedSlots, mFreeSlots, " 416 "mFreeBuffers, or mActiveBuffers", slot); 417 usleep(PAUSE_TIME); 418 } 419 } 420 421 if (allocatedSlots != getMaxBufferCountLocked()) { 422 BQ_LOGE("Number of allocated slots is incorrect. Allocated = %d, " 423 "Should be %d (%zu free slots, %zu free buffers, " 424 "%zu activeBuffers, %zu unusedSlots)", allocatedSlots, 425 getMaxBufferCountLocked(), mFreeSlots.size(), 426 mFreeBuffers.size(), mActiveBuffers.size(), 427 mUnusedSlots.size()); 428 } 429 } 430 #endif 431 432 } // namespace android 433