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