• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "BufferQueueCore"
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19 //#define LOG_NDEBUG 0
20 
21 #define EGL_EGLEXT_PROTOTYPES
22 
23 #if DEBUG_ONLY_CODE
24 #define VALIDATE_CONSISTENCY() do { validateConsistencyLocked(); } while (0)
25 #else
26 #define VALIDATE_CONSISTENCY()
27 #endif
28 
29 #include <inttypes.h>
30 
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>
38 
39 namespace android {
40 
getUniqueName()41 static String8 getUniqueName() {
42     static volatile int32_t counter = 0;
43     return String8::format("unnamed-%d-%d", getpid(),
44             android_atomic_inc(&counter));
45 }
46 
getUniqueId()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++;
51 }
52 
BufferQueueCore(const sp<IGraphicBufferAlloc> & allocator)53 BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
54     mAllocator(allocator),
55     mMutex(),
56     mIsAbandoned(false),
57     mConsumerControlledByApp(false),
58     mConsumerName(getUniqueName()),
59     mConsumerListener(),
60     mConsumerUsageBits(0),
61     mConnectedApi(NO_CONNECTED_API),
62     mConnectedProducerListener(),
63     mSlots(),
64     mQueue(),
65     mFreeSlots(),
66     mFreeBuffers(),
67     mUnusedSlots(),
68     mActiveBuffers(),
69     mDequeueCondition(),
70     mDequeueBufferCannotBlock(false),
71     mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
72     mDefaultWidth(1),
73     mDefaultHeight(1),
74     mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
75     mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
76     mMaxAcquiredBufferCount(1),
77     mMaxDequeuedBufferCount(1),
78     mBufferHasBeenQueued(false),
79     mFrameCounter(0),
80     mTransformHint(0),
81     mIsAllocating(false),
82     mIsAllocatingCondition(),
83     mAllowAllocation(true),
84     mBufferAge(0),
85     mGenerationNumber(0),
86     mAsyncMode(false),
87     mSharedBufferMode(false),
88     mAutoRefresh(false),
89     mSharedBufferSlot(INVALID_BUFFER_SLOT),
90     mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
91             HAL_DATASPACE_UNKNOWN),
92     mUniqueId(getUniqueId())
93 {
94     if (allocator == NULL) {
95         sp<ISurfaceComposer> composer(ComposerService::getComposerService());
96         mAllocator = composer->createGraphicBufferAlloc();
97         if (mAllocator == NULL) {
98             BQ_LOGE("createGraphicBufferAlloc failed");
99         }
100     }
101 
102     int numStartingBuffers = getMaxBufferCountLocked();
103     for (int s = 0; s < numStartingBuffers; s++) {
104         mFreeSlots.insert(s);
105     }
106     for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
107             s++) {
108         mUnusedSlots.push_front(s);
109     }
110 }
111 
~BufferQueueCore()112 BufferQueueCore::~BufferQueueCore() {}
113 
dump(String8 & result,const char * prefix) const114 void BufferQueueCore::dump(String8& result, const char* prefix) const {
115     Mutex::Autolock lock(mMutex);
116 
117     String8 fifo;
118     Fifo::const_iterator current(mQueue.begin());
119     while (current != mQueue.end()) {
120         fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
121                 "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n",
122                 current->mSlot, current->mGraphicBuffer.get(),
123                 current->mCrop.left, current->mCrop.top, current->mCrop.right,
124                 current->mCrop.bottom, current->mTransform, current->mTimestamp,
125                 BufferItem::scalingModeName(current->mScalingMode));
126         ++current;
127     }
128 
129     result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
130             "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d "
131             "mAsyncMode=%d, default-size=[%dx%d], default-format=%d, "
132             "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix,
133             mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
134             mDequeueBufferCannotBlock, mAsyncMode, mDefaultWidth,
135             mDefaultHeight, mDefaultBufferFormat, mTransformHint, mQueue.size(),
136             fifo.string());
137 
138     for (int s : mActiveBuffers) {
139         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
140         // A dequeued buffer might be null if it's still being allocated
141         if (buffer.get()) {
142             result.appendFormat("%s%s[%02d:%p] state=%-8s, %p "
143                     "[%4ux%4u:%4u,%3X]\n", prefix,
144                     (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
145                     buffer.get(), mSlots[s].mBufferState.string(),
146                     buffer->handle, buffer->width, buffer->height,
147                     buffer->stride, buffer->format);
148         } else {
149             result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
150                     buffer.get(), mSlots[s].mBufferState.string());
151         }
152     }
153     for (int s : mFreeBuffers) {
154         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
155         result.appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
156                 prefix, s, buffer.get(), mSlots[s].mBufferState.string(),
157                 buffer->handle, buffer->width, buffer->height, buffer->stride,
158                 buffer->format);
159     }
160 
161     for (int s : mFreeSlots) {
162         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
163         result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
164                 buffer.get(), mSlots[s].mBufferState.string());
165     }
166 }
167 
getMinUndequeuedBufferCountLocked() const168 int BufferQueueCore::getMinUndequeuedBufferCountLocked() const {
169     // If dequeueBuffer is allowed to error out, we don't have to add an
170     // extra buffer.
171     if (mAsyncMode || mDequeueBufferCannotBlock) {
172         return mMaxAcquiredBufferCount + 1;
173     }
174 
175     return mMaxAcquiredBufferCount;
176 }
177 
getMinMaxBufferCountLocked() const178 int BufferQueueCore::getMinMaxBufferCountLocked() const {
179     return getMinUndequeuedBufferCountLocked() + 1;
180 }
181 
getMaxBufferCountLocked(bool asyncMode,bool dequeueBufferCannotBlock,int maxBufferCount) const182 int BufferQueueCore::getMaxBufferCountLocked(bool asyncMode,
183         bool dequeueBufferCannotBlock, int maxBufferCount) const {
184     int maxCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
185             ((asyncMode || dequeueBufferCannotBlock) ? 1 : 0);
186     maxCount = std::min(maxBufferCount, maxCount);
187     return maxCount;
188 }
189 
getMaxBufferCountLocked() const190 int BufferQueueCore::getMaxBufferCountLocked() const {
191     int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
192             ((mAsyncMode || mDequeueBufferCannotBlock) ? 1 : 0);
193 
194     // limit maxBufferCount by mMaxBufferCount always
195     maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);
196 
197     return maxBufferCount;
198 }
199 
clearBufferSlotLocked(int slot)200 void BufferQueueCore::clearBufferSlotLocked(int slot) {
201     BQ_LOGV("clearBufferSlotLocked: slot %d", slot);
202 
203     mSlots[slot].mGraphicBuffer.clear();
204     mSlots[slot].mBufferState.reset();
205     mSlots[slot].mRequestBufferCalled = false;
206     mSlots[slot].mFrameNumber = 0;
207     mSlots[slot].mAcquireCalled = false;
208     mSlots[slot].mNeedsReallocation = true;
209 
210     // Destroy fence as BufferQueue now takes ownership
211     if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) {
212         eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence);
213         mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
214     }
215     mSlots[slot].mFence = Fence::NO_FENCE;
216     mSlots[slot].mEglDisplay = EGL_NO_DISPLAY;
217 
218     if (mLastQueuedSlot == slot) {
219         mLastQueuedSlot = INVALID_BUFFER_SLOT;
220     }
221 }
222 
freeAllBuffersLocked()223 void BufferQueueCore::freeAllBuffersLocked() {
224     for (int s : mFreeSlots) {
225         clearBufferSlotLocked(s);
226     }
227 
228     for (int s : mFreeBuffers) {
229         mFreeSlots.insert(s);
230         clearBufferSlotLocked(s);
231     }
232     mFreeBuffers.clear();
233 
234     for (int s : mActiveBuffers) {
235         mFreeSlots.insert(s);
236         clearBufferSlotLocked(s);
237     }
238     mActiveBuffers.clear();
239 
240     for (auto& b : mQueue) {
241         b.mIsStale = true;
242     }
243 
244     VALIDATE_CONSISTENCY();
245 }
246 
discardFreeBuffersLocked()247 void BufferQueueCore::discardFreeBuffersLocked() {
248     for (int s : mFreeBuffers) {
249         mFreeSlots.insert(s);
250         clearBufferSlotLocked(s);
251     }
252     mFreeBuffers.clear();
253 
254     VALIDATE_CONSISTENCY();
255 }
256 
adjustAvailableSlotsLocked(int delta)257 bool BufferQueueCore::adjustAvailableSlotsLocked(int delta) {
258     if (delta >= 0) {
259         // If we're going to fail, do so before modifying anything
260         if (delta > static_cast<int>(mUnusedSlots.size())) {
261             return false;
262         }
263         while (delta > 0) {
264             if (mUnusedSlots.empty()) {
265                 return false;
266             }
267             int slot = mUnusedSlots.back();
268             mUnusedSlots.pop_back();
269             mFreeSlots.insert(slot);
270             delta--;
271         }
272     } else {
273         // If we're going to fail, do so before modifying anything
274         if (-delta > static_cast<int>(mFreeSlots.size() +
275                 mFreeBuffers.size())) {
276             return false;
277         }
278         while (delta < 0) {
279             if (!mFreeSlots.empty()) {
280                 auto slot = mFreeSlots.begin();
281                 clearBufferSlotLocked(*slot);
282                 mUnusedSlots.push_back(*slot);
283                 mFreeSlots.erase(slot);
284             } else if (!mFreeBuffers.empty()) {
285                 int slot = mFreeBuffers.back();
286                 clearBufferSlotLocked(slot);
287                 mUnusedSlots.push_back(slot);
288                 mFreeBuffers.pop_back();
289             } else {
290                 return false;
291             }
292             delta++;
293         }
294     }
295     return true;
296 }
297 
waitWhileAllocatingLocked() const298 void BufferQueueCore::waitWhileAllocatingLocked() const {
299     ATRACE_CALL();
300     while (mIsAllocating) {
301         mIsAllocatingCondition.wait(mMutex);
302     }
303 }
304 
305 #if DEBUG_ONLY_CODE
validateConsistencyLocked() const306 void BufferQueueCore::validateConsistencyLocked() const {
307     static const useconds_t PAUSE_TIME = 0;
308     int allocatedSlots = 0;
309     for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
310         bool isInFreeSlots = mFreeSlots.count(slot) != 0;
311         bool isInFreeBuffers =
312                 std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) !=
313                 mFreeBuffers.cend();
314         bool isInActiveBuffers = mActiveBuffers.count(slot) != 0;
315         bool isInUnusedSlots =
316                 std::find(mUnusedSlots.cbegin(), mUnusedSlots.cend(), slot) !=
317                 mUnusedSlots.cend();
318 
319         if (isInFreeSlots || isInFreeBuffers || isInActiveBuffers) {
320             allocatedSlots++;
321         }
322 
323         if (isInUnusedSlots) {
324             if (isInFreeSlots) {
325                 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeSlots", slot);
326                 usleep(PAUSE_TIME);
327             }
328             if (isInFreeBuffers) {
329                 BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeBuffers", slot);
330                 usleep(PAUSE_TIME);
331             }
332             if (isInActiveBuffers) {
333                 BQ_LOGE("Slot %d is in mUnusedSlots and in mActiveBuffers",
334                         slot);
335                 usleep(PAUSE_TIME);
336             }
337             if (!mSlots[slot].mBufferState.isFree()) {
338                 BQ_LOGE("Slot %d is in mUnusedSlots but is not FREE", slot);
339                 usleep(PAUSE_TIME);
340             }
341             if (mSlots[slot].mGraphicBuffer != NULL) {
342                 BQ_LOGE("Slot %d is in mUnusedSluts but has an active buffer",
343                         slot);
344                 usleep(PAUSE_TIME);
345             }
346         } else if (isInFreeSlots) {
347             if (isInUnusedSlots) {
348                 BQ_LOGE("Slot %d is in mFreeSlots and in mUnusedSlots", slot);
349                 usleep(PAUSE_TIME);
350             }
351             if (isInFreeBuffers) {
352                 BQ_LOGE("Slot %d is in mFreeSlots and in mFreeBuffers", slot);
353                 usleep(PAUSE_TIME);
354             }
355             if (isInActiveBuffers) {
356                 BQ_LOGE("Slot %d is in mFreeSlots and in mActiveBuffers", slot);
357                 usleep(PAUSE_TIME);
358             }
359             if (!mSlots[slot].mBufferState.isFree()) {
360                 BQ_LOGE("Slot %d is in mFreeSlots but is not FREE", slot);
361                 usleep(PAUSE_TIME);
362             }
363             if (mSlots[slot].mGraphicBuffer != NULL) {
364                 BQ_LOGE("Slot %d is in mFreeSlots but has a buffer",
365                         slot);
366                 usleep(PAUSE_TIME);
367             }
368         } else if (isInFreeBuffers) {
369             if (isInUnusedSlots) {
370                 BQ_LOGE("Slot %d is in mFreeBuffers and in mUnusedSlots", slot);
371                 usleep(PAUSE_TIME);
372             }
373             if (isInFreeSlots) {
374                 BQ_LOGE("Slot %d is in mFreeBuffers and in mFreeSlots", slot);
375                 usleep(PAUSE_TIME);
376             }
377             if (isInActiveBuffers) {
378                 BQ_LOGE("Slot %d is in mFreeBuffers and in mActiveBuffers",
379                         slot);
380                 usleep(PAUSE_TIME);
381             }
382             if (!mSlots[slot].mBufferState.isFree()) {
383                 BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE", slot);
384                 usleep(PAUSE_TIME);
385             }
386             if (mSlots[slot].mGraphicBuffer == NULL) {
387                 BQ_LOGE("Slot %d is in mFreeBuffers but has no buffer", slot);
388                 usleep(PAUSE_TIME);
389             }
390         } else if (isInActiveBuffers) {
391             if (isInUnusedSlots) {
392                 BQ_LOGE("Slot %d is in mActiveBuffers and in mUnusedSlots",
393                         slot);
394                 usleep(PAUSE_TIME);
395             }
396             if (isInFreeSlots) {
397                 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeSlots", slot);
398                 usleep(PAUSE_TIME);
399             }
400             if (isInFreeBuffers) {
401                 BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeBuffers",
402                         slot);
403                 usleep(PAUSE_TIME);
404             }
405             if (mSlots[slot].mBufferState.isFree() &&
406                     !mSlots[slot].mBufferState.isShared()) {
407                 BQ_LOGE("Slot %d is in mActiveBuffers but is FREE", slot);
408                 usleep(PAUSE_TIME);
409             }
410             if (mSlots[slot].mGraphicBuffer == NULL && !mIsAllocating) {
411                 BQ_LOGE("Slot %d is in mActiveBuffers but has no buffer", slot);
412                 usleep(PAUSE_TIME);
413             }
414         } else {
415             BQ_LOGE("Slot %d isn't in any of mUnusedSlots, mFreeSlots, "
416                     "mFreeBuffers, or mActiveBuffers", slot);
417             usleep(PAUSE_TIME);
418         }
419     }
420 
421     if (allocatedSlots != getMaxBufferCountLocked()) {
422         BQ_LOGE("Number of allocated slots is incorrect. Allocated = %d, "
423                 "Should be %d (%zu free slots, %zu free buffers, "
424                 "%zu activeBuffers, %zu unusedSlots)", allocatedSlots,
425                 getMaxBufferCountLocked(), mFreeSlots.size(),
426                 mFreeBuffers.size(), mActiveBuffers.size(),
427                 mUnusedSlots.size());
428     }
429 }
430 #endif
431 
432 } // namespace android
433