• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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