blob: d8ad224449a74413732ba6421bc20e979831e355 [file] [log] [blame]
Jesse Hall80e0a392013-03-15 12:32:10 -07001/*
2 * Copyright 2013 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#undef LOG_TAG
18#define LOG_TAG "BQInterposer"
19
20#include "BufferQueueInterposer.h"
21
22// ---------------------------------------------------------------------------
23namespace android {
24// ---------------------------------------------------------------------------
25
26#define BQI_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
27#define BQI_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
28#define BQI_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
29#define BQI_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
30#define BQI_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
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
38BufferQueueInterposer::BufferQueueInterposer(
39 const sp<IGraphicBufferProducer>& sink, const String8& name)
40: mSink(sink),
41 mName(name),
42 mAcquired(false)
43{
44 BQI_LOGV("BufferQueueInterposer sink=%p", sink.get());
45
46 // We need one additional dequeued buffer beyond what the source needs.
47 // To have more than one (the default), we must call setBufferCount. But
48 // we have no way of knowing what the sink has set as the minimum buffer
49 // count, so if we just call setBufferCount(3) it may fail (and does, on
50 // one device using a video encoder sink). So far on the devices we care
51 // about, this is the smallest value that works.
52 //
53 // TODO: Change IGraphicBufferProducer and implementations to support this.
54 // Maybe change it so both the consumer and producer declare how many
55 // buffers they need, and the IGBP adds them? Then BQInterposer would just
56 // add 1 to the source's buffer count.
57 mSink->setBufferCount(6);
58}
59
60BufferQueueInterposer::~BufferQueueInterposer() {
61 Mutex::Autolock lock(mMutex);
62 flushQueuedBuffersLocked();
63 BQI_LOGV("~BufferQueueInterposer");
64}
65
66status_t BufferQueueInterposer::requestBuffer(int slot,
67 sp<GraphicBuffer>* outBuf) {
68 BQI_LOGV("requestBuffer slot=%d", slot);
69 Mutex::Autolock lock(mMutex);
70
71 if (size_t(slot) >= mBuffers.size()) {
72 size_t size = mBuffers.size();
73 mBuffers.insertAt(size, size - slot + 1);
74 }
75 sp<GraphicBuffer>& buf = mBuffers.editItemAt(slot);
76
77 status_t result = mSink->requestBuffer(slot, &buf);
78 *outBuf = buf;
79 return result;
80}
81
82status_t BufferQueueInterposer::setBufferCount(int bufferCount) {
83 BQI_LOGV("setBufferCount count=%d", bufferCount);
84 Mutex::Autolock lock(mMutex);
85
86 bufferCount += 1;
87
88 status_t result = flushQueuedBuffersLocked();
89 if (result != NO_ERROR)
90 return result;
91
92 result = mSink->setBufferCount(bufferCount);
93 if (result != NO_ERROR)
94 return result;
95
96 for (size_t i = 0; i < mBuffers.size(); i++)
97 mBuffers.editItemAt(i).clear();
98 ssize_t n = mBuffers.resize(bufferCount);
99 result = (n < 0) ? n : result;
100
101 return result;
102}
103
104status_t BufferQueueInterposer::dequeueBuffer(int* slot, sp<Fence>* fence,
105 uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
106 BQI_LOGV("dequeueBuffer %ux%u fmt=%u usage=%#x", w, h, format, usage);
107 return mSink->dequeueBuffer(slot, fence, w, h, format, usage);
108}
109
110status_t BufferQueueInterposer::queueBuffer(int slot,
111 const QueueBufferInput& input, QueueBufferOutput* output) {
112 BQI_LOGV("queueBuffer slot=%d", slot);
113 Mutex::Autolock lock(mMutex);
114 mQueue.push(QueuedBuffer(slot, input));
115 *output = mQueueBufferOutput;
116 return NO_ERROR;
117}
118
119void BufferQueueInterposer::cancelBuffer(int slot, const sp<Fence>& fence) {
120 BQI_LOGV("cancelBuffer slot=%d", slot);
121 mSink->cancelBuffer(slot, fence);
122}
123
124int BufferQueueInterposer::query(int what, int* value) {
125 BQI_LOGV("query what=%d", what);
126 return mSink->query(what, value);
127}
128
129status_t BufferQueueInterposer::setSynchronousMode(bool enabled) {
130 BQI_LOGV("setSynchronousMode %s", enabled ? "true" : "false");
131 return mSink->setSynchronousMode(enabled);
132}
133
134status_t BufferQueueInterposer::connect(int api, QueueBufferOutput* output) {
135 BQI_LOGV("connect api=%d", api);
136 Mutex::Autolock lock(mMutex);
137 status_t result = mSink->connect(api, &mQueueBufferOutput);
138 if (result == NO_ERROR) {
139 *output = mQueueBufferOutput;
140 }
141 return result;
142}
143
144status_t BufferQueueInterposer::disconnect(int api) {
145 BQI_LOGV("disconnect: api=%d", api);
146 Mutex::Autolock lock(mMutex);
147 flushQueuedBuffersLocked();
148 return mSink->disconnect(api);
149}
150
151status_t BufferQueueInterposer::pullEmptyBuffer() {
152 status_t result;
153
154 int slot;
155 sp<Fence> fence;
156 result = dequeueBuffer(&slot, &fence, 0, 0, 0, 0);
157 if (result == IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
158 sp<GraphicBuffer> buffer;
159 result = requestBuffer(slot, &buffer);
160 } else if (result != NO_ERROR) {
161 return result;
162 }
163
164 uint32_t w, h, transformHint, numPendingBuffers;
165 mQueueBufferOutput.deflate(&w, &h, &transformHint, &numPendingBuffers);
166
167 IGraphicBufferProducer::QueueBufferInput qbi(0, Rect(w, h),
168 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, fence);
169 IGraphicBufferProducer::QueueBufferOutput qbo;
170 result = queueBuffer(slot, qbi, &qbo);
171 if (result != NO_ERROR)
172 return result;
173
174 return NO_ERROR;
175}
176
177status_t BufferQueueInterposer::acquireBuffer(sp<GraphicBuffer>* buf,
178 sp<Fence>* fence) {
179 Mutex::Autolock lock(mMutex);
180 if (mQueue.empty()) {
181 BQI_LOGV("acquireBuffer: no buffers available");
182 return NO_BUFFER_AVAILABLE;
183 }
184 if (mAcquired) {
185 BQI_LOGE("acquireBuffer: buffer already acquired");
186 return BUFFER_ALREADY_ACQUIRED;
187 }
188 BQI_LOGV("acquireBuffer: acquiring slot %d", mQueue[0].slot);
189
190 *buf = mBuffers[mQueue[0].slot];
191 *fence = mQueue[0].fence;
192 mAcquired = true;
193 return NO_ERROR;
194}
195
196status_t BufferQueueInterposer::releaseBuffer(const sp<Fence>& fence) {
197 Mutex::Autolock lock(mMutex);
198 if (!mAcquired) {
199 BQI_LOGE("releaseBuffer: releasing a non-acquired buffer");
200 return BUFFER_NOT_ACQUIRED;
201 }
202 BQI_LOGV("releaseBuffer: releasing slot %d to sink", mQueue[0].slot);
203
204 const QueuedBuffer& b = mQueue[0];
205 status_t result = mSink->queueBuffer(b.slot,
206 QueueBufferInput(b.timestamp, b.crop, b.scalingMode,
207 b.transform, b.fence),
208 &mQueueBufferOutput);
209 mQueue.removeAt(0);
210 mAcquired = false;
211
212 return result;
213}
214
215status_t BufferQueueInterposer::flushQueuedBuffersLocked() {
216 if (mAcquired) {
217 BQI_LOGE("flushQueuedBuffersLocked: buffer acquired, can't flush");
218 return INVALID_OPERATION;
219 }
220
221 status_t result = NO_ERROR;
222 for (size_t i = 0; i < mQueue.size(); i++) {
223 const QueuedBuffer& b = mQueue[i];
224 BQI_LOGV("flushing queued slot %d to sink", b.slot);
225 status_t err = mSink->queueBuffer(b.slot,
226 QueueBufferInput(b.timestamp, b.crop, b.scalingMode,
227 b.transform, b.fence),
228 &mQueueBufferOutput);
229 if (err != NO_ERROR && result == NO_ERROR) // latch first error
230 result = err;
231 }
232 mQueue.clear();
233 return result;
234}
235
236// ---------------------------------------------------------------------------
237} // namespace android
238// ---------------------------------------------------------------------------