|
42 | 42 |
|
43 | 43 | #include <system/window.h> |
44 | 44 |
|
| 45 | +#include <com_android_graphics_libgui_flags.h> |
| 46 | + |
45 | 47 | namespace android { |
46 | 48 |
|
47 | 49 | // Macros for include BufferQueueCore information in log messages |
@@ -370,79 +372,94 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot, |
370 | 372 | return BAD_VALUE; |
371 | 373 | } |
372 | 374 |
|
373 | | - std::lock_guard<std::mutex> lock(mCore->mMutex); |
| 375 | + sp<IProducerListener> listener; |
| 376 | + { |
| 377 | + std::lock_guard<std::mutex> lock(mCore->mMutex); |
374 | 378 |
|
375 | | - if (mCore->mSharedBufferMode) { |
376 | | - BQ_LOGE("attachBuffer: cannot attach a buffer in shared buffer mode"); |
377 | | - return BAD_VALUE; |
378 | | - } |
| 379 | + if (mCore->mSharedBufferMode) { |
| 380 | + BQ_LOGE("attachBuffer: cannot attach a buffer in shared buffer mode"); |
| 381 | + return BAD_VALUE; |
| 382 | + } |
379 | 383 |
|
380 | | - // Make sure we don't have too many acquired buffers |
381 | | - int numAcquiredBuffers = 0; |
382 | | - for (int s : mCore->mActiveBuffers) { |
383 | | - if (mSlots[s].mBufferState.isAcquired()) { |
384 | | - ++numAcquiredBuffers; |
| 384 | + // Make sure we don't have too many acquired buffers |
| 385 | + int numAcquiredBuffers = 0; |
| 386 | + for (int s : mCore->mActiveBuffers) { |
| 387 | + if (mSlots[s].mBufferState.isAcquired()) { |
| 388 | + ++numAcquiredBuffers; |
| 389 | + } |
385 | 390 | } |
386 | | - } |
387 | 391 |
|
388 | | - if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) { |
389 | | - BQ_LOGE("attachBuffer: max acquired buffer count reached: %d " |
390 | | - "(max %d)", numAcquiredBuffers, |
391 | | - mCore->mMaxAcquiredBufferCount); |
392 | | - return INVALID_OPERATION; |
393 | | - } |
| 392 | + if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) { |
| 393 | + BQ_LOGE("attachBuffer: max acquired buffer count reached: %d " |
| 394 | + "(max %d)", numAcquiredBuffers, |
| 395 | + mCore->mMaxAcquiredBufferCount); |
| 396 | + return INVALID_OPERATION; |
| 397 | + } |
394 | 398 |
|
395 | | - if (buffer->getGenerationNumber() != mCore->mGenerationNumber) { |
396 | | - BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] " |
397 | | - "[queue %u]", buffer->getGenerationNumber(), |
398 | | - mCore->mGenerationNumber); |
399 | | - return BAD_VALUE; |
400 | | - } |
| 399 | + if (buffer->getGenerationNumber() != mCore->mGenerationNumber) { |
| 400 | + BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] " |
| 401 | + "[queue %u]", buffer->getGenerationNumber(), |
| 402 | + mCore->mGenerationNumber); |
| 403 | + return BAD_VALUE; |
| 404 | + } |
401 | 405 |
|
402 | | - // Find a free slot to put the buffer into |
403 | | - int found = BufferQueueCore::INVALID_BUFFER_SLOT; |
404 | | - if (!mCore->mFreeSlots.empty()) { |
405 | | - auto slot = mCore->mFreeSlots.begin(); |
406 | | - found = *slot; |
407 | | - mCore->mFreeSlots.erase(slot); |
408 | | - } else if (!mCore->mFreeBuffers.empty()) { |
409 | | - found = mCore->mFreeBuffers.front(); |
410 | | - mCore->mFreeBuffers.remove(found); |
411 | | - } |
412 | | - if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { |
413 | | - BQ_LOGE("attachBuffer: could not find free buffer slot"); |
414 | | - return NO_MEMORY; |
| 406 | + // Find a free slot to put the buffer into |
| 407 | + int found = BufferQueueCore::INVALID_BUFFER_SLOT; |
| 408 | + if (!mCore->mFreeSlots.empty()) { |
| 409 | + auto slot = mCore->mFreeSlots.begin(); |
| 410 | + found = *slot; |
| 411 | + mCore->mFreeSlots.erase(slot); |
| 412 | + } else if (!mCore->mFreeBuffers.empty()) { |
| 413 | + found = mCore->mFreeBuffers.front(); |
| 414 | + mCore->mFreeBuffers.remove(found); |
| 415 | + } |
| 416 | + if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { |
| 417 | + BQ_LOGE("attachBuffer: could not find free buffer slot"); |
| 418 | + return NO_MEMORY; |
| 419 | + } |
| 420 | + |
| 421 | +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK) |
| 422 | + if (mCore->mBufferAttachedCbEnabled) { |
| 423 | + listener = mCore->mConnectedProducerListener; |
| 424 | + } |
| 425 | +#endif |
| 426 | + |
| 427 | + mCore->mActiveBuffers.insert(found); |
| 428 | + *outSlot = found; |
| 429 | + ATRACE_BUFFER_INDEX(*outSlot); |
| 430 | + BQ_LOGV("attachBuffer: returning slot %d", *outSlot); |
| 431 | + |
| 432 | + mSlots[*outSlot].mGraphicBuffer = buffer; |
| 433 | + mSlots[*outSlot].mBufferState.attachConsumer(); |
| 434 | + mSlots[*outSlot].mNeedsReallocation = true; |
| 435 | + mSlots[*outSlot].mFence = Fence::NO_FENCE; |
| 436 | + mSlots[*outSlot].mFrameNumber = 0; |
| 437 | + |
| 438 | + // mAcquireCalled tells BufferQueue that it doesn't need to send a valid |
| 439 | + // GraphicBuffer pointer on the next acquireBuffer call, which decreases |
| 440 | + // Binder traffic by not un/flattening the GraphicBuffer. However, it |
| 441 | + // requires that the consumer maintain a cached copy of the slot <--> buffer |
| 442 | + // mappings, which is why the consumer doesn't need the valid pointer on |
| 443 | + // acquire. |
| 444 | + // |
| 445 | + // The StreamSplitter is one of the primary users of the attach/detach |
| 446 | + // logic, and while it is running, all buffers it acquires are immediately |
| 447 | + // detached, and all buffers it eventually releases are ones that were |
| 448 | + // attached (as opposed to having been obtained from acquireBuffer), so it |
| 449 | + // doesn't make sense to maintain the slot/buffer mappings, which would |
| 450 | + // become invalid for every buffer during detach/attach. By setting this to |
| 451 | + // false, the valid GraphicBuffer pointer will always be sent with acquire |
| 452 | + // for attached buffers. |
| 453 | + mSlots[*outSlot].mAcquireCalled = false; |
| 454 | + |
| 455 | + VALIDATE_CONSISTENCY(); |
415 | 456 | } |
416 | 457 |
|
417 | | - mCore->mActiveBuffers.insert(found); |
418 | | - *outSlot = found; |
419 | | - ATRACE_BUFFER_INDEX(*outSlot); |
420 | | - BQ_LOGV("attachBuffer: returning slot %d", *outSlot); |
421 | | - |
422 | | - mSlots[*outSlot].mGraphicBuffer = buffer; |
423 | | - mSlots[*outSlot].mBufferState.attachConsumer(); |
424 | | - mSlots[*outSlot].mNeedsReallocation = true; |
425 | | - mSlots[*outSlot].mFence = Fence::NO_FENCE; |
426 | | - mSlots[*outSlot].mFrameNumber = 0; |
427 | | - |
428 | | - // mAcquireCalled tells BufferQueue that it doesn't need to send a valid |
429 | | - // GraphicBuffer pointer on the next acquireBuffer call, which decreases |
430 | | - // Binder traffic by not un/flattening the GraphicBuffer. However, it |
431 | | - // requires that the consumer maintain a cached copy of the slot <--> buffer |
432 | | - // mappings, which is why the consumer doesn't need the valid pointer on |
433 | | - // acquire. |
434 | | - // |
435 | | - // The StreamSplitter is one of the primary users of the attach/detach |
436 | | - // logic, and while it is running, all buffers it acquires are immediately |
437 | | - // detached, and all buffers it eventually releases are ones that were |
438 | | - // attached (as opposed to having been obtained from acquireBuffer), so it |
439 | | - // doesn't make sense to maintain the slot/buffer mappings, which would |
440 | | - // become invalid for every buffer during detach/attach. By setting this to |
441 | | - // false, the valid GraphicBuffer pointer will always be sent with acquire |
442 | | - // for attached buffers. |
443 | | - mSlots[*outSlot].mAcquireCalled = false; |
444 | | - |
445 | | - VALIDATE_CONSISTENCY(); |
| 458 | +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK) |
| 459 | + if (listener != nullptr) { |
| 460 | + listener->onBufferAttached(); |
| 461 | + } |
| 462 | +#endif |
446 | 463 |
|
447 | 464 | return NO_ERROR; |
448 | 465 | } |
|
0 commit comments