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