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