BufferQueue.cpp revision c68f2ecfa02037144d1a3856f637a77f523cf416
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 816 // Check that the consumer doesn't currently have the maximum number of 817 // buffers acquired. We allow the max buffer count to be exceeded by one 818 // buffer, so that the consumer can successfully set up the newly acquired 819 // buffer before releasing the old one. 820 int numAcquiredBuffers = 0; 821 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 822 if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) { 823 numAcquiredBuffers++; 824 } 825 } 826 if (numAcquiredBuffers >= mMaxAcquiredBufferCount+1) { 827 ST_LOGE("acquireBuffer: max acquired buffer count reached: %d (max=%d)", 828 numAcquiredBuffers, mMaxAcquiredBufferCount); 829 return INVALID_OPERATION; 830 } 831 832 // check if queue is empty 833 // In asynchronous mode the list is guaranteed to be one buffer 834 // deep, while in synchronous mode we use the oldest buffer. 835 if (!mQueue.empty()) { 836 Fifo::iterator front(mQueue.begin()); 837 int buf = *front; 838 839 ATRACE_BUFFER_INDEX(buf); 840 841 if (mSlots[buf].mAcquireCalled) { 842 buffer->mGraphicBuffer = NULL; 843 } else { 844 buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer; 845 } 846 buffer->mCrop = mSlots[buf].mCrop; 847 buffer->mTransform = mSlots[buf].mTransform; 848 buffer->mScalingMode = mSlots[buf].mScalingMode; 849 buffer->mFrameNumber = mSlots[buf].mFrameNumber; 850 buffer->mTimestamp = mSlots[buf].mTimestamp; 851 buffer->mBuf = buf; 852 buffer->mFence = mSlots[buf].mFence; 853 854 mSlots[buf].mAcquireCalled = true; 855 mSlots[buf].mNeedsCleanupOnRelease = false; 856 mSlots[buf].mBufferState = BufferSlot::ACQUIRED; 857 mSlots[buf].mFence.clear(); 858 859 mQueue.erase(front); 860 mDequeueCondition.broadcast(); 861 862 ATRACE_INT(mConsumerName.string(), mQueue.size()); 863 } else { 864 return NO_BUFFER_AVAILABLE; 865 } 866 867 return OK; 868} 869 870status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display, 871 EGLSyncKHR eglFence, const sp<Fence>& fence) { 872 ATRACE_CALL(); 873 ATRACE_BUFFER_INDEX(buf); 874 875 Mutex::Autolock _l(mMutex); 876 877 if (buf == INVALID_BUFFER_SLOT) { 878 return -EINVAL; 879 } 880 881 mSlots[buf].mEglDisplay = display; 882 mSlots[buf].mEglFence = eglFence; 883 mSlots[buf].mFence = fence; 884 885 // The buffer can now only be released if its in the acquired state 886 if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) { 887 mSlots[buf].mBufferState = BufferSlot::FREE; 888 } else if (mSlots[buf].mNeedsCleanupOnRelease) { 889 ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState); 890 mSlots[buf].mNeedsCleanupOnRelease = false; 891 return STALE_BUFFER_SLOT; 892 } else { 893 ST_LOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState); 894 return -EINVAL; 895 } 896 897 mDequeueCondition.broadcast(); 898 return OK; 899} 900 901status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) { 902 ST_LOGV("consumerConnect"); 903 Mutex::Autolock lock(mMutex); 904 905 if (mAbandoned) { 906 ST_LOGE("consumerConnect: BufferQueue has been abandoned!"); 907 return NO_INIT; 908 } 909 910 mConsumerListener = consumerListener; 911 912 return OK; 913} 914 915status_t BufferQueue::consumerDisconnect() { 916 ST_LOGV("consumerDisconnect"); 917 Mutex::Autolock lock(mMutex); 918 919 if (mConsumerListener == NULL) { 920 ST_LOGE("consumerDisconnect: No consumer is connected!"); 921 return -EINVAL; 922 } 923 924 mAbandoned = true; 925 mConsumerListener = NULL; 926 mQueue.clear(); 927 freeAllBuffersLocked(); 928 mDequeueCondition.broadcast(); 929 return OK; 930} 931 932status_t BufferQueue::getReleasedBuffers(uint32_t* slotMask) { 933 ST_LOGV("getReleasedBuffers"); 934 Mutex::Autolock lock(mMutex); 935 936 if (mAbandoned) { 937 ST_LOGE("getReleasedBuffers: BufferQueue has been abandoned!"); 938 return NO_INIT; 939 } 940 941 uint32_t mask = 0; 942 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 943 if (!mSlots[i].mAcquireCalled) { 944 mask |= 1 << i; 945 } 946 } 947 *slotMask = mask; 948 949 ST_LOGV("getReleasedBuffers: returning mask %#x", mask); 950 return NO_ERROR; 951} 952 953status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) 954{ 955 ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h); 956 if (!w || !h) { 957 ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", 958 w, h); 959 return BAD_VALUE; 960 } 961 962 Mutex::Autolock lock(mMutex); 963 mDefaultWidth = w; 964 mDefaultHeight = h; 965 return OK; 966} 967 968status_t BufferQueue::setDefaultMaxBufferCount(int bufferCount) { 969 ATRACE_CALL(); 970 Mutex::Autolock lock(mMutex); 971 return setDefaultMaxBufferCountLocked(bufferCount); 972} 973 974status_t BufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { 975 ATRACE_CALL(); 976 Mutex::Autolock lock(mMutex); 977 if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) { 978 ST_LOGE("setMaxAcquiredBufferCount: invalid count specified: %d", 979 maxAcquiredBuffers); 980 return BAD_VALUE; 981 } 982 if (mConnectedApi != NO_CONNECTED_API) { 983 return INVALID_OPERATION; 984 } 985 mMaxAcquiredBufferCount = maxAcquiredBuffers; 986 return OK; 987} 988 989void BufferQueue::freeAllBuffersExceptHeadLocked() { 990 int head = -1; 991 if (!mQueue.empty()) { 992 Fifo::iterator front(mQueue.begin()); 993 head = *front; 994 } 995 mBufferHasBeenQueued = false; 996 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 997 if (i != head) { 998 freeBufferLocked(i); 999 } 1000 } 1001} 1002 1003status_t BufferQueue::drainQueueLocked() { 1004 while (mSynchronousMode && !mQueue.isEmpty()) { 1005 mDequeueCondition.wait(mMutex); 1006 if (mAbandoned) { 1007 ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!"); 1008 return NO_INIT; 1009 } 1010 if (mConnectedApi == NO_CONNECTED_API) { 1011 ST_LOGE("drainQueueLocked: BufferQueue is not connected!"); 1012 return NO_INIT; 1013 } 1014 } 1015 return NO_ERROR; 1016} 1017 1018status_t BufferQueue::drainQueueAndFreeBuffersLocked() { 1019 status_t err = drainQueueLocked(); 1020 if (err == NO_ERROR) { 1021 if (mSynchronousMode) { 1022 freeAllBuffersLocked(); 1023 } else { 1024 freeAllBuffersExceptHeadLocked(); 1025 } 1026 } 1027 return err; 1028} 1029 1030int BufferQueue::getMinMaxBufferCountLocked() const { 1031 return getMinUndequeuedBufferCountLocked() + 1; 1032} 1033 1034int BufferQueue::getMinUndequeuedBufferCountLocked() const { 1035 return mSynchronousMode ? mMaxAcquiredBufferCount : 1036 mMaxAcquiredBufferCount + 1; 1037} 1038 1039int BufferQueue::getMaxBufferCountLocked() const { 1040 int minMaxBufferCount = getMinMaxBufferCountLocked(); 1041 1042 int maxBufferCount = mDefaultMaxBufferCount; 1043 if (maxBufferCount < minMaxBufferCount) { 1044 maxBufferCount = minMaxBufferCount; 1045 } 1046 if (mOverrideMaxBufferCount != 0) { 1047 assert(mOverrideMaxBufferCount >= minMaxBufferCount); 1048 maxBufferCount = mOverrideMaxBufferCount; 1049 } 1050 1051 // Any buffers that are dequeued by the producer or sitting in the queue 1052 // waiting to be consumed need to have their slots preserved. Such 1053 // buffers will temporarily keep the max buffer count up until the slots 1054 // no longer need to be preserved. 1055 for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) { 1056 BufferSlot::BufferState state = mSlots[i].mBufferState; 1057 if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) { 1058 maxBufferCount = i + 1; 1059 } 1060 } 1061 1062 return maxBufferCount; 1063} 1064 1065BufferQueue::ProxyConsumerListener::ProxyConsumerListener( 1066 const wp<BufferQueue::ConsumerListener>& consumerListener): 1067 mConsumerListener(consumerListener) {} 1068 1069BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} 1070 1071void BufferQueue::ProxyConsumerListener::onFrameAvailable() { 1072 sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote()); 1073 if (listener != NULL) { 1074 listener->onFrameAvailable(); 1075 } 1076} 1077 1078void BufferQueue::ProxyConsumerListener::onBuffersReleased() { 1079 sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote()); 1080 if (listener != NULL) { 1081 listener->onBuffersReleased(); 1082 } 1083} 1084 1085}; // namespace android 1086