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