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