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