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