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