blob: 8acdfed8f58a6449611ce428609deeded651dc3c [file] [log] [blame]
Jamie Gennis1a4d8832012-08-02 20:11:05 -07001/*
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
Mark Salyzyn91100452014-06-09 14:27:45 -070017#include <inttypes.h>
18
Jamie Gennis1a4d8832012-08-02 20:11:05 -070019#define LOG_TAG "ConsumerBase"
20#define ATRACE_TAG ATRACE_TAG_GRAPHICS
21//#define LOG_NDEBUG 0
22
Jamie Gennis1a4d8832012-08-02 20:11:05 -070023#define EGL_EGLEXT_PROTOTYPES
24
25#include <EGL/egl.h>
26#include <EGL/eglext.h>
27
28#include <hardware/hardware.h>
29
Mathias Agopiane9e9fe42017-02-28 16:25:16 -080030#include <cutils/atomic.h>
31
Dan Stozacf3834d2015-03-11 14:04:22 -070032#include <gui/BufferItem.h>
Jamie Gennis1a4d8832012-08-02 20:11:05 -070033#include <gui/IGraphicBufferAlloc.h>
34#include <gui/ISurfaceComposer.h>
35#include <gui/SurfaceComposerClient.h>
36#include <gui/ConsumerBase.h>
37
38#include <private/gui/ComposerService.h>
39
40#include <utils/Log.h>
41#include <utils/String8.h>
42#include <utils/Trace.h>
43
44// Macros for including the ConsumerBase name in log messages
Dan Albert8b491252014-09-08 18:53:39 -070045#define CB_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
Dan Stoza3be1c6b2014-11-18 10:24:03 -080046//#define CB_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
47//#define CB_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
48//#define CB_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
Dan Albert8b491252014-09-08 18:53:39 -070049#define CB_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
Jamie Gennis1a4d8832012-08-02 20:11:05 -070050
51namespace android {
52
53// Get an ID that's unique within this process.
54static int32_t createProcessUniqueId() {
55 static volatile int32_t globalCounter = 0;
56 return android_atomic_inc(&globalCounter);
57}
58
Mathias Agopiandb89edc2013-08-02 01:40:18 -070059ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
Jamie Gennis9fea3422012-08-07 18:03:04 -070060 mAbandoned(false),
Brian Anderson3546a3f2016-07-14 11:51:14 -070061 mConsumer(bufferQueue),
62 mPrevFinalReleaseFence(Fence::NO_FENCE) {
Jamie Gennis1a4d8832012-08-02 20:11:05 -070063 // Choose a name using the PID and a process-unique ID.
64 mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
65
66 // Note that we can't create an sp<...>(this) in a ctor that will not keep a
67 // reference once the ctor ends, as that would cause the refcount of 'this'
68 // dropping to 0 at the end of the ctor. Since all we need is a wp<...>
69 // that's what we create.
Mathias Agopiana4e19522013-07-31 20:09:53 -070070 wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
71 sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
Jamie Gennis1a4d8832012-08-02 20:11:05 -070072
Mathias Agopiandb89edc2013-08-02 01:40:18 -070073 status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
Jamie Gennis1a4d8832012-08-02 20:11:05 -070074 if (err != NO_ERROR) {
Andy McFadden2adaf042012-12-18 09:49:45 -080075 CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
Jamie Gennis1a4d8832012-08-02 20:11:05 -070076 strerror(-err), err);
77 } else {
Mathias Agopiandb89edc2013-08-02 01:40:18 -070078 mConsumer->setConsumerName(mName);
Jamie Gennis1a4d8832012-08-02 20:11:05 -070079 }
80}
81
82ConsumerBase::~ConsumerBase() {
Jamie Gennisad669b02013-04-05 16:41:27 -070083 CB_LOGV("~ConsumerBase");
Pablo Ceballos22b57022016-02-19 17:41:54 -080084 Mutex::Autolock lock(mMutex);
Pablo Ceballose07e3e52016-03-15 15:07:54 -070085
Jamie Gennisad669b02013-04-05 16:41:27 -070086 // Verify that abandon() has been called before we get here. This should
87 // be done by ConsumerBase::onLastStrongRef(), but it's possible for a
88 // derived class to override that method and not call
89 // ConsumerBase::onLastStrongRef().
90 LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~ConsumerBase was called, but the "
91 "consumer is not abandoned!", mName.string());
92}
93
Igor Murashkin7d2d1602013-11-12 18:02:20 -080094void ConsumerBase::onLastStrongRef(const void* id __attribute__((unused))) {
Jamie Gennis1a4d8832012-08-02 20:11:05 -070095 abandon();
96}
97
98void ConsumerBase::freeBufferLocked(int slotIndex) {
99 CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
100 mSlots[slotIndex].mGraphicBuffer = 0;
Jamie Gennis1df8c342012-12-20 14:05:45 -0800101 mSlots[slotIndex].mFence = Fence::NO_FENCE;
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700102 mSlots[slotIndex].mFrameNumber = 0;
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700103}
104
Dan Stoza8dc55392014-11-04 11:37:46 -0800105void ConsumerBase::onFrameAvailable(const BufferItem& item) {
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700106 CB_LOGV("onFrameAvailable");
107
108 sp<FrameAvailableListener> listener;
109 { // scope for the lock
110 Mutex::Autolock lock(mMutex);
Igor Murashkina4a31492012-10-29 13:36:11 -0700111 listener = mFrameAvailableListener.promote();
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700112 }
113
114 if (listener != NULL) {
115 CB_LOGV("actually calling onFrameAvailable");
Dan Stoza8dc55392014-11-04 11:37:46 -0800116 listener->onFrameAvailable(item);
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700117 }
118}
119
Dan Stozadc13c5b2015-05-11 15:33:01 -0700120void ConsumerBase::onFrameReplaced(const BufferItem &item) {
121 CB_LOGV("onFrameReplaced");
122
123 sp<FrameAvailableListener> listener;
124 {
125 Mutex::Autolock lock(mMutex);
126 listener = mFrameAvailableListener.promote();
127 }
128
129 if (listener != NULL) {
130 CB_LOGV("actually calling onFrameReplaced");
131 listener->onFrameReplaced(item);
132 }
133}
134
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700135void ConsumerBase::onBuffersReleased() {
Jamie Gennis72c3f7d2012-12-07 00:41:56 -0800136 Mutex::Autolock lock(mMutex);
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700137
Jamie Gennis72c3f7d2012-12-07 00:41:56 -0800138 CB_LOGV("onBuffersReleased");
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700139
Jamie Gennis72c3f7d2012-12-07 00:41:56 -0800140 if (mAbandoned) {
141 // Nothing to do if we're already abandoned.
142 return;
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700143 }
144
Dan Stozafebd4f42014-04-09 16:14:51 -0700145 uint64_t mask = 0;
Mathias Agopiandb89edc2013-08-02 01:40:18 -0700146 mConsumer->getReleasedBuffers(&mask);
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700147 for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
Dan Stozafebd4f42014-04-09 16:14:51 -0700148 if (mask & (1ULL << i)) {
Jamie Gennis72c3f7d2012-12-07 00:41:56 -0800149 freeBufferLocked(i);
150 }
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700151 }
152}
153
Jesse Hall399184a2014-03-03 15:42:54 -0800154void ConsumerBase::onSidebandStreamChanged() {
155}
156
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700157void ConsumerBase::abandon() {
158 CB_LOGV("abandon");
159 Mutex::Autolock lock(mMutex);
160
161 if (!mAbandoned) {
162 abandonLocked();
163 mAbandoned = true;
164 }
165}
166
167void ConsumerBase::abandonLocked() {
Brian Carlstrom83b1e682016-03-12 16:07:59 -0800168 CB_LOGV("abandonLocked");
Pablo Ceballos65d9f6d2016-05-04 13:59:35 -0700169 if (mAbandoned) {
170 CB_LOGE("abandonLocked: ConsumerBase is abandoned!");
171 return;
172 }
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700173 for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
174 freeBufferLocked(i);
175 }
176 // disconnect from the BufferQueue
Mathias Agopiandb89edc2013-08-02 01:40:18 -0700177 mConsumer->consumerDisconnect();
178 mConsumer.clear();
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700179}
180
John Recke4783052015-05-14 15:55:11 -0700181bool ConsumerBase::isAbandoned() {
182 Mutex::Autolock _l(mMutex);
183 return mAbandoned;
184}
185
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700186void ConsumerBase::setFrameAvailableListener(
Igor Murashkina4a31492012-10-29 13:36:11 -0700187 const wp<FrameAvailableListener>& listener) {
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700188 CB_LOGV("setFrameAvailableListener");
189 Mutex::Autolock lock(mMutex);
190 mFrameAvailableListener = listener;
191}
192
Dan Stoza634f5ee2015-04-03 14:22:05 -0700193status_t ConsumerBase::detachBuffer(int slot) {
194 CB_LOGV("detachBuffer");
195 Mutex::Autolock lock(mMutex);
196
Pablo Ceballos65d9f6d2016-05-04 13:59:35 -0700197 if (mAbandoned) {
198 CB_LOGE("detachBuffer: ConsumerBase is abandoned!");
199 return NO_INIT;
200 }
201
Dan Stoza634f5ee2015-04-03 14:22:05 -0700202 status_t result = mConsumer->detachBuffer(slot);
203 if (result != NO_ERROR) {
204 CB_LOGE("Failed to detach buffer: %d", result);
205 return result;
206 }
207
208 freeBufferLocked(slot);
209
210 return result;
211}
212
Michael Lentine847f11e2015-05-18 13:41:23 -0700213status_t ConsumerBase::setDefaultBufferSize(uint32_t width, uint32_t height) {
214 Mutex::Autolock _l(mMutex);
Pablo Ceballos65d9f6d2016-05-04 13:59:35 -0700215 if (mAbandoned) {
216 CB_LOGE("setDefaultBufferSize: ConsumerBase is abandoned!");
217 return NO_INIT;
218 }
Michael Lentine847f11e2015-05-18 13:41:23 -0700219 return mConsumer->setDefaultBufferSize(width, height);
220}
221
222status_t ConsumerBase::setDefaultBufferFormat(PixelFormat defaultFormat) {
223 Mutex::Autolock _l(mMutex);
Pablo Ceballos65d9f6d2016-05-04 13:59:35 -0700224 if (mAbandoned) {
225 CB_LOGE("setDefaultBufferFormat: ConsumerBase is abandoned!");
226 return NO_INIT;
227 }
Michael Lentine847f11e2015-05-18 13:41:23 -0700228 return mConsumer->setDefaultBufferFormat(defaultFormat);
229}
230
231status_t ConsumerBase::setDefaultBufferDataSpace(
232 android_dataspace defaultDataSpace) {
233 Mutex::Autolock _l(mMutex);
Pablo Ceballos65d9f6d2016-05-04 13:59:35 -0700234 if (mAbandoned) {
235 CB_LOGE("setDefaultBufferDataSpace: ConsumerBase is abandoned!");
236 return NO_INIT;
237 }
Michael Lentine847f11e2015-05-18 13:41:23 -0700238 return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
239}
240
Dan Stozae77c7662016-05-13 11:37:28 -0700241status_t ConsumerBase::getOccupancyHistory(bool forceFlush,
242 std::vector<OccupancyTracker::Segment>* outHistory) {
243 Mutex::Autolock _l(mMutex);
244 if (mAbandoned) {
245 CB_LOGE("getOccupancyHistory: ConsumerBase is abandoned!");
246 return NO_INIT;
247 }
248 return mConsumer->getOccupancyHistory(forceFlush, outHistory);
249}
250
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -0700251status_t ConsumerBase::discardFreeBuffers() {
252 Mutex::Autolock _l(mMutex);
253 if (mAbandoned) {
254 CB_LOGE("discardFreeBuffers: ConsumerBase is abandoned!");
255 return NO_INIT;
256 }
257 return mConsumer->discardFreeBuffers();
258}
259
Colin Crossdc782512016-09-26 18:10:16 -0700260void ConsumerBase::dumpState(String8& result) const {
261 dumpState(result, "");
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700262}
263
Colin Crossdc782512016-09-26 18:10:16 -0700264void ConsumerBase::dumpState(String8& result, const char* prefix) const {
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700265 Mutex::Autolock _l(mMutex);
Mathias Agopian74d211a2013-04-22 16:55:35 +0200266 dumpLocked(result, prefix);
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700267}
268
Mathias Agopian74d211a2013-04-22 16:55:35 +0200269void ConsumerBase::dumpLocked(String8& result, const char* prefix) const {
270 result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700271
272 if (!mAbandoned) {
Colin Crossdc782512016-09-26 18:10:16 -0700273 mConsumer->dumpState(result, prefix);
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700274 }
275}
276
Dan Stozacf3834d2015-03-11 14:04:22 -0700277status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
Dan Stozaa4650a52015-05-12 12:56:16 -0700278 nsecs_t presentWhen, uint64_t maxFrameNumber) {
Pablo Ceballos65d9f6d2016-05-04 13:59:35 -0700279 if (mAbandoned) {
280 CB_LOGE("acquireBufferLocked: ConsumerBase is abandoned!");
281 return NO_INIT;
282 }
283
Dan Stozaa4650a52015-05-12 12:56:16 -0700284 status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700285 if (err != NO_ERROR) {
286 return err;
287 }
288
289 if (item->mGraphicBuffer != NULL) {
Pablo Ceballos47650f42015-08-04 16:38:17 -0700290 mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700291 }
292
Pablo Ceballos47650f42015-08-04 16:38:17 -0700293 mSlots[item->mSlot].mFrameNumber = item->mFrameNumber;
294 mSlots[item->mSlot].mFence = item->mFence;
Jamie Gennisb2725412012-09-05 20:09:05 -0700295
Mark Salyzyn91100452014-06-09 14:27:45 -0700296 CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
Pablo Ceballos47650f42015-08-04 16:38:17 -0700297 item->mSlot, item->mFrameNumber);
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700298
299 return OK;
300}
301
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700302status_t ConsumerBase::addReleaseFence(int slot,
303 const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
Jesse Hall9504eb92012-10-05 14:34:21 -0700304 Mutex::Autolock lock(mMutex);
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700305 return addReleaseFenceLocked(slot, graphicBuffer, fence);
Jesse Hall9504eb92012-10-05 14:34:21 -0700306}
307
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700308status_t ConsumerBase::addReleaseFenceLocked(int slot,
309 const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
Jesse Hall9504eb92012-10-05 14:34:21 -0700310 CB_LOGV("addReleaseFenceLocked: slot=%d", slot);
Jamie Gennisb2725412012-09-05 20:09:05 -0700311
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700312 // If consumer no longer tracks this graphicBuffer, we can safely
313 // drop this fence, as it will never be received by the producer.
314 if (!stillTracking(slot, graphicBuffer)) {
315 return OK;
316 }
317
Jamie Gennisb2725412012-09-05 20:09:05 -0700318 if (!mSlots[slot].mFence.get()) {
319 mSlots[slot].mFence = fence;
Matthew Bouyack377c2032016-10-07 15:06:15 -0700320 return OK;
321 }
322
Dan Stozaa34320a2017-02-16 14:55:03 -0800323 auto status = mSlots[slot].mFence->getStatus();
Matthew Bouyack377c2032016-10-07 15:06:15 -0700324
Dan Stozaa34320a2017-02-16 14:55:03 -0800325 if (status == Fence::Status::Invalid) {
Matthew Bouyack377c2032016-10-07 15:06:15 -0700326 CB_LOGE("fence has invalid state");
327 return BAD_VALUE;
328 }
329
Dan Stozaa34320a2017-02-16 14:55:03 -0800330 if (status == Fence::Status::Signaled) {
Matthew Bouyack377c2032016-10-07 15:06:15 -0700331 mSlots[slot].mFence = fence;
Dan Stozaa34320a2017-02-16 14:55:03 -0800332 } else { // status == Fence::Status::Unsignaled
Matthew Bouyackfd4c8c32016-10-07 14:26:47 -0700333 char fenceName[32] = {};
334 snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot);
Jamie Gennisb2725412012-09-05 20:09:05 -0700335 sp<Fence> mergedFence = Fence::merge(
Matthew Bouyackfd4c8c32016-10-07 14:26:47 -0700336 fenceName, mSlots[slot].mFence, fence);
Jamie Gennisb2725412012-09-05 20:09:05 -0700337 if (!mergedFence.get()) {
338 CB_LOGE("failed to merge release fences");
339 // synchronization is broken, the best we can do is hope fences
340 // signal in order so the new fence will act like a union
341 mSlots[slot].mFence = fence;
342 return BAD_VALUE;
343 }
344 mSlots[slot].mFence = mergedFence;
345 }
346
347 return OK;
348}
349
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700350status_t ConsumerBase::releaseBufferLocked(
351 int slot, const sp<GraphicBuffer> graphicBuffer,
352 EGLDisplay display, EGLSyncKHR eglFence) {
Pablo Ceballos65d9f6d2016-05-04 13:59:35 -0700353 if (mAbandoned) {
354 CB_LOGE("releaseBufferLocked: ConsumerBase is abandoned!");
355 return NO_INIT;
356 }
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700357 // If consumer no longer tracks this graphicBuffer (we received a new
358 // buffer on the same slot), the buffer producer is definitely no longer
359 // tracking it.
360 if (!stillTracking(slot, graphicBuffer)) {
361 return OK;
362 }
363
Mark Salyzyn91100452014-06-09 14:27:45 -0700364 CB_LOGV("releaseBufferLocked: slot=%d/%" PRIu64,
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700365 slot, mSlots[slot].mFrameNumber);
Mathias Agopiandb89edc2013-08-02 01:40:18 -0700366 status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700367 display, eglFence, mSlots[slot].mFence);
Igor Murashkin7d2d1602013-11-12 18:02:20 -0800368 if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700369 freeBufferLocked(slot);
370 }
371
Brian Anderson3546a3f2016-07-14 11:51:14 -0700372 mPrevFinalReleaseFence = mSlots[slot].mFence;
Jamie Gennis1df8c342012-12-20 14:05:45 -0800373 mSlots[slot].mFence = Fence::NO_FENCE;
Jamie Gennis1a4d8832012-08-02 20:11:05 -0700374
375 return err;
376}
377
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700378bool ConsumerBase::stillTracking(int slot,
379 const sp<GraphicBuffer> graphicBuffer) {
380 if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
381 return false;
382 }
383 return (mSlots[slot].mGraphicBuffer != NULL &&
384 mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
385}
386
Andy McFadden2adaf042012-12-18 09:49:45 -0800387} // namespace android