blob: bf2539fb6c7af466483c0b9ef294e02ffc849352 [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
117 err = mBufferSlot[buf]->lock(
118 GraphicBuffer::USAGE_SW_READ_OFTEN,
119 b.mCrop,
120 &mBufferPointers[buf]);
121
122 if (mBufferPointers[buf] != NULL && err != OK) {
123 CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)", strerror(-err),
124 err);
125 return err;
126 }
127
128 nativeBuffer->data = reinterpret_cast<uint8_t*>(mBufferPointers[buf]);
129 nativeBuffer->width = mBufferSlot[buf]->getWidth();
130 nativeBuffer->height = mBufferSlot[buf]->getHeight();
131 nativeBuffer->format = mBufferSlot[buf]->getPixelFormat();
132 nativeBuffer->stride = mBufferSlot[buf]->getStride();
133
134 nativeBuffer->crop = b.mCrop;
135 nativeBuffer->transform = b.mTransform;
136 nativeBuffer->scalingMode = b.mScalingMode;
137 nativeBuffer->timestamp = b.mTimestamp;
138 nativeBuffer->frameNumber = b.mFrameNumber;
139
140 mCurrentLockedBuffers++;
141
142 return OK;
143}
144
145status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
146 Mutex::Autolock _l(mMutex);
147 int buf = 0;
148 status_t err;
149
150 void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data);
151 for (; buf < BufferQueue::NUM_BUFFER_SLOTS; buf++) {
152 if (bufPtr == mBufferPointers[buf]) break;
153 }
154 if (buf == BufferQueue::NUM_BUFFER_SLOTS) {
155 CC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
156 return BAD_VALUE;
157 }
158
159 mBufferPointers[buf] = NULL;
160 err = mBufferSlot[buf]->unlock();
161 if (err != OK) {
162 CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf);
163 return err;
164 }
Jesse Hallef194142012-06-14 14:45:17 -0700165 err = mBufferQueue->releaseBuffer(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
166 Fence::NO_FENCE);
Eino-Ville Talvalae41b3182012-04-16 17:54:33 -0700167 if (err == BufferQueue::STALE_BUFFER_SLOT) {
168 freeBufferLocked(buf);
169 } else if (err != OK) {
170 CC_LOGE("%s: Unable to release graphic buffer %d to queue", __FUNCTION__,
171 buf);
172 return err;
173 }
174
175 mCurrentLockedBuffers--;
176
177 return OK;
178}
179
180void CpuConsumer::setFrameAvailableListener(
181 const sp<FrameAvailableListener>& listener) {
182 CC_LOGV("setFrameAvailableListener");
183 Mutex::Autolock lock(mMutex);
184 mFrameAvailableListener = listener;
185}
186
187
188void CpuConsumer::onFrameAvailable() {
189 CC_LOGV("onFrameAvailable");
190 sp<FrameAvailableListener> listener;
191 { // scope for the lock
192 Mutex::Autolock _l(mMutex);
193 listener = mFrameAvailableListener;
194 }
195
196 if (listener != NULL) {
197 CC_LOGV("actually calling onFrameAvailable");
198 listener->onFrameAvailable();
199 }
200}
201
202void CpuConsumer::onBuffersReleased() {
203 CC_LOGV("onBuffersReleased");
204
205 Mutex::Autolock lock(mMutex);
206
207 uint32_t mask = 0;
208 mBufferQueue->getReleasedBuffers(&mask);
209 for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
210 if (mask & (1 << i)) {
211 freeBufferLocked(i);
212 }
213 }
214
215}
216
217status_t CpuConsumer::freeBufferLocked(int buf) {
218 status_t err = OK;
219
220 if (mBufferPointers[buf] != NULL) {
221 CC_LOGW("Buffer %d freed while locked by consumer", buf);
222 mBufferPointers[buf] = NULL;
223 err = mBufferSlot[buf]->unlock();
224 if (err != OK) {
225 CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf);
226 }
227 mCurrentLockedBuffers--;
228 }
229 mBufferSlot[buf] = NULL;
230 return err;
231}
232
233} // namespace android