BufferQueueProducer.cpp revision ccdfd60d79a8b7f1ed6401d0f2e8e29166a10584
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 "BufferQueueProducer" 20#define ATRACE_TAG ATRACE_TAG_GRAPHICS 21//#define LOG_NDEBUG 0 22 23#define EGL_EGLEXT_PROTOTYPES 24 25#include <gui/BufferItem.h> 26#include <gui/BufferQueueCore.h> 27#include <gui/BufferQueueProducer.h> 28#include <gui/IConsumerListener.h> 29#include <gui/IGraphicBufferAlloc.h> 30#include <gui/IProducerListener.h> 31 32#include <utils/Log.h> 33#include <utils/Trace.h> 34 35namespace android { 36 37BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) : 38 mCore(core), 39 mSlots(core->mSlots), 40 mConsumerName(), 41 mStickyTransform(0), 42 mLastQueueBufferFence(Fence::NO_FENCE), 43 mCallbackMutex(), 44 mNextCallbackTicket(0), 45 mCurrentCallbackTicket(0), 46 mCallbackCondition() {} 47 48BufferQueueProducer::~BufferQueueProducer() {} 49 50status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) { 51 ATRACE_CALL(); 52 BQ_LOGV("requestBuffer: slot %d", slot); 53 Mutex::Autolock lock(mCore->mMutex); 54 55 if (mCore->mIsAbandoned) { 56 BQ_LOGE("requestBuffer: BufferQueue has been abandoned"); 57 return NO_INIT; 58 } 59 60 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) { 61 BQ_LOGE("requestBuffer: BufferQueue has no connected producer"); 62 return NO_INIT; 63 } 64 65 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 66 BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)", 67 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 68 return BAD_VALUE; 69 } else if (!mSlots[slot].mBufferState.isDequeued()) { 70 BQ_LOGE("requestBuffer: slot %d is not owned by the producer " 71 "(state = %s)", slot, mSlots[slot].mBufferState.string()); 72 return BAD_VALUE; 73 } 74 75 mSlots[slot].mRequestBufferCalled = true; 76 *buf = mSlots[slot].mGraphicBuffer; 77 return NO_ERROR; 78} 79 80status_t BufferQueueProducer::setMaxDequeuedBufferCount( 81 int maxDequeuedBuffers) { 82 ATRACE_CALL(); 83 BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d", 84 maxDequeuedBuffers); 85 86 sp<IConsumerListener> listener; 87 { // Autolock scope 88 Mutex::Autolock lock(mCore->mMutex); 89 mCore->waitWhileAllocatingLocked(); 90 91 if (mCore->mIsAbandoned) { 92 BQ_LOGE("setMaxDequeuedBufferCount: BufferQueue has been " 93 "abandoned"); 94 return NO_INIT; 95 } 96 97 // There must be no dequeued buffers when changing the buffer count. 98 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 99 if (mSlots[s].mBufferState.isDequeued()) { 100 BQ_LOGE("setMaxDequeuedBufferCount: buffer owned by producer"); 101 return BAD_VALUE; 102 } 103 } 104 105 int bufferCount = mCore->getMinUndequeuedBufferCountLocked(); 106 bufferCount += maxDequeuedBuffers; 107 108 if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) { 109 BQ_LOGE("setMaxDequeuedBufferCount: bufferCount %d too large " 110 "(max %d)", bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS); 111 return BAD_VALUE; 112 } 113 114 const int minBufferSlots = mCore->getMinMaxBufferCountLocked(); 115 if (bufferCount < minBufferSlots) { 116 BQ_LOGE("setMaxDequeuedBufferCount: requested buffer count %d is " 117 "less than minimum %d", bufferCount, minBufferSlots); 118 return BAD_VALUE; 119 } 120 121 if (bufferCount > mCore->mMaxBufferCount) { 122 BQ_LOGE("setMaxDequeuedBufferCount: %d dequeued buffers would " 123 "exceed the maxBufferCount (%d) (maxAcquired %d async %d " 124 "mDequeuedBufferCannotBlock %d)", maxDequeuedBuffers, 125 mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount, 126 mCore->mAsyncMode, mCore->mDequeueBufferCannotBlock); 127 return BAD_VALUE; 128 } 129 130 // Here we are guaranteed that the producer doesn't have any dequeued 131 // buffers and will release all of its buffer references. We don't 132 // clear the queue, however, so that currently queued buffers still 133 // get displayed. 134 mCore->freeAllBuffersLocked(); 135 mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers; 136 mCore->mDequeueCondition.broadcast(); 137 listener = mCore->mConsumerListener; 138 } // Autolock scope 139 140 // Call back without lock held 141 if (listener != NULL) { 142 listener->onBuffersReleased(); 143 } 144 145 return NO_ERROR; 146} 147 148status_t BufferQueueProducer::setAsyncMode(bool async) { 149 ATRACE_CALL(); 150 BQ_LOGV("setAsyncMode: async = %d", async); 151 152 sp<IConsumerListener> listener; 153 { // Autolock scope 154 Mutex::Autolock lock(mCore->mMutex); 155 mCore->waitWhileAllocatingLocked(); 156 157 if (mCore->mIsAbandoned) { 158 BQ_LOGE("setAsyncMode: BufferQueue has been abandoned"); 159 return NO_INIT; 160 } 161 162 if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount + 163 (async || mCore->mDequeueBufferCannotBlock ? 1 : 0)) > 164 mCore->mMaxBufferCount) { 165 BQ_LOGE("setAsyncMode(%d): this call would cause the " 166 "maxBufferCount (%d) to be exceeded (maxAcquired %d " 167 "maxDequeued %d mDequeueBufferCannotBlock %d)", async, 168 mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount, 169 mCore->mMaxDequeuedBufferCount, 170 mCore->mDequeueBufferCannotBlock); 171 return BAD_VALUE; 172 } 173 174 mCore->mAsyncMode = async; 175 mCore->mDequeueCondition.broadcast(); 176 listener = mCore->mConsumerListener; 177 } // Autolock scope 178 179 // Call back without lock held 180 if (listener != NULL) { 181 listener->onBuffersReleased(); 182 } 183 return NO_ERROR; 184} 185 186status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller, 187 int* found, status_t* returnFlags) const { 188 bool tryAgain = true; 189 while (tryAgain) { 190 if (mCore->mIsAbandoned) { 191 BQ_LOGE("%s: BufferQueue has been abandoned", caller); 192 return NO_INIT; 193 } 194 195 const int maxBufferCount = mCore->getMaxBufferCountLocked(); 196 197 // Free up any buffers that are in slots beyond the max buffer count 198 for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 199 assert(mSlots[s].mBufferState.isFree()); 200 if (mSlots[s].mGraphicBuffer != NULL) { 201 mCore->freeBufferLocked(s); 202 *returnFlags |= RELEASE_ALL_BUFFERS; 203 } 204 } 205 206 int dequeuedCount = 0; 207 int acquiredCount = 0; 208 for (int s = 0; s < maxBufferCount; ++s) { 209 if (mSlots[s].mBufferState.isDequeued()) { 210 ++dequeuedCount; 211 } 212 if (mSlots[s].mBufferState.isAcquired()) { 213 ++acquiredCount; 214 } 215 } 216 217 // Producers are not allowed to dequeue more than 218 // mMaxDequeuedBufferCount buffers. 219 // This check is only done if a buffer has already been queued 220 if (mCore->mBufferHasBeenQueued && 221 dequeuedCount >= mCore->mMaxDequeuedBufferCount) { 222 BQ_LOGE("%s: attempting to exceed the max dequeued buffer count " 223 "(%d)", caller, mCore->mMaxDequeuedBufferCount); 224 return INVALID_OPERATION; 225 } 226 227 *found = BufferQueueCore::INVALID_BUFFER_SLOT; 228 229 // If we disconnect and reconnect quickly, we can be in a state where 230 // our slots are empty but we have many buffers in the queue. This can 231 // cause us to run out of memory if we outrun the consumer. Wait here if 232 // it looks like we have too many buffers queued up. 233 bool tooManyBuffers = mCore->mQueue.size() 234 > static_cast<size_t>(maxBufferCount); 235 if (tooManyBuffers) { 236 BQ_LOGV("%s: queue size is %zu, waiting", caller, 237 mCore->mQueue.size()); 238 } else { 239 // If in single buffer mode and a shared buffer exists, always 240 // return it. 241 if (mCore->mSingleBufferMode && mCore->mSingleBufferSlot != 242 BufferQueueCore::INVALID_BUFFER_SLOT) { 243 *found = mCore->mSingleBufferSlot; 244 } else if (!mCore->mFreeBuffers.empty()) { 245 auto slot = mCore->mFreeBuffers.begin(); 246 *found = *slot; 247 mCore->mFreeBuffers.erase(slot); 248 } else if (mCore->mAllowAllocation && !mCore->mFreeSlots.empty()) { 249 auto slot = mCore->mFreeSlots.begin(); 250 // Only return free slots up to the max buffer count 251 if (*slot < maxBufferCount) { 252 *found = *slot; 253 mCore->mFreeSlots.erase(slot); 254 } 255 } 256 } 257 258 // If no buffer is found, or if the queue has too many buffers 259 // outstanding, wait for a buffer to be acquired or released, or for the 260 // max buffer count to change. 261 tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) || 262 tooManyBuffers; 263 if (tryAgain) { 264 // Return an error if we're in non-blocking mode (producer and 265 // consumer are controlled by the application). 266 // However, the consumer is allowed to briefly acquire an extra 267 // buffer (which could cause us to have to wait here), which is 268 // okay, since it is only used to implement an atomic acquire + 269 // release (e.g., in GLConsumer::updateTexImage()) 270 if ((mCore->mDequeueBufferCannotBlock || mCore->mAsyncMode) && 271 (acquiredCount <= mCore->mMaxAcquiredBufferCount)) { 272 return WOULD_BLOCK; 273 } 274 mCore->mDequeueCondition.wait(mCore->mMutex); 275 } 276 } // while (tryAgain) 277 278 return NO_ERROR; 279} 280 281status_t BufferQueueProducer::dequeueBuffer(int *outSlot, 282 sp<android::Fence> *outFence, uint32_t width, uint32_t height, 283 PixelFormat format, uint32_t usage) { 284 ATRACE_CALL(); 285 { // Autolock scope 286 Mutex::Autolock lock(mCore->mMutex); 287 mConsumerName = mCore->mConsumerName; 288 289 if (mCore->mIsAbandoned) { 290 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned"); 291 return NO_INIT; 292 } 293 294 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) { 295 BQ_LOGE("dequeueBuffer: BufferQueue has no connected producer"); 296 return NO_INIT; 297 } 298 } // Autolock scope 299 300 BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#x", width, height, 301 format, usage); 302 303 if ((width && !height) || (!width && height)) { 304 BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height); 305 return BAD_VALUE; 306 } 307 308 status_t returnFlags = NO_ERROR; 309 EGLDisplay eglDisplay = EGL_NO_DISPLAY; 310 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR; 311 bool attachedByConsumer = false; 312 313 { // Autolock scope 314 Mutex::Autolock lock(mCore->mMutex); 315 mCore->waitWhileAllocatingLocked(); 316 317 if (format == 0) { 318 format = mCore->mDefaultBufferFormat; 319 } 320 321 // Enable the usage bits the consumer requested 322 usage |= mCore->mConsumerUsageBits; 323 324 const bool useDefaultSize = !width && !height; 325 if (useDefaultSize) { 326 width = mCore->mDefaultWidth; 327 height = mCore->mDefaultHeight; 328 } 329 330 int found = BufferItem::INVALID_BUFFER_SLOT; 331 while (found == BufferItem::INVALID_BUFFER_SLOT) { 332 status_t status = waitForFreeSlotThenRelock("dequeueBuffer", &found, 333 &returnFlags); 334 if (status != NO_ERROR) { 335 return status; 336 } 337 338 // This should not happen 339 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 340 BQ_LOGE("dequeueBuffer: no available buffer slots"); 341 return -EBUSY; 342 } 343 344 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); 345 346 // If we are not allowed to allocate new buffers, 347 // waitForFreeSlotThenRelock must have returned a slot containing a 348 // buffer. If this buffer would require reallocation to meet the 349 // requested attributes, we free it and attempt to get another one. 350 if (!mCore->mAllowAllocation) { 351 if (buffer->needsReallocation(width, height, format, usage)) { 352 if (mCore->mSingleBufferMode && 353 mCore->mSingleBufferSlot == found) { 354 BQ_LOGE("dequeueBuffer: cannot re-allocate a shared" 355 "buffer"); 356 return BAD_VALUE; 357 } 358 359 mCore->freeBufferLocked(found); 360 found = BufferItem::INVALID_BUFFER_SLOT; 361 continue; 362 } 363 } 364 } 365 366 *outSlot = found; 367 ATRACE_BUFFER_INDEX(found); 368 369 attachedByConsumer = mSlots[found].mAttachedByConsumer; 370 371 mSlots[found].mBufferState.dequeue(); 372 373 // If single buffer mode has just been enabled, cache the slot of the 374 // first buffer that is dequeued and mark it as the shared buffer. 375 if (mCore->mSingleBufferMode && mCore->mSingleBufferSlot == 376 BufferQueueCore::INVALID_BUFFER_SLOT) { 377 mCore->mSingleBufferSlot = found; 378 mSlots[found].mBufferState.mShared = true; 379 } 380 381 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); 382 if ((buffer == NULL) || 383 buffer->needsReallocation(width, height, format, usage)) 384 { 385 mSlots[found].mAcquireCalled = false; 386 mSlots[found].mGraphicBuffer = NULL; 387 mSlots[found].mRequestBufferCalled = false; 388 mSlots[found].mEglDisplay = EGL_NO_DISPLAY; 389 mSlots[found].mEglFence = EGL_NO_SYNC_KHR; 390 mSlots[found].mFence = Fence::NO_FENCE; 391 mCore->mBufferAge = 0; 392 mCore->mIsAllocating = true; 393 394 returnFlags |= BUFFER_NEEDS_REALLOCATION; 395 } else { 396 // We add 1 because that will be the frame number when this buffer 397 // is queued 398 mCore->mBufferAge = 399 mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber; 400 } 401 402 BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64, 403 mCore->mBufferAge); 404 405 if (CC_UNLIKELY(mSlots[found].mFence == NULL)) { 406 BQ_LOGE("dequeueBuffer: about to return a NULL fence - " 407 "slot=%d w=%d h=%d format=%u", 408 found, buffer->width, buffer->height, buffer->format); 409 } 410 411 eglDisplay = mSlots[found].mEglDisplay; 412 eglFence = mSlots[found].mEglFence; 413 *outFence = mSlots[found].mFence; 414 mSlots[found].mEglFence = EGL_NO_SYNC_KHR; 415 mSlots[found].mFence = Fence::NO_FENCE; 416 417 mCore->validateConsistencyLocked(); 418 } // Autolock scope 419 420 if (returnFlags & BUFFER_NEEDS_REALLOCATION) { 421 status_t error; 422 BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot); 423 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( 424 width, height, format, usage, &error)); 425 { // Autolock scope 426 Mutex::Autolock lock(mCore->mMutex); 427 428 if (graphicBuffer != NULL && !mCore->mIsAbandoned) { 429 graphicBuffer->setGenerationNumber(mCore->mGenerationNumber); 430 mSlots[*outSlot].mGraphicBuffer = graphicBuffer; 431 } 432 433 mCore->mIsAllocating = false; 434 mCore->mIsAllocatingCondition.broadcast(); 435 436 if (graphicBuffer == NULL) { 437 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed"); 438 return error; 439 } 440 441 if (mCore->mIsAbandoned) { 442 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned"); 443 return NO_INIT; 444 } 445 } // Autolock scope 446 } 447 448 if (attachedByConsumer) { 449 returnFlags |= BUFFER_NEEDS_REALLOCATION; 450 } 451 452 if (eglFence != EGL_NO_SYNC_KHR) { 453 EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0, 454 1000000000); 455 // If something goes wrong, log the error, but return the buffer without 456 // synchronizing access to it. It's too late at this point to abort the 457 // dequeue operation. 458 if (result == EGL_FALSE) { 459 BQ_LOGE("dequeueBuffer: error %#x waiting for fence", 460 eglGetError()); 461 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 462 BQ_LOGE("dequeueBuffer: timeout waiting for fence"); 463 } 464 eglDestroySyncKHR(eglDisplay, eglFence); 465 } 466 467 BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x", 468 *outSlot, 469 mSlots[*outSlot].mFrameNumber, 470 mSlots[*outSlot].mGraphicBuffer->handle, returnFlags); 471 472 return returnFlags; 473} 474 475status_t BufferQueueProducer::detachBuffer(int slot) { 476 ATRACE_CALL(); 477 ATRACE_BUFFER_INDEX(slot); 478 BQ_LOGV("detachBuffer: slot %d", slot); 479 Mutex::Autolock lock(mCore->mMutex); 480 481 if (mCore->mIsAbandoned) { 482 BQ_LOGE("detachBuffer: BufferQueue has been abandoned"); 483 return NO_INIT; 484 } 485 486 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) { 487 BQ_LOGE("detachBuffer: BufferQueue has no connected producer"); 488 return NO_INIT; 489 } 490 491 if (mCore->mSingleBufferMode) { 492 BQ_LOGE("detachBuffer: cannot detach a buffer in single buffer" 493 "mode"); 494 return BAD_VALUE; 495 } 496 497 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 498 BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)", 499 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 500 return BAD_VALUE; 501 } else if (!mSlots[slot].mBufferState.isDequeued()) { 502 BQ_LOGE("detachBuffer: slot %d is not owned by the producer " 503 "(state = %s)", slot, mSlots[slot].mBufferState.string()); 504 return BAD_VALUE; 505 } else if (!mSlots[slot].mRequestBufferCalled) { 506 BQ_LOGE("detachBuffer: buffer in slot %d has not been requested", 507 slot); 508 return BAD_VALUE; 509 } 510 511 mSlots[slot].mBufferState.detachProducer(); 512 mCore->freeBufferLocked(slot); 513 mCore->mDequeueCondition.broadcast(); 514 mCore->validateConsistencyLocked(); 515 516 return NO_ERROR; 517} 518 519status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer, 520 sp<Fence>* outFence) { 521 ATRACE_CALL(); 522 523 if (outBuffer == NULL) { 524 BQ_LOGE("detachNextBuffer: outBuffer must not be NULL"); 525 return BAD_VALUE; 526 } else if (outFence == NULL) { 527 BQ_LOGE("detachNextBuffer: outFence must not be NULL"); 528 return BAD_VALUE; 529 } 530 531 Mutex::Autolock lock(mCore->mMutex); 532 533 if (mCore->mIsAbandoned) { 534 BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned"); 535 return NO_INIT; 536 } 537 538 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) { 539 BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer"); 540 return NO_INIT; 541 } 542 543 if (mCore->mSingleBufferMode) { 544 BQ_LOGE("detachNextBuffer: cannot detach a buffer in single buffer" 545 "mode"); 546 return BAD_VALUE; 547 } 548 549 mCore->waitWhileAllocatingLocked(); 550 551 if (mCore->mFreeBuffers.empty()) { 552 return NO_MEMORY; 553 } 554 555 int found = mCore->mFreeBuffers.front(); 556 mCore->mFreeBuffers.remove(found); 557 558 BQ_LOGV("detachNextBuffer detached slot %d", found); 559 560 *outBuffer = mSlots[found].mGraphicBuffer; 561 *outFence = mSlots[found].mFence; 562 mCore->freeBufferLocked(found); 563 mCore->validateConsistencyLocked(); 564 565 return NO_ERROR; 566} 567 568status_t BufferQueueProducer::attachBuffer(int* outSlot, 569 const sp<android::GraphicBuffer>& buffer) { 570 ATRACE_CALL(); 571 572 if (outSlot == NULL) { 573 BQ_LOGE("attachBuffer: outSlot must not be NULL"); 574 return BAD_VALUE; 575 } else if (buffer == NULL) { 576 BQ_LOGE("attachBuffer: cannot attach NULL buffer"); 577 return BAD_VALUE; 578 } 579 580 Mutex::Autolock lock(mCore->mMutex); 581 582 if (mCore->mIsAbandoned) { 583 BQ_LOGE("attachBuffer: BufferQueue has been abandoned"); 584 return NO_INIT; 585 } 586 587 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) { 588 BQ_LOGE("attachBuffer: BufferQueue has no connected producer"); 589 return NO_INIT; 590 } 591 592 if (mCore->mSingleBufferMode) { 593 BQ_LOGE("attachBuffer: cannot atach a buffer in single buffer mode"); 594 return BAD_VALUE; 595 } 596 597 if (buffer->getGenerationNumber() != mCore->mGenerationNumber) { 598 BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] " 599 "[queue %u]", buffer->getGenerationNumber(), 600 mCore->mGenerationNumber); 601 return BAD_VALUE; 602 } 603 604 mCore->waitWhileAllocatingLocked(); 605 606 status_t returnFlags = NO_ERROR; 607 int found; 608 status_t status = waitForFreeSlotThenRelock("attachBuffer", &found, 609 &returnFlags); 610 if (status != NO_ERROR) { 611 return status; 612 } 613 614 // This should not happen 615 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 616 BQ_LOGE("attachBuffer: no available buffer slots"); 617 return -EBUSY; 618 } 619 620 *outSlot = found; 621 ATRACE_BUFFER_INDEX(*outSlot); 622 BQ_LOGV("attachBuffer: returning slot %d flags=%#x", 623 *outSlot, returnFlags); 624 625 mSlots[*outSlot].mGraphicBuffer = buffer; 626 mSlots[*outSlot].mBufferState.attachProducer(); 627 mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR; 628 mSlots[*outSlot].mFence = Fence::NO_FENCE; 629 mSlots[*outSlot].mRequestBufferCalled = true; 630 631 mCore->validateConsistencyLocked(); 632 633 return returnFlags; 634} 635 636status_t BufferQueueProducer::queueBuffer(int slot, 637 const QueueBufferInput &input, QueueBufferOutput *output) { 638 ATRACE_CALL(); 639 ATRACE_BUFFER_INDEX(slot); 640 641 int64_t timestamp; 642 bool isAutoTimestamp; 643 android_dataspace dataSpace; 644 Rect crop(Rect::EMPTY_RECT); 645 int scalingMode; 646 uint32_t transform; 647 uint32_t stickyTransform; 648 sp<Fence> fence; 649 input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode, 650 &transform, &fence, &stickyTransform); 651 Region surfaceDamage = input.getSurfaceDamage(); 652 653 if (fence == NULL) { 654 BQ_LOGE("queueBuffer: fence is NULL"); 655 return BAD_VALUE; 656 } 657 658 switch (scalingMode) { 659 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 660 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 661 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: 662 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: 663 break; 664 default: 665 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode); 666 return BAD_VALUE; 667 } 668 669 sp<IConsumerListener> frameAvailableListener; 670 sp<IConsumerListener> frameReplacedListener; 671 int callbackTicket = 0; 672 BufferItem item; 673 { // Autolock scope 674 Mutex::Autolock lock(mCore->mMutex); 675 676 if (mCore->mIsAbandoned) { 677 BQ_LOGE("queueBuffer: BufferQueue has been abandoned"); 678 return NO_INIT; 679 } 680 681 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) { 682 BQ_LOGE("queueBuffer: BufferQueue has no connected producer"); 683 return NO_INIT; 684 } 685 686 const int maxBufferCount = mCore->getMaxBufferCountLocked(); 687 688 if (slot < 0 || slot >= maxBufferCount) { 689 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)", 690 slot, maxBufferCount); 691 return BAD_VALUE; 692 } else if (!mSlots[slot].mBufferState.isDequeued()) { 693 BQ_LOGE("queueBuffer: slot %d is not owned by the producer " 694 "(state = %s)", slot, mSlots[slot].mBufferState.string()); 695 return BAD_VALUE; 696 } else if (!mSlots[slot].mRequestBufferCalled) { 697 BQ_LOGE("queueBuffer: slot %d was queued without requesting " 698 "a buffer", slot); 699 return BAD_VALUE; 700 } 701 702 BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d" 703 " crop=[%d,%d,%d,%d] transform=%#x scale=%s", 704 slot, mCore->mFrameCounter + 1, timestamp, dataSpace, 705 crop.left, crop.top, crop.right, crop.bottom, transform, 706 BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode))); 707 708 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer); 709 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); 710 Rect croppedRect(Rect::EMPTY_RECT); 711 crop.intersect(bufferRect, &croppedRect); 712 if (croppedRect != crop) { 713 BQ_LOGE("queueBuffer: crop rect is not contained within the " 714 "buffer in slot %d", slot); 715 return BAD_VALUE; 716 } 717 718 // Override UNKNOWN dataspace with consumer default 719 if (dataSpace == HAL_DATASPACE_UNKNOWN) { 720 dataSpace = mCore->mDefaultBufferDataSpace; 721 } 722 723 mSlots[slot].mFence = fence; 724 mSlots[slot].mBufferState.queue(); 725 726 ++mCore->mFrameCounter; 727 mSlots[slot].mFrameNumber = mCore->mFrameCounter; 728 729 item.mAcquireCalled = mSlots[slot].mAcquireCalled; 730 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; 731 item.mCrop = crop; 732 item.mTransform = transform & 733 ~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY); 734 item.mTransformToDisplayInverse = 735 (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0; 736 item.mScalingMode = static_cast<uint32_t>(scalingMode); 737 item.mTimestamp = timestamp; 738 item.mIsAutoTimestamp = isAutoTimestamp; 739 item.mDataSpace = dataSpace; 740 item.mFrameNumber = mCore->mFrameCounter; 741 item.mSlot = slot; 742 item.mFence = fence; 743 item.mIsDroppable = mCore->mAsyncMode || 744 mCore->mDequeueBufferCannotBlock || 745 (mCore->mSingleBufferMode && mCore->mSingleBufferSlot == slot); 746 item.mSurfaceDamage = surfaceDamage; 747 748 mStickyTransform = stickyTransform; 749 750 // Cache the shared buffer data so that the BufferItem can be recreated. 751 if (mCore->mSingleBufferMode) { 752 mCore->mSingleBufferCache.crop = crop; 753 mCore->mSingleBufferCache.transform = transform; 754 mCore->mSingleBufferCache.scalingMode = static_cast<uint32_t>( 755 scalingMode); 756 mCore->mSingleBufferCache.dataspace = dataSpace; 757 } 758 759 if (mCore->mQueue.empty()) { 760 // When the queue is empty, we can ignore mDequeueBufferCannotBlock 761 // and simply queue this buffer 762 mCore->mQueue.push_back(item); 763 frameAvailableListener = mCore->mConsumerListener; 764 } else { 765 // When the queue is not empty, we need to look at the front buffer 766 // state to see if we need to replace it 767 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); 768 if (front->mIsDroppable) { 769 // If the front queued buffer is still being tracked, we first 770 // mark it as freed 771 if (mCore->stillTracking(front)) { 772 mSlots[front->mSlot].mBufferState.freeQueued(); 773 774 // After leaving single buffer mode, the shared buffer will 775 // still be around. Mark it as no longer shared if this 776 // operation causes it to be free. 777 if (!mCore->mSingleBufferMode && 778 mSlots[front->mSlot].mBufferState.isFree()) { 779 mSlots[front->mSlot].mBufferState.mShared = false; 780 } 781 // Don't put the shared buffer on the free list. 782 if (!mSlots[front->mSlot].mBufferState.isShared()) { 783 mCore->mFreeBuffers.push_front(front->mSlot); 784 } 785 } 786 // Overwrite the droppable buffer with the incoming one 787 *front = item; 788 frameReplacedListener = mCore->mConsumerListener; 789 } else { 790 mCore->mQueue.push_back(item); 791 frameAvailableListener = mCore->mConsumerListener; 792 } 793 } 794 795 mCore->mBufferHasBeenQueued = true; 796 mCore->mDequeueCondition.broadcast(); 797 798 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, 799 mCore->mTransformHint, 800 static_cast<uint32_t>(mCore->mQueue.size())); 801 802 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); 803 804 // Take a ticket for the callback functions 805 callbackTicket = mNextCallbackTicket++; 806 807 mCore->validateConsistencyLocked(); 808 } // Autolock scope 809 810 // Wait without lock held 811 if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) { 812 // Waiting here allows for two full buffers to be queued but not a 813 // third. In the event that frames take varying time, this makes a 814 // small trade-off in favor of latency rather than throughput. 815 mLastQueueBufferFence->waitForever("Throttling EGL Production"); 816 mLastQueueBufferFence = fence; 817 } 818 819 // Don't send the GraphicBuffer through the callback, and don't send 820 // the slot number, since the consumer shouldn't need it 821 item.mGraphicBuffer.clear(); 822 item.mSlot = BufferItem::INVALID_BUFFER_SLOT; 823 824 // Call back without the main BufferQueue lock held, but with the callback 825 // lock held so we can ensure that callbacks occur in order 826 { 827 Mutex::Autolock lock(mCallbackMutex); 828 while (callbackTicket != mCurrentCallbackTicket) { 829 mCallbackCondition.wait(mCallbackMutex); 830 } 831 832 if (frameAvailableListener != NULL) { 833 frameAvailableListener->onFrameAvailable(item); 834 } else if (frameReplacedListener != NULL) { 835 frameReplacedListener->onFrameReplaced(item); 836 } 837 838 ++mCurrentCallbackTicket; 839 mCallbackCondition.broadcast(); 840 } 841 842 return NO_ERROR; 843} 844 845status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) { 846 ATRACE_CALL(); 847 BQ_LOGV("cancelBuffer: slot %d", slot); 848 Mutex::Autolock lock(mCore->mMutex); 849 850 if (mCore->mIsAbandoned) { 851 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned"); 852 return NO_INIT; 853 } 854 855 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) { 856 BQ_LOGE("cancelBuffer: BufferQueue has no connected producer"); 857 return NO_INIT; 858 } 859 860 if (mCore->mSingleBufferMode) { 861 BQ_LOGE("cancelBuffer: cannot cancel a buffer in single buffer mode"); 862 return BAD_VALUE; 863 } 864 865 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 866 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", 867 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 868 return BAD_VALUE; 869 } else if (!mSlots[slot].mBufferState.isDequeued()) { 870 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer " 871 "(state = %s)", slot, mSlots[slot].mBufferState.string()); 872 return BAD_VALUE; 873 } else if (fence == NULL) { 874 BQ_LOGE("cancelBuffer: fence is NULL"); 875 return BAD_VALUE; 876 } 877 878 mSlots[slot].mBufferState.cancel(); 879 880 // After leaving single buffer mode, the shared buffer will still be around. 881 // Mark it as no longer shared if this operation causes it to be free. 882 if (!mCore->mSingleBufferMode && mSlots[slot].mBufferState.isFree()) { 883 mSlots[slot].mBufferState.mShared = false; 884 } 885 886 // Don't put the shared buffer on the free list. 887 if (!mSlots[slot].mBufferState.isShared()) { 888 mCore->mFreeBuffers.push_front(slot); 889 } 890 mSlots[slot].mFence = fence; 891 mCore->mDequeueCondition.broadcast(); 892 mCore->validateConsistencyLocked(); 893 894 return NO_ERROR; 895} 896 897int BufferQueueProducer::query(int what, int *outValue) { 898 ATRACE_CALL(); 899 Mutex::Autolock lock(mCore->mMutex); 900 901 if (outValue == NULL) { 902 BQ_LOGE("query: outValue was NULL"); 903 return BAD_VALUE; 904 } 905 906 if (mCore->mIsAbandoned) { 907 BQ_LOGE("query: BufferQueue has been abandoned"); 908 return NO_INIT; 909 } 910 911 int value; 912 switch (what) { 913 case NATIVE_WINDOW_WIDTH: 914 value = static_cast<int32_t>(mCore->mDefaultWidth); 915 break; 916 case NATIVE_WINDOW_HEIGHT: 917 value = static_cast<int32_t>(mCore->mDefaultHeight); 918 break; 919 case NATIVE_WINDOW_FORMAT: 920 value = static_cast<int32_t>(mCore->mDefaultBufferFormat); 921 break; 922 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 923 value = mCore->getMinUndequeuedBufferCountLocked(); 924 break; 925 case NATIVE_WINDOW_STICKY_TRANSFORM: 926 value = static_cast<int32_t>(mStickyTransform); 927 break; 928 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: 929 value = (mCore->mQueue.size() > 1); 930 break; 931 case NATIVE_WINDOW_CONSUMER_USAGE_BITS: 932 value = static_cast<int32_t>(mCore->mConsumerUsageBits); 933 break; 934 case NATIVE_WINDOW_DEFAULT_DATASPACE: 935 value = static_cast<int32_t>(mCore->mDefaultBufferDataSpace); 936 break; 937 case NATIVE_WINDOW_BUFFER_AGE: 938 if (mCore->mBufferAge > INT32_MAX) { 939 value = 0; 940 } else { 941 value = static_cast<int32_t>(mCore->mBufferAge); 942 } 943 break; 944 default: 945 return BAD_VALUE; 946 } 947 948 BQ_LOGV("query: %d? %d", what, value); 949 *outValue = value; 950 return NO_ERROR; 951} 952 953status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, 954 int api, bool producerControlledByApp, QueueBufferOutput *output) { 955 ATRACE_CALL(); 956 Mutex::Autolock lock(mCore->mMutex); 957 mConsumerName = mCore->mConsumerName; 958 BQ_LOGV("connect: api=%d producerControlledByApp=%s", api, 959 producerControlledByApp ? "true" : "false"); 960 961 if (mCore->mIsAbandoned) { 962 BQ_LOGE("connect: BufferQueue has been abandoned"); 963 return NO_INIT; 964 } 965 966 if (mCore->mConsumerListener == NULL) { 967 BQ_LOGE("connect: BufferQueue has no consumer"); 968 return NO_INIT; 969 } 970 971 if (output == NULL) { 972 BQ_LOGE("connect: output was NULL"); 973 return BAD_VALUE; 974 } 975 976 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { 977 BQ_LOGE("connect: already connected (cur=%d req=%d)", 978 mCore->mConnectedApi, api); 979 return BAD_VALUE; 980 } 981 982 int status = NO_ERROR; 983 switch (api) { 984 case NATIVE_WINDOW_API_EGL: 985 case NATIVE_WINDOW_API_CPU: 986 case NATIVE_WINDOW_API_MEDIA: 987 case NATIVE_WINDOW_API_CAMERA: 988 mCore->mConnectedApi = api; 989 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, 990 mCore->mTransformHint, 991 static_cast<uint32_t>(mCore->mQueue.size())); 992 993 // Set up a death notification so that we can disconnect 994 // automatically if the remote producer dies 995 if (listener != NULL && 996 IInterface::asBinder(listener)->remoteBinder() != NULL) { 997 status = IInterface::asBinder(listener)->linkToDeath( 998 static_cast<IBinder::DeathRecipient*>(this)); 999 if (status != NO_ERROR) { 1000 BQ_LOGE("connect: linkToDeath failed: %s (%d)", 1001 strerror(-status), status); 1002 } 1003 } 1004 mCore->mConnectedProducerListener = listener; 1005 break; 1006 default: 1007 BQ_LOGE("connect: unknown API %d", api); 1008 status = BAD_VALUE; 1009 break; 1010 } 1011 1012 mCore->mBufferHasBeenQueued = false; 1013 mCore->mDequeueBufferCannotBlock = mCore->mConsumerControlledByApp && 1014 producerControlledByApp; 1015 mCore->mAllowAllocation = true; 1016 1017 return status; 1018} 1019 1020status_t BufferQueueProducer::disconnect(int api) { 1021 ATRACE_CALL(); 1022 BQ_LOGV("disconnect: api %d", api); 1023 1024 int status = NO_ERROR; 1025 sp<IConsumerListener> listener; 1026 { // Autolock scope 1027 Mutex::Autolock lock(mCore->mMutex); 1028 mCore->waitWhileAllocatingLocked(); 1029 1030 if (mCore->mIsAbandoned) { 1031 // It's not really an error to disconnect after the surface has 1032 // been abandoned; it should just be a no-op. 1033 return NO_ERROR; 1034 } 1035 1036 switch (api) { 1037 case NATIVE_WINDOW_API_EGL: 1038 case NATIVE_WINDOW_API_CPU: 1039 case NATIVE_WINDOW_API_MEDIA: 1040 case NATIVE_WINDOW_API_CAMERA: 1041 if (mCore->mConnectedApi == api) { 1042 mCore->freeAllBuffersLocked(); 1043 1044 // Remove our death notification callback if we have one 1045 if (mCore->mConnectedProducerListener != NULL) { 1046 sp<IBinder> token = 1047 IInterface::asBinder(mCore->mConnectedProducerListener); 1048 // This can fail if we're here because of the death 1049 // notification, but we just ignore it 1050 token->unlinkToDeath( 1051 static_cast<IBinder::DeathRecipient*>(this)); 1052 } 1053 mCore->mConnectedProducerListener = NULL; 1054 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API; 1055 mCore->mSidebandStream.clear(); 1056 mCore->mDequeueCondition.broadcast(); 1057 listener = mCore->mConsumerListener; 1058 } else if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { 1059 BQ_LOGE("disconnect: still connected to another API " 1060 "(cur=%d req=%d)", mCore->mConnectedApi, api); 1061 status = BAD_VALUE; 1062 } 1063 break; 1064 default: 1065 BQ_LOGE("disconnect: unknown API %d", api); 1066 status = BAD_VALUE; 1067 break; 1068 } 1069 } // Autolock scope 1070 1071 // Call back without lock held 1072 if (listener != NULL) { 1073 listener->onBuffersReleased(); 1074 } 1075 1076 return status; 1077} 1078 1079status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) { 1080 sp<IConsumerListener> listener; 1081 { // Autolock scope 1082 Mutex::Autolock _l(mCore->mMutex); 1083 mCore->mSidebandStream = stream; 1084 listener = mCore->mConsumerListener; 1085 } // Autolock scope 1086 1087 if (listener != NULL) { 1088 listener->onSidebandStreamChanged(); 1089 } 1090 return NO_ERROR; 1091} 1092 1093void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height, 1094 PixelFormat format, uint32_t usage) { 1095 ATRACE_CALL(); 1096 while (true) { 1097 Vector<int> freeSlots; 1098 size_t newBufferCount = 0; 1099 uint32_t allocWidth = 0; 1100 uint32_t allocHeight = 0; 1101 PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN; 1102 uint32_t allocUsage = 0; 1103 { // Autolock scope 1104 Mutex::Autolock lock(mCore->mMutex); 1105 mCore->waitWhileAllocatingLocked(); 1106 1107 if (!mCore->mAllowAllocation) { 1108 BQ_LOGE("allocateBuffers: allocation is not allowed for this " 1109 "BufferQueue"); 1110 return; 1111 } 1112 1113 int currentBufferCount = 0; 1114 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { 1115 if (mSlots[slot].mGraphicBuffer != NULL) { 1116 ++currentBufferCount; 1117 } else { 1118 if (!mSlots[slot].mBufferState.isFree()) { 1119 BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE", 1120 slot); 1121 continue; 1122 } 1123 1124 freeSlots.push_back(slot); 1125 } 1126 } 1127 1128 int maxBufferCount = mCore->getMaxBufferCountLocked(); 1129 BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers", 1130 currentBufferCount, maxBufferCount); 1131 if (maxBufferCount <= currentBufferCount) 1132 return; 1133 newBufferCount = 1134 static_cast<size_t>(maxBufferCount - currentBufferCount); 1135 if (freeSlots.size() < newBufferCount) { 1136 BQ_LOGE("allocateBuffers: ran out of free slots"); 1137 return; 1138 } 1139 allocWidth = width > 0 ? width : mCore->mDefaultWidth; 1140 allocHeight = height > 0 ? height : mCore->mDefaultHeight; 1141 allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat; 1142 allocUsage = usage | mCore->mConsumerUsageBits; 1143 1144 mCore->mIsAllocating = true; 1145 } // Autolock scope 1146 1147 Vector<sp<GraphicBuffer>> buffers; 1148 for (size_t i = 0; i < newBufferCount; ++i) { 1149 status_t result = NO_ERROR; 1150 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( 1151 allocWidth, allocHeight, allocFormat, allocUsage, &result)); 1152 if (result != NO_ERROR) { 1153 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format" 1154 " %u, usage %u)", width, height, format, usage); 1155 Mutex::Autolock lock(mCore->mMutex); 1156 mCore->mIsAllocating = false; 1157 mCore->mIsAllocatingCondition.broadcast(); 1158 return; 1159 } 1160 buffers.push_back(graphicBuffer); 1161 } 1162 1163 { // Autolock scope 1164 Mutex::Autolock lock(mCore->mMutex); 1165 uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth; 1166 uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight; 1167 PixelFormat checkFormat = format != 0 ? 1168 format : mCore->mDefaultBufferFormat; 1169 uint32_t checkUsage = usage | mCore->mConsumerUsageBits; 1170 if (checkWidth != allocWidth || checkHeight != allocHeight || 1171 checkFormat != allocFormat || checkUsage != allocUsage) { 1172 // Something changed while we released the lock. Retry. 1173 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying."); 1174 mCore->mIsAllocating = false; 1175 mCore->mIsAllocatingCondition.broadcast(); 1176 continue; 1177 } 1178 1179 for (size_t i = 0; i < newBufferCount; ++i) { 1180 int slot = freeSlots[i]; 1181 if (!mSlots[slot].mBufferState.isFree()) { 1182 // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we 1183 // allocated. 1184 BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. " 1185 "Dropping allocated buffer.", slot); 1186 continue; 1187 } 1188 mCore->freeBufferLocked(slot); // Clean up the slot first 1189 mSlots[slot].mGraphicBuffer = buffers[i]; 1190 mSlots[slot].mFence = Fence::NO_FENCE; 1191 1192 // freeBufferLocked puts this slot on the free slots list. Since 1193 // we then attached a buffer, move the slot to free buffer list. 1194 mCore->mFreeSlots.erase(slot); 1195 mCore->mFreeBuffers.push_front(slot); 1196 1197 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot); 1198 } 1199 1200 mCore->mIsAllocating = false; 1201 mCore->mIsAllocatingCondition.broadcast(); 1202 mCore->validateConsistencyLocked(); 1203 } // Autolock scope 1204 } 1205} 1206 1207status_t BufferQueueProducer::allowAllocation(bool allow) { 1208 ATRACE_CALL(); 1209 BQ_LOGV("allowAllocation: %s", allow ? "true" : "false"); 1210 1211 Mutex::Autolock lock(mCore->mMutex); 1212 mCore->mAllowAllocation = allow; 1213 return NO_ERROR; 1214} 1215 1216status_t BufferQueueProducer::setGenerationNumber(uint32_t generationNumber) { 1217 ATRACE_CALL(); 1218 BQ_LOGV("setGenerationNumber: %u", generationNumber); 1219 1220 Mutex::Autolock lock(mCore->mMutex); 1221 mCore->mGenerationNumber = generationNumber; 1222 return NO_ERROR; 1223} 1224 1225String8 BufferQueueProducer::getConsumerName() const { 1226 ATRACE_CALL(); 1227 BQ_LOGV("getConsumerName: %s", mConsumerName.string()); 1228 return mConsumerName; 1229} 1230 1231uint64_t BufferQueueProducer::getNextFrameNumber() const { 1232 ATRACE_CALL(); 1233 1234 Mutex::Autolock lock(mCore->mMutex); 1235 uint64_t nextFrameNumber = mCore->mFrameCounter + 1; 1236 return nextFrameNumber; 1237} 1238 1239status_t BufferQueueProducer::setSingleBufferMode(bool singleBufferMode) { 1240 ATRACE_CALL(); 1241 BQ_LOGV("setSingleBufferMode: %d", singleBufferMode); 1242 1243 Mutex::Autolock lock(mCore->mMutex); 1244 if (!singleBufferMode) { 1245 mCore->mSingleBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT; 1246 } 1247 mCore->mSingleBufferMode = singleBufferMode; 1248 1249 return NO_ERROR; 1250} 1251 1252void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) { 1253 // If we're here, it means that a producer we were connected to died. 1254 // We're guaranteed that we are still connected to it because we remove 1255 // this callback upon disconnect. It's therefore safe to read mConnectedApi 1256 // without synchronization here. 1257 int api = mCore->mConnectedApi; 1258 disconnect(api); 1259} 1260 1261} // namespace android 1262