BufferQueueProducer.cpp revision ae3c3682333f25e860fe54e2bae3599bb466cdb6
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::attachBuffer(int* outSlot, 409 const sp<android::GraphicBuffer>& buffer) { 410 ATRACE_CALL(); 411 412 if (outSlot == NULL) { 413 BQ_LOGE("attachBuffer(P): outSlot must not be NULL"); 414 return BAD_VALUE; 415 } else if (buffer == NULL) { 416 BQ_LOGE("attachBuffer(P): cannot attach NULL buffer"); 417 return BAD_VALUE; 418 } 419 420 Mutex::Autolock lock(mCore->mMutex); 421 422 status_t returnFlags = NO_ERROR; 423 int found; 424 // TODO: Should we provide an async flag to attachBuffer? It seems 425 // unlikely that buffers which we are attaching to a BufferQueue will 426 // be asynchronous (droppable), but it may not be impossible. 427 status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false, 428 &found, &returnFlags); 429 if (status != NO_ERROR) { 430 return status; 431 } 432 433 // This should not happen 434 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 435 BQ_LOGE("attachBuffer(P): no available buffer slots"); 436 return -EBUSY; 437 } 438 439 *outSlot = found; 440 ATRACE_BUFFER_INDEX(*outSlot); 441 BQ_LOGV("attachBuffer(P): returning slot %d flags=%#x", 442 *outSlot, returnFlags); 443 444 mSlots[*outSlot].mGraphicBuffer = buffer; 445 mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED; 446 mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR; 447 mSlots[*outSlot].mFence = Fence::NO_FENCE; 448 mSlots[*outSlot].mRequestBufferCalled = true; 449 450 return returnFlags; 451} 452 453status_t BufferQueueProducer::queueBuffer(int slot, 454 const QueueBufferInput &input, QueueBufferOutput *output) { 455 ATRACE_CALL(); 456 ATRACE_BUFFER_INDEX(slot); 457 458 int64_t timestamp; 459 bool isAutoTimestamp; 460 Rect crop; 461 int scalingMode; 462 uint32_t transform; 463 bool async; 464 sp<Fence> fence; 465 input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform, 466 &async, &fence); 467 468 if (fence == NULL) { 469 BQ_LOGE("queueBuffer: fence is NULL"); 470 return BAD_VALUE; 471 } 472 473 switch (scalingMode) { 474 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 475 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 476 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: 477 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: 478 break; 479 default: 480 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode); 481 return BAD_VALUE; 482 } 483 484 sp<IConsumerListener> listener; 485 { // Autolock scope 486 Mutex::Autolock lock(mCore->mMutex); 487 488 if (mCore->mIsAbandoned) { 489 BQ_LOGE("queueBuffer: BufferQueue has been abandoned"); 490 return NO_INIT; 491 } 492 493 const int maxBufferCount = mCore->getMaxBufferCountLocked(async); 494 if (async && mCore->mOverrideMaxBufferCount) { 495 // FIXME: Some drivers are manually setting the buffer count 496 // (which they shouldn't), so we do this extra test here to 497 // handle that case. This is TEMPORARY until we get this fixed. 498 if (mCore->mOverrideMaxBufferCount < maxBufferCount) { 499 BQ_LOGE("queueBuffer: async mode is invalid with " 500 "buffer count override"); 501 return BAD_VALUE; 502 } 503 } 504 505 if (slot < 0 || slot >= maxBufferCount) { 506 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)", 507 slot, maxBufferCount); 508 return BAD_VALUE; 509 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 510 BQ_LOGE("queueBuffer: slot %d is not owned by the producer " 511 "(state = %d)", slot, mSlots[slot].mBufferState); 512 return BAD_VALUE; 513 } else if (!mSlots[slot].mRequestBufferCalled) { 514 BQ_LOGE("queueBuffer: slot %d was queued without requesting " 515 "a buffer", slot); 516 return BAD_VALUE; 517 } 518 519 BQ_LOGV("queueBuffer: slot=%d/%llu time=%llu crop=[%d,%d,%d,%d] " 520 "transform=%#x scale=%s", 521 slot, mCore->mFrameCounter + 1, timestamp, 522 crop.left, crop.top, crop.right, crop.bottom, 523 transform, BufferItem::scalingModeName(scalingMode)); 524 525 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer); 526 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); 527 Rect croppedRect; 528 crop.intersect(bufferRect, &croppedRect); 529 if (croppedRect != crop) { 530 BQ_LOGE("queueBuffer: crop rect is not contained within the " 531 "buffer in slot %d", slot); 532 return BAD_VALUE; 533 } 534 535 mSlots[slot].mFence = fence; 536 mSlots[slot].mBufferState = BufferSlot::QUEUED; 537 ++mCore->mFrameCounter; 538 mSlots[slot].mFrameNumber = mCore->mFrameCounter; 539 540 BufferItem item; 541 item.mAcquireCalled = mSlots[slot].mAcquireCalled; 542 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; 543 item.mCrop = crop; 544 item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; 545 item.mTransformToDisplayInverse = 546 bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY); 547 item.mScalingMode = scalingMode; 548 item.mTimestamp = timestamp; 549 item.mIsAutoTimestamp = isAutoTimestamp; 550 item.mFrameNumber = mCore->mFrameCounter; 551 item.mSlot = slot; 552 item.mFence = fence; 553 item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async; 554 555 if (mCore->mQueue.empty()) { 556 // When the queue is empty, we can ignore mDequeueBufferCannotBlock 557 // and simply queue this buffer 558 mCore->mQueue.push_back(item); 559 listener = mCore->mConsumerListener; 560 } else { 561 // When the queue is not empty, we need to look at the front buffer 562 // state to see if we need to replace it 563 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); 564 if (front->mIsDroppable) { 565 // If the front queued buffer is still being tracked, we first 566 // mark it as freed 567 if (mCore->stillTracking(front)) { 568 mSlots[front->mSlot].mBufferState = BufferSlot::FREE; 569 // Reset the frame number of the freed buffer so that it is 570 // the first in line to be dequeued again 571 mSlots[front->mSlot].mFrameNumber = 0; 572 } 573 // Overwrite the droppable buffer with the incoming one 574 *front = item; 575 } else { 576 mCore->mQueue.push_back(item); 577 listener = mCore->mConsumerListener; 578 } 579 } 580 581 mCore->mBufferHasBeenQueued = true; 582 mCore->mDequeueCondition.broadcast(); 583 584 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, 585 mCore->mTransformHint, mCore->mQueue.size()); 586 587 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); 588 } // Autolock scope 589 590 // Call back without lock held 591 if (listener != NULL) { 592 listener->onFrameAvailable(); 593 } 594 595 return NO_ERROR; 596} 597 598void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) { 599 ATRACE_CALL(); 600 BQ_LOGV("cancelBuffer: slot %d", slot); 601 Mutex::Autolock lock(mCore->mMutex); 602 603 if (mCore->mIsAbandoned) { 604 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned"); 605 return; 606 } 607 608 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 609 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", 610 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 611 return; 612 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 613 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer " 614 "(state = %d)", slot, mSlots[slot].mBufferState); 615 return; 616 } else if (fence == NULL) { 617 BQ_LOGE("cancelBuffer: fence is NULL"); 618 return; 619 } 620 621 mSlots[slot].mBufferState = BufferSlot::FREE; 622 mSlots[slot].mFrameNumber = 0; 623 mSlots[slot].mFence = fence; 624 mCore->mDequeueCondition.broadcast(); 625} 626 627int BufferQueueProducer::query(int what, int *outValue) { 628 ATRACE_CALL(); 629 Mutex::Autolock lock(mCore->mMutex); 630 631 if (outValue == NULL) { 632 BQ_LOGE("query: outValue was NULL"); 633 return BAD_VALUE; 634 } 635 636 if (mCore->mIsAbandoned) { 637 BQ_LOGE("query: BufferQueue has been abandoned"); 638 return NO_INIT; 639 } 640 641 int value; 642 switch (what) { 643 case NATIVE_WINDOW_WIDTH: 644 value = mCore->mDefaultWidth; 645 break; 646 case NATIVE_WINDOW_HEIGHT: 647 value = mCore->mDefaultHeight; 648 break; 649 case NATIVE_WINDOW_FORMAT: 650 value = mCore->mDefaultBufferFormat; 651 break; 652 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 653 value = mCore->getMinUndequeuedBufferCountLocked(false); 654 break; 655 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: 656 value = (mCore->mQueue.size() > 1); 657 break; 658 case NATIVE_WINDOW_CONSUMER_USAGE_BITS: 659 value = mCore->mConsumerUsageBits; 660 break; 661 default: 662 return BAD_VALUE; 663 } 664 665 BQ_LOGV("query: %d? %d", what, value); 666 *outValue = value; 667 return NO_ERROR; 668} 669 670status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, 671 int api, bool producerControlledByApp, QueueBufferOutput *output) { 672 ATRACE_CALL(); 673 Mutex::Autolock lock(mCore->mMutex); 674 mConsumerName = mCore->mConsumerName; 675 BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api, 676 producerControlledByApp ? "true" : "false"); 677 678 if (mCore->mIsAbandoned) { 679 BQ_LOGE("connect(P): BufferQueue has been abandoned"); 680 return NO_INIT; 681 } 682 683 if (mCore->mConsumerListener == NULL) { 684 BQ_LOGE("connect(P): BufferQueue has no consumer"); 685 return NO_INIT; 686 } 687 688 if (output == NULL) { 689 BQ_LOGE("connect(P): output was NULL"); 690 return BAD_VALUE; 691 } 692 693 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { 694 BQ_LOGE("connect(P): already connected (cur=%d req=%d)", 695 mCore->mConnectedApi, api); 696 return BAD_VALUE; 697 } 698 699 int status = NO_ERROR; 700 switch (api) { 701 case NATIVE_WINDOW_API_EGL: 702 case NATIVE_WINDOW_API_CPU: 703 case NATIVE_WINDOW_API_MEDIA: 704 case NATIVE_WINDOW_API_CAMERA: 705 mCore->mConnectedApi = api; 706 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, 707 mCore->mTransformHint, mCore->mQueue.size()); 708 709 // Set up a death notification so that we can disconnect 710 // automatically if the remote producer dies 711 if (listener != NULL && 712 listener->asBinder()->remoteBinder() != NULL) { 713 status = listener->asBinder()->linkToDeath( 714 static_cast<IBinder::DeathRecipient*>(this)); 715 if (status != NO_ERROR) { 716 BQ_LOGE("connect(P): linkToDeath failed: %s (%d)", 717 strerror(-status), status); 718 } 719 } 720 mCore->mConnectedProducerListener = listener; 721 break; 722 default: 723 BQ_LOGE("connect(P): unknown API %d", api); 724 status = BAD_VALUE; 725 break; 726 } 727 728 mCore->mBufferHasBeenQueued = false; 729 mCore->mDequeueBufferCannotBlock = 730 mCore->mConsumerControlledByApp && producerControlledByApp; 731 732 return status; 733} 734 735status_t BufferQueueProducer::disconnect(int api) { 736 ATRACE_CALL(); 737 BQ_LOGV("disconnect(P): api %d", api); 738 739 int status = NO_ERROR; 740 sp<IConsumerListener> listener; 741 { // Autolock scope 742 Mutex::Autolock lock(mCore->mMutex); 743 744 if (mCore->mIsAbandoned) { 745 // It's not really an error to disconnect after the surface has 746 // been abandoned; it should just be a no-op. 747 return NO_ERROR; 748 } 749 750 switch (api) { 751 case NATIVE_WINDOW_API_EGL: 752 case NATIVE_WINDOW_API_CPU: 753 case NATIVE_WINDOW_API_MEDIA: 754 case NATIVE_WINDOW_API_CAMERA: 755 if (mCore->mConnectedApi == api) { 756 mCore->freeAllBuffersLocked(); 757 758 // Remove our death notification callback if we have one 759 if (mCore->mConnectedProducerListener != NULL) { 760 sp<IBinder> token = 761 mCore->mConnectedProducerListener->asBinder(); 762 // This can fail if we're here because of the death 763 // notification, but we just ignore it 764 token->unlinkToDeath( 765 static_cast<IBinder::DeathRecipient*>(this)); 766 } 767 mCore->mConnectedProducerListener = NULL; 768 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API; 769 mCore->mSidebandStream.clear(); 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 793status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) { 794 sp<IConsumerListener> listener; 795 { // Autolock scope 796 Mutex::Autolock _l(mCore->mMutex); 797 mCore->mSidebandStream = stream; 798 listener = mCore->mConsumerListener; 799 } // Autolock scope 800 801 if (listener != NULL) { 802 listener->onSidebandStreamChanged(); 803 } 804 return NO_ERROR; 805} 806 807void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) { 808 // If we're here, it means that a producer we were connected to died. 809 // We're guaranteed that we are still connected to it because we remove 810 // this callback upon disconnect. It's therefore safe to read mConnectedApi 811 // without synchronization here. 812 int api = mCore->mConnectedApi; 813 disconnect(api); 814} 815 816} // namespace android 817