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