BufferQueueCore.cpp revision 99b18b447dec188bcec37b415603b9dd400fc7e1
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#include <inttypes.h>
24
25#include <gui/BufferItem.h>
26#include <gui/BufferQueueCore.h>
27#include <gui/IConsumerListener.h>
28#include <gui/IGraphicBufferAlloc.h>
29#include <gui/IProducerListener.h>
30#include <gui/ISurfaceComposer.h>
31#include <private/gui/ComposerService.h>
32
33template <typename T>
34static inline T max(T a, T b) { return a > b ? a : b; }
35
36namespace android {
37
38static String8 getUniqueName() {
39    static volatile int32_t counter = 0;
40    return String8::format("unnamed-%d-%d", getpid(),
41            android_atomic_inc(&counter));
42}
43
44BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
45    mAllocator(allocator),
46    mMutex(),
47    mIsAbandoned(false),
48    mConsumerControlledByApp(false),
49    mConsumerName(getUniqueName()),
50    mConsumerListener(),
51    mConsumerUsageBits(0),
52    mConnectedApi(NO_CONNECTED_API),
53    mConnectedProducerListener(),
54    mSlots(),
55    mQueue(),
56    mOverrideMaxBufferCount(0),
57    mDequeueCondition(),
58    mUseAsyncBuffer(true),
59    mDequeueBufferCannotBlock(false),
60    mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
61    mDefaultWidth(1),
62    mDefaultHeight(1),
63    mDefaultMaxBufferCount(2),
64    mMaxAcquiredBufferCount(1),
65    mBufferHasBeenQueued(false),
66    mFrameCounter(0),
67    mTransformHint(0)
68{
69    if (allocator == NULL) {
70        sp<ISurfaceComposer> composer(ComposerService::getComposerService());
71        mAllocator = composer->createGraphicBufferAlloc();
72        if (mAllocator == NULL) {
73            BQ_LOGE("createGraphicBufferAlloc failed");
74        }
75    }
76}
77
78BufferQueueCore::~BufferQueueCore() {}
79
80void BufferQueueCore::dump(String8& result, const char* prefix) const {
81    Mutex::Autolock lock(mMutex);
82
83    String8 fifo;
84    Fifo::const_iterator current(mQueue.begin());
85    while (current != mQueue.end()) {
86        fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
87                "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n",
88                current->mSlot, current->mGraphicBuffer.get(),
89                current->mCrop.left, current->mCrop.top, current->mCrop.right,
90                current->mCrop.bottom, current->mTransform, current->mTimestamp,
91                BufferItem::scalingModeName(current->mScalingMode));
92        ++current;
93    }
94
95    result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
96            "mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
97            "default-format=%d, transform-hint=%02x, FIFO(%zu)={%s}\n",
98            prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock,
99            mDefaultWidth, mDefaultHeight, mDefaultBufferFormat, mTransformHint,
100            mQueue.size(), fifo.string());
101
102    // Trim the free buffers so as to not spam the dump
103    int maxBufferCount = 0;
104    for (int s = BufferQueueDefs::NUM_BUFFER_SLOTS - 1; s >= 0; --s) {
105        const BufferSlot& slot(mSlots[s]);
106        if (slot.mBufferState != BufferSlot::FREE ||
107                slot.mGraphicBuffer != NULL) {
108            maxBufferCount = s + 1;
109            break;
110        }
111    }
112
113    for (int s = 0; s < maxBufferCount; ++s) {
114        const BufferSlot& slot(mSlots[s]);
115        const sp<GraphicBuffer>& buffer(slot.mGraphicBuffer);
116        result.appendFormat("%s%s[%02d:%p] state=%-8s", prefix,
117                (slot.mBufferState == BufferSlot::ACQUIRED) ? ">" : " ",
118                s, buffer.get(),
119                BufferSlot::bufferStateName(slot.mBufferState));
120
121        if (buffer != NULL) {
122            result.appendFormat(", %p [%4ux%4u:%4u,%3X]", buffer->handle,
123                    buffer->width, buffer->height, buffer->stride,
124                    buffer->format);
125        }
126
127        result.append("\n");
128    }
129}
130
131int BufferQueueCore::getMinUndequeuedBufferCountLocked(bool async) const {
132    // If dequeueBuffer is allowed to error out, we don't have to add an
133    // extra buffer.
134    if (!mUseAsyncBuffer) {
135        return mMaxAcquiredBufferCount;
136    }
137
138    if (mDequeueBufferCannotBlock || async) {
139        return mMaxAcquiredBufferCount + 1;
140    }
141
142    return mMaxAcquiredBufferCount;
143}
144
145int BufferQueueCore::getMinMaxBufferCountLocked(bool async) const {
146    return getMinUndequeuedBufferCountLocked(async) + 1;
147}
148
149int BufferQueueCore::getMaxBufferCountLocked(bool async) const {
150    int minMaxBufferCount = getMinMaxBufferCountLocked(async);
151
152    int maxBufferCount = max(mDefaultMaxBufferCount, minMaxBufferCount);
153    if (mOverrideMaxBufferCount != 0) {
154        assert(mOverrideMaxBufferCount >= minMaxBufferCount);
155        maxBufferCount = mOverrideMaxBufferCount;
156    }
157
158    // Any buffers that are dequeued by the producer or sitting in the queue
159    // waiting to be consumed need to have their slots preserved. Such buffers
160    // will temporarily keep the max buffer count up until the slots no longer
161    // need to be preserved.
162    for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
163        BufferSlot::BufferState state = mSlots[s].mBufferState;
164        if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) {
165            maxBufferCount = s + 1;
166        }
167    }
168
169    return maxBufferCount;
170}
171
172status_t BufferQueueCore::setDefaultMaxBufferCountLocked(int count) {
173    const int minBufferCount = mUseAsyncBuffer ? 2 : 1;
174    if (count < minBufferCount || count > BufferQueueDefs::NUM_BUFFER_SLOTS) {
175        BQ_LOGV("setDefaultMaxBufferCount: invalid count %d, should be in "
176                "[%d, %d]", minBufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
177        return BAD_VALUE;
178    }
179
180    BQ_LOGV("setDefaultMaxBufferCount: setting count to %d", count);
181    mDefaultMaxBufferCount = count;
182    mDequeueCondition.broadcast();
183
184    return NO_ERROR;
185}
186
187void BufferQueueCore::freeBufferLocked(int slot) {
188    BQ_LOGV("freeBufferLocked: slot %d", slot);
189    mSlots[slot].mGraphicBuffer.clear();
190    if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) {
191        mSlots[slot].mNeedsCleanupOnRelease = true;
192    }
193    mSlots[slot].mBufferState = BufferSlot::FREE;
194    mSlots[slot].mFrameNumber = UINT32_MAX;
195    mSlots[slot].mAcquireCalled = false;
196
197    // Destroy fence as BufferQueue now takes ownership
198    if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) {
199        eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence);
200        mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
201    }
202    mSlots[slot].mFence = Fence::NO_FENCE;
203}
204
205void BufferQueueCore::freeAllBuffersLocked() {
206    mBufferHasBeenQueued = false;
207    for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
208        freeBufferLocked(s);
209    }
210}
211
212bool BufferQueueCore::stillTracking(const BufferItem* item) const {
213    const BufferSlot& slot = mSlots[item->mSlot];
214
215    BQ_LOGV("stillTracking: item { slot=%d/%llu buffer=%p } "
216            "slot { slot=%d/%llu buffer=%p }",
217            item->mSlot, item->mFrameNumber,
218            (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0),
219            item->mSlot, slot.mFrameNumber,
220            (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0));
221
222    // Compare item with its original buffer slot. We can check the slot as
223    // the buffer would not be moved to a different slot by the producer.
224    return (slot.mGraphicBuffer != NULL) &&
225           (item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle);
226}
227
228} // namespace android
229