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