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