BufferQueueProducer.cpp revision d9822a3843017444364899afc3c23fb5be6b9cb9
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 no buffer is found, wait for a buffer to be released or for 209 // the max buffer count to change 210 tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT); 211 if (tryAgain) { 212 // Return an error if we're in non-blocking mode (producer and 213 // consumer are controlled by the application). 214 // However, the consumer is allowed to briefly acquire an extra 215 // buffer (which could cause us to have to wait here), which is 216 // okay, since it is only used to implement an atomic acquire + 217 // release (e.g., in GLConsumer::updateTexImage()) 218 if (mCore->mDequeueBufferCannotBlock && 219 (acquiredCount <= mCore->mMaxAcquiredBufferCount)) { 220 return WOULD_BLOCK; 221 } 222 mCore->mDequeueCondition.wait(mCore->mMutex); 223 } 224 } // while (tryAgain) 225 226 return NO_ERROR; 227} 228 229status_t BufferQueueProducer::dequeueBuffer(int *outSlot, 230 sp<android::Fence> *outFence, bool async, 231 uint32_t width, uint32_t height, uint32_t format, uint32_t usage) { 232 ATRACE_CALL(); 233 { // Autolock scope 234 Mutex::Autolock lock(mCore->mMutex); 235 mConsumerName = mCore->mConsumerName; 236 } // Autolock scope 237 238 BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x", 239 async ? "true" : "false", width, height, format, usage); 240 241 if ((width && !height) || (!width && height)) { 242 BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height); 243 return BAD_VALUE; 244 } 245 246 status_t returnFlags = NO_ERROR; 247 EGLDisplay eglDisplay = EGL_NO_DISPLAY; 248 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR; 249 bool attachedByConsumer = false; 250 251 { // Autolock scope 252 Mutex::Autolock lock(mCore->mMutex); 253 254 if (format == 0) { 255 format = mCore->mDefaultBufferFormat; 256 } 257 258 // Enable the usage bits the consumer requested 259 usage |= mCore->mConsumerUsageBits; 260 261 int found; 262 status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async, 263 &found, &returnFlags); 264 if (status != NO_ERROR) { 265 return status; 266 } 267 268 // This should not happen 269 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 270 BQ_LOGE("dequeueBuffer: no available buffer slots"); 271 return -EBUSY; 272 } 273 274 *outSlot = found; 275 ATRACE_BUFFER_INDEX(found); 276 277 attachedByConsumer = mSlots[found].mAttachedByConsumer; 278 279 const bool useDefaultSize = !width && !height; 280 if (useDefaultSize) { 281 width = mCore->mDefaultWidth; 282 height = mCore->mDefaultHeight; 283 } 284 285 mSlots[found].mBufferState = BufferSlot::DEQUEUED; 286 287 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); 288 if ((buffer == NULL) || 289 (static_cast<uint32_t>(buffer->width) != width) || 290 (static_cast<uint32_t>(buffer->height) != height) || 291 (static_cast<uint32_t>(buffer->format) != format) || 292 ((static_cast<uint32_t>(buffer->usage) & usage) != usage)) 293 { 294 mSlots[found].mAcquireCalled = false; 295 mSlots[found].mGraphicBuffer = NULL; 296 mSlots[found].mRequestBufferCalled = false; 297 mSlots[found].mEglDisplay = EGL_NO_DISPLAY; 298 mSlots[found].mEglFence = EGL_NO_SYNC_KHR; 299 mSlots[found].mFence = Fence::NO_FENCE; 300 301 returnFlags |= BUFFER_NEEDS_REALLOCATION; 302 } 303 304 if (CC_UNLIKELY(mSlots[found].mFence == NULL)) { 305 BQ_LOGE("dequeueBuffer: about to return a NULL fence - " 306 "slot=%d w=%d h=%d format=%u", 307 found, buffer->width, buffer->height, buffer->format); 308 } 309 310 eglDisplay = mSlots[found].mEglDisplay; 311 eglFence = mSlots[found].mEglFence; 312 *outFence = mSlots[found].mFence; 313 mSlots[found].mEglFence = EGL_NO_SYNC_KHR; 314 mSlots[found].mFence = Fence::NO_FENCE; 315 } // Autolock scope 316 317 if (returnFlags & BUFFER_NEEDS_REALLOCATION) { 318 status_t error; 319 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( 320 width, height, format, usage, &error)); 321 if (graphicBuffer == NULL) { 322 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed"); 323 return error; 324 } 325 326 { // Autolock scope 327 Mutex::Autolock lock(mCore->mMutex); 328 329 if (mCore->mIsAbandoned) { 330 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned"); 331 return NO_INIT; 332 } 333 334 mSlots[*outSlot].mFrameNumber = UINT32_MAX; 335 mSlots[*outSlot].mGraphicBuffer = graphicBuffer; 336 } // Autolock scope 337 } 338 339 if (attachedByConsumer) { 340 returnFlags |= BUFFER_NEEDS_REALLOCATION; 341 } 342 343 if (eglFence != EGL_NO_SYNC_KHR) { 344 EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0, 345 1000000000); 346 // If something goes wrong, log the error, but return the buffer without 347 // synchronizing access to it. It's too late at this point to abort the 348 // dequeue operation. 349 if (result == EGL_FALSE) { 350 BQ_LOGE("dequeueBuffer: error %#x waiting for fence", 351 eglGetError()); 352 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 353 BQ_LOGE("dequeueBuffer: timeout waiting for fence"); 354 } 355 eglDestroySyncKHR(eglDisplay, eglFence); 356 } 357 358 BQ_LOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outSlot, 359 mSlots[*outSlot].mFrameNumber, 360 mSlots[*outSlot].mGraphicBuffer->handle, returnFlags); 361 362 return returnFlags; 363} 364 365status_t BufferQueueProducer::detachBuffer(int slot) { 366 ATRACE_CALL(); 367 ATRACE_BUFFER_INDEX(slot); 368 BQ_LOGV("detachBuffer(P): slot %d", slot); 369 Mutex::Autolock lock(mCore->mMutex); 370 371 if (mCore->mIsAbandoned) { 372 BQ_LOGE("detachBuffer(P): BufferQueue has been abandoned"); 373 return NO_INIT; 374 } 375 376 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 377 BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)", 378 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 379 return BAD_VALUE; 380 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 381 BQ_LOGE("detachBuffer(P): slot %d is not owned by the producer " 382 "(state = %d)", slot, mSlots[slot].mBufferState); 383 return BAD_VALUE; 384 } else if (!mSlots[slot].mRequestBufferCalled) { 385 BQ_LOGE("detachBuffer(P): buffer in slot %d has not been requested", 386 slot); 387 return BAD_VALUE; 388 } 389 390 mCore->freeBufferLocked(slot); 391 mCore->mDequeueCondition.broadcast(); 392 393 return NO_ERROR; 394} 395 396status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer, 397 sp<Fence>* outFence) { 398 ATRACE_CALL(); 399 400 if (outBuffer == NULL) { 401 BQ_LOGE("detachNextBuffer: outBuffer must not be NULL"); 402 return BAD_VALUE; 403 } else if (outFence == NULL) { 404 BQ_LOGE("detachNextBuffer: outFence must not be NULL"); 405 return BAD_VALUE; 406 } 407 408 Mutex::Autolock lock(mCore->mMutex); 409 410 if (mCore->mIsAbandoned) { 411 BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned"); 412 return NO_INIT; 413 } 414 415 // Find the oldest valid slot 416 int found = BufferQueueCore::INVALID_BUFFER_SLOT; 417 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 418 if (mSlots[s].mBufferState == BufferSlot::FREE && 419 mSlots[s].mGraphicBuffer != NULL) { 420 if (found == BufferQueueCore::INVALID_BUFFER_SLOT || 421 mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) { 422 found = s; 423 } 424 } 425 } 426 427 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 428 return NO_MEMORY; 429 } 430 431 BQ_LOGV("detachNextBuffer detached slot %d", found); 432 433 *outBuffer = mSlots[found].mGraphicBuffer; 434 *outFence = mSlots[found].mFence; 435 mCore->freeBufferLocked(found); 436 437 return NO_ERROR; 438} 439 440status_t BufferQueueProducer::attachBuffer(int* outSlot, 441 const sp<android::GraphicBuffer>& buffer) { 442 ATRACE_CALL(); 443 444 if (outSlot == NULL) { 445 BQ_LOGE("attachBuffer(P): outSlot must not be NULL"); 446 return BAD_VALUE; 447 } else if (buffer == NULL) { 448 BQ_LOGE("attachBuffer(P): cannot attach NULL buffer"); 449 return BAD_VALUE; 450 } 451 452 Mutex::Autolock lock(mCore->mMutex); 453 454 status_t returnFlags = NO_ERROR; 455 int found; 456 // TODO: Should we provide an async flag to attachBuffer? It seems 457 // unlikely that buffers which we are attaching to a BufferQueue will 458 // be asynchronous (droppable), but it may not be impossible. 459 status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false, 460 &found, &returnFlags); 461 if (status != NO_ERROR) { 462 return status; 463 } 464 465 // This should not happen 466 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 467 BQ_LOGE("attachBuffer(P): no available buffer slots"); 468 return -EBUSY; 469 } 470 471 *outSlot = found; 472 ATRACE_BUFFER_INDEX(*outSlot); 473 BQ_LOGV("attachBuffer(P): returning slot %d flags=%#x", 474 *outSlot, returnFlags); 475 476 mSlots[*outSlot].mGraphicBuffer = buffer; 477 mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED; 478 mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR; 479 mSlots[*outSlot].mFence = Fence::NO_FENCE; 480 mSlots[*outSlot].mRequestBufferCalled = true; 481 482 return returnFlags; 483} 484 485status_t BufferQueueProducer::queueBuffer(int slot, 486 const QueueBufferInput &input, QueueBufferOutput *output) { 487 ATRACE_CALL(); 488 ATRACE_BUFFER_INDEX(slot); 489 490 int64_t timestamp; 491 bool isAutoTimestamp; 492 Rect crop; 493 int scalingMode; 494 uint32_t transform; 495 bool async; 496 sp<Fence> fence; 497 input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform, 498 &async, &fence); 499 500 if (fence == NULL) { 501 BQ_LOGE("queueBuffer: fence is NULL"); 502 return BAD_VALUE; 503 } 504 505 switch (scalingMode) { 506 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 507 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 508 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: 509 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: 510 break; 511 default: 512 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode); 513 return BAD_VALUE; 514 } 515 516 sp<IConsumerListener> listener; 517 { // Autolock scope 518 Mutex::Autolock lock(mCore->mMutex); 519 520 if (mCore->mIsAbandoned) { 521 BQ_LOGE("queueBuffer: BufferQueue has been abandoned"); 522 return NO_INIT; 523 } 524 525 const int maxBufferCount = mCore->getMaxBufferCountLocked(async); 526 if (async && mCore->mOverrideMaxBufferCount) { 527 // FIXME: Some drivers are manually setting the buffer count 528 // (which they shouldn't), so we do this extra test here to 529 // handle that case. This is TEMPORARY until we get this fixed. 530 if (mCore->mOverrideMaxBufferCount < maxBufferCount) { 531 BQ_LOGE("queueBuffer: async mode is invalid with " 532 "buffer count override"); 533 return BAD_VALUE; 534 } 535 } 536 537 if (slot < 0 || slot >= maxBufferCount) { 538 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)", 539 slot, maxBufferCount); 540 return BAD_VALUE; 541 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 542 BQ_LOGE("queueBuffer: slot %d is not owned by the producer " 543 "(state = %d)", slot, mSlots[slot].mBufferState); 544 return BAD_VALUE; 545 } else if (!mSlots[slot].mRequestBufferCalled) { 546 BQ_LOGE("queueBuffer: slot %d was queued without requesting " 547 "a buffer", slot); 548 return BAD_VALUE; 549 } 550 551 BQ_LOGV("queueBuffer: slot=%d/%llu time=%llu crop=[%d,%d,%d,%d] " 552 "transform=%#x scale=%s", 553 slot, mCore->mFrameCounter + 1, timestamp, 554 crop.left, crop.top, crop.right, crop.bottom, 555 transform, BufferItem::scalingModeName(scalingMode)); 556 557 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer); 558 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); 559 Rect croppedRect; 560 crop.intersect(bufferRect, &croppedRect); 561 if (croppedRect != crop) { 562 BQ_LOGE("queueBuffer: crop rect is not contained within the " 563 "buffer in slot %d", slot); 564 return BAD_VALUE; 565 } 566 567 mSlots[slot].mFence = fence; 568 mSlots[slot].mBufferState = BufferSlot::QUEUED; 569 ++mCore->mFrameCounter; 570 mSlots[slot].mFrameNumber = mCore->mFrameCounter; 571 572 BufferItem item; 573 item.mAcquireCalled = mSlots[slot].mAcquireCalled; 574 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; 575 item.mCrop = crop; 576 item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; 577 item.mTransformToDisplayInverse = 578 bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY); 579 item.mScalingMode = scalingMode; 580 item.mTimestamp = timestamp; 581 item.mIsAutoTimestamp = isAutoTimestamp; 582 item.mFrameNumber = mCore->mFrameCounter; 583 item.mSlot = slot; 584 item.mFence = fence; 585 item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async; 586 587 if (mCore->mQueue.empty()) { 588 // When the queue is empty, we can ignore mDequeueBufferCannotBlock 589 // and simply queue this buffer 590 mCore->mQueue.push_back(item); 591 listener = mCore->mConsumerListener; 592 } else { 593 // When the queue is not empty, we need to look at the front buffer 594 // state to see if we need to replace it 595 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); 596 if (front->mIsDroppable) { 597 // If the front queued buffer is still being tracked, we first 598 // mark it as freed 599 if (mCore->stillTracking(front)) { 600 mSlots[front->mSlot].mBufferState = BufferSlot::FREE; 601 // Reset the frame number of the freed buffer so that it is 602 // the first in line to be dequeued again 603 mSlots[front->mSlot].mFrameNumber = 0; 604 } 605 // Overwrite the droppable buffer with the incoming one 606 *front = item; 607 } else { 608 mCore->mQueue.push_back(item); 609 listener = mCore->mConsumerListener; 610 } 611 } 612 613 mCore->mBufferHasBeenQueued = true; 614 mCore->mDequeueCondition.broadcast(); 615 616 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, 617 mCore->mTransformHint, mCore->mQueue.size()); 618 619 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); 620 } // Autolock scope 621 622 // Call back without lock held 623 if (listener != NULL) { 624 listener->onFrameAvailable(); 625 } 626 627 return NO_ERROR; 628} 629 630void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) { 631 ATRACE_CALL(); 632 BQ_LOGV("cancelBuffer: slot %d", slot); 633 Mutex::Autolock lock(mCore->mMutex); 634 635 if (mCore->mIsAbandoned) { 636 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned"); 637 return; 638 } 639 640 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 641 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", 642 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 643 return; 644 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 645 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer " 646 "(state = %d)", slot, mSlots[slot].mBufferState); 647 return; 648 } else if (fence == NULL) { 649 BQ_LOGE("cancelBuffer: fence is NULL"); 650 return; 651 } 652 653 mSlots[slot].mBufferState = BufferSlot::FREE; 654 mSlots[slot].mFrameNumber = 0; 655 mSlots[slot].mFence = fence; 656 mCore->mDequeueCondition.broadcast(); 657} 658 659int BufferQueueProducer::query(int what, int *outValue) { 660 ATRACE_CALL(); 661 Mutex::Autolock lock(mCore->mMutex); 662 663 if (outValue == NULL) { 664 BQ_LOGE("query: outValue was NULL"); 665 return BAD_VALUE; 666 } 667 668 if (mCore->mIsAbandoned) { 669 BQ_LOGE("query: BufferQueue has been abandoned"); 670 return NO_INIT; 671 } 672 673 int value; 674 switch (what) { 675 case NATIVE_WINDOW_WIDTH: 676 value = mCore->mDefaultWidth; 677 break; 678 case NATIVE_WINDOW_HEIGHT: 679 value = mCore->mDefaultHeight; 680 break; 681 case NATIVE_WINDOW_FORMAT: 682 value = mCore->mDefaultBufferFormat; 683 break; 684 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 685 value = mCore->getMinUndequeuedBufferCountLocked(false); 686 break; 687 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: 688 value = (mCore->mQueue.size() > 1); 689 break; 690 case NATIVE_WINDOW_CONSUMER_USAGE_BITS: 691 value = mCore->mConsumerUsageBits; 692 break; 693 default: 694 return BAD_VALUE; 695 } 696 697 BQ_LOGV("query: %d? %d", what, value); 698 *outValue = value; 699 return NO_ERROR; 700} 701 702status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, 703 int api, bool producerControlledByApp, QueueBufferOutput *output) { 704 ATRACE_CALL(); 705 Mutex::Autolock lock(mCore->mMutex); 706 mConsumerName = mCore->mConsumerName; 707 BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api, 708 producerControlledByApp ? "true" : "false"); 709 710 // If we disconnect and reconnect quickly, we can be in a state where our 711 // slots are empty but we have many buffers in the queue. This can cause us 712 // to run out of memory if we outrun the consumer. Wait here if it looks 713 // like we have too many buffers queued up. 714 while (true) { 715 if (mCore->mIsAbandoned) { 716 BQ_LOGE("connect(P): BufferQueue has been abandoned"); 717 return NO_INIT; 718 } 719 720 if (mCore->mConsumerListener == NULL) { 721 BQ_LOGE("connect(P): BufferQueue has no consumer"); 722 return NO_INIT; 723 } 724 725 if (output == NULL) { 726 BQ_LOGE("connect(P): output was NULL"); 727 return BAD_VALUE; 728 } 729 730 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { 731 BQ_LOGE("connect(P): already connected (cur=%d req=%d)", 732 mCore->mConnectedApi, api); 733 return BAD_VALUE; 734 } 735 736 size_t maxBufferCount = mCore->getMaxBufferCountLocked(false); 737 if (mCore->mQueue.size() <= maxBufferCount) { 738 // The queue size seems small enough to proceed 739 // TODO: Make this bound tighter? 740 break; 741 } 742 743 BQ_LOGV("connect(P): queue size is %d, waiting", mCore->mQueue.size()); 744 mCore->mDequeueCondition.wait(mCore->mMutex); 745 } 746 747 int status = NO_ERROR; 748 switch (api) { 749 case NATIVE_WINDOW_API_EGL: 750 case NATIVE_WINDOW_API_CPU: 751 case NATIVE_WINDOW_API_MEDIA: 752 case NATIVE_WINDOW_API_CAMERA: 753 mCore->mConnectedApi = api; 754 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, 755 mCore->mTransformHint, mCore->mQueue.size()); 756 757 // Set up a death notification so that we can disconnect 758 // automatically if the remote producer dies 759 if (listener != NULL && 760 listener->asBinder()->remoteBinder() != NULL) { 761 status = listener->asBinder()->linkToDeath( 762 static_cast<IBinder::DeathRecipient*>(this)); 763 if (status != NO_ERROR) { 764 BQ_LOGE("connect(P): linkToDeath failed: %s (%d)", 765 strerror(-status), status); 766 } 767 } 768 mCore->mConnectedProducerListener = listener; 769 break; 770 default: 771 BQ_LOGE("connect(P): unknown API %d", api); 772 status = BAD_VALUE; 773 break; 774 } 775 776 mCore->mBufferHasBeenQueued = false; 777 mCore->mDequeueBufferCannotBlock = 778 mCore->mConsumerControlledByApp && producerControlledByApp; 779 780 return status; 781} 782 783status_t BufferQueueProducer::disconnect(int api) { 784 ATRACE_CALL(); 785 BQ_LOGV("disconnect(P): api %d", api); 786 787 int status = NO_ERROR; 788 sp<IConsumerListener> listener; 789 { // Autolock scope 790 Mutex::Autolock lock(mCore->mMutex); 791 792 if (mCore->mIsAbandoned) { 793 // It's not really an error to disconnect after the surface has 794 // been abandoned; it should just be a no-op. 795 return NO_ERROR; 796 } 797 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 if (mCore->mConnectedApi == api) { 804 mCore->freeAllBuffersLocked(); 805 806 // Remove our death notification callback if we have one 807 if (mCore->mConnectedProducerListener != NULL) { 808 sp<IBinder> token = 809 mCore->mConnectedProducerListener->asBinder(); 810 // This can fail if we're here because of the death 811 // notification, but we just ignore it 812 token->unlinkToDeath( 813 static_cast<IBinder::DeathRecipient*>(this)); 814 } 815 mCore->mConnectedProducerListener = NULL; 816 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API; 817 mCore->mSidebandStream.clear(); 818 mCore->mDequeueCondition.broadcast(); 819 listener = mCore->mConsumerListener; 820 } else { 821 BQ_LOGE("disconnect(P): connected to another API " 822 "(cur=%d req=%d)", mCore->mConnectedApi, api); 823 status = BAD_VALUE; 824 } 825 break; 826 default: 827 BQ_LOGE("disconnect(P): unknown API %d", api); 828 status = BAD_VALUE; 829 break; 830 } 831 } // Autolock scope 832 833 // Call back without lock held 834 if (listener != NULL) { 835 listener->onBuffersReleased(); 836 } 837 838 return status; 839} 840 841status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) { 842 sp<IConsumerListener> listener; 843 { // Autolock scope 844 Mutex::Autolock _l(mCore->mMutex); 845 mCore->mSidebandStream = stream; 846 listener = mCore->mConsumerListener; 847 } // Autolock scope 848 849 if (listener != NULL) { 850 listener->onSidebandStreamChanged(); 851 } 852 return NO_ERROR; 853} 854 855void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) { 856 // If we're here, it means that a producer we were connected to died. 857 // We're guaranteed that we are still connected to it because we remove 858 // this callback upon disconnect. It's therefore safe to read mConnectedApi 859 // without synchronization here. 860 int api = mCore->mConnectedApi; 861 disconnect(api); 862} 863 864} // namespace android 865