BufferQueueProducer.cpp revision 4cbf3c53447215a31f69d3ac615ba0daa902f717
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#define LOG_TAG "BufferQueueProducer" 18#define ATRACE_TAG ATRACE_TAG_GRAPHICS 19//#define LOG_NDEBUG 0 20 21#define EGL_EGLEXT_PROTOTYPES 22 23#include <gui/BufferItem.h> 24#include <gui/BufferQueueCore.h> 25#include <gui/BufferQueueProducer.h> 26#include <gui/IConsumerListener.h> 27#include <gui/IGraphicBufferAlloc.h> 28#include <gui/IProducerListener.h> 29 30#include <utils/Log.h> 31#include <utils/Trace.h> 32 33namespace android { 34 35BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) : 36 mCore(core), 37 mSlots(core->mSlots), 38 mConsumerName() {} 39 40BufferQueueProducer::~BufferQueueProducer() {} 41 42status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) { 43 ATRACE_CALL(); 44 BQ_LOGV("requestBuffer: slot %d", slot); 45 Mutex::Autolock lock(mCore->mMutex); 46 47 if (mCore->mIsAbandoned) { 48 BQ_LOGE("requestBuffer: BufferQueue has been abandoned"); 49 return NO_INIT; 50 } 51 52 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 53 BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)", 54 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 55 return BAD_VALUE; 56 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 57 BQ_LOGE("requestBuffer: slot %d is not owned by the producer " 58 "(state = %d)", slot, mSlots[slot].mBufferState); 59 return BAD_VALUE; 60 } 61 62 mSlots[slot].mRequestBufferCalled = true; 63 *buf = mSlots[slot].mGraphicBuffer; 64 return NO_ERROR; 65} 66 67status_t BufferQueueProducer::setBufferCount(int bufferCount) { 68 ATRACE_CALL(); 69 BQ_LOGV("setBufferCount: count = %d", bufferCount); 70 71 sp<IConsumerListener> listener; 72 { // Autolock scope 73 Mutex::Autolock lock(mCore->mMutex); 74 75 if (mCore->mIsAbandoned) { 76 BQ_LOGE("setBufferCount: BufferQueue has been abandoned"); 77 return NO_INIT; 78 } 79 80 if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) { 81 BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)", 82 bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS); 83 return BAD_VALUE; 84 } 85 86 // There must be no dequeued buffers when changing the buffer count. 87 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 88 if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) { 89 BQ_LOGE("setBufferCount: buffer owned by producer"); 90 return BAD_VALUE; 91 } 92 } 93 94 if (bufferCount == 0) { 95 mCore->mOverrideMaxBufferCount = 0; 96 mCore->mDequeueCondition.broadcast(); 97 return NO_ERROR; 98 } 99 100 const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false); 101 if (bufferCount < minBufferSlots) { 102 BQ_LOGE("setBufferCount: requested buffer count %d is less than " 103 "minimum %d", bufferCount, minBufferSlots); 104 return BAD_VALUE; 105 } 106 107 // Here we are guaranteed that the producer doesn't have any dequeued 108 // buffers and will release all of its buffer references. We don't 109 // clear the queue, however, so that currently queued buffers still 110 // get displayed. 111 mCore->freeAllBuffersLocked(); 112 mCore->mOverrideMaxBufferCount = bufferCount; 113 mCore->mDequeueCondition.broadcast(); 114 listener = mCore->mConsumerListener; 115 } // Autolock scope 116 117 // Call back without lock held 118 if (listener != NULL) { 119 listener->onBuffersReleased(); 120 } 121 122 return NO_ERROR; 123} 124 125status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller, 126 bool async, int* found, status_t* returnFlags) const { 127 bool tryAgain = true; 128 while (tryAgain) { 129 if (mCore->mIsAbandoned) { 130 BQ_LOGE("%s: BufferQueue has been abandoned", caller); 131 return NO_INIT; 132 } 133 134 const int maxBufferCount = mCore->getMaxBufferCountLocked(async); 135 if (async && mCore->mOverrideMaxBufferCount) { 136 // FIXME: Some drivers are manually setting the buffer count 137 // (which they shouldn't), so we do this extra test here to 138 // handle that case. This is TEMPORARY until we get this fixed. 139 if (mCore->mOverrideMaxBufferCount < maxBufferCount) { 140 BQ_LOGE("%s: async mode is invalid with buffer count override", 141 caller); 142 return BAD_VALUE; 143 } 144 } 145 146 // Free up any buffers that are in slots beyond the max buffer count 147 for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 148 assert(mSlots[s].mBufferState == BufferSlot::FREE); 149 if (mSlots[s].mGraphicBuffer != NULL) { 150 mCore->freeBufferLocked(s); 151 *returnFlags |= RELEASE_ALL_BUFFERS; 152 } 153 } 154 155 // Look for a free buffer to give to the client 156 *found = BufferQueueCore::INVALID_BUFFER_SLOT; 157 int dequeuedCount = 0; 158 int acquiredCount = 0; 159 for (int s = 0; s < maxBufferCount; ++s) { 160 switch (mSlots[s].mBufferState) { 161 case BufferSlot::DEQUEUED: 162 ++dequeuedCount; 163 break; 164 case BufferSlot::ACQUIRED: 165 ++acquiredCount; 166 break; 167 case BufferSlot::FREE: 168 // We return the oldest of the free buffers to avoid 169 // stalling the producer if possible, since the consumer 170 // may still have pending reads of in-flight buffers 171 if (*found == BufferQueueCore::INVALID_BUFFER_SLOT || 172 mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) { 173 *found = s; 174 } 175 break; 176 default: 177 break; 178 } 179 } 180 181 // Producers are not allowed to dequeue more than one buffer if they 182 // did not set a buffer count 183 if (!mCore->mOverrideMaxBufferCount && dequeuedCount) { 184 BQ_LOGE("%s: can't dequeue multiple buffers without setting the " 185 "buffer count", caller); 186 return INVALID_OPERATION; 187 } 188 189 // See whether a buffer has been queued since the last 190 // setBufferCount so we know whether to perform the min undequeued 191 // buffers check below 192 if (mCore->mBufferHasBeenQueued) { 193 // Make sure the producer is not trying to dequeue more buffers 194 // than allowed 195 const int newUndequeuedCount = 196 maxBufferCount - (dequeuedCount + 1); 197 const int minUndequeuedCount = 198 mCore->getMinUndequeuedBufferCountLocked(async); 199 if (newUndequeuedCount < minUndequeuedCount) { 200 BQ_LOGE("%s: min undequeued buffer count (%d) exceeded " 201 "(dequeued=%d undequeued=%d)", 202 caller, minUndequeuedCount, 203 dequeuedCount, newUndequeuedCount); 204 return INVALID_OPERATION; 205 } 206 } 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() > maxBufferCount; 213 if (tooManyBuffers) { 214 BQ_LOGV("%s: queue size is %d, waiting", caller, 215 mCore->mQueue.size()); 216 } 217 218 // If no buffer is found, or if the queue has too many buffers 219 // outstanding, wait for a buffer to be acquired or released, or for the 220 // max buffer count to change. 221 tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) || 222 tooManyBuffers; 223 if (tryAgain) { 224 // Return an error if we're in non-blocking mode (producer and 225 // consumer are controlled by the application). 226 // However, the consumer is allowed to briefly acquire an extra 227 // buffer (which could cause us to have to wait here), which is 228 // okay, since it is only used to implement an atomic acquire + 229 // release (e.g., in GLConsumer::updateTexImage()) 230 if (mCore->mDequeueBufferCannotBlock && 231 (acquiredCount <= mCore->mMaxAcquiredBufferCount)) { 232 return WOULD_BLOCK; 233 } 234 mCore->mDequeueCondition.wait(mCore->mMutex); 235 } 236 } // while (tryAgain) 237 238 return NO_ERROR; 239} 240 241status_t BufferQueueProducer::dequeueBuffer(int *outSlot, 242 sp<android::Fence> *outFence, bool async, 243 uint32_t width, uint32_t height, uint32_t format, uint32_t usage) { 244 ATRACE_CALL(); 245 { // Autolock scope 246 Mutex::Autolock lock(mCore->mMutex); 247 mConsumerName = mCore->mConsumerName; 248 } // Autolock scope 249 250 BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x", 251 async ? "true" : "false", width, height, format, usage); 252 253 if ((width && !height) || (!width && height)) { 254 BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height); 255 return BAD_VALUE; 256 } 257 258 status_t returnFlags = NO_ERROR; 259 EGLDisplay eglDisplay = EGL_NO_DISPLAY; 260 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR; 261 bool attachedByConsumer = false; 262 263 { // Autolock scope 264 Mutex::Autolock lock(mCore->mMutex); 265 266 if (format == 0) { 267 format = mCore->mDefaultBufferFormat; 268 } 269 270 // Enable the usage bits the consumer requested 271 usage |= mCore->mConsumerUsageBits; 272 273 int found; 274 status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async, 275 &found, &returnFlags); 276 if (status != NO_ERROR) { 277 return status; 278 } 279 280 // This should not happen 281 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 282 BQ_LOGE("dequeueBuffer: no available buffer slots"); 283 return -EBUSY; 284 } 285 286 *outSlot = found; 287 ATRACE_BUFFER_INDEX(found); 288 289 attachedByConsumer = mSlots[found].mAttachedByConsumer; 290 291 const bool useDefaultSize = !width && !height; 292 if (useDefaultSize) { 293 width = mCore->mDefaultWidth; 294 height = mCore->mDefaultHeight; 295 } 296 297 mSlots[found].mBufferState = BufferSlot::DEQUEUED; 298 299 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); 300 if ((buffer == NULL) || 301 (static_cast<uint32_t>(buffer->width) != width) || 302 (static_cast<uint32_t>(buffer->height) != height) || 303 (static_cast<uint32_t>(buffer->format) != format) || 304 ((static_cast<uint32_t>(buffer->usage) & usage) != usage)) 305 { 306 mSlots[found].mAcquireCalled = false; 307 mSlots[found].mGraphicBuffer = NULL; 308 mSlots[found].mRequestBufferCalled = false; 309 mSlots[found].mEglDisplay = EGL_NO_DISPLAY; 310 mSlots[found].mEglFence = EGL_NO_SYNC_KHR; 311 mSlots[found].mFence = Fence::NO_FENCE; 312 313 returnFlags |= BUFFER_NEEDS_REALLOCATION; 314 } 315 316 if (CC_UNLIKELY(mSlots[found].mFence == NULL)) { 317 BQ_LOGE("dequeueBuffer: about to return a NULL fence - " 318 "slot=%d w=%d h=%d format=%u", 319 found, buffer->width, buffer->height, buffer->format); 320 } 321 322 eglDisplay = mSlots[found].mEglDisplay; 323 eglFence = mSlots[found].mEglFence; 324 *outFence = mSlots[found].mFence; 325 mSlots[found].mEglFence = EGL_NO_SYNC_KHR; 326 mSlots[found].mFence = Fence::NO_FENCE; 327 } // Autolock scope 328 329 if (returnFlags & BUFFER_NEEDS_REALLOCATION) { 330 status_t error; 331 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( 332 width, height, format, usage, &error)); 333 if (graphicBuffer == NULL) { 334 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed"); 335 return error; 336 } 337 338 { // Autolock scope 339 Mutex::Autolock lock(mCore->mMutex); 340 341 if (mCore->mIsAbandoned) { 342 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned"); 343 return NO_INIT; 344 } 345 346 mSlots[*outSlot].mFrameNumber = UINT32_MAX; 347 mSlots[*outSlot].mGraphicBuffer = graphicBuffer; 348 } // Autolock scope 349 } 350 351 if (attachedByConsumer) { 352 returnFlags |= BUFFER_NEEDS_REALLOCATION; 353 } 354 355 if (eglFence != EGL_NO_SYNC_KHR) { 356 EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0, 357 1000000000); 358 // If something goes wrong, log the error, but return the buffer without 359 // synchronizing access to it. It's too late at this point to abort the 360 // dequeue operation. 361 if (result == EGL_FALSE) { 362 BQ_LOGE("dequeueBuffer: error %#x waiting for fence", 363 eglGetError()); 364 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 365 BQ_LOGE("dequeueBuffer: timeout waiting for fence"); 366 } 367 eglDestroySyncKHR(eglDisplay, eglFence); 368 } 369 370 BQ_LOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outSlot, 371 mSlots[*outSlot].mFrameNumber, 372 mSlots[*outSlot].mGraphicBuffer->handle, returnFlags); 373 374 return returnFlags; 375} 376 377status_t BufferQueueProducer::detachBuffer(int slot) { 378 ATRACE_CALL(); 379 ATRACE_BUFFER_INDEX(slot); 380 BQ_LOGV("detachBuffer(P): slot %d", slot); 381 Mutex::Autolock lock(mCore->mMutex); 382 383 if (mCore->mIsAbandoned) { 384 BQ_LOGE("detachBuffer(P): BufferQueue has been abandoned"); 385 return NO_INIT; 386 } 387 388 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 389 BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)", 390 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 391 return BAD_VALUE; 392 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 393 BQ_LOGE("detachBuffer(P): slot %d is not owned by the producer " 394 "(state = %d)", slot, mSlots[slot].mBufferState); 395 return BAD_VALUE; 396 } else if (!mSlots[slot].mRequestBufferCalled) { 397 BQ_LOGE("detachBuffer(P): buffer in slot %d has not been requested", 398 slot); 399 return BAD_VALUE; 400 } 401 402 mCore->freeBufferLocked(slot); 403 mCore->mDequeueCondition.broadcast(); 404 405 return NO_ERROR; 406} 407 408status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer, 409 sp<Fence>* outFence) { 410 ATRACE_CALL(); 411 412 if (outBuffer == NULL) { 413 BQ_LOGE("detachNextBuffer: outBuffer must not be NULL"); 414 return BAD_VALUE; 415 } else if (outFence == NULL) { 416 BQ_LOGE("detachNextBuffer: outFence must not be NULL"); 417 return BAD_VALUE; 418 } 419 420 Mutex::Autolock lock(mCore->mMutex); 421 422 if (mCore->mIsAbandoned) { 423 BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned"); 424 return NO_INIT; 425 } 426 427 // Find the oldest valid slot 428 int found = BufferQueueCore::INVALID_BUFFER_SLOT; 429 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 430 if (mSlots[s].mBufferState == BufferSlot::FREE && 431 mSlots[s].mGraphicBuffer != NULL) { 432 if (found == BufferQueueCore::INVALID_BUFFER_SLOT || 433 mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) { 434 found = s; 435 } 436 } 437 } 438 439 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 440 return NO_MEMORY; 441 } 442 443 BQ_LOGV("detachNextBuffer detached slot %d", found); 444 445 *outBuffer = mSlots[found].mGraphicBuffer; 446 *outFence = mSlots[found].mFence; 447 mCore->freeBufferLocked(found); 448 449 return NO_ERROR; 450} 451 452status_t BufferQueueProducer::attachBuffer(int* outSlot, 453 const sp<android::GraphicBuffer>& buffer) { 454 ATRACE_CALL(); 455 456 if (outSlot == NULL) { 457 BQ_LOGE("attachBuffer(P): outSlot must not be NULL"); 458 return BAD_VALUE; 459 } else if (buffer == NULL) { 460 BQ_LOGE("attachBuffer(P): cannot attach NULL buffer"); 461 return BAD_VALUE; 462 } 463 464 Mutex::Autolock lock(mCore->mMutex); 465 466 status_t returnFlags = NO_ERROR; 467 int found; 468 // TODO: Should we provide an async flag to attachBuffer? It seems 469 // unlikely that buffers which we are attaching to a BufferQueue will 470 // be asynchronous (droppable), but it may not be impossible. 471 status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false, 472 &found, &returnFlags); 473 if (status != NO_ERROR) { 474 return status; 475 } 476 477 // This should not happen 478 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 479 BQ_LOGE("attachBuffer(P): no available buffer slots"); 480 return -EBUSY; 481 } 482 483 *outSlot = found; 484 ATRACE_BUFFER_INDEX(*outSlot); 485 BQ_LOGV("attachBuffer(P): returning slot %d flags=%#x", 486 *outSlot, returnFlags); 487 488 mSlots[*outSlot].mGraphicBuffer = buffer; 489 mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED; 490 mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR; 491 mSlots[*outSlot].mFence = Fence::NO_FENCE; 492 mSlots[*outSlot].mRequestBufferCalled = true; 493 494 return returnFlags; 495} 496 497status_t BufferQueueProducer::queueBuffer(int slot, 498 const QueueBufferInput &input, QueueBufferOutput *output) { 499 ATRACE_CALL(); 500 ATRACE_BUFFER_INDEX(slot); 501 502 int64_t timestamp; 503 bool isAutoTimestamp; 504 Rect crop; 505 int scalingMode; 506 uint32_t transform; 507 bool async; 508 sp<Fence> fence; 509 input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform, 510 &async, &fence); 511 512 if (fence == NULL) { 513 BQ_LOGE("queueBuffer: fence is NULL"); 514 return BAD_VALUE; 515 } 516 517 switch (scalingMode) { 518 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 519 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 520 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: 521 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: 522 break; 523 default: 524 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode); 525 return BAD_VALUE; 526 } 527 528 sp<IConsumerListener> listener; 529 { // Autolock scope 530 Mutex::Autolock lock(mCore->mMutex); 531 532 if (mCore->mIsAbandoned) { 533 BQ_LOGE("queueBuffer: BufferQueue has been abandoned"); 534 return NO_INIT; 535 } 536 537 const int maxBufferCount = mCore->getMaxBufferCountLocked(async); 538 if (async && mCore->mOverrideMaxBufferCount) { 539 // FIXME: Some drivers are manually setting the buffer count 540 // (which they shouldn't), so we do this extra test here to 541 // handle that case. This is TEMPORARY until we get this fixed. 542 if (mCore->mOverrideMaxBufferCount < maxBufferCount) { 543 BQ_LOGE("queueBuffer: async mode is invalid with " 544 "buffer count override"); 545 return BAD_VALUE; 546 } 547 } 548 549 if (slot < 0 || slot >= maxBufferCount) { 550 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)", 551 slot, maxBufferCount); 552 return BAD_VALUE; 553 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 554 BQ_LOGE("queueBuffer: slot %d is not owned by the producer " 555 "(state = %d)", slot, mSlots[slot].mBufferState); 556 return BAD_VALUE; 557 } else if (!mSlots[slot].mRequestBufferCalled) { 558 BQ_LOGE("queueBuffer: slot %d was queued without requesting " 559 "a buffer", slot); 560 return BAD_VALUE; 561 } 562 563 BQ_LOGV("queueBuffer: slot=%d/%llu time=%llu crop=[%d,%d,%d,%d] " 564 "transform=%#x scale=%s", 565 slot, mCore->mFrameCounter + 1, timestamp, 566 crop.left, crop.top, crop.right, crop.bottom, 567 transform, BufferItem::scalingModeName(scalingMode)); 568 569 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer); 570 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); 571 Rect croppedRect; 572 crop.intersect(bufferRect, &croppedRect); 573 if (croppedRect != crop) { 574 BQ_LOGE("queueBuffer: crop rect is not contained within the " 575 "buffer in slot %d", slot); 576 return BAD_VALUE; 577 } 578 579 mSlots[slot].mFence = fence; 580 mSlots[slot].mBufferState = BufferSlot::QUEUED; 581 ++mCore->mFrameCounter; 582 mSlots[slot].mFrameNumber = mCore->mFrameCounter; 583 584 BufferItem item; 585 item.mAcquireCalled = mSlots[slot].mAcquireCalled; 586 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; 587 item.mCrop = crop; 588 item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; 589 item.mTransformToDisplayInverse = 590 bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY); 591 item.mScalingMode = scalingMode; 592 item.mTimestamp = timestamp; 593 item.mIsAutoTimestamp = isAutoTimestamp; 594 item.mFrameNumber = mCore->mFrameCounter; 595 item.mSlot = slot; 596 item.mFence = fence; 597 item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async; 598 599 if (mCore->mQueue.empty()) { 600 // When the queue is empty, we can ignore mDequeueBufferCannotBlock 601 // and simply queue this buffer 602 mCore->mQueue.push_back(item); 603 listener = mCore->mConsumerListener; 604 } else { 605 // When the queue is not empty, we need to look at the front buffer 606 // state to see if we need to replace it 607 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); 608 if (front->mIsDroppable) { 609 // If the front queued buffer is still being tracked, we first 610 // mark it as freed 611 if (mCore->stillTracking(front)) { 612 mSlots[front->mSlot].mBufferState = BufferSlot::FREE; 613 // Reset the frame number of the freed buffer so that it is 614 // the first in line to be dequeued again 615 mSlots[front->mSlot].mFrameNumber = 0; 616 } 617 // Overwrite the droppable buffer with the incoming one 618 *front = item; 619 } else { 620 mCore->mQueue.push_back(item); 621 listener = mCore->mConsumerListener; 622 } 623 } 624 625 mCore->mBufferHasBeenQueued = true; 626 mCore->mDequeueCondition.broadcast(); 627 628 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, 629 mCore->mTransformHint, mCore->mQueue.size()); 630 631 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); 632 } // Autolock scope 633 634 // Call back without lock held 635 if (listener != NULL) { 636 listener->onFrameAvailable(); 637 } 638 639 return NO_ERROR; 640} 641 642void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) { 643 ATRACE_CALL(); 644 BQ_LOGV("cancelBuffer: slot %d", slot); 645 Mutex::Autolock lock(mCore->mMutex); 646 647 if (mCore->mIsAbandoned) { 648 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned"); 649 return; 650 } 651 652 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 653 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", 654 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 655 return; 656 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 657 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer " 658 "(state = %d)", slot, mSlots[slot].mBufferState); 659 return; 660 } else if (fence == NULL) { 661 BQ_LOGE("cancelBuffer: fence is NULL"); 662 return; 663 } 664 665 mSlots[slot].mBufferState = BufferSlot::FREE; 666 mSlots[slot].mFrameNumber = 0; 667 mSlots[slot].mFence = fence; 668 mCore->mDequeueCondition.broadcast(); 669} 670 671int BufferQueueProducer::query(int what, int *outValue) { 672 ATRACE_CALL(); 673 Mutex::Autolock lock(mCore->mMutex); 674 675 if (outValue == NULL) { 676 BQ_LOGE("query: outValue was NULL"); 677 return BAD_VALUE; 678 } 679 680 if (mCore->mIsAbandoned) { 681 BQ_LOGE("query: BufferQueue has been abandoned"); 682 return NO_INIT; 683 } 684 685 int value; 686 switch (what) { 687 case NATIVE_WINDOW_WIDTH: 688 value = mCore->mDefaultWidth; 689 break; 690 case NATIVE_WINDOW_HEIGHT: 691 value = mCore->mDefaultHeight; 692 break; 693 case NATIVE_WINDOW_FORMAT: 694 value = mCore->mDefaultBufferFormat; 695 break; 696 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 697 value = mCore->getMinUndequeuedBufferCountLocked(false); 698 break; 699 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: 700 value = (mCore->mQueue.size() > 1); 701 break; 702 case NATIVE_WINDOW_CONSUMER_USAGE_BITS: 703 value = mCore->mConsumerUsageBits; 704 break; 705 default: 706 return BAD_VALUE; 707 } 708 709 BQ_LOGV("query: %d? %d", what, value); 710 *outValue = value; 711 return NO_ERROR; 712} 713 714status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, 715 int api, bool producerControlledByApp, QueueBufferOutput *output) { 716 ATRACE_CALL(); 717 Mutex::Autolock lock(mCore->mMutex); 718 mConsumerName = mCore->mConsumerName; 719 BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api, 720 producerControlledByApp ? "true" : "false"); 721 722 if (mCore->mIsAbandoned) { 723 BQ_LOGE("connect(P): BufferQueue has been abandoned"); 724 return NO_INIT; 725 } 726 727 if (mCore->mConsumerListener == NULL) { 728 BQ_LOGE("connect(P): BufferQueue has no consumer"); 729 return NO_INIT; 730 } 731 732 if (output == NULL) { 733 BQ_LOGE("connect(P): output was NULL"); 734 return BAD_VALUE; 735 } 736 737 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { 738 BQ_LOGE("connect(P): already connected (cur=%d req=%d)", 739 mCore->mConnectedApi, api); 740 return BAD_VALUE; 741 } 742 743 int status = NO_ERROR; 744 switch (api) { 745 case NATIVE_WINDOW_API_EGL: 746 case NATIVE_WINDOW_API_CPU: 747 case NATIVE_WINDOW_API_MEDIA: 748 case NATIVE_WINDOW_API_CAMERA: 749 mCore->mConnectedApi = api; 750 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, 751 mCore->mTransformHint, mCore->mQueue.size()); 752 753 // Set up a death notification so that we can disconnect 754 // automatically if the remote producer dies 755 if (listener != NULL && 756 listener->asBinder()->remoteBinder() != NULL) { 757 status = listener->asBinder()->linkToDeath( 758 static_cast<IBinder::DeathRecipient*>(this)); 759 if (status != NO_ERROR) { 760 BQ_LOGE("connect(P): linkToDeath failed: %s (%d)", 761 strerror(-status), status); 762 } 763 } 764 mCore->mConnectedProducerListener = listener; 765 break; 766 default: 767 BQ_LOGE("connect(P): unknown API %d", api); 768 status = BAD_VALUE; 769 break; 770 } 771 772 mCore->mBufferHasBeenQueued = false; 773 mCore->mDequeueBufferCannotBlock = 774 mCore->mConsumerControlledByApp && producerControlledByApp; 775 776 return status; 777} 778 779status_t BufferQueueProducer::disconnect(int api) { 780 ATRACE_CALL(); 781 BQ_LOGV("disconnect(P): api %d", api); 782 783 int status = NO_ERROR; 784 sp<IConsumerListener> listener; 785 { // Autolock scope 786 Mutex::Autolock lock(mCore->mMutex); 787 788 if (mCore->mIsAbandoned) { 789 // It's not really an error to disconnect after the surface has 790 // been abandoned; it should just be a no-op. 791 return NO_ERROR; 792 } 793 794 switch (api) { 795 case NATIVE_WINDOW_API_EGL: 796 case NATIVE_WINDOW_API_CPU: 797 case NATIVE_WINDOW_API_MEDIA: 798 case NATIVE_WINDOW_API_CAMERA: 799 if (mCore->mConnectedApi == api) { 800 mCore->freeAllBuffersLocked(); 801 802 // Remove our death notification callback if we have one 803 if (mCore->mConnectedProducerListener != NULL) { 804 sp<IBinder> token = 805 mCore->mConnectedProducerListener->asBinder(); 806 // This can fail if we're here because of the death 807 // notification, but we just ignore it 808 token->unlinkToDeath( 809 static_cast<IBinder::DeathRecipient*>(this)); 810 } 811 mCore->mConnectedProducerListener = NULL; 812 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API; 813 mCore->mSidebandStream.clear(); 814 mCore->mDequeueCondition.broadcast(); 815 listener = mCore->mConsumerListener; 816 } else { 817 BQ_LOGE("disconnect(P): connected to another API " 818 "(cur=%d req=%d)", mCore->mConnectedApi, api); 819 status = BAD_VALUE; 820 } 821 break; 822 default: 823 BQ_LOGE("disconnect(P): unknown API %d", api); 824 status = BAD_VALUE; 825 break; 826 } 827 } // Autolock scope 828 829 // Call back without lock held 830 if (listener != NULL) { 831 listener->onBuffersReleased(); 832 } 833 834 return status; 835} 836 837status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) { 838 sp<IConsumerListener> listener; 839 { // Autolock scope 840 Mutex::Autolock _l(mCore->mMutex); 841 mCore->mSidebandStream = stream; 842 listener = mCore->mConsumerListener; 843 } // Autolock scope 844 845 if (listener != NULL) { 846 listener->onSidebandStreamChanged(); 847 } 848 return NO_ERROR; 849} 850 851void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) { 852 // If we're here, it means that a producer we were connected to died. 853 // We're guaranteed that we are still connected to it because we remove 854 // this callback upon disconnect. It's therefore safe to read mConnectedApi 855 // without synchronization here. 856 int api = mCore->mConnectedApi; 857 disconnect(api); 858} 859 860} // namespace android 861