2 * Copyright 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "BufferQueueCore"
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19 //#define LOG_NDEBUG 0
21 #define EGL_EGLEXT_PROTOTYPES
24 #define VALIDATE_CONSISTENCY() do { validateConsistencyLocked(); } while (0)
26 #define VALIDATE_CONSISTENCY()
31 #include <gui/BufferItem.h>
32 #include <gui/BufferQueueCore.h>
33 #include <gui/IConsumerListener.h>
34 #include <gui/IGraphicBufferAlloc.h>
35 #include <gui/IProducerListener.h>
36 #include <gui/ISurfaceComposer.h>
37 #include <private/gui/ComposerService.h>
41 static String8 getUniqueName() {
42 static volatile int32_t counter = 0;
43 return String8::format("unnamed-%d-%d", getpid(),
44 android_atomic_inc(&counter));
47 static uint64_t getUniqueId() {
48 static std::atomic<uint32_t> counter{0};
49 static uint64_t id = static_cast<uint64_t>(getpid()) << 32;
50 return id | counter++;
53 BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
54 mAllocator(allocator),
57 mConsumerControlledByApp(false),
58 mConsumerName(getUniqueName()),
60 mConsumerUsageBits(0),
61 mConnectedApi(NO_CONNECTED_API),
62 mConnectedProducerListener(),
70 mDequeueBufferCannotBlock(false),
71 mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
74 mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
75 mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
76 mMaxAcquiredBufferCount(1),
77 mMaxDequeuedBufferCount(1),
78 mBufferHasBeenQueued(false),
82 mIsAllocatingCondition(),
83 mAllowAllocation(true),
87 mSharedBufferMode(false),
89 mSharedBufferSlot(INVALID_BUFFER_SLOT),
90 mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
91 HAL_DATASPACE_UNKNOWN),
92 mLastQueuedSlot(INVALID_BUFFER_SLOT),
93 mUniqueId(getUniqueId())
95 if (allocator == NULL) {
96 sp<ISurfaceComposer> composer(ComposerService::getComposerService());
97 mAllocator = composer->createGraphicBufferAlloc();
98 if (mAllocator == NULL) {
99 BQ_LOGE("createGraphicBufferAlloc failed");
103 int numStartingBuffers = getMaxBufferCountLocked();
104 for (int s = 0; s < numStartingBuffers; s++) {
105 mFreeSlots.insert(s);
107 for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
109 mUnusedSlots.push_front(s);
113 BufferQueueCore::~BufferQueueCore() {}
115 void BufferQueueCore::dump(String8& result, const char* prefix) const {
116 Mutex::Autolock lock(mMutex);
119 Fifo::const_iterator current(mQueue.begin());
120 while (current != mQueue.end()) {
121 fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
122 "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n",
123 current->mSlot, current->mGraphicBuffer.get(),
124 current->mCrop.left, current->mCrop.top, current->mCrop.right,
125 current->mCrop.bottom, current->mTransform, current->mTimestamp,
126 BufferItem::scalingModeName(current->mScalingMode));
130 result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
131 "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d "
132 "mAsyncMode=%d, default-size=[%dx%d], default-format=%d, "
133 "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix,
134 mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
135 mDequeueBufferCannotBlock, mAsyncMode, mDefaultWidth,
136 mDefaultHeight, mDefaultBufferFormat, mTransformHint, mQueue.size(),
139 for (int s : mActiveBuffers) {
140 const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
141 // A dequeued buffer might be null if it's still being allocated
143 result.appendFormat("%s%s[%02d:%p] state=%-8s, %p "
144 "[%4ux%4u:%4u,%3X]\n", prefix,
145 (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
146 buffer.get(), mSlots[s].mBufferState.string(),
147 buffer->handle, buffer->width, buffer->height,
148 buffer->stride, buffer->format);
150 result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
151 buffer.get(), mSlots[s].mBufferState.string());
154 for (int s : mFreeBuffers) {
155 const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
156 result.appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
157 prefix, s, buffer.get(), mSlots[s].mBufferState.string(),
158 buffer->handle, buffer->width, buffer->height, buffer->stride,
162 for (int s : mFreeSlots) {
163 const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
164 result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
165 buffer.get(), mSlots[s].mBufferState.string());
169 int BufferQueueCore::getMinUndequeuedBufferCountLocked() const {
170 // If dequeueBuffer is allowed to error out, we don't have to add an
172 if (mAsyncMode || mDequeueBufferCannotBlock) {
173 return mMaxAcquiredBufferCount + 1;
176 return mMaxAcquiredBufferCount;
179 int BufferQueueCore::getMinMaxBufferCountLocked() const {
180 return getMinUndequeuedBufferCountLocked() + 1;
183 int BufferQueueCore::getMaxBufferCountLocked(bool asyncMode,
184 bool dequeueBufferCannotBlock, int maxBufferCount) const {
185 int maxCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
186 ((asyncMode || dequeueBufferCannotBlock) ? 1 : 0);
187 maxCount = std::min(maxBufferCount, maxCount);
191 int BufferQueueCore::getMaxBufferCountLocked() const {
192 int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
193 ((mAsyncMode || mDequeueBufferCannotBlock) ? 1 : 0);
195 // limit maxBufferCount by mMaxBufferCount always
196 maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);
198 return maxBufferCount;
201 void BufferQueueCore::clearBufferSlotLocked(int slot) {
202 BQ_LOGV("clearBufferSlotLocked: slot %d", slot);
204 mSlots[slot].mGraphicBuffer.clear();
205 mSlots[slot].mBufferState.reset();
206 mSlots[slot].mRequestBufferCalled = false;
207 mSlots[slot].mFrameNumber = 0;
208 mSlots[slot].mAcquireCalled = false;
209 mSlots[slot].mNeedsReallocation = true;
211 // Destroy fence as BufferQueue now takes ownership
212 if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) {
213 eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence);
214 mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
216 mSlots[slot].mFence = Fence::NO_FENCE;
217 mSlots[slot].mEglDisplay = EGL_NO_DISPLAY;
219 if (mLastQueuedSlot == slot) {
220 mLastQueuedSlot = INVALID_BUFFER_SLOT;
224 void BufferQueueCore::freeAllBuffersLocked() {
225 for (int s : mFreeSlots) {
226 clearBufferSlotLocked(s);
229 for (int s : mFreeBuffers) {
230 mFreeSlots.insert(s);
231 clearBufferSlotLocked(s);
233 mFreeBuffers.clear();
235 for (int s : mActiveBuffers) {
236 mFreeSlots.insert(s);
237 clearBufferSlotLocked(s);
239 mActiveBuffers.clear();
241 for (auto& b : mQueue) {
245 VALIDATE_CONSISTENCY();
248 void BufferQueueCore::discardFreeBuffersLocked() {
249 for (int s : mFreeBuffers) {
250 mFreeSlots.insert(s);
251 clearBufferSlotLocked(s);
253 mFreeBuffers.clear();
255 VALIDATE_CONSISTENCY();
258 bool BufferQueueCore::adjustAvailableSlotsLocked(int delta) {
260 // If we're going to fail, do so before modifying anything
261 if (delta > static_cast<int>(mUnusedSlots.size())) {
265 if (mUnusedSlots.empty()) {
268 int slot = mUnusedSlots.back();
269 mUnusedSlots.pop_back();
270 mFreeSlots.insert(slot);
274 // If we're going to fail, do so before modifying anything
275 if (-delta > static_cast<int>(mFreeSlots.size() +
276 mFreeBuffers.size())) {
280 if (!mFreeSlots.empty()) {
281 auto slot = mFreeSlots.begin();
282 clearBufferSlotLocked(*slot);
283 mUnusedSlots.push_back(*slot);
284 mFreeSlots.erase(slot);
285 } else if (!mFreeBuffers.empty()) {
286 int slot = mFreeBuffers.back();
287 clearBufferSlotLocked(slot);
288 mUnusedSlots.push_back(slot);
289 mFreeBuffers.pop_back();
299 void BufferQueueCore::waitWhileAllocatingLocked() const {
301 while (mIsAllocating) {
302 mIsAllocatingCondition.wait(mMutex);
307 void BufferQueueCore::validateConsistencyLocked() const {
308 static const useconds_t PAUSE_TIME = 0;
309 int allocatedSlots = 0;
310 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
311 bool isInFreeSlots = mFreeSlots.count(slot) != 0;
312 bool isInFreeBuffers =
313 std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) !=
315 bool isInActiveBuffers = mActiveBuffers.count(slot) != 0;
316 bool isInUnusedSlots =
317 std::find(mUnusedSlots.cbegin(), mUnusedSlots.cend(), slot) !=
320 if (isInFreeSlots || isInFreeBuffers || isInActiveBuffers) {
324 if (isInUnusedSlots) {
326 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeSlots", slot);
329 if (isInFreeBuffers) {
330 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeBuffers", slot);
333 if (isInActiveBuffers) {
334 BQ_LOGE("Slot %d is in mUnusedSlots and in mActiveBuffers",
338 if (!mSlots[slot].mBufferState.isFree()) {
339 BQ_LOGE("Slot %d is in mUnusedSlots but is not FREE", slot);
342 if (mSlots[slot].mGraphicBuffer != NULL) {
343 BQ_LOGE("Slot %d is in mUnusedSluts but has an active buffer",
347 } else if (isInFreeSlots) {
348 if (isInUnusedSlots) {
349 BQ_LOGE("Slot %d is in mFreeSlots and in mUnusedSlots", slot);
352 if (isInFreeBuffers) {
353 BQ_LOGE("Slot %d is in mFreeSlots and in mFreeBuffers", slot);
356 if (isInActiveBuffers) {
357 BQ_LOGE("Slot %d is in mFreeSlots and in mActiveBuffers", slot);
360 if (!mSlots[slot].mBufferState.isFree()) {
361 BQ_LOGE("Slot %d is in mFreeSlots but is not FREE", slot);
364 if (mSlots[slot].mGraphicBuffer != NULL) {
365 BQ_LOGE("Slot %d is in mFreeSlots but has a buffer",
369 } else if (isInFreeBuffers) {
370 if (isInUnusedSlots) {
371 BQ_LOGE("Slot %d is in mFreeBuffers and in mUnusedSlots", slot);
375 BQ_LOGE("Slot %d is in mFreeBuffers and in mFreeSlots", slot);
378 if (isInActiveBuffers) {
379 BQ_LOGE("Slot %d is in mFreeBuffers and in mActiveBuffers",
383 if (!mSlots[slot].mBufferState.isFree()) {
384 BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE", slot);
387 if (mSlots[slot].mGraphicBuffer == NULL) {
388 BQ_LOGE("Slot %d is in mFreeBuffers but has no buffer", slot);
391 } else if (isInActiveBuffers) {
392 if (isInUnusedSlots) {
393 BQ_LOGE("Slot %d is in mActiveBuffers and in mUnusedSlots",
398 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeSlots", slot);
401 if (isInFreeBuffers) {
402 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeBuffers",
406 if (mSlots[slot].mBufferState.isFree() &&
407 !mSlots[slot].mBufferState.isShared()) {
408 BQ_LOGE("Slot %d is in mActiveBuffers but is FREE", slot);
411 if (mSlots[slot].mGraphicBuffer == NULL && !mIsAllocating) {
412 BQ_LOGE("Slot %d is in mActiveBuffers but has no buffer", slot);
416 BQ_LOGE("Slot %d isn't in any of mUnusedSlots, mFreeSlots, "
417 "mFreeBuffers, or mActiveBuffers", slot);
422 if (allocatedSlots != getMaxBufferCountLocked()) {
423 BQ_LOGE("Number of allocated slots is incorrect. Allocated = %d, "
424 "Should be %d (%zu free slots, %zu free buffers, "
425 "%zu activeBuffers, %zu unusedSlots)", allocatedSlots,
426 getMaxBufferCountLocked(), mFreeSlots.size(),
427 mFreeBuffers.size(), mActiveBuffers.size(),
428 mUnusedSlots.size());
433 } // namespace android