BufferQueueProducer.cpp revision 8dc55396fc9bc425b5e2c82e76a38080f2a655ff
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 (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 61 BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)", 62 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 63 return BAD_VALUE; 64 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 65 BQ_LOGE("requestBuffer: slot %d is not owned by the producer " 66 "(state = %d)", slot, mSlots[slot].mBufferState); 67 return BAD_VALUE; 68 } 69 70 mSlots[slot].mRequestBufferCalled = true; 71 *buf = mSlots[slot].mGraphicBuffer; 72 return NO_ERROR; 73} 74 75status_t BufferQueueProducer::setBufferCount(int bufferCount) { 76 ATRACE_CALL(); 77 BQ_LOGV("setBufferCount: count = %d", bufferCount); 78 79 sp<IConsumerListener> listener; 80 { // Autolock scope 81 Mutex::Autolock lock(mCore->mMutex); 82 mCore->waitWhileAllocatingLocked(); 83 84 if (mCore->mIsAbandoned) { 85 BQ_LOGE("setBufferCount: BufferQueue has been abandoned"); 86 return NO_INIT; 87 } 88 89 if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) { 90 BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)", 91 bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS); 92 return BAD_VALUE; 93 } 94 95 // There must be no dequeued buffers when changing the buffer count. 96 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 97 if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) { 98 BQ_LOGE("setBufferCount: buffer owned by producer"); 99 return BAD_VALUE; 100 } 101 } 102 103 if (bufferCount == 0) { 104 mCore->mOverrideMaxBufferCount = 0; 105 mCore->mDequeueCondition.broadcast(); 106 return NO_ERROR; 107 } 108 109 const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false); 110 if (bufferCount < minBufferSlots) { 111 BQ_LOGE("setBufferCount: requested buffer count %d is less than " 112 "minimum %d", bufferCount, minBufferSlots); 113 return BAD_VALUE; 114 } 115 116 // Here we are guaranteed that the producer doesn't have any dequeued 117 // buffers and will release all of its buffer references. We don't 118 // clear the queue, however, so that currently queued buffers still 119 // get displayed. 120 mCore->freeAllBuffersLocked(); 121 mCore->mOverrideMaxBufferCount = bufferCount; 122 mCore->mDequeueCondition.broadcast(); 123 listener = mCore->mConsumerListener; 124 } // Autolock scope 125 126 // Call back without lock held 127 if (listener != NULL) { 128 listener->onBuffersReleased(); 129 } 130 131 return NO_ERROR; 132} 133 134status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller, 135 bool async, int* found, status_t* returnFlags) const { 136 bool tryAgain = true; 137 while (tryAgain) { 138 if (mCore->mIsAbandoned) { 139 BQ_LOGE("%s: BufferQueue has been abandoned", caller); 140 return NO_INIT; 141 } 142 143 const int maxBufferCount = mCore->getMaxBufferCountLocked(async); 144 if (async && mCore->mOverrideMaxBufferCount) { 145 // FIXME: Some drivers are manually setting the buffer count 146 // (which they shouldn't), so we do this extra test here to 147 // handle that case. This is TEMPORARY until we get this fixed. 148 if (mCore->mOverrideMaxBufferCount < maxBufferCount) { 149 BQ_LOGE("%s: async mode is invalid with buffer count override", 150 caller); 151 return BAD_VALUE; 152 } 153 } 154 155 // Free up any buffers that are in slots beyond the max buffer count 156 for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 157 assert(mSlots[s].mBufferState == BufferSlot::FREE); 158 if (mSlots[s].mGraphicBuffer != NULL) { 159 mCore->freeBufferLocked(s); 160 *returnFlags |= RELEASE_ALL_BUFFERS; 161 } 162 } 163 164 // Look for a free buffer to give to the client 165 *found = BufferQueueCore::INVALID_BUFFER_SLOT; 166 int dequeuedCount = 0; 167 int acquiredCount = 0; 168 for (int s = 0; s < maxBufferCount; ++s) { 169 switch (mSlots[s].mBufferState) { 170 case BufferSlot::DEQUEUED: 171 ++dequeuedCount; 172 break; 173 case BufferSlot::ACQUIRED: 174 ++acquiredCount; 175 break; 176 case BufferSlot::FREE: 177 // We return the oldest of the free buffers to avoid 178 // stalling the producer if possible, since the consumer 179 // may still have pending reads of in-flight buffers 180 if (*found == BufferQueueCore::INVALID_BUFFER_SLOT || 181 mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) { 182 *found = s; 183 } 184 break; 185 default: 186 break; 187 } 188 } 189 190 // Producers are not allowed to dequeue more than one buffer if they 191 // did not set a buffer count 192 if (!mCore->mOverrideMaxBufferCount && dequeuedCount) { 193 BQ_LOGE("%s: can't dequeue multiple buffers without setting the " 194 "buffer count", caller); 195 return INVALID_OPERATION; 196 } 197 198 // See whether a buffer has been queued since the last 199 // setBufferCount so we know whether to perform the min undequeued 200 // buffers check below 201 if (mCore->mBufferHasBeenQueued) { 202 // Make sure the producer is not trying to dequeue more buffers 203 // than allowed 204 const int newUndequeuedCount = 205 maxBufferCount - (dequeuedCount + 1); 206 const int minUndequeuedCount = 207 mCore->getMinUndequeuedBufferCountLocked(async); 208 if (newUndequeuedCount < minUndequeuedCount) { 209 BQ_LOGE("%s: min undequeued buffer count (%d) exceeded " 210 "(dequeued=%d undequeued=%d)", 211 caller, minUndequeuedCount, 212 dequeuedCount, newUndequeuedCount); 213 return INVALID_OPERATION; 214 } 215 } 216 217 // If we disconnect and reconnect quickly, we can be in a state where 218 // our slots are empty but we have many buffers in the queue. This can 219 // cause us to run out of memory if we outrun the consumer. Wait here if 220 // it looks like we have too many buffers queued up. 221 bool tooManyBuffers = mCore->mQueue.size() 222 > static_cast<size_t>(maxBufferCount); 223 if (tooManyBuffers) { 224 BQ_LOGV("%s: queue size is %zu, waiting", caller, 225 mCore->mQueue.size()); 226 } 227 228 // If no buffer is found, or if the queue has too many buffers 229 // outstanding, wait for a buffer to be acquired or released, or for the 230 // max buffer count to change. 231 tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) || 232 tooManyBuffers; 233 if (tryAgain) { 234 // Return an error if we're in non-blocking mode (producer and 235 // consumer are controlled by the application). 236 // However, the consumer is allowed to briefly acquire an extra 237 // buffer (which could cause us to have to wait here), which is 238 // okay, since it is only used to implement an atomic acquire + 239 // release (e.g., in GLConsumer::updateTexImage()) 240 if (mCore->mDequeueBufferCannotBlock && 241 (acquiredCount <= mCore->mMaxAcquiredBufferCount)) { 242 return WOULD_BLOCK; 243 } 244 mCore->mDequeueCondition.wait(mCore->mMutex); 245 } 246 } // while (tryAgain) 247 248 return NO_ERROR; 249} 250 251status_t BufferQueueProducer::dequeueBuffer(int *outSlot, 252 sp<android::Fence> *outFence, bool async, 253 uint32_t width, uint32_t height, uint32_t format, uint32_t usage) { 254 ATRACE_CALL(); 255 { // Autolock scope 256 Mutex::Autolock lock(mCore->mMutex); 257 mConsumerName = mCore->mConsumerName; 258 } // Autolock scope 259 260 BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x", 261 async ? "true" : "false", width, height, format, usage); 262 263 if ((width && !height) || (!width && height)) { 264 BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height); 265 return BAD_VALUE; 266 } 267 268 status_t returnFlags = NO_ERROR; 269 EGLDisplay eglDisplay = EGL_NO_DISPLAY; 270 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR; 271 bool attachedByConsumer = false; 272 273 { // Autolock scope 274 Mutex::Autolock lock(mCore->mMutex); 275 mCore->waitWhileAllocatingLocked(); 276 277 if (format == 0) { 278 format = mCore->mDefaultBufferFormat; 279 } 280 281 // Enable the usage bits the consumer requested 282 usage |= mCore->mConsumerUsageBits; 283 284 int found; 285 status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async, 286 &found, &returnFlags); 287 if (status != NO_ERROR) { 288 return status; 289 } 290 291 // This should not happen 292 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 293 BQ_LOGE("dequeueBuffer: no available buffer slots"); 294 return -EBUSY; 295 } 296 297 *outSlot = found; 298 ATRACE_BUFFER_INDEX(found); 299 300 attachedByConsumer = mSlots[found].mAttachedByConsumer; 301 302 const bool useDefaultSize = !width && !height; 303 if (useDefaultSize) { 304 width = mCore->mDefaultWidth; 305 height = mCore->mDefaultHeight; 306 } 307 308 mSlots[found].mBufferState = BufferSlot::DEQUEUED; 309 310 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); 311 if ((buffer == NULL) || 312 (static_cast<uint32_t>(buffer->width) != width) || 313 (static_cast<uint32_t>(buffer->height) != height) || 314 (static_cast<uint32_t>(buffer->format) != format) || 315 ((static_cast<uint32_t>(buffer->usage) & usage) != usage)) 316 { 317 mSlots[found].mAcquireCalled = false; 318 mSlots[found].mGraphicBuffer = NULL; 319 mSlots[found].mRequestBufferCalled = false; 320 mSlots[found].mEglDisplay = EGL_NO_DISPLAY; 321 mSlots[found].mEglFence = EGL_NO_SYNC_KHR; 322 mSlots[found].mFence = Fence::NO_FENCE; 323 324 returnFlags |= BUFFER_NEEDS_REALLOCATION; 325 } 326 327 if (CC_UNLIKELY(mSlots[found].mFence == NULL)) { 328 BQ_LOGE("dequeueBuffer: about to return a NULL fence - " 329 "slot=%d w=%d h=%d format=%u", 330 found, buffer->width, buffer->height, buffer->format); 331 } 332 333 eglDisplay = mSlots[found].mEglDisplay; 334 eglFence = mSlots[found].mEglFence; 335 *outFence = mSlots[found].mFence; 336 mSlots[found].mEglFence = EGL_NO_SYNC_KHR; 337 mSlots[found].mFence = Fence::NO_FENCE; 338 } // Autolock scope 339 340 if (returnFlags & BUFFER_NEEDS_REALLOCATION) { 341 status_t error; 342 BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot); 343 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( 344 width, height, format, usage, &error)); 345 if (graphicBuffer == NULL) { 346 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed"); 347 return error; 348 } 349 350 { // Autolock scope 351 Mutex::Autolock lock(mCore->mMutex); 352 353 if (mCore->mIsAbandoned) { 354 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned"); 355 return NO_INIT; 356 } 357 358 mSlots[*outSlot].mFrameNumber = UINT32_MAX; 359 mSlots[*outSlot].mGraphicBuffer = graphicBuffer; 360 } // Autolock scope 361 } 362 363 if (attachedByConsumer) { 364 returnFlags |= BUFFER_NEEDS_REALLOCATION; 365 } 366 367 if (eglFence != EGL_NO_SYNC_KHR) { 368 EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0, 369 1000000000); 370 // If something goes wrong, log the error, but return the buffer without 371 // synchronizing access to it. It's too late at this point to abort the 372 // dequeue operation. 373 if (result == EGL_FALSE) { 374 BQ_LOGE("dequeueBuffer: error %#x waiting for fence", 375 eglGetError()); 376 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 377 BQ_LOGE("dequeueBuffer: timeout waiting for fence"); 378 } 379 eglDestroySyncKHR(eglDisplay, eglFence); 380 } 381 382 BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x", 383 *outSlot, 384 mSlots[*outSlot].mFrameNumber, 385 mSlots[*outSlot].mGraphicBuffer->handle, returnFlags); 386 387 return returnFlags; 388} 389 390status_t BufferQueueProducer::detachBuffer(int slot) { 391 ATRACE_CALL(); 392 ATRACE_BUFFER_INDEX(slot); 393 BQ_LOGV("detachBuffer(P): slot %d", slot); 394 Mutex::Autolock lock(mCore->mMutex); 395 396 if (mCore->mIsAbandoned) { 397 BQ_LOGE("detachBuffer(P): BufferQueue has been abandoned"); 398 return NO_INIT; 399 } 400 401 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 402 BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)", 403 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 404 return BAD_VALUE; 405 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 406 BQ_LOGE("detachBuffer(P): slot %d is not owned by the producer " 407 "(state = %d)", slot, mSlots[slot].mBufferState); 408 return BAD_VALUE; 409 } else if (!mSlots[slot].mRequestBufferCalled) { 410 BQ_LOGE("detachBuffer(P): buffer in slot %d has not been requested", 411 slot); 412 return BAD_VALUE; 413 } 414 415 mCore->freeBufferLocked(slot); 416 mCore->mDequeueCondition.broadcast(); 417 418 return NO_ERROR; 419} 420 421status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer, 422 sp<Fence>* outFence) { 423 ATRACE_CALL(); 424 425 if (outBuffer == NULL) { 426 BQ_LOGE("detachNextBuffer: outBuffer must not be NULL"); 427 return BAD_VALUE; 428 } else if (outFence == NULL) { 429 BQ_LOGE("detachNextBuffer: outFence must not be NULL"); 430 return BAD_VALUE; 431 } 432 433 Mutex::Autolock lock(mCore->mMutex); 434 mCore->waitWhileAllocatingLocked(); 435 436 if (mCore->mIsAbandoned) { 437 BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned"); 438 return NO_INIT; 439 } 440 441 // Find the oldest valid slot 442 int found = BufferQueueCore::INVALID_BUFFER_SLOT; 443 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 444 if (mSlots[s].mBufferState == BufferSlot::FREE && 445 mSlots[s].mGraphicBuffer != NULL) { 446 if (found == BufferQueueCore::INVALID_BUFFER_SLOT || 447 mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) { 448 found = s; 449 } 450 } 451 } 452 453 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 454 return NO_MEMORY; 455 } 456 457 BQ_LOGV("detachNextBuffer detached slot %d", found); 458 459 *outBuffer = mSlots[found].mGraphicBuffer; 460 *outFence = mSlots[found].mFence; 461 mCore->freeBufferLocked(found); 462 463 return NO_ERROR; 464} 465 466status_t BufferQueueProducer::attachBuffer(int* outSlot, 467 const sp<android::GraphicBuffer>& buffer) { 468 ATRACE_CALL(); 469 470 if (outSlot == NULL) { 471 BQ_LOGE("attachBuffer(P): outSlot must not be NULL"); 472 return BAD_VALUE; 473 } else if (buffer == NULL) { 474 BQ_LOGE("attachBuffer(P): cannot attach NULL buffer"); 475 return BAD_VALUE; 476 } 477 478 Mutex::Autolock lock(mCore->mMutex); 479 mCore->waitWhileAllocatingLocked(); 480 481 status_t returnFlags = NO_ERROR; 482 int found; 483 // TODO: Should we provide an async flag to attachBuffer? It seems 484 // unlikely that buffers which we are attaching to a BufferQueue will 485 // be asynchronous (droppable), but it may not be impossible. 486 status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false, 487 &found, &returnFlags); 488 if (status != NO_ERROR) { 489 return status; 490 } 491 492 // This should not happen 493 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 494 BQ_LOGE("attachBuffer(P): no available buffer slots"); 495 return -EBUSY; 496 } 497 498 *outSlot = found; 499 ATRACE_BUFFER_INDEX(*outSlot); 500 BQ_LOGV("attachBuffer(P): returning slot %d flags=%#x", 501 *outSlot, returnFlags); 502 503 mSlots[*outSlot].mGraphicBuffer = buffer; 504 mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED; 505 mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR; 506 mSlots[*outSlot].mFence = Fence::NO_FENCE; 507 mSlots[*outSlot].mRequestBufferCalled = true; 508 509 return returnFlags; 510} 511 512status_t BufferQueueProducer::queueBuffer(int slot, 513 const QueueBufferInput &input, QueueBufferOutput *output) { 514 ATRACE_CALL(); 515 ATRACE_BUFFER_INDEX(slot); 516 517 int64_t timestamp; 518 bool isAutoTimestamp; 519 Rect crop; 520 int scalingMode; 521 uint32_t transform; 522 uint32_t stickyTransform; 523 bool async; 524 sp<Fence> fence; 525 input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform, 526 &async, &fence, &stickyTransform); 527 528 if (fence == NULL) { 529 BQ_LOGE("queueBuffer: fence is NULL"); 530 // Temporary workaround for b/17946343: soldier-on instead of returning an error. This 531 // prevents the client from dying, at the risk of visible corruption due to hwcomposer 532 // reading the buffer before the producer is done rendering it. Unless the buffer is the 533 // last frame of an animation, the corruption will be transient. 534 fence = Fence::NO_FENCE; 535 // return BAD_VALUE; 536 } 537 538 switch (scalingMode) { 539 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 540 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 541 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: 542 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: 543 break; 544 default: 545 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode); 546 return BAD_VALUE; 547 } 548 549 sp<IConsumerListener> frameAvailableListener; 550 sp<IConsumerListener> frameReplacedListener; 551 int callbackTicket = 0; 552 BufferItem item; 553 { // Autolock scope 554 Mutex::Autolock lock(mCore->mMutex); 555 556 if (mCore->mIsAbandoned) { 557 BQ_LOGE("queueBuffer: BufferQueue has been abandoned"); 558 return NO_INIT; 559 } 560 561 const int maxBufferCount = mCore->getMaxBufferCountLocked(async); 562 if (async && mCore->mOverrideMaxBufferCount) { 563 // FIXME: Some drivers are manually setting the buffer count 564 // (which they shouldn't), so we do this extra test here to 565 // handle that case. This is TEMPORARY until we get this fixed. 566 if (mCore->mOverrideMaxBufferCount < maxBufferCount) { 567 BQ_LOGE("queueBuffer: async mode is invalid with " 568 "buffer count override"); 569 return BAD_VALUE; 570 } 571 } 572 573 if (slot < 0 || slot >= maxBufferCount) { 574 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)", 575 slot, maxBufferCount); 576 return BAD_VALUE; 577 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 578 BQ_LOGE("queueBuffer: slot %d is not owned by the producer " 579 "(state = %d)", slot, mSlots[slot].mBufferState); 580 return BAD_VALUE; 581 } else if (!mSlots[slot].mRequestBufferCalled) { 582 BQ_LOGE("queueBuffer: slot %d was queued without requesting " 583 "a buffer", slot); 584 return BAD_VALUE; 585 } 586 587 BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 588 " crop=[%d,%d,%d,%d] transform=%#x scale=%s", 589 slot, mCore->mFrameCounter + 1, timestamp, 590 crop.left, crop.top, crop.right, crop.bottom, 591 transform, BufferItem::scalingModeName(scalingMode)); 592 593 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer); 594 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); 595 Rect croppedRect; 596 crop.intersect(bufferRect, &croppedRect); 597 if (croppedRect != crop) { 598 BQ_LOGE("queueBuffer: crop rect is not contained within the " 599 "buffer in slot %d", slot); 600 return BAD_VALUE; 601 } 602 603 mSlots[slot].mFence = fence; 604 mSlots[slot].mBufferState = BufferSlot::QUEUED; 605 ++mCore->mFrameCounter; 606 mSlots[slot].mFrameNumber = mCore->mFrameCounter; 607 608 item.mAcquireCalled = mSlots[slot].mAcquireCalled; 609 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; 610 item.mCrop = crop; 611 item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; 612 item.mTransformToDisplayInverse = 613 bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY); 614 item.mScalingMode = scalingMode; 615 item.mTimestamp = timestamp; 616 item.mIsAutoTimestamp = isAutoTimestamp; 617 item.mFrameNumber = mCore->mFrameCounter; 618 item.mSlot = slot; 619 item.mFence = fence; 620 item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async; 621 622 mStickyTransform = stickyTransform; 623 624 if (mCore->mQueue.empty()) { 625 // When the queue is empty, we can ignore mDequeueBufferCannotBlock 626 // and simply queue this buffer 627 mCore->mQueue.push_back(item); 628 frameAvailableListener = mCore->mConsumerListener; 629 } else { 630 // When the queue is not empty, we need to look at the front buffer 631 // state to see if we need to replace it 632 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); 633 if (front->mIsDroppable) { 634 // If the front queued buffer is still being tracked, we first 635 // mark it as freed 636 if (mCore->stillTracking(front)) { 637 mSlots[front->mSlot].mBufferState = BufferSlot::FREE; 638 // Reset the frame number of the freed buffer so that it is 639 // the first in line to be dequeued again 640 mSlots[front->mSlot].mFrameNumber = 0; 641 } 642 // Overwrite the droppable buffer with the incoming one 643 *front = item; 644 frameReplacedListener = mCore->mConsumerListener; 645 } else { 646 mCore->mQueue.push_back(item); 647 frameAvailableListener = mCore->mConsumerListener; 648 } 649 } 650 651 mCore->mBufferHasBeenQueued = true; 652 mCore->mDequeueCondition.broadcast(); 653 654 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, 655 mCore->mTransformHint, mCore->mQueue.size()); 656 657 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); 658 659 // Take a ticket for the callback functions 660 callbackTicket = mNextCallbackTicket++; 661 } // Autolock scope 662 663 // Wait without lock held 664 if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) { 665 // Waiting here allows for two full buffers to be queued but not a 666 // third. In the event that frames take varying time, this makes a 667 // small trade-off in favor of latency rather than throughput. 668 mLastQueueBufferFence->waitForever("Throttling EGL Production"); 669 mLastQueueBufferFence = fence; 670 } 671 672 // Don't send the GraphicBuffer through the callback, and don't send 673 // the slot number, since the consumer shouldn't need it 674 item.mGraphicBuffer.clear(); 675 item.mSlot = BufferItem::INVALID_BUFFER_SLOT; 676 677 // Call back without the main BufferQueue lock held, but with the callback 678 // lock held so we can ensure that callbacks occur in order 679 { 680 Mutex::Autolock lock(mCallbackMutex); 681 while (callbackTicket != mCurrentCallbackTicket) { 682 mCallbackCondition.wait(mCallbackMutex); 683 } 684 685 if (frameAvailableListener != NULL) { 686 frameAvailableListener->onFrameAvailable(item); 687 } else if (frameReplacedListener != NULL) { 688 frameReplacedListener->onFrameReplaced(item); 689 } 690 691 ++mCurrentCallbackTicket; 692 mCallbackCondition.broadcast(); 693 } 694 695 return NO_ERROR; 696} 697 698void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) { 699 ATRACE_CALL(); 700 BQ_LOGV("cancelBuffer: slot %d", slot); 701 Mutex::Autolock lock(mCore->mMutex); 702 703 if (mCore->mIsAbandoned) { 704 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned"); 705 return; 706 } 707 708 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 709 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", 710 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 711 return; 712 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 713 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer " 714 "(state = %d)", slot, mSlots[slot].mBufferState); 715 return; 716 } else if (fence == NULL) { 717 BQ_LOGE("cancelBuffer: fence is NULL"); 718 return; 719 } 720 721 mSlots[slot].mBufferState = BufferSlot::FREE; 722 mSlots[slot].mFrameNumber = 0; 723 mSlots[slot].mFence = fence; 724 mCore->mDequeueCondition.broadcast(); 725} 726 727int BufferQueueProducer::query(int what, int *outValue) { 728 ATRACE_CALL(); 729 Mutex::Autolock lock(mCore->mMutex); 730 731 if (outValue == NULL) { 732 BQ_LOGE("query: outValue was NULL"); 733 return BAD_VALUE; 734 } 735 736 if (mCore->mIsAbandoned) { 737 BQ_LOGE("query: BufferQueue has been abandoned"); 738 return NO_INIT; 739 } 740 741 int value; 742 switch (what) { 743 case NATIVE_WINDOW_WIDTH: 744 value = mCore->mDefaultWidth; 745 break; 746 case NATIVE_WINDOW_HEIGHT: 747 value = mCore->mDefaultHeight; 748 break; 749 case NATIVE_WINDOW_FORMAT: 750 value = mCore->mDefaultBufferFormat; 751 break; 752 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 753 value = mCore->getMinUndequeuedBufferCountLocked(false); 754 break; 755 case NATIVE_WINDOW_STICKY_TRANSFORM: 756 value = static_cast<int>(mStickyTransform); 757 break; 758 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: 759 value = (mCore->mQueue.size() > 1); 760 break; 761 case NATIVE_WINDOW_CONSUMER_USAGE_BITS: 762 value = mCore->mConsumerUsageBits; 763 break; 764 default: 765 return BAD_VALUE; 766 } 767 768 BQ_LOGV("query: %d? %d", what, value); 769 *outValue = value; 770 return NO_ERROR; 771} 772 773status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, 774 int api, bool producerControlledByApp, QueueBufferOutput *output) { 775 ATRACE_CALL(); 776 Mutex::Autolock lock(mCore->mMutex); 777 mConsumerName = mCore->mConsumerName; 778 BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api, 779 producerControlledByApp ? "true" : "false"); 780 781 if (mCore->mIsAbandoned) { 782 BQ_LOGE("connect(P): BufferQueue has been abandoned"); 783 return NO_INIT; 784 } 785 786 if (mCore->mConsumerListener == NULL) { 787 BQ_LOGE("connect(P): BufferQueue has no consumer"); 788 return NO_INIT; 789 } 790 791 if (output == NULL) { 792 BQ_LOGE("connect(P): output was NULL"); 793 return BAD_VALUE; 794 } 795 796 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { 797 BQ_LOGE("connect(P): already connected (cur=%d req=%d)", 798 mCore->mConnectedApi, api); 799 return BAD_VALUE; 800 } 801 802 int status = NO_ERROR; 803 switch (api) { 804 case NATIVE_WINDOW_API_EGL: 805 case NATIVE_WINDOW_API_CPU: 806 case NATIVE_WINDOW_API_MEDIA: 807 case NATIVE_WINDOW_API_CAMERA: 808 mCore->mConnectedApi = api; 809 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, 810 mCore->mTransformHint, mCore->mQueue.size()); 811 812 // Set up a death notification so that we can disconnect 813 // automatically if the remote producer dies 814 if (listener != NULL && 815 listener->asBinder()->remoteBinder() != NULL) { 816 status = listener->asBinder()->linkToDeath( 817 static_cast<IBinder::DeathRecipient*>(this)); 818 if (status != NO_ERROR) { 819 BQ_LOGE("connect(P): linkToDeath failed: %s (%d)", 820 strerror(-status), status); 821 } 822 } 823 mCore->mConnectedProducerListener = listener; 824 break; 825 default: 826 BQ_LOGE("connect(P): unknown API %d", api); 827 status = BAD_VALUE; 828 break; 829 } 830 831 mCore->mBufferHasBeenQueued = false; 832 mCore->mDequeueBufferCannotBlock = 833 mCore->mConsumerControlledByApp && producerControlledByApp; 834 835 return status; 836} 837 838status_t BufferQueueProducer::disconnect(int api) { 839 ATRACE_CALL(); 840 BQ_LOGV("disconnect(P): api %d", api); 841 842 int status = NO_ERROR; 843 sp<IConsumerListener> listener; 844 { // Autolock scope 845 Mutex::Autolock lock(mCore->mMutex); 846 mCore->waitWhileAllocatingLocked(); 847 848 if (mCore->mIsAbandoned) { 849 // It's not really an error to disconnect after the surface has 850 // been abandoned; it should just be a no-op. 851 return NO_ERROR; 852 } 853 854 switch (api) { 855 case NATIVE_WINDOW_API_EGL: 856 case NATIVE_WINDOW_API_CPU: 857 case NATIVE_WINDOW_API_MEDIA: 858 case NATIVE_WINDOW_API_CAMERA: 859 if (mCore->mConnectedApi == api) { 860 mCore->freeAllBuffersLocked(); 861 862 // Remove our death notification callback if we have one 863 if (mCore->mConnectedProducerListener != NULL) { 864 sp<IBinder> token = 865 mCore->mConnectedProducerListener->asBinder(); 866 // This can fail if we're here because of the death 867 // notification, but we just ignore it 868 token->unlinkToDeath( 869 static_cast<IBinder::DeathRecipient*>(this)); 870 } 871 mCore->mConnectedProducerListener = NULL; 872 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API; 873 mCore->mSidebandStream.clear(); 874 mCore->mDequeueCondition.broadcast(); 875 listener = mCore->mConsumerListener; 876 } else { 877 BQ_LOGE("disconnect(P): connected to another API " 878 "(cur=%d req=%d)", mCore->mConnectedApi, api); 879 status = BAD_VALUE; 880 } 881 break; 882 default: 883 BQ_LOGE("disconnect(P): unknown API %d", api); 884 status = BAD_VALUE; 885 break; 886 } 887 } // Autolock scope 888 889 // Call back without lock held 890 if (listener != NULL) { 891 listener->onBuffersReleased(); 892 } 893 894 return status; 895} 896 897status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) { 898 sp<IConsumerListener> listener; 899 { // Autolock scope 900 Mutex::Autolock _l(mCore->mMutex); 901 mCore->mSidebandStream = stream; 902 listener = mCore->mConsumerListener; 903 } // Autolock scope 904 905 if (listener != NULL) { 906 listener->onSidebandStreamChanged(); 907 } 908 return NO_ERROR; 909} 910 911void BufferQueueProducer::allocateBuffers(bool async, uint32_t width, 912 uint32_t height, uint32_t format, uint32_t usage) { 913 ATRACE_CALL(); 914 while (true) { 915 Vector<int> freeSlots; 916 size_t newBufferCount = 0; 917 uint32_t allocWidth = 0; 918 uint32_t allocHeight = 0; 919 uint32_t allocFormat = 0; 920 uint32_t allocUsage = 0; 921 { // Autolock scope 922 Mutex::Autolock lock(mCore->mMutex); 923 mCore->waitWhileAllocatingLocked(); 924 925 int currentBufferCount = 0; 926 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { 927 if (mSlots[slot].mGraphicBuffer != NULL) { 928 ++currentBufferCount; 929 } else { 930 if (mSlots[slot].mBufferState != BufferSlot::FREE) { 931 BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE", 932 slot); 933 continue; 934 } 935 936 freeSlots.push_back(slot); 937 } 938 } 939 940 int maxBufferCount = mCore->getMaxBufferCountLocked(async); 941 BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers", 942 currentBufferCount, maxBufferCount); 943 if (maxBufferCount <= currentBufferCount) 944 return; 945 newBufferCount = maxBufferCount - currentBufferCount; 946 if (freeSlots.size() < newBufferCount) { 947 BQ_LOGE("allocateBuffers: ran out of free slots"); 948 return; 949 } 950 allocWidth = width > 0 ? width : mCore->mDefaultWidth; 951 allocHeight = height > 0 ? height : mCore->mDefaultHeight; 952 allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat; 953 allocUsage = usage | mCore->mConsumerUsageBits; 954 955 mCore->mIsAllocating = true; 956 } // Autolock scope 957 958 Vector<sp<GraphicBuffer> > buffers; 959 for (size_t i = 0; i < newBufferCount; ++i) { 960 status_t result = NO_ERROR; 961 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( 962 allocWidth, allocHeight, allocFormat, allocUsage, &result)); 963 if (result != NO_ERROR) { 964 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format" 965 " %u, usage %u)", width, height, format, usage); 966 Mutex::Autolock lock(mCore->mMutex); 967 mCore->mIsAllocating = false; 968 mCore->mIsAllocatingCondition.broadcast(); 969 return; 970 } 971 buffers.push_back(graphicBuffer); 972 } 973 974 { // Autolock scope 975 Mutex::Autolock lock(mCore->mMutex); 976 uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth; 977 uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight; 978 uint32_t checkFormat = format != 0 ? format : mCore->mDefaultBufferFormat; 979 uint32_t checkUsage = usage | mCore->mConsumerUsageBits; 980 if (checkWidth != allocWidth || checkHeight != allocHeight || 981 checkFormat != allocFormat || checkUsage != allocUsage) { 982 // Something changed while we released the lock. Retry. 983 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying."); 984 mCore->mIsAllocating = false; 985 mCore->mIsAllocatingCondition.broadcast(); 986 continue; 987 } 988 989 for (size_t i = 0; i < newBufferCount; ++i) { 990 int slot = freeSlots[i]; 991 if (mSlots[slot].mBufferState != BufferSlot::FREE) { 992 // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we 993 // allocated. 994 BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. " 995 "Dropping allocated buffer.", slot); 996 continue; 997 } 998 mCore->freeBufferLocked(slot); // Clean up the slot first 999 mSlots[slot].mGraphicBuffer = buffers[i]; 1000 mSlots[slot].mFrameNumber = 0; 1001 mSlots[slot].mFence = Fence::NO_FENCE; 1002 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot); 1003 } 1004 1005 mCore->mIsAllocating = false; 1006 mCore->mIsAllocatingCondition.broadcast(); 1007 } // Autolock scope 1008 } 1009} 1010 1011void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) { 1012 // If we're here, it means that a producer we were connected to died. 1013 // We're guaranteed that we are still connected to it because we remove 1014 // this callback upon disconnect. It's therefore safe to read mConnectedApi 1015 // without synchronization here. 1016 int api = mCore->mConnectedApi; 1017 disconnect(api); 1018} 1019 1020} // namespace android 1021