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