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