blob: 513828c375168338ee48b4ae9ea7dd6ea893d79b [file] [log] [blame]
Eino-Ville Talvalae41b3182012-04-16 17:54:33 -07001/*
2 * Copyright (C) 2012 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_NDEBUG 0
18#define LOG_TAG "CpuConsumer"
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20#include <utils/Log.h>
21
22#include <gui/CpuConsumer.h>
23
24#define CC_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
25#define CC_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
26#define CC_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
27#define CC_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
28#define CC_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
29
30namespace android {
31
32// Get an ID that's unique within this process.
33static int32_t createProcessUniqueId() {
34 static volatile int32_t globalCounter = 0;
35 return android_atomic_inc(&globalCounter);
36}
37
38CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) :
39 mMaxLockedBuffers(maxLockedBuffers),
40 mCurrentLockedBuffers(0)
41{
42 mName = String8::format("cc-unnamed-%d-%d", getpid(),
43 createProcessUniqueId());
44
45 for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
46 mBufferPointers[i] = NULL;
47 }
48
49 mBufferQueue = new BufferQueue(true);
50
51 wp<BufferQueue::ConsumerListener> listener;
52 sp<BufferQueue::ConsumerListener> proxy;
53 listener = static_cast<BufferQueue::ConsumerListener*>(this);
54 proxy = new BufferQueue::ProxyConsumerListener(listener);
55
56 status_t err = mBufferQueue->consumerConnect(proxy);
57 if (err != NO_ERROR) {
58 ALOGE("CpuConsumer: error connecting to BufferQueue: %s (%d)",
59 strerror(-err), err);
60 } else {
61 mBufferQueue->setSynchronousMode(true);
62 mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
63 mBufferQueue->setConsumerName(mName);
64 }
65}
66
67CpuConsumer::~CpuConsumer()
68{
69 Mutex::Autolock _l(mMutex);
70 for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
71 freeBufferLocked(i);
72 }
73 mBufferQueue->consumerDisconnect();
74 mBufferQueue.clear();
75}
76
77void CpuConsumer::setName(const String8& name) {
78 Mutex::Autolock _l(mMutex);
79 mName = name;
80 mBufferQueue->setConsumerName(name);
81}
82
83status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
84 status_t err;
85
86 if (!nativeBuffer) return BAD_VALUE;
87 if (mCurrentLockedBuffers == mMaxLockedBuffers) {
88 return INVALID_OPERATION;
89 }
90
91 BufferQueue::BufferItem b;
92
93 Mutex::Autolock _l(mMutex);
94
95 err = mBufferQueue->acquireBuffer(&b);
96 if (err != OK) {
97 if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
98 return BAD_VALUE;
99 } else {
100 CC_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
101 return err;
102 }
103 }
104
105 int buf = b.mBuf;
106
107 if (b.mGraphicBuffer != NULL) {
108 if (mBufferPointers[buf] != NULL) {
109 CC_LOGE("Reallocation of buffer %d while in consumer use!", buf);
Jesse Hallef194142012-06-14 14:45:17 -0700110 mBufferQueue->releaseBuffer(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
111 Fence::NO_FENCE);
Eino-Ville Talvalae41b3182012-04-16 17:54:33 -0700112 return BAD_VALUE;
113 }
114 mBufferSlot[buf] = b.mGraphicBuffer;
115 }
116
Jesse Hallb42b1ac2012-06-28 14:27:53 -0700117 if (b.mFence.get()) {
118 err = b.mFence->wait(Fence::TIMEOUT_NEVER);
119 if (err != OK) {
120 CC_LOGE("Failed to wait for fence of acquired buffer: %s (%d)",
121 strerror(-err), err);
122 return err;
123 }
124 }
125
Eino-Ville Talvalae41b3182012-04-16 17:54:33 -0700126 err = mBufferSlot[buf]->lock(
127 GraphicBuffer::USAGE_SW_READ_OFTEN,
128 b.mCrop,
129 &mBufferPointers[buf]);
130
131 if (mBufferPointers[buf] != NULL && err != OK) {
132 CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)", strerror(-err),
133 err);
134 return err;
135 }
136
137 nativeBuffer->data = reinterpret_cast<uint8_t*>(mBufferPointers[buf]);
138 nativeBuffer->width = mBufferSlot[buf]->getWidth();
139 nativeBuffer->height = mBufferSlot[buf]->getHeight();
140 nativeBuffer->format = mBufferSlot[buf]->getPixelFormat();
141 nativeBuffer->stride = mBufferSlot[buf]->getStride();
142
143 nativeBuffer->crop = b.mCrop;
144 nativeBuffer->transform = b.mTransform;
145 nativeBuffer->scalingMode = b.mScalingMode;
146 nativeBuffer->timestamp = b.mTimestamp;
147 nativeBuffer->frameNumber = b.mFrameNumber;
148
149 mCurrentLockedBuffers++;
150
151 return OK;
152}
153
154status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
155 Mutex::Autolock _l(mMutex);
156 int buf = 0;
157 status_t err;
158
159 void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data);
160 for (; buf < BufferQueue::NUM_BUFFER_SLOTS; buf++) {
161 if (bufPtr == mBufferPointers[buf]) break;
162 }
163 if (buf == BufferQueue::NUM_BUFFER_SLOTS) {
164 CC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
165 return BAD_VALUE;
166 }
167
168 mBufferPointers[buf] = NULL;
169 err = mBufferSlot[buf]->unlock();
170 if (err != OK) {
171 CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf);
172 return err;
173 }
Jesse Hallef194142012-06-14 14:45:17 -0700174 err = mBufferQueue->releaseBuffer(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
175 Fence::NO_FENCE);
Eino-Ville Talvalae41b3182012-04-16 17:54:33 -0700176 if (err == BufferQueue::STALE_BUFFER_SLOT) {
177 freeBufferLocked(buf);
178 } else if (err != OK) {
179 CC_LOGE("%s: Unable to release graphic buffer %d to queue", __FUNCTION__,
180 buf);
181 return err;
182 }
183
184 mCurrentLockedBuffers--;
185
186 return OK;
187}
188
189void CpuConsumer::setFrameAvailableListener(
190 const sp<FrameAvailableListener>& listener) {
191 CC_LOGV("setFrameAvailableListener");
192 Mutex::Autolock lock(mMutex);
193 mFrameAvailableListener = listener;
194}
195
196
197void CpuConsumer::onFrameAvailable() {
198 CC_LOGV("onFrameAvailable");
199 sp<FrameAvailableListener> listener;
200 { // scope for the lock
201 Mutex::Autolock _l(mMutex);
202 listener = mFrameAvailableListener;
203 }
204
205 if (listener != NULL) {
206 CC_LOGV("actually calling onFrameAvailable");
207 listener->onFrameAvailable();
208 }
209}
210
211void CpuConsumer::onBuffersReleased() {
212 CC_LOGV("onBuffersReleased");
213
214 Mutex::Autolock lock(mMutex);
215
216 uint32_t mask = 0;
217 mBufferQueue->getReleasedBuffers(&mask);
218 for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
219 if (mask & (1 << i)) {
220 freeBufferLocked(i);
221 }
222 }
223
224}
225
226status_t CpuConsumer::freeBufferLocked(int buf) {
227 status_t err = OK;
228
229 if (mBufferPointers[buf] != NULL) {
230 CC_LOGW("Buffer %d freed while locked by consumer", buf);
231 mBufferPointers[buf] = NULL;
232 err = mBufferSlot[buf]->unlock();
233 if (err != OK) {
234 CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf);
235 }
236 mCurrentLockedBuffers--;
237 }
238 mBufferSlot[buf] = NULL;
239 return err;
240}
241
242} // namespace android