BufferQueueConsumer.cpp revision a4650a50a0b35e9e4342d6600b6eb24fd94bb8e5
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#include <inttypes.h> 18 19#define LOG_TAG "BufferQueueConsumer" 20#define ATRACE_TAG ATRACE_TAG_GRAPHICS 21//#define LOG_NDEBUG 0 22 23#include <gui/BufferItem.h> 24#include <gui/BufferQueueConsumer.h> 25#include <gui/BufferQueueCore.h> 26#include <gui/IConsumerListener.h> 27#include <gui/IProducerListener.h> 28 29namespace android { 30 31BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) : 32 mCore(core), 33 mSlots(core->mSlots), 34 mConsumerName() {} 35 36BufferQueueConsumer::~BufferQueueConsumer() {} 37 38status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, 39 nsecs_t expectedPresent, uint64_t maxFrameNumber) { 40 ATRACE_CALL(); 41 Mutex::Autolock lock(mCore->mMutex); 42 43 // Check that the consumer doesn't currently have the maximum number of 44 // buffers acquired. We allow the max buffer count to be exceeded by one 45 // buffer so that the consumer can successfully set up the newly acquired 46 // buffer before releasing the old one. 47 int numAcquiredBuffers = 0; 48 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 49 if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) { 50 ++numAcquiredBuffers; 51 } 52 } 53 if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) { 54 BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)", 55 numAcquiredBuffers, mCore->mMaxAcquiredBufferCount); 56 return INVALID_OPERATION; 57 } 58 59 // Check if the queue is empty. 60 // In asynchronous mode the list is guaranteed to be one buffer deep, 61 // while in synchronous mode we use the oldest buffer. 62 if (mCore->mQueue.empty()) { 63 return NO_BUFFER_AVAILABLE; 64 } 65 66 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); 67 68 // If expectedPresent is specified, we may not want to return a buffer yet. 69 // If it's specified and there's more than one buffer queued, we may want 70 // to drop a buffer. 71 if (expectedPresent != 0) { 72 const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second 73 74 // The 'expectedPresent' argument indicates when the buffer is expected 75 // to be presented on-screen. If the buffer's desired present time is 76 // earlier (less) than expectedPresent -- meaning it will be displayed 77 // on time or possibly late if we show it as soon as possible -- we 78 // acquire and return it. If we don't want to display it until after the 79 // expectedPresent time, we return PRESENT_LATER without acquiring it. 80 // 81 // To be safe, we don't defer acquisition if expectedPresent is more 82 // than one second in the future beyond the desired present time 83 // (i.e., we'd be holding the buffer for a long time). 84 // 85 // NOTE: Code assumes monotonic time values from the system clock 86 // are positive. 87 88 // Start by checking to see if we can drop frames. We skip this check if 89 // the timestamps are being auto-generated by Surface. If the app isn't 90 // generating timestamps explicitly, it probably doesn't want frames to 91 // be discarded based on them. 92 while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) { 93 const BufferItem& bufferItem(mCore->mQueue[1]); 94 95 // If dropping entry[0] would leave us with a buffer that the 96 // consumer is not yet ready for, don't drop it. 97 if (maxFrameNumber && bufferItem.mFrameNumber > maxFrameNumber) { 98 break; 99 } 100 101 // If entry[1] is timely, drop entry[0] (and repeat). We apply an 102 // additional criterion here: we only drop the earlier buffer if our 103 // desiredPresent falls within +/- 1 second of the expected present. 104 // Otherwise, bogus desiredPresent times (e.g., 0 or a small 105 // relative timestamp), which normally mean "ignore the timestamp 106 // and acquire immediately", would cause us to drop frames. 107 // 108 // We may want to add an additional criterion: don't drop the 109 // earlier buffer if entry[1]'s fence hasn't signaled yet. 110 nsecs_t desiredPresent = bufferItem.mTimestamp; 111 if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC || 112 desiredPresent > expectedPresent) { 113 // This buffer is set to display in the near future, or 114 // desiredPresent is garbage. Either way we don't want to drop 115 // the previous buffer just to get this on the screen sooner. 116 BQ_LOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%" 117 PRId64 " (%" PRId64 ") now=%" PRId64, 118 desiredPresent, expectedPresent, 119 desiredPresent - expectedPresent, 120 systemTime(CLOCK_MONOTONIC)); 121 break; 122 } 123 124 BQ_LOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64 125 " size=%zu", 126 desiredPresent, expectedPresent, mCore->mQueue.size()); 127 if (mCore->stillTracking(front)) { 128 // Front buffer is still in mSlots, so mark the slot as free 129 mSlots[front->mSlot].mBufferState = BufferSlot::FREE; 130 mCore->mFreeBuffers.push_back(front->mSlot); 131 } 132 mCore->mQueue.erase(front); 133 front = mCore->mQueue.begin(); 134 } 135 136 // See if the front buffer is ready to be acquired 137 nsecs_t desiredPresent = front->mTimestamp; 138 bool bufferIsDue = desiredPresent <= expectedPresent || 139 desiredPresent > expectedPresent + MAX_REASONABLE_NSEC; 140 bool consumerIsReady = maxFrameNumber > 0 ? 141 front->mFrameNumber <= maxFrameNumber : true; 142 if (!bufferIsDue || !consumerIsReady) { 143 BQ_LOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64 144 " (%" PRId64 ") now=%" PRId64 " frame=%" PRIu64 145 " consumer=%" PRIu64, 146 desiredPresent, expectedPresent, 147 desiredPresent - expectedPresent, 148 systemTime(CLOCK_MONOTONIC), 149 front->mFrameNumber, maxFrameNumber); 150 return PRESENT_LATER; 151 } 152 153 BQ_LOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " " 154 "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent, 155 desiredPresent - expectedPresent, 156 systemTime(CLOCK_MONOTONIC)); 157 } 158 159 int slot = front->mSlot; 160 *outBuffer = *front; 161 ATRACE_BUFFER_INDEX(slot); 162 163 BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }", 164 slot, front->mFrameNumber, front->mGraphicBuffer->handle); 165 // If the front buffer is still being tracked, update its slot state 166 if (mCore->stillTracking(front)) { 167 mSlots[slot].mAcquireCalled = true; 168 mSlots[slot].mNeedsCleanupOnRelease = false; 169 mSlots[slot].mBufferState = BufferSlot::ACQUIRED; 170 mSlots[slot].mFence = Fence::NO_FENCE; 171 } 172 173 // If the buffer has previously been acquired by the consumer, set 174 // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer 175 // on the consumer side 176 if (outBuffer->mAcquireCalled) { 177 outBuffer->mGraphicBuffer = NULL; 178 } 179 180 mCore->mQueue.erase(front); 181 182 // We might have freed a slot while dropping old buffers, or the producer 183 // may be blocked waiting for the number of buffers in the queue to 184 // decrease. 185 mCore->mDequeueCondition.broadcast(); 186 187 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); 188 189 mCore->validateConsistencyLocked(); 190 191 return NO_ERROR; 192} 193 194status_t BufferQueueConsumer::detachBuffer(int slot) { 195 ATRACE_CALL(); 196 ATRACE_BUFFER_INDEX(slot); 197 BQ_LOGV("detachBuffer(C): slot %d", slot); 198 Mutex::Autolock lock(mCore->mMutex); 199 200 if (mCore->mIsAbandoned) { 201 BQ_LOGE("detachBuffer(C): BufferQueue has been abandoned"); 202 return NO_INIT; 203 } 204 205 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 206 BQ_LOGE("detachBuffer(C): slot index %d out of range [0, %d)", 207 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 208 return BAD_VALUE; 209 } else if (mSlots[slot].mBufferState != BufferSlot::ACQUIRED) { 210 BQ_LOGE("detachBuffer(C): slot %d is not owned by the consumer " 211 "(state = %d)", slot, mSlots[slot].mBufferState); 212 return BAD_VALUE; 213 } 214 215 mCore->freeBufferLocked(slot); 216 mCore->mDequeueCondition.broadcast(); 217 mCore->validateConsistencyLocked(); 218 219 return NO_ERROR; 220} 221 222status_t BufferQueueConsumer::attachBuffer(int* outSlot, 223 const sp<android::GraphicBuffer>& buffer) { 224 ATRACE_CALL(); 225 226 if (outSlot == NULL) { 227 BQ_LOGE("attachBuffer(P): outSlot must not be NULL"); 228 return BAD_VALUE; 229 } else if (buffer == NULL) { 230 BQ_LOGE("attachBuffer(P): cannot attach NULL buffer"); 231 return BAD_VALUE; 232 } 233 234 Mutex::Autolock lock(mCore->mMutex); 235 236 // Make sure we don't have too many acquired buffers 237 int numAcquiredBuffers = 0; 238 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 239 if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) { 240 ++numAcquiredBuffers; 241 } 242 } 243 244 if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) { 245 BQ_LOGE("attachBuffer(P): max acquired buffer count reached: %d " 246 "(max %d)", numAcquiredBuffers, 247 mCore->mMaxAcquiredBufferCount); 248 return INVALID_OPERATION; 249 } 250 251 // Find a free slot to put the buffer into 252 int found = BufferQueueCore::INVALID_BUFFER_SLOT; 253 if (!mCore->mFreeSlots.empty()) { 254 auto slot = mCore->mFreeSlots.begin(); 255 found = *slot; 256 mCore->mFreeSlots.erase(slot); 257 } else if (!mCore->mFreeBuffers.empty()) { 258 found = mCore->mFreeBuffers.front(); 259 mCore->mFreeBuffers.remove(found); 260 } 261 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 262 BQ_LOGE("attachBuffer(P): could not find free buffer slot"); 263 return NO_MEMORY; 264 } 265 266 *outSlot = found; 267 ATRACE_BUFFER_INDEX(*outSlot); 268 BQ_LOGV("attachBuffer(C): returning slot %d", *outSlot); 269 270 mSlots[*outSlot].mGraphicBuffer = buffer; 271 mSlots[*outSlot].mBufferState = BufferSlot::ACQUIRED; 272 mSlots[*outSlot].mAttachedByConsumer = true; 273 mSlots[*outSlot].mNeedsCleanupOnRelease = false; 274 mSlots[*outSlot].mFence = Fence::NO_FENCE; 275 mSlots[*outSlot].mFrameNumber = 0; 276 277 // mAcquireCalled tells BufferQueue that it doesn't need to send a valid 278 // GraphicBuffer pointer on the next acquireBuffer call, which decreases 279 // Binder traffic by not un/flattening the GraphicBuffer. However, it 280 // requires that the consumer maintain a cached copy of the slot <--> buffer 281 // mappings, which is why the consumer doesn't need the valid pointer on 282 // acquire. 283 // 284 // The StreamSplitter is one of the primary users of the attach/detach 285 // logic, and while it is running, all buffers it acquires are immediately 286 // detached, and all buffers it eventually releases are ones that were 287 // attached (as opposed to having been obtained from acquireBuffer), so it 288 // doesn't make sense to maintain the slot/buffer mappings, which would 289 // become invalid for every buffer during detach/attach. By setting this to 290 // false, the valid GraphicBuffer pointer will always be sent with acquire 291 // for attached buffers. 292 mSlots[*outSlot].mAcquireCalled = false; 293 294 mCore->validateConsistencyLocked(); 295 296 return NO_ERROR; 297} 298 299status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, 300 const sp<Fence>& releaseFence, EGLDisplay eglDisplay, 301 EGLSyncKHR eglFence) { 302 ATRACE_CALL(); 303 ATRACE_BUFFER_INDEX(slot); 304 305 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS || 306 releaseFence == NULL) { 307 BQ_LOGE("releaseBuffer: slot %d out of range or fence %p NULL", slot, 308 releaseFence.get()); 309 return BAD_VALUE; 310 } 311 312 sp<IProducerListener> listener; 313 { // Autolock scope 314 Mutex::Autolock lock(mCore->mMutex); 315 316 // If the frame number has changed because the buffer has been reallocated, 317 // we can ignore this releaseBuffer for the old buffer 318 if (frameNumber != mSlots[slot].mFrameNumber) { 319 return STALE_BUFFER_SLOT; 320 } 321 322 // Make sure this buffer hasn't been queued while acquired by the consumer 323 BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin()); 324 while (current != mCore->mQueue.end()) { 325 if (current->mSlot == slot) { 326 BQ_LOGE("releaseBuffer: buffer slot %d pending release is " 327 "currently queued", slot); 328 return BAD_VALUE; 329 } 330 ++current; 331 } 332 333 if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) { 334 mSlots[slot].mEglDisplay = eglDisplay; 335 mSlots[slot].mEglFence = eglFence; 336 mSlots[slot].mFence = releaseFence; 337 mSlots[slot].mBufferState = BufferSlot::FREE; 338 mCore->mFreeBuffers.push_back(slot); 339 listener = mCore->mConnectedProducerListener; 340 BQ_LOGV("releaseBuffer: releasing slot %d", slot); 341 } else if (mSlots[slot].mNeedsCleanupOnRelease) { 342 BQ_LOGV("releaseBuffer: releasing a stale buffer slot %d " 343 "(state = %d)", slot, mSlots[slot].mBufferState); 344 mSlots[slot].mNeedsCleanupOnRelease = false; 345 return STALE_BUFFER_SLOT; 346 } else { 347 BQ_LOGE("releaseBuffer: attempted to release buffer slot %d " 348 "but its state was %d", slot, mSlots[slot].mBufferState); 349 return BAD_VALUE; 350 } 351 352 mCore->mDequeueCondition.broadcast(); 353 mCore->validateConsistencyLocked(); 354 } // Autolock scope 355 356 // Call back without lock held 357 if (listener != NULL) { 358 listener->onBufferReleased(); 359 } 360 361 return NO_ERROR; 362} 363 364status_t BufferQueueConsumer::connect( 365 const sp<IConsumerListener>& consumerListener, bool controlledByApp) { 366 ATRACE_CALL(); 367 368 if (consumerListener == NULL) { 369 BQ_LOGE("connect(C): consumerListener may not be NULL"); 370 return BAD_VALUE; 371 } 372 373 BQ_LOGV("connect(C): controlledByApp=%s", 374 controlledByApp ? "true" : "false"); 375 376 Mutex::Autolock lock(mCore->mMutex); 377 378 if (mCore->mIsAbandoned) { 379 BQ_LOGE("connect(C): BufferQueue has been abandoned"); 380 return NO_INIT; 381 } 382 383 mCore->mConsumerListener = consumerListener; 384 mCore->mConsumerControlledByApp = controlledByApp; 385 386 return NO_ERROR; 387} 388 389status_t BufferQueueConsumer::disconnect() { 390 ATRACE_CALL(); 391 392 BQ_LOGV("disconnect(C)"); 393 394 Mutex::Autolock lock(mCore->mMutex); 395 396 if (mCore->mConsumerListener == NULL) { 397 BQ_LOGE("disconnect(C): no consumer is connected"); 398 return BAD_VALUE; 399 } 400 401 mCore->mIsAbandoned = true; 402 mCore->mConsumerListener = NULL; 403 mCore->mQueue.clear(); 404 mCore->freeAllBuffersLocked(); 405 mCore->mDequeueCondition.broadcast(); 406 return NO_ERROR; 407} 408 409status_t BufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) { 410 ATRACE_CALL(); 411 412 if (outSlotMask == NULL) { 413 BQ_LOGE("getReleasedBuffers: outSlotMask may not be NULL"); 414 return BAD_VALUE; 415 } 416 417 Mutex::Autolock lock(mCore->mMutex); 418 419 if (mCore->mIsAbandoned) { 420 BQ_LOGE("getReleasedBuffers: BufferQueue has been abandoned"); 421 return NO_INIT; 422 } 423 424 uint64_t mask = 0; 425 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 426 if (!mSlots[s].mAcquireCalled) { 427 mask |= (1ULL << s); 428 } 429 } 430 431 // Remove from the mask queued buffers for which acquire has been called, 432 // since the consumer will not receive their buffer addresses and so must 433 // retain their cached information 434 BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin()); 435 while (current != mCore->mQueue.end()) { 436 if (current->mAcquireCalled) { 437 mask &= ~(1ULL << current->mSlot); 438 } 439 ++current; 440 } 441 442 BQ_LOGV("getReleasedBuffers: returning mask %#" PRIx64, mask); 443 *outSlotMask = mask; 444 return NO_ERROR; 445} 446 447status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width, 448 uint32_t height) { 449 ATRACE_CALL(); 450 451 if (width == 0 || height == 0) { 452 BQ_LOGV("setDefaultBufferSize: dimensions cannot be 0 (width=%u " 453 "height=%u)", width, height); 454 return BAD_VALUE; 455 } 456 457 BQ_LOGV("setDefaultBufferSize: width=%u height=%u", width, height); 458 459 Mutex::Autolock lock(mCore->mMutex); 460 mCore->mDefaultWidth = width; 461 mCore->mDefaultHeight = height; 462 return NO_ERROR; 463} 464 465status_t BufferQueueConsumer::setDefaultMaxBufferCount(int bufferCount) { 466 ATRACE_CALL(); 467 Mutex::Autolock lock(mCore->mMutex); 468 return mCore->setDefaultMaxBufferCountLocked(bufferCount); 469} 470 471status_t BufferQueueConsumer::disableAsyncBuffer() { 472 ATRACE_CALL(); 473 474 Mutex::Autolock lock(mCore->mMutex); 475 476 if (mCore->mConsumerListener != NULL) { 477 BQ_LOGE("disableAsyncBuffer: consumer already connected"); 478 return INVALID_OPERATION; 479 } 480 481 BQ_LOGV("disableAsyncBuffer"); 482 mCore->mUseAsyncBuffer = false; 483 return NO_ERROR; 484} 485 486status_t BufferQueueConsumer::setMaxAcquiredBufferCount( 487 int maxAcquiredBuffers) { 488 ATRACE_CALL(); 489 490 if (maxAcquiredBuffers < 1 || 491 maxAcquiredBuffers > BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) { 492 BQ_LOGE("setMaxAcquiredBufferCount: invalid count %d", 493 maxAcquiredBuffers); 494 return BAD_VALUE; 495 } 496 497 Mutex::Autolock lock(mCore->mMutex); 498 499 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { 500 BQ_LOGE("setMaxAcquiredBufferCount: producer is already connected"); 501 return INVALID_OPERATION; 502 } 503 504 BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers); 505 mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers; 506 return NO_ERROR; 507} 508 509void BufferQueueConsumer::setConsumerName(const String8& name) { 510 ATRACE_CALL(); 511 BQ_LOGV("setConsumerName: '%s'", name.string()); 512 Mutex::Autolock lock(mCore->mMutex); 513 mCore->mConsumerName = name; 514 mConsumerName = name; 515} 516 517status_t BufferQueueConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) { 518 ATRACE_CALL(); 519 BQ_LOGV("setDefaultBufferFormat: %u", defaultFormat); 520 Mutex::Autolock lock(mCore->mMutex); 521 mCore->mDefaultBufferFormat = defaultFormat; 522 return NO_ERROR; 523} 524 525status_t BufferQueueConsumer::setDefaultBufferDataSpace( 526 android_dataspace defaultDataSpace) { 527 ATRACE_CALL(); 528 BQ_LOGV("setDefaultBufferDataSpace: %u", defaultDataSpace); 529 Mutex::Autolock lock(mCore->mMutex); 530 mCore->mDefaultBufferDataSpace = defaultDataSpace; 531 return NO_ERROR; 532} 533 534status_t BufferQueueConsumer::setConsumerUsageBits(uint32_t usage) { 535 ATRACE_CALL(); 536 BQ_LOGV("setConsumerUsageBits: %#x", usage); 537 Mutex::Autolock lock(mCore->mMutex); 538 mCore->mConsumerUsageBits = usage; 539 return NO_ERROR; 540} 541 542status_t BufferQueueConsumer::setTransformHint(uint32_t hint) { 543 ATRACE_CALL(); 544 BQ_LOGV("setTransformHint: %#x", hint); 545 Mutex::Autolock lock(mCore->mMutex); 546 mCore->mTransformHint = hint; 547 return NO_ERROR; 548} 549 550sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const { 551 return mCore->mSidebandStream; 552} 553 554void BufferQueueConsumer::dump(String8& result, const char* prefix) const { 555 mCore->dump(result, prefix); 556} 557 558} // namespace android 559