BufferQueue.cpp revision 31a353da225af5329735451c761b430d82dfda1b
1/* 2 * Copyright (C) 2012 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 "BufferQueue" 18#define ATRACE_TAG ATRACE_TAG_GRAPHICS 19//#define LOG_NDEBUG 0 20 21#define GL_GLEXT_PROTOTYPES 22#define EGL_EGLEXT_PROTOTYPES 23 24#include <EGL/egl.h> 25#include <EGL/eglext.h> 26 27#include <gui/BufferQueue.h> 28#include <gui/ISurfaceComposer.h> 29#include <private/gui/ComposerService.h> 30 31#include <utils/Log.h> 32#include <gui/SurfaceTexture.h> 33#include <utils/Trace.h> 34 35// This compile option causes SurfaceTexture to return the buffer that is currently 36// attached to the GL texture from dequeueBuffer when no other buffers are 37// available. It requires the drivers (Gralloc, GL, OMX IL, and Camera) to do 38// implicit cross-process synchronization to prevent the buffer from being 39// written to before the buffer has (a) been detached from the GL texture and 40// (b) all GL reads from the buffer have completed. 41 42// During refactoring, do not support dequeuing the current buffer 43#undef ALLOW_DEQUEUE_CURRENT_BUFFER 44 45#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER 46#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER true 47#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled" 48#else 49#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER false 50#endif 51 52// Macros for including the BufferQueue name in log messages 53#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) 54#define ST_LOGD(x, ...) ALOGD("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) 55#define ST_LOGI(x, ...) ALOGI("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) 56#define ST_LOGW(x, ...) ALOGW("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) 57#define ST_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) 58 59#define ATRACE_BUFFER_INDEX(index) \ 60 if (ATRACE_ENABLED()) { \ 61 char ___traceBuf[1024]; \ 62 snprintf(___traceBuf, 1024, "%s: %d", mConsumerName.string(), \ 63 (index)); \ 64 android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf); \ 65 } 66 67namespace android { 68 69// Get an ID that's unique within this process. 70static int32_t createProcessUniqueId() { 71 static volatile int32_t globalCounter = 0; 72 return android_atomic_inc(&globalCounter); 73} 74 75static const char* scalingModeName(int scalingMode) { 76 switch (scalingMode) { 77 case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE"; 78 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW"; 79 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP"; 80 default: return "Unknown"; 81 } 82} 83 84BufferQueue::BufferQueue(bool allowSynchronousMode, int bufferCount, 85 const sp<IGraphicBufferAlloc>& allocator) : 86 mDefaultWidth(1), 87 mDefaultHeight(1), 88 mMinUndequeuedBuffers(bufferCount), 89 mMaxBufferCount(bufferCount + 1), 90 mDefaultMaxBufferCount(bufferCount + 1), 91 mOverrideMaxBufferCount(0), 92 mSynchronousMode(false), 93 mAllowSynchronousMode(allowSynchronousMode), 94 mConnectedApi(NO_CONNECTED_API), 95 mAbandoned(false), 96 mFrameCounter(0), 97 mBufferHasBeenQueued(false), 98 mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), 99 mConsumerUsageBits(0), 100 mTransformHint(0) 101{ 102 // Choose a name using the PID and a process-unique ID. 103 mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); 104 105 ST_LOGV("BufferQueue"); 106 if (allocator == NULL) { 107 sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 108 mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); 109 if (mGraphicBufferAlloc == 0) { 110 ST_LOGE("createGraphicBufferAlloc() failed in BufferQueue()"); 111 } 112 } else { 113 mGraphicBufferAlloc = allocator; 114 } 115} 116 117BufferQueue::~BufferQueue() { 118 ST_LOGV("~BufferQueue"); 119} 120 121status_t BufferQueue::setDefaultMaxBufferCountLocked(int count) { 122 if (count > NUM_BUFFER_SLOTS) 123 return BAD_VALUE; 124 125 mDefaultMaxBufferCount = count; 126 127 if (count == mMaxBufferCount) 128 return OK; 129 130 if (!mOverrideMaxBufferCount && 131 count >= mMaxBufferCount) { 132 // easy, we just have more buffers 133 mMaxBufferCount = count; 134 mDequeueCondition.broadcast(); 135 } else { 136 // we're here because we're either 137 // - reducing the number of available buffers 138 // - or there is a client-buffer-count in effect 139 140 // less than 2 buffers is never allowed 141 if (count < 2) 142 return BAD_VALUE; 143 144 // When there is no client-buffer-count in effect, the client is not 145 // allowed to dequeue more than one buffer at a time, so the next time 146 // they dequeue a buffer, we know that they don't own one. the actual 147 // resizing will happen during the next dequeueBuffer. 148 149 // We signal this condition in case there is already a blocked 150 // dequeueBuffer call. 151 mDequeueCondition.broadcast(); 152 } 153 return OK; 154} 155 156bool BufferQueue::isSynchronousMode() const { 157 Mutex::Autolock lock(mMutex); 158 return mSynchronousMode; 159} 160 161void BufferQueue::setConsumerName(const String8& name) { 162 Mutex::Autolock lock(mMutex); 163 mConsumerName = name; 164} 165 166status_t BufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) { 167 Mutex::Autolock lock(mMutex); 168 mDefaultBufferFormat = defaultFormat; 169 return OK; 170} 171 172status_t BufferQueue::setConsumerUsageBits(uint32_t usage) { 173 Mutex::Autolock lock(mMutex); 174 mConsumerUsageBits = usage; 175 return OK; 176} 177 178status_t BufferQueue::setTransformHint(uint32_t hint) { 179 Mutex::Autolock lock(mMutex); 180 mTransformHint = hint; 181 return OK; 182} 183 184status_t BufferQueue::setBufferCount(int bufferCount) { 185 ST_LOGV("setBufferCount: count=%d", bufferCount); 186 187 sp<ConsumerListener> listener; 188 { 189 Mutex::Autolock lock(mMutex); 190 191 if (mAbandoned) { 192 ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!"); 193 return NO_INIT; 194 } 195 if (bufferCount > NUM_BUFFER_SLOTS) { 196 ST_LOGE("setBufferCount: bufferCount larger than slots available"); 197 return BAD_VALUE; 198 } 199 200 // Error out if the user has dequeued buffers 201 for (int i=0 ; i<mMaxBufferCount ; i++) { 202 if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { 203 ST_LOGE("setBufferCount: client owns some buffers"); 204 return -EINVAL; 205 } 206 } 207 208 const int minBufferSlots = getMinMaxBufferCountLocked(); 209 if (bufferCount == 0) { 210 mOverrideMaxBufferCount = 0; 211 bufferCount = (mDefaultMaxBufferCount >= minBufferSlots) ? 212 mDefaultMaxBufferCount : minBufferSlots; 213 return setDefaultMaxBufferCountLocked(bufferCount); 214 } 215 216 if (bufferCount < minBufferSlots) { 217 ST_LOGE("setBufferCount: requested buffer count (%d) is less than " 218 "minimum (%d)", bufferCount, minBufferSlots); 219 return BAD_VALUE; 220 } 221 222 // here we're guaranteed that the client doesn't have dequeued buffers 223 // and will release all of its buffer references. 224 freeAllBuffersLocked(); 225 mMaxBufferCount = bufferCount; 226 mOverrideMaxBufferCount = bufferCount; 227 mBufferHasBeenQueued = false; 228 mQueue.clear(); 229 mDequeueCondition.broadcast(); 230 listener = mConsumerListener; 231 } // scope for lock 232 233 if (listener != NULL) { 234 listener->onBuffersReleased(); 235 } 236 237 return OK; 238} 239 240int BufferQueue::query(int what, int* outValue) 241{ 242 ATRACE_CALL(); 243 Mutex::Autolock lock(mMutex); 244 245 if (mAbandoned) { 246 ST_LOGE("query: SurfaceTexture has been abandoned!"); 247 return NO_INIT; 248 } 249 250 int value; 251 switch (what) { 252 case NATIVE_WINDOW_WIDTH: 253 value = mDefaultWidth; 254 break; 255 case NATIVE_WINDOW_HEIGHT: 256 value = mDefaultHeight; 257 break; 258 case NATIVE_WINDOW_FORMAT: 259 value = mDefaultBufferFormat; 260 break; 261 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 262 value = mSynchronousMode ? 263 (mMinUndequeuedBuffers-1) : mMinUndequeuedBuffers; 264 break; 265 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: 266 value = (mQueue.size() >= 2); 267 break; 268 default: 269 return BAD_VALUE; 270 } 271 outValue[0] = value; 272 return NO_ERROR; 273} 274 275status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) { 276 ATRACE_CALL(); 277 ST_LOGV("requestBuffer: slot=%d", slot); 278 Mutex::Autolock lock(mMutex); 279 if (mAbandoned) { 280 ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!"); 281 return NO_INIT; 282 } 283 if (slot < 0 || mMaxBufferCount <= slot) { 284 ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d", 285 mMaxBufferCount, slot); 286 return BAD_VALUE; 287 } 288 mSlots[slot].mRequestBufferCalled = true; 289 *buf = mSlots[slot].mGraphicBuffer; 290 return NO_ERROR; 291} 292 293status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, 294 uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { 295 ATRACE_CALL(); 296 ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage); 297 298 if ((w && !h) || (!w && h)) { 299 ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); 300 return BAD_VALUE; 301 } 302 303 status_t returnFlags(OK); 304 EGLDisplay dpy = EGL_NO_DISPLAY; 305 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR; 306 307 { // Scope for the lock 308 Mutex::Autolock lock(mMutex); 309 310 if (format == 0) { 311 format = mDefaultBufferFormat; 312 } 313 // turn on usage bits the consumer requested 314 usage |= mConsumerUsageBits; 315 316 int found = -1; 317 int dequeuedCount = 0; 318 bool tryAgain = true; 319 while (tryAgain) { 320 if (mAbandoned) { 321 ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); 322 return NO_INIT; 323 } 324 325 // We need to wait for the FIFO to drain if the number of buffer 326 // needs to change. 327 // 328 // The condition "number of buffers needs to change" is true if 329 // - the client doesn't care about how many buffers there are 330 // - AND the actual number of buffer is different from what was 331 // set in the last setDefaultMaxBufferCount() 332 // - OR - 333 // setDefaultMaxBufferCount() was set to a value incompatible with 334 // the synchronization mode (for instance because the sync mode 335 // changed since) 336 // 337 // As long as this condition is true AND the FIFO is not empty, we 338 // wait on mDequeueCondition. 339 340 const int minBufferCountNeeded = getMinMaxBufferCountLocked(); 341 342 const bool numberOfBuffersNeedsToChange = !mOverrideMaxBufferCount && 343 ((mDefaultMaxBufferCount != mMaxBufferCount) || 344 (mDefaultMaxBufferCount < minBufferCountNeeded)); 345 346 if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) { 347 // wait for the FIFO to drain 348 mDequeueCondition.wait(mMutex); 349 // NOTE: we continue here because we need to reevaluate our 350 // whole state (eg: we could be abandoned or disconnected) 351 continue; 352 } 353 354 if (numberOfBuffersNeedsToChange) { 355 // here we're guaranteed that mQueue is empty 356 freeAllBuffersLocked(); 357 mMaxBufferCount = mDefaultMaxBufferCount; 358 if (mMaxBufferCount < minBufferCountNeeded) 359 mMaxBufferCount = minBufferCountNeeded; 360 mBufferHasBeenQueued = false; 361 returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS; 362 } 363 364 // look for a free buffer to give to the client 365 found = INVALID_BUFFER_SLOT; 366 dequeuedCount = 0; 367 for (int i = 0; i < mMaxBufferCount; i++) { 368 const int state = mSlots[i].mBufferState; 369 if (state == BufferSlot::DEQUEUED) { 370 dequeuedCount++; 371 } 372 373 // this logic used to be if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) 374 // but dequeuing the current buffer is disabled. 375 if (false) { 376 // This functionality has been temporarily removed so 377 // BufferQueue and SurfaceTexture can be refactored into 378 // separate objects 379 } else { 380 if (state == BufferSlot::FREE) { 381 /* We return the oldest of the free buffers to avoid 382 * stalling the producer if possible. This is because 383 * the consumer may still have pending reads of the 384 * buffers in flight. 385 */ 386 bool isOlder = mSlots[i].mFrameNumber < 387 mSlots[found].mFrameNumber; 388 if (found < 0 || isOlder) { 389 found = i; 390 } 391 } 392 } 393 } 394 395 // clients are not allowed to dequeue more than one buffer 396 // if they didn't set a buffer count. 397 if (!mOverrideMaxBufferCount && dequeuedCount) { 398 ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without " 399 "setting the buffer count"); 400 return -EINVAL; 401 } 402 403 // See whether a buffer has been queued since the last 404 // setBufferCount so we know whether to perform the 405 // mMinUndequeuedBuffers check below. 406 if (mBufferHasBeenQueued) { 407 // make sure the client is not trying to dequeue more buffers 408 // than allowed. 409 const int avail = mMaxBufferCount - (dequeuedCount+1); 410 if (avail < (mMinUndequeuedBuffers-int(mSynchronousMode))) { 411 ST_LOGE("dequeueBuffer: mMinUndequeuedBuffers=%d exceeded " 412 "(dequeued=%d)", 413 mMinUndequeuedBuffers-int(mSynchronousMode), 414 dequeuedCount); 415 return -EBUSY; 416 } 417 } 418 419 // if no buffer is found, wait for a buffer to be released 420 tryAgain = found == INVALID_BUFFER_SLOT; 421 if (tryAgain) { 422 mDequeueCondition.wait(mMutex); 423 } 424 } 425 426 427 if (found == INVALID_BUFFER_SLOT) { 428 // This should not happen. 429 ST_LOGE("dequeueBuffer: no available buffer slots"); 430 return -EBUSY; 431 } 432 433 const int buf = found; 434 *outBuf = found; 435 436 ATRACE_BUFFER_INDEX(buf); 437 438 const bool useDefaultSize = !w && !h; 439 if (useDefaultSize) { 440 // use the default size 441 w = mDefaultWidth; 442 h = mDefaultHeight; 443 } 444 445 // buffer is now in DEQUEUED (but can also be current at the same time, 446 // if we're in synchronous mode) 447 mSlots[buf].mBufferState = BufferSlot::DEQUEUED; 448 449 const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); 450 if ((buffer == NULL) || 451 (uint32_t(buffer->width) != w) || 452 (uint32_t(buffer->height) != h) || 453 (uint32_t(buffer->format) != format) || 454 ((uint32_t(buffer->usage) & usage) != usage)) 455 { 456 status_t error; 457 sp<GraphicBuffer> graphicBuffer( 458 mGraphicBufferAlloc->createGraphicBuffer( 459 w, h, format, usage, &error)); 460 if (graphicBuffer == 0) { 461 ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer " 462 "failed"); 463 return error; 464 } 465 466 mSlots[buf].mAcquireCalled = false; 467 mSlots[buf].mGraphicBuffer = graphicBuffer; 468 mSlots[buf].mRequestBufferCalled = false; 469 mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; 470 mSlots[buf].mFence.clear(); 471 mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; 472 473 returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; 474 } 475 476 dpy = mSlots[buf].mEglDisplay; 477 eglFence = mSlots[buf].mEglFence; 478 outFence = mSlots[buf].mFence; 479 mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; 480 mSlots[buf].mFence.clear(); 481 } // end lock scope 482 483 if (eglFence != EGL_NO_SYNC_KHR) { 484 EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000); 485 // If something goes wrong, log the error, but return the buffer without 486 // synchronizing access to it. It's too late at this point to abort the 487 // dequeue operation. 488 if (result == EGL_FALSE) { 489 ST_LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError()); 490 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 491 ST_LOGE("dequeueBuffer: timeout waiting for fence"); 492 } 493 eglDestroySyncKHR(dpy, eglFence); 494 } 495 496 ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf, 497 mSlots[*outBuf].mGraphicBuffer->handle, returnFlags); 498 499 return returnFlags; 500} 501 502status_t BufferQueue::setSynchronousMode(bool enabled) { 503 ATRACE_CALL(); 504 ST_LOGV("setSynchronousMode: enabled=%d", enabled); 505 Mutex::Autolock lock(mMutex); 506 507 if (mAbandoned) { 508 ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!"); 509 return NO_INIT; 510 } 511 512 status_t err = OK; 513 if (!mAllowSynchronousMode && enabled) 514 return err; 515 516 if (!enabled) { 517 // going to asynchronous mode, drain the queue 518 err = drainQueueLocked(); 519 if (err != NO_ERROR) 520 return err; 521 } 522 523 if (mSynchronousMode != enabled) { 524 // - if we're going to asynchronous mode, the queue is guaranteed to be 525 // empty here 526 // - if the client set the number of buffers, we're guaranteed that 527 // we have at least 3 (because we don't allow less) 528 mSynchronousMode = enabled; 529 mDequeueCondition.broadcast(); 530 } 531 return err; 532} 533 534status_t BufferQueue::queueBuffer(int buf, 535 const QueueBufferInput& input, QueueBufferOutput* output) { 536 ATRACE_CALL(); 537 ATRACE_BUFFER_INDEX(buf); 538 539 Rect crop; 540 uint32_t transform; 541 int scalingMode; 542 int64_t timestamp; 543 sp<Fence> fence; 544 545 input.deflate(×tamp, &crop, &scalingMode, &transform, &fence); 546 547 ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x " 548 "scale=%s", 549 buf, timestamp, crop.left, crop.top, crop.right, crop.bottom, 550 transform, scalingModeName(scalingMode)); 551 552 sp<ConsumerListener> listener; 553 554 { // scope for the lock 555 Mutex::Autolock lock(mMutex); 556 if (mAbandoned) { 557 ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!"); 558 return NO_INIT; 559 } 560 if (buf < 0 || buf >= mMaxBufferCount) { 561 ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d", 562 mMaxBufferCount, buf); 563 return -EINVAL; 564 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 565 ST_LOGE("queueBuffer: slot %d is not owned by the client " 566 "(state=%d)", buf, mSlots[buf].mBufferState); 567 return -EINVAL; 568 } else if (!mSlots[buf].mRequestBufferCalled) { 569 ST_LOGE("queueBuffer: slot %d was enqueued without requesting a " 570 "buffer", buf); 571 return -EINVAL; 572 } 573 574 const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer); 575 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); 576 Rect croppedCrop; 577 crop.intersect(bufferRect, &croppedCrop); 578 if (croppedCrop != crop) { 579 ST_LOGE("queueBuffer: crop rect is not contained within the " 580 "buffer in slot %d", buf); 581 return -EINVAL; 582 } 583 584 if (mSynchronousMode) { 585 // In synchronous mode we queue all buffers in a FIFO. 586 mQueue.push_back(buf); 587 588 // Synchronous mode always signals that an additional frame should 589 // be consumed. 590 listener = mConsumerListener; 591 } else { 592 // In asynchronous mode we only keep the most recent buffer. 593 if (mQueue.empty()) { 594 mQueue.push_back(buf); 595 596 // Asynchronous mode only signals that a frame should be 597 // consumed if no previous frame was pending. If a frame were 598 // pending then the consumer would have already been notified. 599 listener = mConsumerListener; 600 } else { 601 Fifo::iterator front(mQueue.begin()); 602 // buffer currently queued is freed 603 mSlots[*front].mBufferState = BufferSlot::FREE; 604 // and we record the new buffer index in the queued list 605 *front = buf; 606 } 607 } 608 609 mSlots[buf].mTimestamp = timestamp; 610 mSlots[buf].mCrop = crop; 611 mSlots[buf].mTransform = transform; 612 mSlots[buf].mFence = fence; 613 614 switch (scalingMode) { 615 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 616 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 617 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: 618 break; 619 default: 620 ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode); 621 scalingMode = mSlots[buf].mScalingMode; 622 break; 623 } 624 625 mSlots[buf].mBufferState = BufferSlot::QUEUED; 626 mSlots[buf].mScalingMode = scalingMode; 627 mFrameCounter++; 628 mSlots[buf].mFrameNumber = mFrameCounter; 629 630 mBufferHasBeenQueued = true; 631 mDequeueCondition.broadcast(); 632 633 output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, 634 mQueue.size()); 635 636 ATRACE_INT(mConsumerName.string(), mQueue.size()); 637 } // scope for the lock 638 639 // call back without lock held 640 if (listener != 0) { 641 listener->onFrameAvailable(); 642 } 643 return OK; 644} 645 646void BufferQueue::cancelBuffer(int buf, sp<Fence> fence) { 647 ATRACE_CALL(); 648 ST_LOGV("cancelBuffer: slot=%d", buf); 649 Mutex::Autolock lock(mMutex); 650 651 if (mAbandoned) { 652 ST_LOGW("cancelBuffer: BufferQueue has been abandoned!"); 653 return; 654 } 655 656 if (buf < 0 || buf >= mMaxBufferCount) { 657 ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d", 658 mMaxBufferCount, buf); 659 return; 660 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 661 ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", 662 buf, mSlots[buf].mBufferState); 663 return; 664 } 665 mSlots[buf].mBufferState = BufferSlot::FREE; 666 mSlots[buf].mFrameNumber = 0; 667 mSlots[buf].mFence = fence; 668 mDequeueCondition.broadcast(); 669} 670 671status_t BufferQueue::connect(int api, QueueBufferOutput* output) { 672 ATRACE_CALL(); 673 ST_LOGV("connect: api=%d", api); 674 Mutex::Autolock lock(mMutex); 675 676 if (mAbandoned) { 677 ST_LOGE("connect: BufferQueue has been abandoned!"); 678 return NO_INIT; 679 } 680 681 if (mConsumerListener == NULL) { 682 ST_LOGE("connect: BufferQueue has no consumer!"); 683 return NO_INIT; 684 } 685 686 int err = NO_ERROR; 687 switch (api) { 688 case NATIVE_WINDOW_API_EGL: 689 case NATIVE_WINDOW_API_CPU: 690 case NATIVE_WINDOW_API_MEDIA: 691 case NATIVE_WINDOW_API_CAMERA: 692 if (mConnectedApi != NO_CONNECTED_API) { 693 ST_LOGE("connect: already connected (cur=%d, req=%d)", 694 mConnectedApi, api); 695 err = -EINVAL; 696 } else { 697 mConnectedApi = api; 698 output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, 699 mQueue.size()); 700 } 701 break; 702 default: 703 err = -EINVAL; 704 break; 705 } 706 707 mBufferHasBeenQueued = false; 708 709 return err; 710} 711 712status_t BufferQueue::disconnect(int api) { 713 ATRACE_CALL(); 714 ST_LOGV("disconnect: api=%d", api); 715 716 int err = NO_ERROR; 717 sp<ConsumerListener> listener; 718 719 { // Scope for the lock 720 Mutex::Autolock lock(mMutex); 721 722 if (mAbandoned) { 723 // it is not really an error to disconnect after the surface 724 // has been abandoned, it should just be a no-op. 725 return NO_ERROR; 726 } 727 728 switch (api) { 729 case NATIVE_WINDOW_API_EGL: 730 case NATIVE_WINDOW_API_CPU: 731 case NATIVE_WINDOW_API_MEDIA: 732 case NATIVE_WINDOW_API_CAMERA: 733 if (mConnectedApi == api) { 734 drainQueueAndFreeBuffersLocked(); 735 mConnectedApi = NO_CONNECTED_API; 736 mDequeueCondition.broadcast(); 737 listener = mConsumerListener; 738 } else { 739 ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)", 740 mConnectedApi, api); 741 err = -EINVAL; 742 } 743 break; 744 default: 745 ST_LOGE("disconnect: unknown API %d", api); 746 err = -EINVAL; 747 break; 748 } 749 } 750 751 if (listener != NULL) { 752 listener->onBuffersReleased(); 753 } 754 755 return err; 756} 757 758void BufferQueue::dump(String8& result) const 759{ 760 char buffer[1024]; 761 BufferQueue::dump(result, "", buffer, 1024); 762} 763 764void BufferQueue::dump(String8& result, const char* prefix, 765 char* buffer, size_t SIZE) const 766{ 767 Mutex::Autolock _l(mMutex); 768 769 String8 fifo; 770 int fifoSize = 0; 771 Fifo::const_iterator i(mQueue.begin()); 772 while (i != mQueue.end()) { 773 snprintf(buffer, SIZE, "%02d ", *i++); 774 fifoSize++; 775 fifo.append(buffer); 776 } 777 778 snprintf(buffer, SIZE, 779 "%s-BufferQueue mMaxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " 780 "default-format=%d, FIFO(%d)={%s}\n", 781 prefix, mMaxBufferCount, mSynchronousMode, mDefaultWidth, 782 mDefaultHeight, mDefaultBufferFormat, fifoSize, fifo.string()); 783 result.append(buffer); 784 785 786 struct { 787 const char * operator()(int state) const { 788 switch (state) { 789 case BufferSlot::DEQUEUED: return "DEQUEUED"; 790 case BufferSlot::QUEUED: return "QUEUED"; 791 case BufferSlot::FREE: return "FREE"; 792 case BufferSlot::ACQUIRED: return "ACQUIRED"; 793 default: return "Unknown"; 794 } 795 } 796 } stateName; 797 798 for (int i=0 ; i<mMaxBufferCount ; i++) { 799 const BufferSlot& slot(mSlots[i]); 800 snprintf(buffer, SIZE, 801 "%s%s[%02d] " 802 "state=%-8s, crop=[%d,%d,%d,%d], " 803 "xform=0x%02x, time=%#llx, scale=%s", 804 prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, 805 stateName(slot.mBufferState), 806 slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, 807 slot.mCrop.bottom, slot.mTransform, slot.mTimestamp, 808 scalingModeName(slot.mScalingMode) 809 ); 810 result.append(buffer); 811 812 const sp<GraphicBuffer>& buf(slot.mGraphicBuffer); 813 if (buf != NULL) { 814 snprintf(buffer, SIZE, 815 ", %p [%4ux%4u:%4u,%3X]", 816 buf->handle, buf->width, buf->height, buf->stride, 817 buf->format); 818 result.append(buffer); 819 } 820 result.append("\n"); 821 } 822} 823 824void BufferQueue::freeBufferLocked(int slot) { 825 ST_LOGV("freeBufferLocked: slot=%d", slot); 826 mSlots[slot].mGraphicBuffer = 0; 827 if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) { 828 mSlots[slot].mNeedsCleanupOnRelease = true; 829 } 830 mSlots[slot].mBufferState = BufferSlot::FREE; 831 mSlots[slot].mFrameNumber = 0; 832 mSlots[slot].mAcquireCalled = false; 833 834 // destroy fence as BufferQueue now takes ownership 835 if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) { 836 eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence); 837 mSlots[slot].mEglFence = EGL_NO_SYNC_KHR; 838 } 839 mSlots[slot].mFence.clear(); 840} 841 842void BufferQueue::freeAllBuffersLocked() { 843 ALOGW_IF(!mQueue.isEmpty(), 844 "freeAllBuffersLocked called but mQueue is not empty"); 845 mQueue.clear(); 846 mBufferHasBeenQueued = false; 847 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 848 freeBufferLocked(i); 849 } 850} 851 852status_t BufferQueue::acquireBuffer(BufferItem *buffer) { 853 ATRACE_CALL(); 854 Mutex::Autolock _l(mMutex); 855 // check if queue is empty 856 // In asynchronous mode the list is guaranteed to be one buffer 857 // deep, while in synchronous mode we use the oldest buffer. 858 if (!mQueue.empty()) { 859 Fifo::iterator front(mQueue.begin()); 860 int buf = *front; 861 862 ATRACE_BUFFER_INDEX(buf); 863 864 if (mSlots[buf].mAcquireCalled) { 865 buffer->mGraphicBuffer = NULL; 866 } else { 867 buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer; 868 } 869 buffer->mCrop = mSlots[buf].mCrop; 870 buffer->mTransform = mSlots[buf].mTransform; 871 buffer->mScalingMode = mSlots[buf].mScalingMode; 872 buffer->mFrameNumber = mSlots[buf].mFrameNumber; 873 buffer->mTimestamp = mSlots[buf].mTimestamp; 874 buffer->mBuf = buf; 875 buffer->mFence = mSlots[buf].mFence; 876 877 mSlots[buf].mAcquireCalled = true; 878 mSlots[buf].mNeedsCleanupOnRelease = false; 879 mSlots[buf].mBufferState = BufferSlot::ACQUIRED; 880 mSlots[buf].mFence.clear(); 881 882 mQueue.erase(front); 883 mDequeueCondition.broadcast(); 884 885 ATRACE_INT(mConsumerName.string(), mQueue.size()); 886 } else { 887 return NO_BUFFER_AVAILABLE; 888 } 889 890 return OK; 891} 892 893status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display, 894 EGLSyncKHR eglFence, const sp<Fence>& fence) { 895 ATRACE_CALL(); 896 ATRACE_BUFFER_INDEX(buf); 897 898 Mutex::Autolock _l(mMutex); 899 900 if (buf == INVALID_BUFFER_SLOT) { 901 return -EINVAL; 902 } 903 904 mSlots[buf].mEglDisplay = display; 905 mSlots[buf].mEglFence = eglFence; 906 mSlots[buf].mFence = fence; 907 908 // The buffer can now only be released if its in the acquired state 909 if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) { 910 mSlots[buf].mBufferState = BufferSlot::FREE; 911 } else if (mSlots[buf].mNeedsCleanupOnRelease) { 912 ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState); 913 mSlots[buf].mNeedsCleanupOnRelease = false; 914 return STALE_BUFFER_SLOT; 915 } else { 916 ST_LOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState); 917 return -EINVAL; 918 } 919 920 mDequeueCondition.broadcast(); 921 return OK; 922} 923 924status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) { 925 ST_LOGV("consumerConnect"); 926 Mutex::Autolock lock(mMutex); 927 928 if (mAbandoned) { 929 ST_LOGE("consumerConnect: BufferQueue has been abandoned!"); 930 return NO_INIT; 931 } 932 933 mConsumerListener = consumerListener; 934 935 return OK; 936} 937 938status_t BufferQueue::consumerDisconnect() { 939 ST_LOGV("consumerDisconnect"); 940 Mutex::Autolock lock(mMutex); 941 942 if (mConsumerListener == NULL) { 943 ST_LOGE("consumerDisconnect: No consumer is connected!"); 944 return -EINVAL; 945 } 946 947 mAbandoned = true; 948 mConsumerListener = NULL; 949 mQueue.clear(); 950 freeAllBuffersLocked(); 951 mDequeueCondition.broadcast(); 952 return OK; 953} 954 955status_t BufferQueue::getReleasedBuffers(uint32_t* slotMask) { 956 ST_LOGV("getReleasedBuffers"); 957 Mutex::Autolock lock(mMutex); 958 959 if (mAbandoned) { 960 ST_LOGE("getReleasedBuffers: BufferQueue has been abandoned!"); 961 return NO_INIT; 962 } 963 964 uint32_t mask = 0; 965 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 966 if (!mSlots[i].mAcquireCalled) { 967 mask |= 1 << i; 968 } 969 } 970 *slotMask = mask; 971 972 ST_LOGV("getReleasedBuffers: returning mask %#x", mask); 973 return NO_ERROR; 974} 975 976status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) 977{ 978 ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h); 979 if (!w || !h) { 980 ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", 981 w, h); 982 return BAD_VALUE; 983 } 984 985 Mutex::Autolock lock(mMutex); 986 mDefaultWidth = w; 987 mDefaultHeight = h; 988 return OK; 989} 990 991status_t BufferQueue::setDefaultMaxBufferCount(int bufferCount) { 992 ATRACE_CALL(); 993 Mutex::Autolock lock(mMutex); 994 return setDefaultMaxBufferCountLocked(bufferCount); 995} 996 997void BufferQueue::freeAllBuffersExceptHeadLocked() { 998 int head = -1; 999 if (!mQueue.empty()) { 1000 Fifo::iterator front(mQueue.begin()); 1001 head = *front; 1002 } 1003 mBufferHasBeenQueued = false; 1004 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 1005 if (i != head) { 1006 freeBufferLocked(i); 1007 } 1008 } 1009} 1010 1011status_t BufferQueue::drainQueueLocked() { 1012 while (mSynchronousMode && !mQueue.isEmpty()) { 1013 mDequeueCondition.wait(mMutex); 1014 if (mAbandoned) { 1015 ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!"); 1016 return NO_INIT; 1017 } 1018 if (mConnectedApi == NO_CONNECTED_API) { 1019 ST_LOGE("drainQueueLocked: BufferQueue is not connected!"); 1020 return NO_INIT; 1021 } 1022 } 1023 return NO_ERROR; 1024} 1025 1026status_t BufferQueue::drainQueueAndFreeBuffersLocked() { 1027 status_t err = drainQueueLocked(); 1028 if (err == NO_ERROR) { 1029 if (mSynchronousMode) { 1030 freeAllBuffersLocked(); 1031 } else { 1032 freeAllBuffersExceptHeadLocked(); 1033 } 1034 } 1035 return err; 1036} 1037 1038int BufferQueue::getMinMaxBufferCountLocked() const { 1039 return mSynchronousMode ? mMinUndequeuedBuffers : mMinUndequeuedBuffers + 1; 1040} 1041 1042BufferQueue::ProxyConsumerListener::ProxyConsumerListener( 1043 const wp<BufferQueue::ConsumerListener>& consumerListener): 1044 mConsumerListener(consumerListener) {} 1045 1046BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} 1047 1048void BufferQueue::ProxyConsumerListener::onFrameAvailable() { 1049 sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote()); 1050 if (listener != NULL) { 1051 listener->onFrameAvailable(); 1052 } 1053} 1054 1055void BufferQueue::ProxyConsumerListener::onBuffersReleased() { 1056 sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote()); 1057 if (listener != NULL) { 1058 listener->onBuffersReleased(); 1059 } 1060} 1061 1062}; // namespace android 1063