BufferQueueConsumer.cpp revision 99b18b447dec188bcec37b415603b9dd400fc7e1
1/* 2 * Copyright 2014 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 "BufferQueueConsumer" 18#define ATRACE_TAG ATRACE_TAG_GRAPHICS 19//#define LOG_NDEBUG 0 20 21#include <gui/BufferItem.h> 22#include <gui/BufferQueueConsumer.h> 23#include <gui/BufferQueueCore.h> 24#include <gui/IConsumerListener.h> 25#include <gui/IProducerListener.h> 26 27namespace android { 28 29BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) : 30 mCore(core), 31 mSlots(core->mSlots), 32 mConsumerName() {} 33 34BufferQueueConsumer::~BufferQueueConsumer() {} 35 36status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, 37 nsecs_t expectedPresent) { 38 ATRACE_CALL(); 39 Mutex::Autolock lock(mCore->mMutex); 40 41 // Check that the consumer doesn't currently have the maximum number of 42 // buffers acquired. We allow the max buffer count to be exceeded by one 43 // buffer so that the consumer can successfully set up the newly acquired 44 // buffer before releasing the old one. 45 int numAcquiredBuffers = 0; 46 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 47 if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) { 48 ++numAcquiredBuffers; 49 } 50 } 51 if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) { 52 BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)", 53 numAcquiredBuffers, mCore->mMaxAcquiredBufferCount); 54 return INVALID_OPERATION; 55 } 56 57 // Check if the queue is empty. 58 // In asynchronous mode the list is guaranteed to be one buffer deep, 59 // while in synchronous mode we use the oldest buffer. 60 if (mCore->mQueue.empty()) { 61 return NO_BUFFER_AVAILABLE; 62 } 63 64 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); 65 66 // If expectedPresent is specified, we may not want to return a buffer yet. 67 // If it's specified and there's more than one buffer queued, we may want 68 // to drop a buffer. 69 if (expectedPresent != 0) { 70 const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second 71 72 // The 'expectedPresent' argument indicates when the buffer is expected 73 // to be presented on-screen. If the buffer's desired present time is 74 // earlier (less) than expectedPresent -- meaning it will be displayed 75 // on time or possibly late if we show it as soon as possible -- we 76 // acquire and return it. If we don't want to display it until after the 77 // expectedPresent time, we return PRESENT_LATER without acquiring it. 78 // 79 // To be safe, we don't defer acquisition if expectedPresent is more 80 // than one second in the future beyond the desired present time 81 // (i.e., we'd be holding the buffer for a long time). 82 // 83 // NOTE: Code assumes monotonic time values from the system clock 84 // are positive. 85 86 // Start by checking to see if we can drop frames. We skip this check if 87 // the timestamps are being auto-generated by Surface. If the app isn't 88 // generating timestamps explicitly, it probably doesn't want frames to 89 // be discarded based on them. 90 while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) { 91 // If entry[1] is timely, drop entry[0] (and repeat). We apply an 92 // additional criterion here: we only drop the earlier buffer if our 93 // desiredPresent falls within +/- 1 second of the expected present. 94 // Otherwise, bogus desiredPresent times (e.g., 0 or a small 95 // relative timestamp), which normally mean "ignore the timestamp 96 // and acquire immediately", would cause us to drop frames. 97 // 98 // We may want to add an additional criterion: don't drop the 99 // earlier buffer if entry[1]'s fence hasn't signaled yet. 100 const BufferItem& bufferItem(mCore->mQueue[1]); 101 nsecs_t desiredPresent = bufferItem.mTimestamp; 102 if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC || 103 desiredPresent > expectedPresent) { 104 // This buffer is set to display in the near future, or 105 // desiredPresent is garbage. Either way we don't want to drop 106 // the previous buffer just to get this on the screen sooner. 107 BQ_LOGV("acquireBuffer: nodrop desire=%lld expect=%lld " 108 "(%lld) now=%lld", desiredPresent, expectedPresent, 109 desiredPresent - expectedPresent, 110 systemTime(CLOCK_MONOTONIC)); 111 break; 112 } 113 114 BQ_LOGV("acquireBuffer: drop desire=%lld expect=%lld size=%d", 115 desiredPresent, expectedPresent, mCore->mQueue.size()); 116 if (mCore->stillTracking(front)) { 117 // Front buffer is still in mSlots, so mark the slot as free 118 mSlots[front->mSlot].mBufferState = BufferSlot::FREE; 119 } 120 mCore->mQueue.erase(front); 121 front = mCore->mQueue.begin(); 122 } 123 124 // See if the front buffer is due 125 nsecs_t desiredPresent = front->mTimestamp; 126 if (desiredPresent > expectedPresent && 127 desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) { 128 BQ_LOGV("acquireBuffer: defer desire=%lld expect=%lld " 129 "(%lld) now=%lld", desiredPresent, expectedPresent, 130 desiredPresent - expectedPresent, 131 systemTime(CLOCK_MONOTONIC)); 132 return PRESENT_LATER; 133 } 134 135 BQ_LOGV("acquireBuffer: accept desire=%lld expect=%lld " 136 "(%lld) now=%lld", desiredPresent, expectedPresent, 137 desiredPresent - expectedPresent, 138 systemTime(CLOCK_MONOTONIC)); 139 } 140 141 int slot = front->mSlot; 142 *outBuffer = *front; 143 ATRACE_BUFFER_INDEX(slot); 144 145 BQ_LOGV("acquireBuffer: acquiring { slot=%d/%llu buffer=%p }", 146 slot, front->mFrameNumber, front->mGraphicBuffer->handle); 147 // If the front buffer is still being tracked, update its slot state 148 if (mCore->stillTracking(front)) { 149 mSlots[slot].mAcquireCalled = true; 150 mSlots[slot].mNeedsCleanupOnRelease = false; 151 mSlots[slot].mBufferState = BufferSlot::ACQUIRED; 152 mSlots[slot].mFence = Fence::NO_FENCE; 153 } 154 155 // If the buffer has previously been acquired by the consumer, set 156 // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer 157 // on the consumer side 158 if (outBuffer->mAcquireCalled) { 159 outBuffer->mGraphicBuffer = NULL; 160 } 161 162 mCore->mQueue.erase(front); 163 // TODO: Should this call be after we free a slot while dropping buffers? 164 // Simply acquiring the next buffer doesn't enable a producer to dequeue. 165 mCore->mDequeueCondition.broadcast(); 166 167 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); 168 169 return NO_ERROR; 170} 171 172status_t BufferQueueConsumer::detachBuffer(int slot) { 173 ATRACE_CALL(); 174 ATRACE_BUFFER_INDEX(slot); 175 BQ_LOGV("detachBuffer(C): slot %d", slot); 176 Mutex::Autolock lock(mCore->mMutex); 177 178 if (mCore->mIsAbandoned) { 179 BQ_LOGE("detachBuffer(C): BufferQueue has been abandoned"); 180 return NO_INIT; 181 } 182 183 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 184 BQ_LOGE("detachBuffer(C): slot index %d out of range [0, %d)", 185 slot, BufferQueueDefs::NUM_BUFFER_SLOTS); 186 return BAD_VALUE; 187 } else if (mSlots[slot].mBufferState != BufferSlot::ACQUIRED) { 188 BQ_LOGE("detachBuffer(C): slot %d is not owned by the consumer " 189 "(state = %d)", slot, mSlots[slot].mBufferState); 190 return BAD_VALUE; 191 } 192 193 mCore->freeBufferLocked(slot); 194 mCore->mDequeueCondition.broadcast(); 195 196 return NO_ERROR; 197} 198 199status_t BufferQueueConsumer::attachBuffer(int* outSlot, 200 const sp<android::GraphicBuffer>& buffer) { 201 ATRACE_CALL(); 202 203 if (outSlot == NULL) { 204 BQ_LOGE("attachBuffer(P): outSlot must not be NULL"); 205 return BAD_VALUE; 206 } else if (buffer == NULL) { 207 BQ_LOGE("attachBuffer(P): cannot attach NULL buffer"); 208 return BAD_VALUE; 209 } 210 211 Mutex::Autolock lock(mCore->mMutex); 212 213 // Make sure we don't have too many acquired buffers and find a free slot 214 // to put the buffer into (the oldest if there are multiple). 215 int numAcquiredBuffers = 0; 216 int found = BufferQueueCore::INVALID_BUFFER_SLOT; 217 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 218 if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) { 219 ++numAcquiredBuffers; 220 } else if (mSlots[s].mBufferState == BufferSlot::FREE) { 221 if (found == BufferQueueCore::INVALID_BUFFER_SLOT || 222 mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) { 223 found = s; 224 } 225 } 226 } 227 228 if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) { 229 BQ_LOGE("attachBuffer(P): max acquired buffer count reached: %d " 230 "(max %d)", numAcquiredBuffers, 231 mCore->mMaxAcquiredBufferCount); 232 return INVALID_OPERATION; 233 } 234 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 235 BQ_LOGE("attachBuffer(P): could not find free buffer slot"); 236 return NO_MEMORY; 237 } 238 239 *outSlot = found; 240 ATRACE_BUFFER_INDEX(*outSlot); 241 BQ_LOGV("attachBuffer(C): returning slot %d", *outSlot); 242 243 mSlots[*outSlot].mGraphicBuffer = buffer; 244 mSlots[*outSlot].mBufferState = BufferSlot::ACQUIRED; 245 mSlots[*outSlot].mAttachedByConsumer = true; 246 mSlots[*outSlot].mNeedsCleanupOnRelease = false; 247 mSlots[*outSlot].mFence = Fence::NO_FENCE; 248 mSlots[*outSlot].mFrameNumber = 0; 249 250 // mAcquireCalled tells BufferQueue that it doesn't need to send a valid 251 // GraphicBuffer pointer on the next acquireBuffer call, which decreases 252 // Binder traffic by not un/flattening the GraphicBuffer. However, it 253 // requires that the consumer maintain a cached copy of the slot <--> buffer 254 // mappings, which is why the consumer doesn't need the valid pointer on 255 // acquire. 256 // 257 // The StreamSplitter is one of the primary users of the attach/detach 258 // logic, and while it is running, all buffers it acquires are immediately 259 // detached, and all buffers it eventually releases are ones that were 260 // attached (as opposed to having been obtained from acquireBuffer), so it 261 // doesn't make sense to maintain the slot/buffer mappings, which would 262 // become invalid for every buffer during detach/attach. By setting this to 263 // false, the valid GraphicBuffer pointer will always be sent with acquire 264 // for attached buffers. 265 mSlots[*outSlot].mAcquireCalled = false; 266 267 return NO_ERROR; 268} 269 270status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, 271 const sp<Fence>& releaseFence, EGLDisplay eglDisplay, 272 EGLSyncKHR eglFence) { 273 ATRACE_CALL(); 274 ATRACE_BUFFER_INDEX(slot); 275 276 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS || 277 releaseFence == NULL) { 278 return BAD_VALUE; 279 } 280 281 sp<IProducerListener> listener; 282 { // Autolock scope 283 Mutex::Autolock lock(mCore->mMutex); 284 285 // If the frame number has changed because the buffer has been reallocated, 286 // we can ignore this releaseBuffer for the old buffer 287 if (frameNumber != mSlots[slot].mFrameNumber) { 288 return STALE_BUFFER_SLOT; 289 } 290 291 // Make sure this buffer hasn't been queued while acquired by the consumer 292 BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin()); 293 while (current != mCore->mQueue.end()) { 294 if (current->mSlot == slot) { 295 BQ_LOGE("releaseBuffer: buffer slot %d pending release is " 296 "currently queued", slot); 297 return BAD_VALUE; 298 } 299 ++current; 300 } 301 302 if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) { 303 mSlots[slot].mEglDisplay = eglDisplay; 304 mSlots[slot].mEglFence = eglFence; 305 mSlots[slot].mFence = releaseFence; 306 mSlots[slot].mBufferState = BufferSlot::FREE; 307 listener = mCore->mConnectedProducerListener; 308 BQ_LOGV("releaseBuffer: releasing slot %d", slot); 309 } else if (mSlots[slot].mNeedsCleanupOnRelease) { 310 BQ_LOGV("releaseBuffer: releasing a stale buffer slot %d " 311 "(state = %d)", slot, mSlots[slot].mBufferState); 312 mSlots[slot].mNeedsCleanupOnRelease = false; 313 return STALE_BUFFER_SLOT; 314 } else { 315 BQ_LOGV("releaseBuffer: attempted to release buffer slot %d " 316 "but its state was %d", slot, mSlots[slot].mBufferState); 317 return BAD_VALUE; 318 } 319 320 mCore->mDequeueCondition.broadcast(); 321 } // Autolock scope 322 323 // Call back without lock held 324 if (listener != NULL) { 325 listener->onBufferReleased(); 326 } 327 328 return NO_ERROR; 329} 330 331status_t BufferQueueConsumer::connect( 332 const sp<IConsumerListener>& consumerListener, bool controlledByApp) { 333 ATRACE_CALL(); 334 335 if (consumerListener == NULL) { 336 BQ_LOGE("connect(C): consumerListener may not be NULL"); 337 return BAD_VALUE; 338 } 339 340 BQ_LOGV("connect(C): controlledByApp=%s", 341 controlledByApp ? "true" : "false"); 342 343 Mutex::Autolock lock(mCore->mMutex); 344 345 if (mCore->mIsAbandoned) { 346 BQ_LOGE("connect(C): BufferQueue has been abandoned"); 347 return NO_INIT; 348 } 349 350 mCore->mConsumerListener = consumerListener; 351 mCore->mConsumerControlledByApp = controlledByApp; 352 353 return NO_ERROR; 354} 355 356status_t BufferQueueConsumer::disconnect() { 357 ATRACE_CALL(); 358 359 BQ_LOGV("disconnect(C)"); 360 361 Mutex::Autolock lock(mCore->mMutex); 362 363 if (mCore->mConsumerListener == NULL) { 364 BQ_LOGE("disconnect(C): no consumer is connected"); 365 return BAD_VALUE; 366 } 367 368 mCore->mIsAbandoned = true; 369 mCore->mConsumerListener = NULL; 370 mCore->mQueue.clear(); 371 mCore->freeAllBuffersLocked(); 372 mCore->mDequeueCondition.broadcast(); 373 return NO_ERROR; 374} 375 376status_t BufferQueueConsumer::getReleasedBuffers(uint32_t *outSlotMask) { 377 ATRACE_CALL(); 378 379 if (outSlotMask == NULL) { 380 BQ_LOGE("getReleasedBuffers: outSlotMask may not be NULL"); 381 return BAD_VALUE; 382 } 383 384 Mutex::Autolock lock(mCore->mMutex); 385 386 if (mCore->mIsAbandoned) { 387 BQ_LOGE("getReleasedBuffers: BufferQueue has been abandoned"); 388 return NO_INIT; 389 } 390 391 uint32_t mask = 0; 392 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 393 if (!mSlots[s].mAcquireCalled) { 394 mask |= (1u << s); 395 } 396 } 397 398 // Remove from the mask queued buffers for which acquire has been called, 399 // since the consumer will not receive their buffer addresses and so must 400 // retain their cached information 401 BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin()); 402 while (current != mCore->mQueue.end()) { 403 if (current->mAcquireCalled) { 404 mask &= ~(1u << current->mSlot); 405 } 406 ++current; 407 } 408 409 BQ_LOGV("getReleasedBuffers: returning mask %#x", mask); 410 *outSlotMask = mask; 411 return NO_ERROR; 412} 413 414status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width, 415 uint32_t height) { 416 ATRACE_CALL(); 417 418 if (width == 0 || height == 0) { 419 BQ_LOGV("setDefaultBufferSize: dimensions cannot be 0 (width=%u " 420 "height=%u)", width, height); 421 return BAD_VALUE; 422 } 423 424 BQ_LOGV("setDefaultBufferSize: width=%u height=%u", width, height); 425 426 Mutex::Autolock lock(mCore->mMutex); 427 mCore->mDefaultWidth = width; 428 mCore->mDefaultHeight = height; 429 return NO_ERROR; 430} 431 432status_t BufferQueueConsumer::setDefaultMaxBufferCount(int bufferCount) { 433 ATRACE_CALL(); 434 Mutex::Autolock lock(mCore->mMutex); 435 return mCore->setDefaultMaxBufferCountLocked(bufferCount); 436} 437 438status_t BufferQueueConsumer::disableAsyncBuffer() { 439 ATRACE_CALL(); 440 441 Mutex::Autolock lock(mCore->mMutex); 442 443 if (mCore->mConsumerListener != NULL) { 444 BQ_LOGE("disableAsyncBuffer: consumer already connected"); 445 return INVALID_OPERATION; 446 } 447 448 BQ_LOGV("disableAsyncBuffer"); 449 mCore->mUseAsyncBuffer = false; 450 return NO_ERROR; 451} 452 453status_t BufferQueueConsumer::setMaxAcquiredBufferCount( 454 int maxAcquiredBuffers) { 455 ATRACE_CALL(); 456 457 if (maxAcquiredBuffers < 1 || 458 maxAcquiredBuffers > BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) { 459 BQ_LOGE("setMaxAcquiredBufferCount: invalid count %d", 460 maxAcquiredBuffers); 461 return BAD_VALUE; 462 } 463 464 Mutex::Autolock lock(mCore->mMutex); 465 466 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { 467 BQ_LOGE("setMaxAcquiredBufferCount: producer is already connected"); 468 return INVALID_OPERATION; 469 } 470 471 BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers); 472 mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers; 473 return NO_ERROR; 474} 475 476void BufferQueueConsumer::setConsumerName(const String8& name) { 477 ATRACE_CALL(); 478 BQ_LOGV("setConsumerName: '%s'", name.string()); 479 Mutex::Autolock lock(mCore->mMutex); 480 mCore->mConsumerName = name; 481 mConsumerName = name; 482} 483 484status_t BufferQueueConsumer::setDefaultBufferFormat(uint32_t defaultFormat) { 485 ATRACE_CALL(); 486 BQ_LOGV("setDefaultBufferFormat: %u", defaultFormat); 487 Mutex::Autolock lock(mCore->mMutex); 488 mCore->mDefaultBufferFormat = defaultFormat; 489 return NO_ERROR; 490} 491 492status_t BufferQueueConsumer::setConsumerUsageBits(uint32_t usage) { 493 ATRACE_CALL(); 494 BQ_LOGV("setConsumerUsageBits: %#x", usage); 495 Mutex::Autolock lock(mCore->mMutex); 496 mCore->mConsumerUsageBits = usage; 497 return NO_ERROR; 498} 499 500status_t BufferQueueConsumer::setTransformHint(uint32_t hint) { 501 ATRACE_CALL(); 502 BQ_LOGV("setTransformHint: %#x", hint); 503 Mutex::Autolock lock(mCore->mMutex); 504 mCore->mTransformHint = hint; 505 return NO_ERROR; 506} 507 508sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const { 509 return mCore->mSidebandStream; 510} 511 512void BufferQueueConsumer::dump(String8& result, const char* prefix) const { 513 mCore->dump(result, prefix); 514} 515 516} // namespace android 517