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