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 35 namespace android { 36 BufferQueueProducer(const sp<BufferQueueCore> & core)37 BufferQueueProducer::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 ~BufferQueueProducer()48 BufferQueueProducer::~BufferQueueProducer() {} 49 requestBuffer(int slot,sp<GraphicBuffer> * buf)50 status_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 setBufferCount(int bufferCount)75 status_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 waitForFreeSlotThenRelock(const char * caller,bool async,int * found,status_t * returnFlags) const134 status_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 dequeueBuffer(int * outSlot,sp<android::Fence> * outFence,bool async,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)251 status_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 detachBuffer(int slot)390 status_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 detachNextBuffer(sp<GraphicBuffer> * outBuffer,sp<Fence> * outFence)421 status_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 attachBuffer(int * outSlot,const sp<android::GraphicBuffer> & buffer)466 status_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 queueBuffer(int slot,const QueueBufferInput & input,QueueBufferOutput * output)512 status_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 return BAD_VALUE; 531 } 532 533 switch (scalingMode) { 534 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 535 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 536 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: 537 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: 538 break; 539 default: 540 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode); 541 return BAD_VALUE; 542 } 543 544 sp<IConsumerListener> frameAvailableListener; 545 sp<IConsumerListener> frameReplacedListener; 546 int callbackTicket = 0; 547 BufferItem item; 548 { // Autolock scope 549 Mutex::Autolock lock(mCore->mMutex); 550 551 if (mCore->mIsAbandoned) { 552 BQ_LOGE("queueBuffer: BufferQueue has been abandoned"); 553 return NO_INIT; 554 } 555 556 const int maxBufferCount = mCore->getMaxBufferCountLocked(async); 557 if (async && mCore->mOverrideMaxBufferCount) { 558 // FIXME: Some drivers are manually setting the buffer count 559 // (which they shouldn't), so we do this extra test here to 560 // handle that case. This is TEMPORARY until we get this fixed. 561 if (mCore->mOverrideMaxBufferCount < maxBufferCount) { 562 BQ_LOGE("queueBuffer: async mode is invalid with " 563 "buffer count override"); 564 return BAD_VALUE; 565 } 566 } 567 568 if (slot < 0 || slot >= maxBufferCount) { 569 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)", 570 slot, maxBufferCount); 571 return BAD_VALUE; 572 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 573 BQ_LOGE("queueBuffer: slot %d is not owned by the producer " 574 "(state = %d)", slot, mSlots[slot].mBufferState); 575 return BAD_VALUE; 576 } else if (!mSlots[slot].mRequestBufferCalled) { 577 BQ_LOGE("queueBuffer: slot %d was queued without requesting " 578 "a buffer", slot); 579 return BAD_VALUE; 580 } 581 582 BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 583 " crop=[%d,%d,%d,%d] transform=%#x scale=%s", 584 slot, mCore->mFrameCounter + 1, timestamp, 585 crop.left, crop.top, crop.right, crop.bottom, 586 transform, BufferItem::scalingModeName(scalingMode)); 587 588 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer); 589 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); 590 Rect croppedRect; 591 crop.intersect(bufferRect, &croppedRect); 592 if (croppedRect != crop) { 593 BQ_LOGE("queueBuffer: crop rect is not contained within the " 594 "buffer in slot %d", slot); 595 return BAD_VALUE; 596 } 597 598 mSlots[slot].mFence = fence; 599 mSlots[slot].mBufferState = BufferSlot::QUEUED; 600 ++mCore->mFrameCounter; 601 mSlots[slot].mFrameNumber = mCore->mFrameCounter; 602 603 item.mAcquireCalled = mSlots[slot].mAcquireCalled; 604 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; 605 item.mCrop = crop; 606 item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; 607 item.mTransformToDisplayInverse = 608 bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY); 609 item.mScalingMode = scalingMode; 610 item.mTimestamp = timestamp; 611 item.mIsAutoTimestamp = isAutoTimestamp; 612 item.mFrameNumber = mCore->mFrameCounter; 613 item.mSlot = slot; 614 item.mFence = fence; 615 item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async; 616 617 mStickyTransform = stickyTransform; 618 619 if (mCore->mQueue.empty()) { 620 // When the queue is empty, we can ignore mDequeueBufferCannotBlock 621 // and simply queue this buffer 622 mCore->mQueue.push_back(item); 623 frameAvailableListener = mCore->mConsumerListener; 624 } else { 625 // When the queue is not empty, we need to look at the front buffer 626 // state to see if we need to replace it 627 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); 628 if (front->mIsDroppable) { 629 // If the front queued buffer is still being tracked, we first 630 // mark it as freed 631 if (mCore->stillTracking(front)) { 632 mSlots[front->mSlot].mBufferState = BufferSlot::FREE; 633 // Reset the frame number of the freed buffer so that it is 634 // the first in line to be dequeued again 635 mSlots[front->mSlot].mFrameNumber = 0; 636 } 637 // Overwrite the droppable buffer with the incoming one 638 *front = item; 639 frameReplacedListener = mCore->mConsumerListener; 640 } else { 641 mCore->mQueue.push_back(item); 642 frameAvailableListener = mCore->mConsumerListener; 643 } 644 } 645 646 mCore->mBufferHasBeenQueued = true; 647 mCore->mDequeueCondition.broadcast(); 648 649 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, 650 mCore->mTransformHint, mCore->mQueue.size()); 651 652 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); 653 654 // Take a ticket for the callback functions 655 callbackTicket = mNextCallbackTicket++; 656 } // Autolock scope 657 658 // Wait without lock held 659 if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) { 660 // Waiting here allows for two full buffers to be queued but not a 661 // third. In the event that frames take varying time, this makes a 662 // small trade-off in favor of latency rather than throughput. 663 mLastQueueBufferFence->waitForever("Throttling EGL Production"); 664 mLastQueueBufferFence = fence; 665 } 666 667 // Don't send the GraphicBuffer through the callback, and don't send 668 // the slot number, since the consumer shouldn't need it 669 item.mGraphicBuffer.clear(); 670 item.mSlot = BufferItem::INVALID_BUFFER_SLOT; 671 672 // Call back without the main BufferQueue lock held, but with the callback 673 // lock held so we can ensure that callbacks occur in order 674 { 675 Mutex::Autolock lock(mCallbackMutex); 676 while (callbackTicket != mCurrentCallbackTicket) { 677 mCallbackCondition.wait(mCallbackMutex); 678 } 679 680 if (frameAvailableListener != NULL) { 681 frameAvailableListener->onFrameAvailable(item); 682 } else if (frameReplacedListener != NULL) { 683 frameReplacedListener->onFrameReplaced(item); 684 } 685 686 ++mCurrentCallbackTicket; 687 mCallbackCondition.broadcast(); 688 } 689 690 return NO_ERROR; 691 } 692 cancelBuffer(int slot,const sp<Fence> & fence)693 void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) { 694 ATRACE_CALL(); 695 BQ_LOGV("cancelBuffer: slot %d", slot); 696 Mutex::Autolock lock(mCore->mMutex); 697 698 if (mCore->mIsAbandoned) { 699 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned"); 700 return; 701 } 702 703 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 704 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", 705 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 706 return; 707 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 708 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer " 709 "(state = %d)", slot, mSlots[slot].mBufferState); 710 return; 711 } else if (fence == NULL) { 712 BQ_LOGE("cancelBuffer: fence is NULL"); 713 return; 714 } 715 716 mSlots[slot].mBufferState = BufferSlot::FREE; 717 mSlots[slot].mFrameNumber = 0; 718 mSlots[slot].mFence = fence; 719 mCore->mDequeueCondition.broadcast(); 720 } 721 query(int what,int * outValue)722 int BufferQueueProducer::query(int what, int *outValue) { 723 ATRACE_CALL(); 724 Mutex::Autolock lock(mCore->mMutex); 725 726 if (outValue == NULL) { 727 BQ_LOGE("query: outValue was NULL"); 728 return BAD_VALUE; 729 } 730 731 if (mCore->mIsAbandoned) { 732 BQ_LOGE("query: BufferQueue has been abandoned"); 733 return NO_INIT; 734 } 735 736 int value; 737 switch (what) { 738 case NATIVE_WINDOW_WIDTH: 739 value = mCore->mDefaultWidth; 740 break; 741 case NATIVE_WINDOW_HEIGHT: 742 value = mCore->mDefaultHeight; 743 break; 744 case NATIVE_WINDOW_FORMAT: 745 value = mCore->mDefaultBufferFormat; 746 break; 747 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 748 value = mCore->getMinUndequeuedBufferCountLocked(false); 749 break; 750 case NATIVE_WINDOW_STICKY_TRANSFORM: 751 value = static_cast<int>(mStickyTransform); 752 break; 753 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: 754 value = (mCore->mQueue.size() > 1); 755 break; 756 case NATIVE_WINDOW_CONSUMER_USAGE_BITS: 757 value = mCore->mConsumerUsageBits; 758 break; 759 default: 760 return BAD_VALUE; 761 } 762 763 BQ_LOGV("query: %d? %d", what, value); 764 *outValue = value; 765 return NO_ERROR; 766 } 767 connect(const sp<IProducerListener> & listener,int api,bool producerControlledByApp,QueueBufferOutput * output)768 status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, 769 int api, bool producerControlledByApp, QueueBufferOutput *output) { 770 ATRACE_CALL(); 771 Mutex::Autolock lock(mCore->mMutex); 772 mConsumerName = mCore->mConsumerName; 773 BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api, 774 producerControlledByApp ? "true" : "false"); 775 776 if (mCore->mIsAbandoned) { 777 BQ_LOGE("connect(P): BufferQueue has been abandoned"); 778 return NO_INIT; 779 } 780 781 if (mCore->mConsumerListener == NULL) { 782 BQ_LOGE("connect(P): BufferQueue has no consumer"); 783 return NO_INIT; 784 } 785 786 if (output == NULL) { 787 BQ_LOGE("connect(P): output was NULL"); 788 return BAD_VALUE; 789 } 790 791 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { 792 BQ_LOGE("connect(P): already connected (cur=%d req=%d)", 793 mCore->mConnectedApi, api); 794 return BAD_VALUE; 795 } 796 797 int status = NO_ERROR; 798 switch (api) { 799 case NATIVE_WINDOW_API_EGL: 800 case NATIVE_WINDOW_API_CPU: 801 case NATIVE_WINDOW_API_MEDIA: 802 case NATIVE_WINDOW_API_CAMERA: 803 mCore->mConnectedApi = api; 804 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, 805 mCore->mTransformHint, mCore->mQueue.size()); 806 807 // Set up a death notification so that we can disconnect 808 // automatically if the remote producer dies 809 if (listener != NULL && 810 listener->asBinder()->remoteBinder() != NULL) { 811 status = listener->asBinder()->linkToDeath( 812 static_cast<IBinder::DeathRecipient*>(this)); 813 if (status != NO_ERROR) { 814 BQ_LOGE("connect(P): linkToDeath failed: %s (%d)", 815 strerror(-status), status); 816 } 817 } 818 mCore->mConnectedProducerListener = listener; 819 break; 820 default: 821 BQ_LOGE("connect(P): unknown API %d", api); 822 status = BAD_VALUE; 823 break; 824 } 825 826 mCore->mBufferHasBeenQueued = false; 827 mCore->mDequeueBufferCannotBlock = 828 mCore->mConsumerControlledByApp && producerControlledByApp; 829 830 return status; 831 } 832 disconnect(int api)833 status_t BufferQueueProducer::disconnect(int api) { 834 ATRACE_CALL(); 835 BQ_LOGV("disconnect(P): api %d", api); 836 837 int status = NO_ERROR; 838 sp<IConsumerListener> listener; 839 { // Autolock scope 840 Mutex::Autolock lock(mCore->mMutex); 841 mCore->waitWhileAllocatingLocked(); 842 843 if (mCore->mIsAbandoned) { 844 // It's not really an error to disconnect after the surface has 845 // been abandoned; it should just be a no-op. 846 return NO_ERROR; 847 } 848 849 switch (api) { 850 case NATIVE_WINDOW_API_EGL: 851 case NATIVE_WINDOW_API_CPU: 852 case NATIVE_WINDOW_API_MEDIA: 853 case NATIVE_WINDOW_API_CAMERA: 854 if (mCore->mConnectedApi == api) { 855 mCore->freeAllBuffersLocked(); 856 857 // Remove our death notification callback if we have one 858 if (mCore->mConnectedProducerListener != NULL) { 859 sp<IBinder> token = 860 mCore->mConnectedProducerListener->asBinder(); 861 // This can fail if we're here because of the death 862 // notification, but we just ignore it 863 token->unlinkToDeath( 864 static_cast<IBinder::DeathRecipient*>(this)); 865 } 866 mCore->mConnectedProducerListener = NULL; 867 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API; 868 mCore->mSidebandStream.clear(); 869 mCore->mDequeueCondition.broadcast(); 870 listener = mCore->mConsumerListener; 871 } else { 872 BQ_LOGE("disconnect(P): connected to another API " 873 "(cur=%d req=%d)", mCore->mConnectedApi, api); 874 status = BAD_VALUE; 875 } 876 break; 877 default: 878 BQ_LOGE("disconnect(P): unknown API %d", api); 879 status = BAD_VALUE; 880 break; 881 } 882 } // Autolock scope 883 884 // Call back without lock held 885 if (listener != NULL) { 886 listener->onBuffersReleased(); 887 } 888 889 return status; 890 } 891 setSidebandStream(const sp<NativeHandle> & stream)892 status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) { 893 sp<IConsumerListener> listener; 894 { // Autolock scope 895 Mutex::Autolock _l(mCore->mMutex); 896 mCore->mSidebandStream = stream; 897 listener = mCore->mConsumerListener; 898 } // Autolock scope 899 900 if (listener != NULL) { 901 listener->onSidebandStreamChanged(); 902 } 903 return NO_ERROR; 904 } 905 allocateBuffers(bool async,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)906 void BufferQueueProducer::allocateBuffers(bool async, uint32_t width, 907 uint32_t height, uint32_t format, uint32_t usage) { 908 ATRACE_CALL(); 909 while (true) { 910 Vector<int> freeSlots; 911 size_t newBufferCount = 0; 912 uint32_t allocWidth = 0; 913 uint32_t allocHeight = 0; 914 uint32_t allocFormat = 0; 915 uint32_t allocUsage = 0; 916 { // Autolock scope 917 Mutex::Autolock lock(mCore->mMutex); 918 mCore->waitWhileAllocatingLocked(); 919 920 int currentBufferCount = 0; 921 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { 922 if (mSlots[slot].mGraphicBuffer != NULL) { 923 ++currentBufferCount; 924 } else { 925 if (mSlots[slot].mBufferState != BufferSlot::FREE) { 926 BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE", 927 slot); 928 continue; 929 } 930 931 freeSlots.push_back(slot); 932 } 933 } 934 935 int maxBufferCount = mCore->getMaxBufferCountLocked(async); 936 BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers", 937 currentBufferCount, maxBufferCount); 938 if (maxBufferCount <= currentBufferCount) 939 return; 940 newBufferCount = maxBufferCount - currentBufferCount; 941 if (freeSlots.size() < newBufferCount) { 942 BQ_LOGE("allocateBuffers: ran out of free slots"); 943 return; 944 } 945 allocWidth = width > 0 ? width : mCore->mDefaultWidth; 946 allocHeight = height > 0 ? height : mCore->mDefaultHeight; 947 allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat; 948 allocUsage = usage | mCore->mConsumerUsageBits; 949 950 mCore->mIsAllocating = true; 951 } // Autolock scope 952 953 Vector<sp<GraphicBuffer> > buffers; 954 for (size_t i = 0; i < newBufferCount; ++i) { 955 status_t result = NO_ERROR; 956 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( 957 allocWidth, allocHeight, allocFormat, allocUsage, &result)); 958 if (result != NO_ERROR) { 959 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format" 960 " %u, usage %u)", width, height, format, usage); 961 Mutex::Autolock lock(mCore->mMutex); 962 mCore->mIsAllocating = false; 963 mCore->mIsAllocatingCondition.broadcast(); 964 return; 965 } 966 buffers.push_back(graphicBuffer); 967 } 968 969 { // Autolock scope 970 Mutex::Autolock lock(mCore->mMutex); 971 uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth; 972 uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight; 973 uint32_t checkFormat = format != 0 ? format : mCore->mDefaultBufferFormat; 974 uint32_t checkUsage = usage | mCore->mConsumerUsageBits; 975 if (checkWidth != allocWidth || checkHeight != allocHeight || 976 checkFormat != allocFormat || checkUsage != allocUsage) { 977 // Something changed while we released the lock. Retry. 978 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying."); 979 mCore->mIsAllocating = false; 980 mCore->mIsAllocatingCondition.broadcast(); 981 continue; 982 } 983 984 for (size_t i = 0; i < newBufferCount; ++i) { 985 int slot = freeSlots[i]; 986 if (mSlots[slot].mBufferState != BufferSlot::FREE) { 987 // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we 988 // allocated. 989 BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. " 990 "Dropping allocated buffer.", slot); 991 continue; 992 } 993 mCore->freeBufferLocked(slot); // Clean up the slot first 994 mSlots[slot].mGraphicBuffer = buffers[i]; 995 mSlots[slot].mFrameNumber = 0; 996 mSlots[slot].mFence = Fence::NO_FENCE; 997 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot); 998 } 999 1000 mCore->mIsAllocating = false; 1001 mCore->mIsAllocatingCondition.broadcast(); 1002 } // Autolock scope 1003 } 1004 } 1005 binderDied(const wp<android::IBinder> &)1006 void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) { 1007 // If we're here, it means that a producer we were connected to died. 1008 // We're guaranteed that we are still connected to it because we remove 1009 // this callback upon disconnect. It's therefore safe to read mConnectedApi 1010 // without synchronization here. 1011 int api = mCore->mConnectedApi; 1012 disconnect(api); 1013 } 1014 1015 } // namespace android 1016