1 /*
2 * Copyright (C) 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 #define ATRACE_TAG ATRACE_TAG_RS
18
19 #include "rsContext.h"
20 #include "rsAllocation.h"
21 #include "rs_hal.h"
22
23 #include <cutils/compiler.h>
24 #include <utils/Log.h>
25 #include "rsGrallocConsumer.h"
26 #include <gui/BufferItem.h>
27 #include <ui/GraphicBuffer.h>
28
29
30 namespace android {
31 namespace renderscript {
32
GrallocConsumer(Allocation * a,const sp<IGraphicBufferConsumer> & bq,int flags,uint32_t numAlloc)33 GrallocConsumer::GrallocConsumer(Allocation *a, const sp<IGraphicBufferConsumer>& bq, int flags, uint32_t numAlloc) :
34 ConsumerBase(bq, true)
35 {
36 mAlloc = new Allocation *[numAlloc];
37 mAcquiredBuffer = new AcquiredBuffer[numAlloc];
38 isIdxUsed = new bool[numAlloc];
39
40 mAlloc[0] = a;
41 isIdxUsed[0] = true;
42 mNumAlloc = numAlloc;
43 if (flags == 0) {
44 flags = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_RENDERSCRIPT;
45 } else {
46 flags |= GRALLOC_USAGE_RENDERSCRIPT;
47 }
48 mConsumer->setConsumerUsageBits(flags);
49 mConsumer->setMaxAcquiredBufferCount(numAlloc + 1);
50
51 uint32_t y = a->mHal.drvState.lod[0].dimY;
52 if (y < 1) y = 1;
53 mConsumer->setDefaultBufferSize(a->mHal.drvState.lod[0].dimX, y);
54
55 if (a->mHal.state.yuv) {
56 bq->setDefaultBufferFormat(a->mHal.state.yuv);
57 }
58 for (uint32_t i = 1; i < numAlloc; i++) {
59 isIdxUsed[i] = false;
60 }
61 //mBufferQueue->setConsumerName(name);
62 }
63
~GrallocConsumer()64 GrallocConsumer::~GrallocConsumer() {
65 delete[] mAlloc;
66 delete[] mAcquiredBuffer;
67 delete[] isIdxUsed;
68 }
69
70
71
lockNextBuffer(uint32_t idx)72 status_t GrallocConsumer::lockNextBuffer(uint32_t idx) {
73 Mutex::Autolock _l(mMutex);
74 status_t err;
75
76 if (idx >= mNumAlloc) {
77 ALOGE("Invalid buffer index: %d", idx);
78 return BAD_VALUE;
79 }
80
81 if (mAcquiredBuffer[idx].mSlot != BufferQueue::INVALID_BUFFER_SLOT) {
82 err = releaseAcquiredBufferLocked(idx);
83 if (err) {
84 return err;
85 }
86 }
87
88 BufferItem b;
89
90 err = acquireBufferLocked(&b, 0);
91 if (err != OK) {
92 if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
93 return BAD_VALUE;
94 } else {
95 ALOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
96 return err;
97 }
98 }
99
100 int slot = b.mSlot;
101
102 if (b.mFence.get()) {
103 err = b.mFence->waitForever("GrallocConsumer::lockNextBuffer");
104 if (err != OK) {
105 ALOGE("Failed to wait for fence of acquired buffer: %s (%d)",
106 strerror(-err), err);
107 return err;
108 }
109 }
110
111 void *bufferPointer = nullptr;
112 android_ycbcr ycbcr = android_ycbcr();
113
114 if (mSlots[slot].mGraphicBuffer->getPixelFormat() ==
115 HAL_PIXEL_FORMAT_YCbCr_420_888) {
116 err = mSlots[slot].mGraphicBuffer->lockYCbCr(
117 GraphicBuffer::USAGE_SW_READ_OFTEN,
118 b.mCrop,
119 &ycbcr);
120
121 if (err != OK) {
122 ALOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
123 strerror(-err), err);
124 return err;
125 }
126 bufferPointer = ycbcr.y;
127 } else {
128 err = mSlots[slot].mGraphicBuffer->lock(
129 GraphicBuffer::USAGE_SW_READ_OFTEN,
130 b.mCrop,
131 &bufferPointer);
132
133 if (err != OK) {
134 ALOGE("Unable to lock buffer for CPU reading: %s (%d)",
135 strerror(-err), err);
136 return err;
137 }
138 }
139
140 size_t lockedIdx = 0;
141 rsAssert(mAcquiredBuffer[idx].mSlot == BufferQueue::INVALID_BUFFER_SLOT);
142
143 mAcquiredBuffer[idx].mSlot = slot;
144 mAcquiredBuffer[idx].mBufferPointer = bufferPointer;
145 mAcquiredBuffer[idx].mGraphicBuffer = mSlots[slot].mGraphicBuffer;
146
147 mAlloc[idx]->mHal.drvState.lod[0].mallocPtr = reinterpret_cast<uint8_t*>(bufferPointer);
148 mAlloc[idx]->mHal.drvState.lod[0].stride = mSlots[slot].mGraphicBuffer->getStride() *
149 mAlloc[idx]->mHal.state.type->getElementSizeBytes();
150 mAlloc[idx]->mHal.state.nativeBuffer = mAcquiredBuffer[idx].mGraphicBuffer->getNativeBuffer();
151 mAlloc[idx]->mHal.state.timestamp = b.mTimestamp;
152
153 rsAssert(mAlloc[idx]->mHal.drvState.lod[0].dimX ==
154 mSlots[slot].mGraphicBuffer->getWidth());
155 rsAssert(mAlloc[idx]->mHal.drvState.lod[0].dimY ==
156 mSlots[slot].mGraphicBuffer->getHeight());
157
158 //mAlloc->format = mSlots[buf].mGraphicBuffer->getPixelFormat();
159
160 //mAlloc->crop = b.mCrop;
161 //mAlloc->transform = b.mTransform;
162 //mAlloc->scalingMode = b.mScalingMode;
163 //mAlloc->frameNumber = b.mFrameNumber;
164
165 // For YUV Allocations, we need to populate the drvState with details of how
166 // the data is layed out.
167 // RenderScript requests a buffer in the YCbCr_420_888 format.
168 // The Camera HAL can return a buffer of YCbCr_420_888 or YV12, regardless
169 // of the requested format.
170 // mHal.state.yuv contains the requested format,
171 // mGraphicBuffer->getPixelFormat() is the returned format.
172 if (mAlloc[idx]->mHal.state.yuv == HAL_PIXEL_FORMAT_YCbCr_420_888) {
173 const int yWidth = mAlloc[idx]->mHal.drvState.lod[0].dimX;
174 const int yHeight = mAlloc[idx]->mHal.drvState.lod[0].dimY;
175
176 if (mSlots[slot].mGraphicBuffer->getPixelFormat() ==
177 HAL_PIXEL_FORMAT_YCbCr_420_888) {
178 const int cWidth = yWidth / 2;
179 const int cHeight = yHeight / 2;
180
181 mAlloc[idx]->mHal.drvState.lod[1].dimX = cWidth;
182 mAlloc[idx]->mHal.drvState.lod[1].dimY = cHeight;
183 mAlloc[idx]->mHal.drvState.lod[2].dimX = cWidth;
184 mAlloc[idx]->mHal.drvState.lod[2].dimY = cHeight;
185
186 mAlloc[idx]->mHal.drvState.lod[0].mallocPtr = ycbcr.y;
187 mAlloc[idx]->mHal.drvState.lod[1].mallocPtr = ycbcr.cb;
188 mAlloc[idx]->mHal.drvState.lod[2].mallocPtr = ycbcr.cr;
189
190 mAlloc[idx]->mHal.drvState.lod[0].stride = ycbcr.ystride;
191 mAlloc[idx]->mHal.drvState.lod[1].stride = ycbcr.cstride;
192 mAlloc[idx]->mHal.drvState.lod[2].stride = ycbcr.cstride;
193
194 mAlloc[idx]->mHal.drvState.yuv.shift = 1;
195 mAlloc[idx]->mHal.drvState.yuv.step = ycbcr.chroma_step;
196 mAlloc[idx]->mHal.drvState.lodCount = 3;
197 } else if (mSlots[slot].mGraphicBuffer->getPixelFormat() ==
198 HAL_PIXEL_FORMAT_YV12) {
199 // For YV12, the data layout is Y, followed by Cr, followed by Cb;
200 // for YCbCr_420_888, it's Y, followed by Cb, followed by Cr.
201 // RenderScript assumes lod[0] is Y, lod[1] is Cb, and lod[2] is Cr.
202 const int cWidth = yWidth / 2;
203 const int cHeight = yHeight / 2;
204
205 mAlloc[idx]->mHal.drvState.lod[1].dimX = cWidth;
206 mAlloc[idx]->mHal.drvState.lod[1].dimY = cHeight;
207 mAlloc[idx]->mHal.drvState.lod[2].dimX = cWidth;
208 mAlloc[idx]->mHal.drvState.lod[2].dimY = cHeight;
209
210 size_t yStride = rsRound(yWidth *
211 mAlloc[idx]->mHal.state.type->getElementSizeBytes(), 16);
212 size_t cStride = rsRound(yStride >> 1, 16);
213
214 uint8_t *yPtr = (uint8_t *)mAlloc[idx]->mHal.drvState.lod[0].mallocPtr;
215 uint8_t *crPtr = yPtr + yStride * yHeight;
216 uint8_t *cbPtr = crPtr + cStride * cHeight;
217
218 mAlloc[idx]->mHal.drvState.lod[1].mallocPtr = cbPtr;
219 mAlloc[idx]->mHal.drvState.lod[2].mallocPtr = crPtr;
220
221 mAlloc[idx]->mHal.drvState.lod[0].stride = yStride;
222 mAlloc[idx]->mHal.drvState.lod[1].stride = cStride;
223 mAlloc[idx]->mHal.drvState.lod[2].stride = cStride;
224
225 mAlloc[idx]->mHal.drvState.yuv.shift = 1;
226 mAlloc[idx]->mHal.drvState.yuv.step = 1;
227 mAlloc[idx]->mHal.drvState.lodCount = 3;
228 } else {
229 ALOGD("Unrecognized format: %d",
230 mSlots[slot].mGraphicBuffer->getPixelFormat());
231 }
232 }
233
234 return OK;
235 }
236
unlockBuffer(uint32_t idx)237 status_t GrallocConsumer::unlockBuffer(uint32_t idx) {
238 Mutex::Autolock _l(mMutex);
239 return releaseAcquiredBufferLocked(idx);
240 }
241
releaseAcquiredBufferLocked(uint32_t idx)242 status_t GrallocConsumer::releaseAcquiredBufferLocked(uint32_t idx) {
243 status_t err;
244
245 if (idx >= mNumAlloc) {
246 ALOGE("Invalid buffer index: %d", idx);
247 return BAD_VALUE;
248 }
249 if (mAcquiredBuffer[idx].mGraphicBuffer == nullptr) {
250 return OK;
251 }
252
253 err = mAcquiredBuffer[idx].mGraphicBuffer->unlock();
254 if (err != OK) {
255 ALOGE("%s: Unable to unlock graphic buffer", __FUNCTION__);
256 return err;
257 }
258 int buf = mAcquiredBuffer[idx].mSlot;
259
260 // release the buffer if it hasn't already been freed by the BufferQueue.
261 // This can happen, for example, when the producer of this buffer
262 // disconnected after this buffer was acquired.
263 if (CC_LIKELY(mAcquiredBuffer[idx].mGraphicBuffer ==
264 mSlots[buf].mGraphicBuffer)) {
265 releaseBufferLocked(
266 buf, mAcquiredBuffer[idx].mGraphicBuffer,
267 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
268 }
269
270 mAcquiredBuffer[idx].mSlot = BufferQueue::INVALID_BUFFER_SLOT;
271 mAcquiredBuffer[idx].mBufferPointer = nullptr;
272 mAcquiredBuffer[idx].mGraphicBuffer.clear();
273 return OK;
274 }
275
getNextAvailableIdx(Allocation * a)276 uint32_t GrallocConsumer::getNextAvailableIdx(Allocation *a) {
277 for (uint32_t i = 0; i < mNumAlloc; i++) {
278 if (isIdxUsed[i] == false) {
279 mAlloc[i] = a;
280 isIdxUsed[i] = true;
281 return i;
282 }
283 }
284 return mNumAlloc;
285 }
286
releaseIdx(uint32_t idx)287 bool GrallocConsumer::releaseIdx(uint32_t idx) {
288 if (idx >= mNumAlloc) {
289 ALOGE("Invalid buffer index: %d", idx);
290 return false;
291 }
292 if (isIdxUsed[idx] == false) {
293 ALOGV("Buffer index already released: %d", idx);
294 return true;
295 }
296 status_t err;
297 err = unlockBuffer(idx);
298 if (err != OK) {
299 ALOGE("Unable to unlock graphic buffer");
300 return false;
301 }
302 mAlloc[idx] = nullptr;
303 isIdxUsed[idx] = false;
304 return true;
305 }
306
307 } // namespace renderscript
308 } // namespace android
309