1 /*
2 * Copyright (C) 2010 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 #include <inttypes.h>
18
19 #define LOG_TAG "ConsumerBase"
20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21 //#define LOG_NDEBUG 0
22
23 #define EGL_EGLEXT_PROTOTYPES
24
25 #include <EGL/egl.h>
26 #include <EGL/eglext.h>
27
28 #include <hardware/hardware.h>
29
30 #include <gui/IGraphicBufferAlloc.h>
31 #include <gui/ISurfaceComposer.h>
32 #include <gui/SurfaceComposerClient.h>
33 #include <gui/ConsumerBase.h>
34
35 #include <private/gui/ComposerService.h>
36
37 #include <utils/Log.h>
38 #include <utils/String8.h>
39 #include <utils/Trace.h>
40
41 // Macros for including the ConsumerBase name in log messages
42 #define CB_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
43 #define CB_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
44 #define CB_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
45 #define CB_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
46 #define CB_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
47
48 namespace android {
49
50 // Get an ID that's unique within this process.
createProcessUniqueId()51 static int32_t createProcessUniqueId() {
52 static volatile int32_t globalCounter = 0;
53 return android_atomic_inc(&globalCounter);
54 }
55
ConsumerBase(const sp<IGraphicBufferConsumer> & bufferQueue,bool controlledByApp)56 ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
57 mAbandoned(false),
58 mConsumer(bufferQueue) {
59 // Choose a name using the PID and a process-unique ID.
60 mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
61
62 // Note that we can't create an sp<...>(this) in a ctor that will not keep a
63 // reference once the ctor ends, as that would cause the refcount of 'this'
64 // dropping to 0 at the end of the ctor. Since all we need is a wp<...>
65 // that's what we create.
66 wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
67 sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
68
69 status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
70 if (err != NO_ERROR) {
71 CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
72 strerror(-err), err);
73 } else {
74 mConsumer->setConsumerName(mName);
75 }
76 }
77
~ConsumerBase()78 ConsumerBase::~ConsumerBase() {
79 CB_LOGV("~ConsumerBase");
80 Mutex::Autolock lock(mMutex);
81
82 // Verify that abandon() has been called before we get here. This should
83 // be done by ConsumerBase::onLastStrongRef(), but it's possible for a
84 // derived class to override that method and not call
85 // ConsumerBase::onLastStrongRef().
86 LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~ConsumerBase was called, but the "
87 "consumer is not abandoned!", mName.string());
88 }
89
onLastStrongRef(const void * id)90 void ConsumerBase::onLastStrongRef(const void* id __attribute__((unused))) {
91 abandon();
92 }
93
freeBufferLocked(int slotIndex)94 void ConsumerBase::freeBufferLocked(int slotIndex) {
95 CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
96 mSlots[slotIndex].mGraphicBuffer = 0;
97 mSlots[slotIndex].mFence = Fence::NO_FENCE;
98 mSlots[slotIndex].mFrameNumber = 0;
99 }
100
onFrameAvailable()101 void ConsumerBase::onFrameAvailable() {
102 CB_LOGV("onFrameAvailable");
103
104 sp<FrameAvailableListener> listener;
105 { // scope for the lock
106 Mutex::Autolock lock(mMutex);
107 listener = mFrameAvailableListener.promote();
108 }
109
110 if (listener != NULL) {
111 CB_LOGV("actually calling onFrameAvailable");
112 listener->onFrameAvailable();
113 }
114 }
115
onBuffersReleased()116 void ConsumerBase::onBuffersReleased() {
117 Mutex::Autolock lock(mMutex);
118
119 CB_LOGV("onBuffersReleased");
120
121 if (mAbandoned) {
122 // Nothing to do if we're already abandoned.
123 return;
124 }
125
126 uint64_t mask = 0;
127 mConsumer->getReleasedBuffers(&mask);
128 for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
129 if (mask & (1ULL << i)) {
130 freeBufferLocked(i);
131 }
132 }
133 }
134
onSidebandStreamChanged()135 void ConsumerBase::onSidebandStreamChanged() {
136 }
137
abandon()138 void ConsumerBase::abandon() {
139 CB_LOGV("abandon");
140 Mutex::Autolock lock(mMutex);
141
142 if (!mAbandoned) {
143 abandonLocked();
144 mAbandoned = true;
145 }
146 }
147
abandonLocked()148 void ConsumerBase::abandonLocked() {
149 CB_LOGV("abandonLocked");
150 for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
151 freeBufferLocked(i);
152 }
153 // disconnect from the BufferQueue
154 mConsumer->consumerDisconnect();
155 mConsumer.clear();
156 }
157
setFrameAvailableListener(const wp<FrameAvailableListener> & listener)158 void ConsumerBase::setFrameAvailableListener(
159 const wp<FrameAvailableListener>& listener) {
160 CB_LOGV("setFrameAvailableListener");
161 Mutex::Autolock lock(mMutex);
162 mFrameAvailableListener = listener;
163 }
164
dump(String8 & result) const165 void ConsumerBase::dump(String8& result) const {
166 dump(result, "");
167 }
168
dump(String8 & result,const char * prefix) const169 void ConsumerBase::dump(String8& result, const char* prefix) const {
170 Mutex::Autolock _l(mMutex);
171 dumpLocked(result, prefix);
172 }
173
dumpLocked(String8 & result,const char * prefix) const174 void ConsumerBase::dumpLocked(String8& result, const char* prefix) const {
175 result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
176
177 if (!mAbandoned) {
178 mConsumer->dump(result, prefix);
179 }
180 }
181
acquireBufferLocked(BufferQueue::BufferItem * item,nsecs_t presentWhen)182 status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item,
183 nsecs_t presentWhen) {
184 status_t err = mConsumer->acquireBuffer(item, presentWhen);
185 if (err != NO_ERROR) {
186 return err;
187 }
188
189 if (item->mGraphicBuffer != NULL) {
190 mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
191 }
192
193 mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
194 mSlots[item->mBuf].mFence = item->mFence;
195
196 CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
197 item->mBuf, item->mFrameNumber);
198
199 return OK;
200 }
201
addReleaseFence(int slot,const sp<GraphicBuffer> graphicBuffer,const sp<Fence> & fence)202 status_t ConsumerBase::addReleaseFence(int slot,
203 const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
204 Mutex::Autolock lock(mMutex);
205 return addReleaseFenceLocked(slot, graphicBuffer, fence);
206 }
207
addReleaseFenceLocked(int slot,const sp<GraphicBuffer> graphicBuffer,const sp<Fence> & fence)208 status_t ConsumerBase::addReleaseFenceLocked(int slot,
209 const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
210 CB_LOGV("addReleaseFenceLocked: slot=%d", slot);
211
212 // If consumer no longer tracks this graphicBuffer, we can safely
213 // drop this fence, as it will never be received by the producer.
214 if (!stillTracking(slot, graphicBuffer)) {
215 return OK;
216 }
217
218 if (!mSlots[slot].mFence.get()) {
219 mSlots[slot].mFence = fence;
220 } else {
221 sp<Fence> mergedFence = Fence::merge(
222 String8::format("%.28s:%d", mName.string(), slot),
223 mSlots[slot].mFence, fence);
224 if (!mergedFence.get()) {
225 CB_LOGE("failed to merge release fences");
226 // synchronization is broken, the best we can do is hope fences
227 // signal in order so the new fence will act like a union
228 mSlots[slot].mFence = fence;
229 return BAD_VALUE;
230 }
231 mSlots[slot].mFence = mergedFence;
232 }
233
234 return OK;
235 }
236
releaseBufferLocked(int slot,const sp<GraphicBuffer> graphicBuffer,EGLDisplay display,EGLSyncKHR eglFence)237 status_t ConsumerBase::releaseBufferLocked(
238 int slot, const sp<GraphicBuffer> graphicBuffer,
239 EGLDisplay display, EGLSyncKHR eglFence) {
240 // If consumer no longer tracks this graphicBuffer (we received a new
241 // buffer on the same slot), the buffer producer is definitely no longer
242 // tracking it.
243 if (!stillTracking(slot, graphicBuffer)) {
244 return OK;
245 }
246
247 CB_LOGV("releaseBufferLocked: slot=%d/%" PRIu64,
248 slot, mSlots[slot].mFrameNumber);
249 status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
250 display, eglFence, mSlots[slot].mFence);
251 if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
252 freeBufferLocked(slot);
253 }
254
255 mSlots[slot].mFence = Fence::NO_FENCE;
256
257 return err;
258 }
259
stillTracking(int slot,const sp<GraphicBuffer> graphicBuffer)260 bool ConsumerBase::stillTracking(int slot,
261 const sp<GraphicBuffer> graphicBuffer) {
262 if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
263 return false;
264 }
265 return (mSlots[slot].mGraphicBuffer != NULL &&
266 mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
267 }
268
269 } // namespace android
270