BufferQueue.cpp revision ba93b3f8e403636b614a4a379f9421bc70dca84f
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2012 The Android Open Source Project 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License. 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at 7ccecf1425412beb2bc3bb38d470293fdc244d6f1Elliott Hughes * 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License. 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_TAG "BufferQueue" 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ATRACE_TAG ATRACE_TAG_GRAPHICS 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//#define LOG_NDEBUG 0 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define GL_GLEXT_PROTOTYPES 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define EGL_EGLEXT_PROTOTYPES 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <EGL/egl.h> 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <EGL/eglext.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <gui/BufferQueue.h> 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <gui/ISurfaceComposer.h> 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <private/gui/ComposerService.h> 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <utils/Log.h> 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <utils/Trace.h> 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <utils/CallStack.h> 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// Macros for including the BufferQueue name in log messages 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ST_LOGD(x, ...) ALOGD("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ST_LOGI(x, ...) ALOGI("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ST_LOGW(x, ...) ALOGW("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ST_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ATRACE_BUFFER_INDEX(index) \ 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ATRACE_ENABLED()) { \ 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char ___traceBuf[1024]; \ 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project snprintf(___traceBuf, 1024, "%s: %d", mConsumerName.string(), \ 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project (index)); \ 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf); \ 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectnamespace android { 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// Get an ID that's unique within this process. 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int32_t createProcessUniqueId() { 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project static volatile int32_t globalCounter = 0; 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return android_atomic_inc(&globalCounter); 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic const char* scalingModeName(int scalingMode) { 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project switch (scalingMode) { 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE"; 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW"; 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP"; 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project default: return "Unknown"; 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectBufferQueue::BufferQueue(const sp<IGraphicBufferAlloc>& allocator) : 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mDefaultWidth(1), 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mDefaultHeight(1), 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mMaxAcquiredBufferCount(1), 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mDefaultMaxBufferCount(2), 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mOverrideMaxBufferCount(0), 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mConsumerControlledByApp(false), 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mDequeueBufferCannotBlock(false), 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mUseAsyncBuffer(true), 76eeed45fa24f3bc3046f352bf9788061715b44dcfGreg Hackmann mConnectedApi(NO_CONNECTED_API), 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mAbandoned(false), 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mFrameCounter(0), 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mBufferHasBeenQueued(false), 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mConsumerUsageBits(0), 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mTransformHint(0) 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Choose a name using the PID and a process-unique ID. 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ST_LOGV("BufferQueue"); 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (allocator == NULL) { 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (mGraphicBufferAlloc == 0) { 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ST_LOGE("createGraphicBufferAlloc() failed in BufferQueue()"); 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mGraphicBufferAlloc = allocator; 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 98 99BufferQueue::~BufferQueue() { 100 ST_LOGV("~BufferQueue"); 101} 102 103status_t BufferQueue::setDefaultMaxBufferCountLocked(int count) { 104 const int minBufferCount = mUseAsyncBuffer ? 2 : 1; 105 if (count < minBufferCount || count > NUM_BUFFER_SLOTS) 106 return BAD_VALUE; 107 108 mDefaultMaxBufferCount = count; 109 mDequeueCondition.broadcast(); 110 111 return NO_ERROR; 112} 113 114void BufferQueue::setConsumerName(const String8& name) { 115 Mutex::Autolock lock(mMutex); 116 mConsumerName = name; 117} 118 119status_t BufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) { 120 Mutex::Autolock lock(mMutex); 121 mDefaultBufferFormat = defaultFormat; 122 return NO_ERROR; 123} 124 125status_t BufferQueue::setConsumerUsageBits(uint32_t usage) { 126 Mutex::Autolock lock(mMutex); 127 mConsumerUsageBits = usage; 128 return NO_ERROR; 129} 130 131status_t BufferQueue::setTransformHint(uint32_t hint) { 132 ST_LOGV("setTransformHint: %02x", hint); 133 Mutex::Autolock lock(mMutex); 134 mTransformHint = hint; 135 return NO_ERROR; 136} 137 138status_t BufferQueue::setBufferCount(int bufferCount) { 139 ST_LOGV("setBufferCount: count=%d", bufferCount); 140 141 sp<ConsumerListener> listener; 142 { 143 Mutex::Autolock lock(mMutex); 144 145 if (mAbandoned) { 146 ST_LOGE("setBufferCount: BufferQueue has been abandoned!"); 147 return NO_INIT; 148 } 149 if (bufferCount > NUM_BUFFER_SLOTS) { 150 ST_LOGE("setBufferCount: bufferCount too large (max %d)", 151 NUM_BUFFER_SLOTS); 152 return BAD_VALUE; 153 } 154 155 // Error out if the user has dequeued buffers 156 for (int i=0 ; i<NUM_BUFFER_SLOTS; i++) { 157 if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { 158 ST_LOGE("setBufferCount: client owns some buffers"); 159 return -EINVAL; 160 } 161 } 162 163 if (bufferCount == 0) { 164 mOverrideMaxBufferCount = 0; 165 mDequeueCondition.broadcast(); 166 return NO_ERROR; 167 } 168 169 // fine to assume async to false before we're setting the buffer count 170 const int minBufferSlots = getMinMaxBufferCountLocked(false); 171 if (bufferCount < minBufferSlots) { 172 ST_LOGE("setBufferCount: requested buffer count (%d) is less than " 173 "minimum (%d)", bufferCount, minBufferSlots); 174 return BAD_VALUE; 175 } 176 177 // here we're guaranteed that the client doesn't have dequeued buffers 178 // and will release all of its buffer references. We don't clear the 179 // queue, however, so currently queued buffers still get displayed. 180 freeAllBuffersLocked(); 181 mOverrideMaxBufferCount = bufferCount; 182 mDequeueCondition.broadcast(); 183 listener = mConsumerListener; 184 } // scope for lock 185 186 if (listener != NULL) { 187 listener->onBuffersReleased(); 188 } 189 190 return NO_ERROR; 191} 192 193int BufferQueue::query(int what, int* outValue) 194{ 195 ATRACE_CALL(); 196 Mutex::Autolock lock(mMutex); 197 198 if (mAbandoned) { 199 ST_LOGE("query: BufferQueue has been abandoned!"); 200 return NO_INIT; 201 } 202 203 int value; 204 switch (what) { 205 case NATIVE_WINDOW_WIDTH: 206 value = mDefaultWidth; 207 break; 208 case NATIVE_WINDOW_HEIGHT: 209 value = mDefaultHeight; 210 break; 211 case NATIVE_WINDOW_FORMAT: 212 value = mDefaultBufferFormat; 213 break; 214 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 215 value = getMinUndequeuedBufferCount(false); 216 break; 217 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: 218 value = (mQueue.size() >= 2); 219 break; 220 default: 221 return BAD_VALUE; 222 } 223 outValue[0] = value; 224 return NO_ERROR; 225} 226 227status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) { 228 ATRACE_CALL(); 229 ST_LOGV("requestBuffer: slot=%d", slot); 230 Mutex::Autolock lock(mMutex); 231 if (mAbandoned) { 232 ST_LOGE("requestBuffer: BufferQueue has been abandoned!"); 233 return NO_INIT; 234 } 235 if (slot < 0 || slot >= NUM_BUFFER_SLOTS) { 236 ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d", 237 NUM_BUFFER_SLOTS, slot); 238 return BAD_VALUE; 239 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 240 ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)", 241 slot, mSlots[slot].mBufferState); 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, sp<Fence>* outFence, bool async, 250 uint32_t w, uint32_t h, 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 eglFence = EGL_NO_SYNC_KHR; 262 263 { // Scope for the lock 264 Mutex::Autolock lock(mMutex); 265 266 if (format == 0) { 267 format = mDefaultBufferFormat; 268 } 269 // turn on usage bits the consumer requested 270 usage |= mConsumerUsageBits; 271 272 int found = -1; 273 bool tryAgain = true; 274 while (tryAgain) { 275 if (mAbandoned) { 276 ST_LOGE("dequeueBuffer: BufferQueue has been abandoned!"); 277 return NO_INIT; 278 } 279 280 const int maxBufferCount = getMaxBufferCountLocked(async); 281 if (async && mOverrideMaxBufferCount) { 282 // FIXME: some drivers are manually setting the buffer-count (which they 283 // shouldn't), so we do this extra test here to handle that case. 284 // This is TEMPORARY, until we get this fixed. 285 if (mOverrideMaxBufferCount < maxBufferCount) { 286 ST_LOGE("dequeueBuffer: async mode is invalid with buffercount override"); 287 return BAD_VALUE; 288 } 289 } 290 291 // Free up any buffers that are in slots beyond the max buffer 292 // count. 293 for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) { 294 assert(mSlots[i].mBufferState == BufferSlot::FREE); 295 if (mSlots[i].mGraphicBuffer != NULL) { 296 freeBufferLocked(i); 297 returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS; 298 } 299 } 300 301 // look for a free buffer to give to the client 302 found = INVALID_BUFFER_SLOT; 303 int dequeuedCount = 0; 304 int acquiredCount = 0; 305 for (int i = 0; i < maxBufferCount; i++) { 306 const int state = mSlots[i].mBufferState; 307 switch (state) { 308 case BufferSlot::DEQUEUED: 309 dequeuedCount++; 310 break; 311 case BufferSlot::ACQUIRED: 312 acquiredCount++; 313 break; 314 case BufferSlot::FREE: 315 /* We return the oldest of the free buffers to avoid 316 * stalling the producer if possible. This is because 317 * the consumer may still have pending reads of the 318 * buffers in flight. 319 */ 320 if ((found < 0) || 321 mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) { 322 found = i; 323 } 324 break; 325 } 326 } 327 328 // clients are not allowed to dequeue more than one buffer 329 // if they didn't set a buffer count. 330 if (!mOverrideMaxBufferCount && dequeuedCount) { 331 ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without " 332 "setting the buffer count"); 333 return -EINVAL; 334 } 335 336 // See whether a buffer has been queued since the last 337 // setBufferCount so we know whether to perform the min undequeued 338 // buffers check below. 339 if (mBufferHasBeenQueued) { 340 // make sure the client is not trying to dequeue more buffers 341 // than allowed. 342 const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1); 343 const int minUndequeuedCount = getMinUndequeuedBufferCount(async); 344 if (newUndequeuedCount < minUndequeuedCount) { 345 ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) " 346 "exceeded (dequeued=%d undequeudCount=%d)", 347 minUndequeuedCount, dequeuedCount, 348 newUndequeuedCount); 349 return -EBUSY; 350 } 351 } 352 353 // If no buffer is found, wait for a buffer to be released or for 354 // the max buffer count to change. 355 tryAgain = found == INVALID_BUFFER_SLOT; 356 if (tryAgain) { 357 // return an error if we're in "cannot block" mode (producer and consumer 358 // are controlled by the application) -- however, the consumer is allowed 359 // to acquire briefly an extra buffer (which could cause us to have to wait here) 360 // and that's okay because we know the wait will be brief (it happens 361 // if we dequeue a buffer while the consumer has acquired one but not released 362 // the old one yet -- for e.g.: see GLConsumer::updateTexImage()). 363 if (mDequeueBufferCannotBlock && (acquiredCount <= mMaxAcquiredBufferCount)) { 364 ST_LOGE("dequeueBuffer: would block! returning an error instead."); 365 return WOULD_BLOCK; 366 } 367 mDequeueCondition.wait(mMutex); 368 } 369 } 370 371 372 if (found == INVALID_BUFFER_SLOT) { 373 // This should not happen. 374 ST_LOGE("dequeueBuffer: no available buffer slots"); 375 return -EBUSY; 376 } 377 378 const int buf = found; 379 *outBuf = found; 380 381 ATRACE_BUFFER_INDEX(buf); 382 383 const bool useDefaultSize = !w && !h; 384 if (useDefaultSize) { 385 // use the default size 386 w = mDefaultWidth; 387 h = mDefaultHeight; 388 } 389 390 mSlots[buf].mBufferState = BufferSlot::DEQUEUED; 391 392 const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); 393 if ((buffer == NULL) || 394 (uint32_t(buffer->width) != w) || 395 (uint32_t(buffer->height) != h) || 396 (uint32_t(buffer->format) != format) || 397 ((uint32_t(buffer->usage) & usage) != usage)) 398 { 399 mSlots[buf].mAcquireCalled = false; 400 mSlots[buf].mGraphicBuffer = NULL; 401 mSlots[buf].mRequestBufferCalled = false; 402 mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; 403 mSlots[buf].mFence = Fence::NO_FENCE; 404 mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; 405 406 returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION; 407 } 408 409 410 if (CC_UNLIKELY(mSlots[buf].mFence == NULL)) { 411 ST_LOGE("dequeueBuffer: about to return a NULL fence from mSlot. " 412 "buf=%d, w=%d, h=%d, format=%d", 413 buf, buffer->width, buffer->height, buffer->format); 414 } 415 416 dpy = mSlots[buf].mEglDisplay; 417 eglFence = mSlots[buf].mEglFence; 418 *outFence = mSlots[buf].mFence; 419 mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; 420 mSlots[buf].mFence = Fence::NO_FENCE; 421 } // end lock scope 422 423 if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) { 424 status_t error; 425 sp<GraphicBuffer> graphicBuffer( 426 mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage, &error)); 427 if (graphicBuffer == 0) { 428 ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed"); 429 return error; 430 } 431 432 { // Scope for the lock 433 Mutex::Autolock lock(mMutex); 434 435 if (mAbandoned) { 436 ST_LOGE("dequeueBuffer: BufferQueue has been abandoned!"); 437 return NO_INIT; 438 } 439 440 mSlots[*outBuf].mFrameNumber = ~0; 441 mSlots[*outBuf].mGraphicBuffer = graphicBuffer; 442 } 443 } 444 445 if (eglFence != EGL_NO_SYNC_KHR) { 446 EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 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 ST_LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError()); 452 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 453 ST_LOGE("dequeueBuffer: timeout waiting for fence"); 454 } 455 eglDestroySyncKHR(dpy, eglFence); 456 } 457 458 ST_LOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outBuf, 459 mSlots[*outBuf].mFrameNumber, 460 mSlots[*outBuf].mGraphicBuffer->handle, returnFlags); 461 462 return returnFlags; 463} 464 465status_t BufferQueue::queueBuffer(int buf, 466 const QueueBufferInput& input, QueueBufferOutput* output) { 467 ATRACE_CALL(); 468 ATRACE_BUFFER_INDEX(buf); 469 470 Rect crop; 471 uint32_t transform; 472 int scalingMode; 473 int64_t timestamp; 474 bool async; 475 sp<Fence> fence; 476 477 input.deflate(×tamp, &crop, &scalingMode, &transform, &async, &fence); 478 479 if (fence == NULL) { 480 ST_LOGE("queueBuffer: fence is NULL"); 481 return BAD_VALUE; 482 } 483 484 switch (scalingMode) { 485 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 486 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 487 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: 488 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: 489 break; 490 default: 491 ST_LOGE("unknown scaling mode: %d", scalingMode); 492 return -EINVAL; 493 } 494 495 sp<ConsumerListener> listener; 496 497 { // scope for the lock 498 Mutex::Autolock lock(mMutex); 499 500 if (mAbandoned) { 501 ST_LOGE("queueBuffer: BufferQueue has been abandoned!"); 502 return NO_INIT; 503 } 504 505 const int maxBufferCount = getMaxBufferCountLocked(async); 506 if (async && mOverrideMaxBufferCount) { 507 // FIXME: some drivers are manually setting the buffer-count (which they 508 // shouldn't), so we do this extra test here to handle that case. 509 // This is TEMPORARY, until we get this fixed. 510 if (mOverrideMaxBufferCount < maxBufferCount) { 511 ST_LOGE("queueBuffer: async mode is invalid with buffercount override"); 512 return BAD_VALUE; 513 } 514 } 515 if (buf < 0 || buf >= maxBufferCount) { 516 ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d", 517 maxBufferCount, buf); 518 return -EINVAL; 519 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 520 ST_LOGE("queueBuffer: slot %d is not owned by the client " 521 "(state=%d)", buf, mSlots[buf].mBufferState); 522 return -EINVAL; 523 } else if (!mSlots[buf].mRequestBufferCalled) { 524 ST_LOGE("queueBuffer: slot %d was enqueued without requesting a " 525 "buffer", buf); 526 return -EINVAL; 527 } 528 529 ST_LOGV("queueBuffer: slot=%d/%llu time=%#llx crop=[%d,%d,%d,%d] " 530 "tr=%#x scale=%s", 531 buf, mFrameCounter + 1, timestamp, 532 crop.left, crop.top, crop.right, crop.bottom, 533 transform, scalingModeName(scalingMode)); 534 535 const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer); 536 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); 537 Rect croppedCrop; 538 crop.intersect(bufferRect, &croppedCrop); 539 if (croppedCrop != crop) { 540 ST_LOGE("queueBuffer: crop rect is not contained within the " 541 "buffer in slot %d", buf); 542 return -EINVAL; 543 } 544 545 mSlots[buf].mFence = fence; 546 mSlots[buf].mBufferState = BufferSlot::QUEUED; 547 mFrameCounter++; 548 mSlots[buf].mFrameNumber = mFrameCounter; 549 550 BufferItem item; 551 item.mAcquireCalled = mSlots[buf].mAcquireCalled; 552 item.mGraphicBuffer = mSlots[buf].mGraphicBuffer; 553 item.mCrop = crop; 554 item.mTransform = transform; 555 item.mScalingMode = scalingMode; 556 item.mTimestamp = timestamp; 557 item.mFrameNumber = mFrameCounter; 558 item.mBuf = buf; 559 item.mFence = fence; 560 item.mIsDroppable = mDequeueBufferCannotBlock || async; 561 562 if (mQueue.empty()) { 563 // when the queue is empty, we can ignore "mDequeueBufferCannotBlock", and 564 // simply queue this buffer. 565 mQueue.push_back(item); 566 listener = mConsumerListener; 567 } else { 568 // when the queue is not empty, we need to look at the front buffer 569 // state and see if we need to replace it. 570 Fifo::iterator front(mQueue.begin()); 571 if (front->mIsDroppable) { 572 // buffer slot currently queued is marked free if still tracked 573 if (stillTracking(front)) { 574 mSlots[front->mBuf].mBufferState = BufferSlot::FREE; 575 // reset the frame number of the freed buffer so that it is the first in 576 // line to be dequeued again. 577 mSlots[front->mBuf].mFrameNumber = 0; 578 } 579 // and we record the new buffer in the queued list 580 *front = item; 581 } else { 582 mQueue.push_back(item); 583 listener = mConsumerListener; 584 } 585 } 586 587 mBufferHasBeenQueued = true; 588 mDequeueCondition.broadcast(); 589 590 output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, 591 mQueue.size()); 592 593 ATRACE_INT(mConsumerName.string(), mQueue.size()); 594 } // scope for the lock 595 596 // call back without lock held 597 if (listener != 0) { 598 listener->onFrameAvailable(); 599 } 600 return NO_ERROR; 601} 602 603void BufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) { 604 ATRACE_CALL(); 605 ST_LOGV("cancelBuffer: slot=%d", buf); 606 Mutex::Autolock lock(mMutex); 607 608 if (mAbandoned) { 609 ST_LOGW("cancelBuffer: BufferQueue has been abandoned!"); 610 return; 611 } 612 613 if (buf < 0 || buf >= NUM_BUFFER_SLOTS) { 614 ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d", 615 NUM_BUFFER_SLOTS, buf); 616 return; 617 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 618 ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", 619 buf, mSlots[buf].mBufferState); 620 return; 621 } else if (fence == NULL) { 622 ST_LOGE("cancelBuffer: fence is NULL"); 623 return; 624 } 625 mSlots[buf].mBufferState = BufferSlot::FREE; 626 mSlots[buf].mFrameNumber = 0; 627 mSlots[buf].mFence = fence; 628 mDequeueCondition.broadcast(); 629} 630 631status_t BufferQueue::connect(int api, bool producerControlledByApp, QueueBufferOutput* output) { 632 ATRACE_CALL(); 633 ST_LOGV("connect: api=%d", api); 634 Mutex::Autolock lock(mMutex); 635 636 if (mAbandoned) { 637 ST_LOGE("connect: BufferQueue has been abandoned!"); 638 return NO_INIT; 639 } 640 641 if (mConsumerListener == NULL) { 642 ST_LOGE("connect: BufferQueue has no consumer!"); 643 return NO_INIT; 644 } 645 646 int err = NO_ERROR; 647 switch (api) { 648 case NATIVE_WINDOW_API_EGL: 649 case NATIVE_WINDOW_API_CPU: 650 case NATIVE_WINDOW_API_MEDIA: 651 case NATIVE_WINDOW_API_CAMERA: 652 if (mConnectedApi != NO_CONNECTED_API) { 653 ST_LOGE("connect: already connected (cur=%d, req=%d)", 654 mConnectedApi, api); 655 err = -EINVAL; 656 } else { 657 mConnectedApi = api; 658 output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, 659 mQueue.size()); 660 } 661 break; 662 default: 663 err = -EINVAL; 664 break; 665 } 666 667 mBufferHasBeenQueued = false; 668 mDequeueBufferCannotBlock = mConsumerControlledByApp && producerControlledByApp; 669 670 return err; 671} 672 673status_t BufferQueue::disconnect(int api) { 674 ATRACE_CALL(); 675 ST_LOGV("disconnect: api=%d", api); 676 677 int err = NO_ERROR; 678 sp<ConsumerListener> listener; 679 680 { // Scope for the lock 681 Mutex::Autolock lock(mMutex); 682 683 if (mAbandoned) { 684 // it is not really an error to disconnect after the surface 685 // has been abandoned, it should just be a no-op. 686 return NO_ERROR; 687 } 688 689 switch (api) { 690 case NATIVE_WINDOW_API_EGL: 691 case NATIVE_WINDOW_API_CPU: 692 case NATIVE_WINDOW_API_MEDIA: 693 case NATIVE_WINDOW_API_CAMERA: 694 if (mConnectedApi == api) { 695 freeAllBuffersLocked(); 696 mConnectedApi = NO_CONNECTED_API; 697 mDequeueCondition.broadcast(); 698 listener = mConsumerListener; 699 } else { 700 ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)", 701 mConnectedApi, api); 702 err = -EINVAL; 703 } 704 break; 705 default: 706 ST_LOGE("disconnect: unknown API %d", api); 707 err = -EINVAL; 708 break; 709 } 710 } 711 712 if (listener != NULL) { 713 listener->onBuffersReleased(); 714 } 715 716 return err; 717} 718 719void BufferQueue::dump(String8& result) const { 720 BufferQueue::dump(result, ""); 721} 722 723void BufferQueue::dump(String8& result, const char* prefix) const { 724 Mutex::Autolock _l(mMutex); 725 726 String8 fifo; 727 int fifoSize = 0; 728 Fifo::const_iterator i(mQueue.begin()); 729 while (i != mQueue.end()) { 730 fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], " 731 "xform=0x%02x, time=%#llx, scale=%s\n", 732 i->mBuf, i->mGraphicBuffer.get(), 733 i->mCrop.left, i->mCrop.top, i->mCrop.right, 734 i->mCrop.bottom, i->mTransform, i->mTimestamp, 735 scalingModeName(i->mScalingMode) 736 ); 737 i++; 738 fifoSize++; 739 } 740 741 742 result.appendFormat( 743 "%s-BufferQueue mMaxAcquiredBufferCount=%d, mDequeueBufferCannotBlock=%d, default-size=[%dx%d], " 744 "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n", 745 prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, mDefaultWidth, 746 mDefaultHeight, mDefaultBufferFormat, mTransformHint, 747 fifoSize, fifo.string()); 748 749 struct { 750 const char * operator()(int state) const { 751 switch (state) { 752 case BufferSlot::DEQUEUED: return "DEQUEUED"; 753 case BufferSlot::QUEUED: return "QUEUED"; 754 case BufferSlot::FREE: return "FREE"; 755 case BufferSlot::ACQUIRED: return "ACQUIRED"; 756 default: return "Unknown"; 757 } 758 } 759 } stateName; 760 761 // just trim the free buffers to not spam the dump 762 int maxBufferCount = 0; 763 for (int i=NUM_BUFFER_SLOTS-1 ; i>=0 ; i--) { 764 const BufferSlot& slot(mSlots[i]); 765 if ((slot.mBufferState != BufferSlot::FREE) || (slot.mGraphicBuffer != NULL)) { 766 maxBufferCount = i+1; 767 break; 768 } 769 } 770 771 for (int i=0 ; i<maxBufferCount ; i++) { 772 const BufferSlot& slot(mSlots[i]); 773 const sp<GraphicBuffer>& buf(slot.mGraphicBuffer); 774 result.appendFormat( 775 "%s%s[%02d:%p] state=%-8s", 776 prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, buf.get(), 777 stateName(slot.mBufferState) 778 ); 779 780 if (buf != NULL) { 781 result.appendFormat( 782 ", %p [%4ux%4u:%4u,%3X]", 783 buf->handle, buf->width, buf->height, buf->stride, 784 buf->format); 785 } 786 result.append("\n"); 787 } 788} 789 790void BufferQueue::freeBufferLocked(int slot) { 791 ST_LOGV("freeBufferLocked: slot=%d", slot); 792 mSlots[slot].mGraphicBuffer = 0; 793 if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) { 794 mSlots[slot].mNeedsCleanupOnRelease = true; 795 } 796 mSlots[slot].mBufferState = BufferSlot::FREE; 797 mSlots[slot].mFrameNumber = 0; 798 mSlots[slot].mAcquireCalled = false; 799 800 // destroy fence as BufferQueue now takes ownership 801 if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) { 802 eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence); 803 mSlots[slot].mEglFence = EGL_NO_SYNC_KHR; 804 } 805 mSlots[slot].mFence = Fence::NO_FENCE; 806} 807 808void BufferQueue::freeAllBuffersLocked() { 809 mBufferHasBeenQueued = false; 810 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 811 freeBufferLocked(i); 812 } 813} 814 815status_t BufferQueue::acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) { 816 ATRACE_CALL(); 817 Mutex::Autolock _l(mMutex); 818 819 // Check that the consumer doesn't currently have the maximum number of 820 // buffers acquired. We allow the max buffer count to be exceeded by one 821 // buffer, so that the consumer can successfully set up the newly acquired 822 // buffer before releasing the old one. 823 int numAcquiredBuffers = 0; 824 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 825 if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) { 826 numAcquiredBuffers++; 827 } 828 } 829 if (numAcquiredBuffers >= mMaxAcquiredBufferCount+1) { 830 ST_LOGE("acquireBuffer: max acquired buffer count reached: %d (max=%d)", 831 numAcquiredBuffers, mMaxAcquiredBufferCount); 832 return INVALID_OPERATION; 833 } 834 835 // check if queue is empty 836 // In asynchronous mode the list is guaranteed to be one buffer 837 // deep, while in synchronous mode we use the oldest buffer. 838 if (mQueue.empty()) { 839 return NO_BUFFER_AVAILABLE; 840 } 841 842 Fifo::iterator front(mQueue.begin()); 843 int buf = front->mBuf; 844 845 // Compare the buffer's desired presentation time to the predicted 846 // actual display time. 847 // 848 // The "presentWhen" argument indicates when the buffer is expected 849 // to be presented on-screen. If the buffer's desired-present time 850 // is earlier (less) than presentWhen, meaning it'll be displayed 851 // on time or possibly late, we acquire and return it. If we don't want 852 // to display it until after the presentWhen time, we return PRESENT_LATER 853 // without acquiring it. 854 // 855 // To be safe, we don't refuse to acquire the buffer if presentWhen is 856 // more than one second in the future beyond the desired present time 857 // (i.e. we'd be holding the buffer for a really long time). 858 const int MAX_FUTURE_NSEC = 1000000000ULL; 859 nsecs_t desiredPresent = front->mTimestamp; 860 if (presentWhen != 0 && desiredPresent > presentWhen && 861 desiredPresent - presentWhen < MAX_FUTURE_NSEC) 862 { 863 ST_LOGV("pts defer: des=%lld when=%lld (%lld) now=%lld", 864 desiredPresent, presentWhen, desiredPresent - presentWhen, 865 systemTime(CLOCK_MONOTONIC)); 866 return PRESENT_LATER; 867 } 868 if (presentWhen != 0) { 869 ST_LOGV("pts accept: %p[%d] sig=%lld des=%lld when=%lld (%lld)", 870 mSlots, buf, mSlots[buf].mFence->getSignalTime(), 871 desiredPresent, presentWhen, desiredPresent - presentWhen); 872 } 873 874 *buffer = *front; 875 ATRACE_BUFFER_INDEX(buf); 876 877 ST_LOGV("acquireBuffer: acquiring { slot=%d/%llu, buffer=%p }", 878 front->mBuf, front->mFrameNumber, 879 front->mGraphicBuffer->handle); 880 // if front buffer still being tracked update slot state 881 if (stillTracking(front)) { 882 mSlots[buf].mAcquireCalled = true; 883 mSlots[buf].mNeedsCleanupOnRelease = false; 884 mSlots[buf].mBufferState = BufferSlot::ACQUIRED; 885 mSlots[buf].mFence = Fence::NO_FENCE; 886 } 887 888 // If the buffer has previously been acquired by the consumer, set 889 // mGraphicBuffer to NULL to avoid unnecessarily remapping this 890 // buffer on the consumer side. 891 if (buffer->mAcquireCalled) { 892 buffer->mGraphicBuffer = NULL; 893 } 894 895 mQueue.erase(front); 896 mDequeueCondition.broadcast(); 897 898 ATRACE_INT(mConsumerName.string(), mQueue.size()); 899 900 return NO_ERROR; 901} 902 903status_t BufferQueue::releaseBuffer( 904 int buf, uint64_t frameNumber, EGLDisplay display, 905 EGLSyncKHR eglFence, const sp<Fence>& fence) { 906 ATRACE_CALL(); 907 ATRACE_BUFFER_INDEX(buf); 908 909 if (buf == INVALID_BUFFER_SLOT || fence == NULL) { 910 return BAD_VALUE; 911 } 912 913 Mutex::Autolock _l(mMutex); 914 915 // If the frame number has changed because buffer has been reallocated, 916 // we can ignore this releaseBuffer for the old buffer. 917 if (frameNumber != mSlots[buf].mFrameNumber) { 918 return STALE_BUFFER_SLOT; 919 } 920 921 922 // Internal state consistency checks: 923 // Make sure this buffers hasn't been queued while we were owning it (acquired) 924 Fifo::iterator front(mQueue.begin()); 925 Fifo::const_iterator const end(mQueue.end()); 926 while (front != end) { 927 if (front->mBuf == buf) { 928 LOG_ALWAYS_FATAL("[%s] received new buffer(#%lld) on slot #%d that has not yet been " 929 "acquired", mConsumerName.string(), frameNumber, buf); 930 break; // never reached 931 } 932 front++; 933 } 934 935 // The buffer can now only be released if its in the acquired state 936 if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) { 937 mSlots[buf].mEglDisplay = display; 938 mSlots[buf].mEglFence = eglFence; 939 mSlots[buf].mFence = fence; 940 mSlots[buf].mBufferState = BufferSlot::FREE; 941 } else if (mSlots[buf].mNeedsCleanupOnRelease) { 942 ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState); 943 mSlots[buf].mNeedsCleanupOnRelease = false; 944 return STALE_BUFFER_SLOT; 945 } else { 946 ST_LOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState); 947 return -EINVAL; 948 } 949 950 mDequeueCondition.broadcast(); 951 return NO_ERROR; 952} 953 954status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener, 955 bool controlledByApp) { 956 ST_LOGV("consumerConnect"); 957 Mutex::Autolock lock(mMutex); 958 959 if (mAbandoned) { 960 ST_LOGE("consumerConnect: BufferQueue has been abandoned!"); 961 return NO_INIT; 962 } 963 if (consumerListener == NULL) { 964 ST_LOGE("consumerConnect: consumerListener may not be NULL"); 965 return BAD_VALUE; 966 } 967 968 mConsumerListener = consumerListener; 969 mConsumerControlledByApp = controlledByApp; 970 971 return NO_ERROR; 972} 973 974status_t BufferQueue::consumerDisconnect() { 975 ST_LOGV("consumerDisconnect"); 976 Mutex::Autolock lock(mMutex); 977 978 if (mConsumerListener == NULL) { 979 ST_LOGE("consumerDisconnect: No consumer is connected!"); 980 return -EINVAL; 981 } 982 983 mAbandoned = true; 984 mConsumerListener = NULL; 985 mQueue.clear(); 986 freeAllBuffersLocked(); 987 mDequeueCondition.broadcast(); 988 return NO_ERROR; 989} 990 991status_t BufferQueue::getReleasedBuffers(uint32_t* slotMask) { 992 ST_LOGV("getReleasedBuffers"); 993 Mutex::Autolock lock(mMutex); 994 995 if (mAbandoned) { 996 ST_LOGE("getReleasedBuffers: BufferQueue has been abandoned!"); 997 return NO_INIT; 998 } 999 1000 uint32_t mask = 0; 1001 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 1002 if (!mSlots[i].mAcquireCalled) { 1003 mask |= 1 << i; 1004 } 1005 } 1006 1007 // Remove buffers in flight (on the queue) from the mask where acquire has 1008 // been called, as the consumer will not receive the buffer address, so 1009 // it should not free these slots. 1010 Fifo::iterator front(mQueue.begin()); 1011 while (front != mQueue.end()) { 1012 if (front->mAcquireCalled) 1013 mask &= ~(1 << front->mBuf); 1014 front++; 1015 } 1016 1017 *slotMask = mask; 1018 1019 ST_LOGV("getReleasedBuffers: returning mask %#x", mask); 1020 return NO_ERROR; 1021} 1022 1023status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) { 1024 ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h); 1025 if (!w || !h) { 1026 ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", 1027 w, h); 1028 return BAD_VALUE; 1029 } 1030 1031 Mutex::Autolock lock(mMutex); 1032 mDefaultWidth = w; 1033 mDefaultHeight = h; 1034 return NO_ERROR; 1035} 1036 1037status_t BufferQueue::setDefaultMaxBufferCount(int bufferCount) { 1038 ATRACE_CALL(); 1039 Mutex::Autolock lock(mMutex); 1040 return setDefaultMaxBufferCountLocked(bufferCount); 1041} 1042 1043status_t BufferQueue::disableAsyncBuffer() { 1044 ATRACE_CALL(); 1045 Mutex::Autolock lock(mMutex); 1046 if (mConsumerListener != NULL) { 1047 ST_LOGE("disableAsyncBuffer: consumer already connected!"); 1048 return INVALID_OPERATION; 1049 } 1050 mUseAsyncBuffer = false; 1051 return NO_ERROR; 1052} 1053 1054status_t BufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { 1055 ATRACE_CALL(); 1056 Mutex::Autolock lock(mMutex); 1057 if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) { 1058 ST_LOGE("setMaxAcquiredBufferCount: invalid count specified: %d", 1059 maxAcquiredBuffers); 1060 return BAD_VALUE; 1061 } 1062 if (mConnectedApi != NO_CONNECTED_API) { 1063 return INVALID_OPERATION; 1064 } 1065 mMaxAcquiredBufferCount = maxAcquiredBuffers; 1066 return NO_ERROR; 1067} 1068 1069int BufferQueue::getMinUndequeuedBufferCount(bool async) const { 1070 // if dequeueBuffer is allowed to error out, we don't have to 1071 // add an extra buffer. 1072 if (!mUseAsyncBuffer) 1073 return mMaxAcquiredBufferCount; 1074 1075 // we're in async mode, or we want to prevent the app to 1076 // deadlock itself, we throw-in an extra buffer to guarantee it. 1077 if (mDequeueBufferCannotBlock || async) 1078 return mMaxAcquiredBufferCount+1; 1079 1080 return mMaxAcquiredBufferCount; 1081} 1082 1083int BufferQueue::getMinMaxBufferCountLocked(bool async) const { 1084 return getMinUndequeuedBufferCount(async) + 1; 1085} 1086 1087int BufferQueue::getMaxBufferCountLocked(bool async) const { 1088 int minMaxBufferCount = getMinMaxBufferCountLocked(async); 1089 1090 int maxBufferCount = mDefaultMaxBufferCount; 1091 if (maxBufferCount < minMaxBufferCount) { 1092 maxBufferCount = minMaxBufferCount; 1093 } 1094 if (mOverrideMaxBufferCount != 0) { 1095 assert(mOverrideMaxBufferCount >= minMaxBufferCount); 1096 maxBufferCount = mOverrideMaxBufferCount; 1097 } 1098 1099 // Any buffers that are dequeued by the producer or sitting in the queue 1100 // waiting to be consumed need to have their slots preserved. Such 1101 // buffers will temporarily keep the max buffer count up until the slots 1102 // no longer need to be preserved. 1103 for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) { 1104 BufferSlot::BufferState state = mSlots[i].mBufferState; 1105 if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) { 1106 maxBufferCount = i + 1; 1107 } 1108 } 1109 1110 return maxBufferCount; 1111} 1112 1113bool BufferQueue::stillTracking(const BufferItem *item) const { 1114 const BufferSlot &slot = mSlots[item->mBuf]; 1115 1116 ST_LOGV("stillTracking?: item: { slot=%d/%llu, buffer=%p }, " 1117 "slot: { slot=%d/%llu, buffer=%p }", 1118 item->mBuf, item->mFrameNumber, 1119 (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0), 1120 item->mBuf, slot.mFrameNumber, 1121 (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0)); 1122 1123 // Compare item with its original buffer slot. We can check the slot 1124 // as the buffer would not be moved to a different slot by the producer. 1125 return (slot.mGraphicBuffer != NULL && 1126 item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle); 1127} 1128 1129BufferQueue::ProxyConsumerListener::ProxyConsumerListener( 1130 const wp<BufferQueue::ConsumerListener>& consumerListener): 1131 mConsumerListener(consumerListener) {} 1132 1133BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} 1134 1135void BufferQueue::ProxyConsumerListener::onFrameAvailable() { 1136 sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote()); 1137 if (listener != NULL) { 1138 listener->onFrameAvailable(); 1139 } 1140} 1141 1142void BufferQueue::ProxyConsumerListener::onBuffersReleased() { 1143 sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote()); 1144 if (listener != NULL) { 1145 listener->onBuffersReleased(); 1146 } 1147} 1148 1149}; // namespace android 1150