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