BufferQueueConsumer.cpp revision 289ade165e60b5f71734d30e535f16eb1f4313ad
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#include <gui/BufferItem.h> 18#include <gui/BufferQueueConsumer.h> 19#include <gui/BufferQueueCore.h> 20#include <gui/IConsumerListener.h> 21 22namespace android { 23 24BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) : 25 mCore(core), 26 mSlots(core->mSlots), 27 mConsumerName() {} 28 29BufferQueueConsumer::~BufferQueueConsumer() {} 30 31status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, 32 nsecs_t expectedPresent) { 33 ATRACE_CALL(); 34 Mutex::Autolock lock(mCore->mMutex); 35 36 // Check that the consumer doesn't currently have the maximum number of 37 // buffers acquired. We allow the max buffer count to be exceeded by one 38 // buffer so that the consumer can successfully set up the newly acquired 39 // buffer before releasing the old one. 40 int numAcquiredBuffers = 0; 41 for (int s = 0; s < BufferQueueCore::NUM_BUFFER_SLOTS; ++s) { 42 if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) { 43 ++numAcquiredBuffers; 44 } 45 } 46 if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) { 47 BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)", 48 numAcquiredBuffers, mCore->mMaxAcquiredBufferCount); 49 return INVALID_OPERATION; 50 } 51 52 // Check if the queue is empty. 53 // In asynchronous mode the list is guaranteed to be one buffer deep, 54 // while in synchronous mode we use the oldest buffer. 55 if (mCore->mQueue.empty()) { 56 return NO_BUFFER_AVAILABLE; 57 } 58 59 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); 60 61 // If expectedPresent is specified, we may not want to return a buffer yet. 62 // If it's specified and there's more than one buffer queued, we may want 63 // to drop a buffer. 64 if (expectedPresent != 0) { 65 const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second 66 67 // The 'expectedPresent' argument indicates when the buffer is expected 68 // to be presented on-screen. If the buffer's desired present time is 69 // earlier (less) than expectedPresent -- meaning it will be displayed 70 // on time or possibly late if we show it as soon as possible -- we 71 // acquire and return it. If we don't want to display it until after the 72 // expectedPresent time, we return PRESENT_LATER without acquiring it. 73 // 74 // To be safe, we don't defer acquisition if expectedPresent is more 75 // than one second in the future beyond the desired present time 76 // (i.e., we'd be holding the buffer for a long time). 77 // 78 // NOTE: Code assumes monotonic time values from the system clock 79 // are positive. 80 81 // Start by checking to see if we can drop frames. We skip this check if 82 // the timestamps are being auto-generated by Surface. If the app isn't 83 // generating timestamps explicitly, it probably doesn't want frames to 84 // be discarded based on them. 85 while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) { 86 // If entry[1] is timely, drop entry[0] (and repeat). We apply an 87 // additional criterion here: we only drop the earlier buffer if our 88 // desiredPresent falls within +/- 1 second of the expected present. 89 // Otherwise, bogus desiredPresent times (e.g., 0 or a small 90 // relative timestamp), which normally mean "ignore the timestamp 91 // and acquire immediately", would cause us to drop frames. 92 // 93 // We may want to add an additional criterion: don't drop the 94 // earlier buffer if entry[1]'s fence hasn't signaled yet. 95 const BufferItem& bufferItem(mCore->mQueue[1]); 96 nsecs_t desiredPresent = bufferItem.mTimestamp; 97 if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC || 98 desiredPresent > expectedPresent) { 99 // This buffer is set to display in the near future, or 100 // desiredPresent is garbage. Either way we don't want to drop 101 // the previous buffer just to get this on the screen sooner. 102 BQ_LOGV("acquireBuffer: nodrop desire=%lld expect=%lld " 103 "(%lld) now=%lld", desiredPresent, expectedPresent, 104 desiredPresent - expectedPresent, 105 systemTime(CLOCK_MONOTONIC)); 106 break; 107 } 108 109 BQ_LOGV("acquireBuffer: drop desire=%lld expect=%lld size=%d", 110 desiredPresent, expectedPresent, mCore->mQueue.size()); 111 if (mCore->stillTracking(front)) { 112 // Front buffer is still in mSlots, so mark the slot as free 113 mSlots[front->mSlot].mBufferState = BufferSlot::FREE; 114 } 115 mCore->mQueue.erase(front); 116 front = mCore->mQueue.begin(); 117 } 118 119 // See if the front buffer is due 120 nsecs_t desiredPresent = front->mTimestamp; 121 if (desiredPresent > expectedPresent && 122 desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) { 123 BQ_LOGV("acquireBuffer: defer desire=%lld expect=%lld " 124 "(%lld) now=%lld", desiredPresent, expectedPresent, 125 desiredPresent - expectedPresent, 126 systemTime(CLOCK_MONOTONIC)); 127 return PRESENT_LATER; 128 } 129 130 BQ_LOGV("acquireBuffer: accept desire=%lld expect=%lld " 131 "(%lld) now=%lld", desiredPresent, expectedPresent, 132 desiredPresent - expectedPresent, 133 systemTime(CLOCK_MONOTONIC)); 134 } 135 136 int slot = front->mSlot; 137 *outBuffer = *front; 138 ATRACE_BUFFER_INDEX(slot); 139 140 BQ_LOGV("acquireBuffer: acquiring { slot=%d/%llu buffer=%p }", 141 slot, front->mFrameNumber, front->mGraphicBuffer->handle); 142 // If the front buffer is still being tracked, update its slot state 143 if (mCore->stillTracking(front)) { 144 mSlots[slot].mAcquireCalled = true; 145 mSlots[slot].mNeedsCleanupOnRelease = false; 146 mSlots[slot].mBufferState = BufferSlot::ACQUIRED; 147 mSlots[slot].mFence = Fence::NO_FENCE; 148 } 149 150 // If the buffer has previously been acquired by the consumer, set 151 // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer 152 // on the consumer side 153 if (outBuffer->mAcquireCalled) { 154 outBuffer->mGraphicBuffer = NULL; 155 } 156 157 mCore->mQueue.erase(front); 158 // TODO: Should this call be after we free a slot while dropping buffers? 159 // Simply acquiring the next buffer doesn't enable a producer to dequeue. 160 mCore->mDequeueCondition.broadcast(); 161 162 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); 163 164 return NO_ERROR; 165} 166 167status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, 168 const sp<Fence>& releaseFence, EGLDisplay eglDisplay, 169 EGLSyncKHR eglFence) { 170 ATRACE_CALL(); 171 ATRACE_BUFFER_INDEX(slot); 172 173 if (slot == BufferQueueCore::INVALID_BUFFER_SLOT || releaseFence == NULL) { 174 return BAD_VALUE; 175 } 176 177 Mutex::Autolock lock(mCore->mMutex); 178 179 // If the frame number has changed because the buffer has been reallocated, 180 // we can ignore this releaseBuffer for the old buffer 181 if (frameNumber != mSlots[slot].mFrameNumber) { 182 return STALE_BUFFER_SLOT; 183 } 184 185 // Make sure this buffer hasn't been queued while acquired by the consumer 186 BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin()); 187 while (current != mCore->mQueue.end()) { 188 if (current->mSlot == slot) { 189 BQ_LOGE("releaseBuffer: buffer slot %d pending release is " 190 "currently queued", slot); 191 return -EINVAL; 192 } 193 ++current; 194 } 195 196 if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) { 197 mSlots[slot].mEglDisplay = eglDisplay; 198 mSlots[slot].mEglFence = eglFence; 199 mSlots[slot].mFence = releaseFence; 200 mSlots[slot].mBufferState = BufferSlot::FREE; 201 } else if (mSlots[slot].mNeedsCleanupOnRelease) { 202 BQ_LOGV("releaseBuffer: releasing a stale buffer slot %d " 203 "(state = %d)", slot, mSlots[slot].mBufferState); 204 mSlots[slot].mNeedsCleanupOnRelease = false; 205 return STALE_BUFFER_SLOT; 206 } else { 207 BQ_LOGV("releaseBuffer: attempted to release buffer slot %d " 208 "but its state was %d", slot, mSlots[slot].mBufferState); 209 return -EINVAL; 210 } 211 212 mCore->mDequeueCondition.broadcast(); 213 214 return NO_ERROR; 215} 216 217status_t BufferQueueConsumer::connect( 218 const sp<IConsumerListener>& consumerListener, bool controlledByApp) { 219 ATRACE_CALL(); 220 221 if (consumerListener == NULL) { 222 BQ_LOGE("connect(C): consumerListener may not be NULL"); 223 return BAD_VALUE; 224 } 225 226 BQ_LOGV("connect(C): controlledByApp=%s", 227 controlledByApp ? "true" : "false"); 228 229 Mutex::Autolock lock(mCore->mMutex); 230 231 if (mCore->mIsAbandoned) { 232 BQ_LOGE("connect(C): BufferQueue has been abandoned"); 233 return NO_INIT; 234 } 235 236 mCore->mConsumerListener = consumerListener; 237 mCore->mConsumerControlledByApp = controlledByApp; 238 239 return NO_ERROR; 240} 241 242status_t BufferQueueConsumer::disconnect() { 243 ATRACE_CALL(); 244 245 BQ_LOGV("disconnect(C)"); 246 247 Mutex::Autolock lock(mCore->mMutex); 248 249 if (mCore->mConsumerListener == NULL) { 250 BQ_LOGE("disconnect(C): no consumer is connected"); 251 return -EINVAL; 252 } 253 254 mCore->mIsAbandoned = true; 255 mCore->mConsumerListener = NULL; 256 mCore->mQueue.clear(); 257 mCore->freeAllBuffersLocked(); 258 mCore->mDequeueCondition.broadcast(); 259 return NO_ERROR; 260} 261 262status_t BufferQueueConsumer::getReleasedBuffers(uint32_t *outSlotMask) { 263 ATRACE_CALL(); 264 265 if (outSlotMask == NULL) { 266 BQ_LOGE("getReleasedBuffers: outSlotMask may not be NULL"); 267 return BAD_VALUE; 268 } 269 270 Mutex::Autolock lock(mCore->mMutex); 271 272 if (mCore->mIsAbandoned) { 273 BQ_LOGE("getReleasedBuffers: BufferQueue has been abandoned"); 274 return NO_INIT; 275 } 276 277 uint32_t mask = 0; 278 for (int s = 0; s < BufferQueueCore::NUM_BUFFER_SLOTS; ++s) { 279 if (!mSlots[s].mAcquireCalled) { 280 mask |= (1u << s); 281 } 282 } 283 284 // Remove from the mask queued buffers for which acquire has been called, 285 // since the consumer will not receive their buffer addresses and so must 286 // retain their cached information 287 BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin()); 288 while (current != mCore->mQueue.end()) { 289 if (current->mAcquireCalled) { 290 mask &= ~(1u << current->mSlot); 291 } 292 ++current; 293 } 294 295 BQ_LOGV("getReleasedBuffers: returning mask %#x", mask); 296 *outSlotMask = mask; 297 return NO_ERROR; 298} 299 300status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width, 301 uint32_t height) { 302 ATRACE_CALL(); 303 304 if (width == 0 || height == 0) { 305 BQ_LOGV("setDefaultBufferSize: dimensions cannot be 0 (width=%u " 306 "height=%u)", width, height); 307 return BAD_VALUE; 308 } 309 310 BQ_LOGV("setDefaultBufferSize: width=%u height=%u", width, height); 311 312 Mutex::Autolock lock(mCore->mMutex); 313 mCore->mDefaultWidth = width; 314 mCore->mDefaultHeight = height; 315 return NO_ERROR; 316} 317 318status_t BufferQueueConsumer::setDefaultMaxBufferCount(int bufferCount) { 319 ATRACE_CALL(); 320 Mutex::Autolock lock(mCore->mMutex); 321 return mCore->setDefaultMaxBufferCountLocked(bufferCount); 322} 323 324status_t BufferQueueConsumer::disableAsyncBuffer() { 325 ATRACE_CALL(); 326 327 Mutex::Autolock lock(mCore->mMutex); 328 329 if (mCore->mConsumerListener != NULL) { 330 BQ_LOGE("disableAsyncBuffer: consumer already connected"); 331 return INVALID_OPERATION; 332 } 333 334 BQ_LOGV("disableAsyncBuffer"); 335 mCore->mUseAsyncBuffer = false; 336 return NO_ERROR; 337} 338 339status_t BufferQueueConsumer::setMaxAcquiredBufferCount( 340 int maxAcquiredBuffers) { 341 ATRACE_CALL(); 342 343 if (maxAcquiredBuffers < 1 || 344 maxAcquiredBuffers > BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) { 345 BQ_LOGE("setMaxAcquiredBufferCount: invalid count %d", 346 maxAcquiredBuffers); 347 return BAD_VALUE; 348 } 349 350 Mutex::Autolock lock(mCore->mMutex); 351 352 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) { 353 BQ_LOGE("setMaxAcquiredBufferCount: producer is already connected"); 354 return INVALID_OPERATION; 355 } 356 357 BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers); 358 mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers; 359 return NO_ERROR; 360} 361 362void BufferQueueConsumer::setConsumerName(const String8& name) { 363 ATRACE_CALL(); 364 BQ_LOGV("setConsumerName: '%s'", name.string()); 365 Mutex::Autolock lock(mCore->mMutex); 366 mCore->mConsumerName = name; 367 mConsumerName = name; 368} 369 370status_t BufferQueueConsumer::setDefaultBufferFormat(uint32_t defaultFormat) { 371 ATRACE_CALL(); 372 BQ_LOGV("setDefaultBufferFormat: %u", defaultFormat); 373 Mutex::Autolock lock(mCore->mMutex); 374 mCore->mDefaultBufferFormat = defaultFormat; 375 return NO_ERROR; 376} 377 378status_t BufferQueueConsumer::setConsumerUsageBits(uint32_t usage) { 379 ATRACE_CALL(); 380 BQ_LOGV("setConsumerUsageBits: %#x", usage); 381 Mutex::Autolock lock(mCore->mMutex); 382 mCore->mConsumerUsageBits = usage; 383 return NO_ERROR; 384} 385 386status_t BufferQueueConsumer::setTransformHint(uint32_t hint) { 387 ATRACE_CALL(); 388 BQ_LOGV("setTransformHint: %#x", hint); 389 Mutex::Autolock lock(mCore->mMutex); 390 mCore->mTransformHint = hint; 391 return NO_ERROR; 392} 393 394void BufferQueueConsumer::dump(String8& result, const char* prefix) const { 395 mCore->dump(result, prefix); 396} 397 398} // namespace android 399