Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2013 Mozilla Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
18 #define LOG_TAG "GonkConsumerBase"
19 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
20 //#define LOG_NDEBUG 0
22 #define EGL_EGLEXT_PROTOTYPES
24 #include <hardware/hardware.h>
26 #include <gui/IGraphicBufferAlloc.h>
27 #include <utils/Log.h>
28 #include <utils/String8.h>
30 #include "GonkConsumerBaseKK.h"
32 // Macros for including the GonkConsumerBase name in log messages
33 #define CB_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
34 #define CB_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
35 #define CB_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
36 #define CB_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
37 #define CB_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
39 namespace android {
41 // Get an ID that's unique within this process.
42 static int32_t createProcessUniqueId() {
43 static volatile int32_t globalCounter = 0;
44 return android_atomic_inc(&globalCounter);
45 }
47 GonkConsumerBase::GonkConsumerBase(const sp<GonkBufferQueue>& bufferQueue, bool controlledByApp) :
48 mAbandoned(false),
49 mConsumer(bufferQueue) {
50 // Choose a name using the PID and a process-unique ID.
51 mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
53 // Note that we can't create an sp<...>(this) in a ctor that will not keep a
54 // reference once the ctor ends, as that would cause the refcount of 'this'
55 // dropping to 0 at the end of the ctor. Since all we need is a wp<...>
56 // that's what we create.
57 wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
58 sp<IConsumerListener> proxy = new GonkBufferQueue::ProxyConsumerListener(listener);
60 status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
61 if (err != NO_ERROR) {
62 CB_LOGE("GonkConsumerBase: error connecting to GonkBufferQueue: %s (%d)",
63 strerror(-err), err);
64 } else {
65 mConsumer->setConsumerName(mName);
66 }
67 }
69 GonkConsumerBase::~GonkConsumerBase() {
70 CB_LOGV("~GonkConsumerBase");
71 Mutex::Autolock lock(mMutex);
73 // Verify that abandon() has been called before we get here. This should
74 // be done by GonkConsumerBase::onLastStrongRef(), but it's possible for a
75 // derived class to override that method and not call
76 // GonkConsumerBase::onLastStrongRef().
77 LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~GonkConsumerBase was called, but the "
78 "consumer is not abandoned!", mName.string());
79 }
81 void GonkConsumerBase::onLastStrongRef(const void* id) {
82 abandon();
83 }
85 void GonkConsumerBase::freeBufferLocked(int slotIndex) {
86 CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
87 mSlots[slotIndex].mGraphicBuffer = 0;
88 mSlots[slotIndex].mFence = Fence::NO_FENCE;
89 mSlots[slotIndex].mFrameNumber = 0;
90 }
92 // Used for refactoring, should not be in final interface
93 sp<GonkBufferQueue> GonkConsumerBase::getBufferQueue() const {
94 Mutex::Autolock lock(mMutex);
95 return mConsumer;
96 }
98 void GonkConsumerBase::onFrameAvailable() {
99 CB_LOGV("onFrameAvailable");
101 sp<FrameAvailableListener> listener;
102 { // scope for the lock
103 Mutex::Autolock lock(mMutex);
104 listener = mFrameAvailableListener.promote();
105 }
107 if (listener != NULL) {
108 CB_LOGV("actually calling onFrameAvailable");
109 listener->onFrameAvailable();
110 }
111 }
113 void GonkConsumerBase::onBuffersReleased() {
114 Mutex::Autolock lock(mMutex);
116 CB_LOGV("onBuffersReleased");
118 if (mAbandoned) {
119 // Nothing to do if we're already abandoned.
120 return;
121 }
123 uint32_t mask = 0;
124 mConsumer->getReleasedBuffers(&mask);
125 for (int i = 0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) {
126 if (mask & (1 << i)) {
127 freeBufferLocked(i);
128 }
129 }
130 }
132 void GonkConsumerBase::abandon() {
133 CB_LOGV("abandon");
134 Mutex::Autolock lock(mMutex);
136 if (!mAbandoned) {
137 abandonLocked();
138 mAbandoned = true;
139 }
140 }
142 void GonkConsumerBase::abandonLocked() {
143 CB_LOGV("abandonLocked");
144 for (int i =0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) {
145 freeBufferLocked(i);
146 }
147 // disconnect from the BufferQueue
148 mConsumer->consumerDisconnect();
149 mConsumer.clear();
150 }
152 void GonkConsumerBase::setFrameAvailableListener(
153 const wp<FrameAvailableListener>& listener) {
154 CB_LOGV("setFrameAvailableListener");
155 Mutex::Autolock lock(mMutex);
156 mFrameAvailableListener = listener;
157 }
159 void GonkConsumerBase::dump(String8& result) const {
160 dump(result, "");
161 }
163 void GonkConsumerBase::dump(String8& result, const char* prefix) const {
164 Mutex::Autolock _l(mMutex);
165 dumpLocked(result, prefix);
166 }
168 void GonkConsumerBase::dumpLocked(String8& result, const char* prefix) const {
169 result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
171 if (!mAbandoned) {
172 mConsumer->dump(result, prefix);
173 }
174 }
176 status_t GonkConsumerBase::acquireBufferLocked(IGonkGraphicBufferConsumer::BufferItem *item,
177 nsecs_t presentWhen) {
178 status_t err = mConsumer->acquireBuffer(item, presentWhen);
179 if (err != NO_ERROR) {
180 return err;
181 }
183 if (item->mGraphicBuffer != NULL) {
184 mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
185 }
187 mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
188 mSlots[item->mBuf].mFence = item->mFence;
190 CB_LOGV("acquireBufferLocked: -> slot=%d", item->mBuf);
192 return OK;
193 }
195 status_t GonkConsumerBase::addReleaseFence(int slot,
196 const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
197 Mutex::Autolock lock(mMutex);
198 return addReleaseFenceLocked(slot, graphicBuffer, fence);
199 }
201 status_t GonkConsumerBase::addReleaseFenceLocked(int slot,
202 const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
203 CB_LOGV("addReleaseFenceLocked: slot=%d", slot);
205 // If consumer no longer tracks this graphicBuffer, we can safely
206 // drop this fence, as it will never be received by the producer.
207 if (!stillTracking(slot, graphicBuffer)) {
208 return OK;
209 }
211 if (!mSlots[slot].mFence.get()) {
212 mSlots[slot].mFence = fence;
213 } else {
214 sp<Fence> mergedFence = Fence::merge(
215 String8::format("%.28s:%d", mName.string(), slot),
216 mSlots[slot].mFence, fence);
217 if (!mergedFence.get()) {
218 CB_LOGE("failed to merge release fences");
219 // synchronization is broken, the best we can do is hope fences
220 // signal in order so the new fence will act like a union
221 mSlots[slot].mFence = fence;
222 return BAD_VALUE;
223 }
224 mSlots[slot].mFence = mergedFence;
225 }
227 return OK;
228 }
230 status_t GonkConsumerBase::releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) {
231 // If consumer no longer tracks this graphicBuffer (we received a new
232 // buffer on the same slot), the buffer producer is definitely no longer
233 // tracking it.
234 if (!stillTracking(slot, graphicBuffer)) {
235 return OK;
236 }
238 CB_LOGV("releaseBufferLocked: slot=%d/%llu",
239 slot, mSlots[slot].mFrameNumber);
240 status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber, mSlots[slot].mFence);
241 if (err == GonkBufferQueue::STALE_BUFFER_SLOT) {
242 freeBufferLocked(slot);
243 }
245 mSlots[slot].mFence = Fence::NO_FENCE;
247 return err;
248 }
250 bool GonkConsumerBase::stillTracking(int slot,
251 const sp<GraphicBuffer> graphicBuffer) {
252 if (slot < 0 || slot >= GonkBufferQueue::NUM_BUFFER_SLOTS) {
253 return false;
254 }
255 return (mSlots[slot].mGraphicBuffer != NULL &&
256 mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
257 }
259 } // namespace android