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