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