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