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 #include "rsAllocation.h"
18 #include "rsContext.h"
19 #include "rsGrallocConsumer.h"
20 #include "rs_hal.h"
21
22 namespace android {
23 namespace renderscript {
24
GrallocConsumer(const Context * rsc,Allocation * a,uint32_t numAlloc)25 GrallocConsumer::GrallocConsumer (const Context *rsc, Allocation *a, uint32_t numAlloc)
26 {
27 mCtx = rsc;
28 mAlloc = new Allocation *[numAlloc];
29 mAcquiredBuffer = new AcquiredBuffer[numAlloc];
30 isIdxUsed = new bool[numAlloc];
31
32 mAlloc[0] = a;
33 isIdxUsed[0] = true;
34 mNumAlloc = numAlloc;
35
36 uint32_t width = a->mHal.drvState.lod[0].dimX;
37 uint32_t height = a->mHal.drvState.lod[0].dimY;
38 if (height < 1) height = 1;
39
40 int32_t format = AIMAGE_FORMAT_RGBA_8888;
41 if (a->mHal.state.yuv) {
42 format = AIMAGE_FORMAT_YUV_420_888;
43 }
44
45 // GRALLOC_USAGE_RENDERSCRIPT
46 const uint64_t USAGE_RENDERSCRIPT = 0x00100000U;
47 uint64_t usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | USAGE_RENDERSCRIPT;
48 media_status_t ret = AImageReader_newWithUsage(
49 width, height, format, usage,
50 mNumAlloc, &mImgReader);
51 if (ret != AMEDIA_OK || mImgReader == nullptr) {
52 ALOGE("Error creating image reader. ret %d", ret);
53 }
54
55 ret = AImageReader_getWindow(mImgReader, &mNativeWindow);
56 if (ret != AMEDIA_OK || mNativeWindow == nullptr) {
57 ALOGE("Error creating native window. ret %d", ret);
58 }
59
60 mReaderCb = {this, GrallocConsumer::onFrameAvailable};
61 ret = AImageReader_setImageListener(mImgReader, &mReaderCb);
62
63 for (uint32_t i = 1; i < numAlloc; i++) {
64 isIdxUsed[i] = false;
65 }
66 }
67
~GrallocConsumer()68 GrallocConsumer::~GrallocConsumer() {
69 AImageReader_delete(mImgReader);
70 delete[] mAlloc;
71 delete[] mAcquiredBuffer;
72 delete[] isIdxUsed;
73 }
74
onFrameAvailable(void * obj,AImageReader * reader)75 void GrallocConsumer::onFrameAvailable(void* obj, AImageReader* reader) {
76 GrallocConsumer* consumer = (GrallocConsumer *) obj;
77 for (uint32_t i = 0; i < consumer->mNumAlloc; i++) {
78 if (consumer->mAlloc[i] != nullptr) {
79 intptr_t ip = (intptr_t)(consumer->mAlloc[i]);
80 consumer->mCtx->sendMessageToClient(&ip,
81 RS_MESSAGE_TO_CLIENT_NEW_BUFFER, 0, sizeof(ip), true);
82 }
83 }
84 }
85
getNativeWindow()86 ANativeWindow* GrallocConsumer::getNativeWindow() {
87 return mNativeWindow;
88 }
89
lockNextBuffer(uint32_t idx)90 media_status_t GrallocConsumer::lockNextBuffer(uint32_t idx) {
91 media_status_t ret;
92
93 if (idx >= mNumAlloc) {
94 ALOGE("Invalid buffer index: %d", idx);
95 return AMEDIA_ERROR_INVALID_PARAMETER;
96 }
97
98 if (mAcquiredBuffer[idx].mImg != nullptr) {
99 ret = unlockBuffer(idx);
100 if (ret != AMEDIA_OK) {
101 return ret;
102 }
103 }
104
105 ret = AImageReader_acquireNextImage(mImgReader, &(mAcquiredBuffer[idx].mImg));
106 if (ret != AMEDIA_OK || mAcquiredBuffer[idx].mImg == nullptr) {
107 ALOGE("%s: acquire image from reader %p failed! ret: %d, img %p",
108 __FUNCTION__, mImgReader, ret, mAcquiredBuffer[idx].mImg);
109 return ret;
110 }
111
112 AImage *img = mAcquiredBuffer[idx].mImg;
113 int32_t format = -1;
114 ret = AImage_getFormat(img, &format);
115 if (ret != AMEDIA_OK || format == -1) {
116 ALOGE("%s: get format for image %p failed! ret: %d, format %d",
117 __FUNCTION__, img, ret, format);
118 return ret;
119 }
120
121 if (format != AIMAGE_FORMAT_YUV_420_888 && format != AIMAGE_FORMAT_RGBA_8888) {
122 ALOGE("Format %d not supported", format);
123 return AMEDIA_ERROR_INVALID_OBJECT;
124 }
125
126 uint8_t *data = nullptr;
127 int dataLength = 0;
128 ret = AImage_getPlaneData(img, 0, &data, &dataLength);
129 if (ret != AMEDIA_OK || data == nullptr || dataLength <= 0) {
130 ALOGE("%s: get data for image %p failed! ret: %d, data %p, len %d",
131 __FUNCTION__, img, ret, data, dataLength);
132 return ret;
133 }
134
135 int64_t timestamp = -1;
136 ret = AImage_getTimestamp(img, ×tamp);
137 if (ret != AMEDIA_OK || timestamp == -1) {
138 ALOGE("%s: get timestamp for image %p failed! ret: %d",
139 __FUNCTION__, img, ret);
140 return ret;
141 }
142
143 int32_t rowstride = -1;
144 ret = AImage_getPlaneRowStride(img, 0, &rowstride);
145 if (ret != AMEDIA_OK || rowstride == -1) {
146 ALOGE("%s: get row stride for image %p failed! ret: %d, rowstride %d",
147 __FUNCTION__, img, ret, rowstride);
148 return ret;
149 }
150
151 AHardwareBuffer *hardwareBuffer = nullptr;
152 ret = AImage_getHardwareBuffer(img, &hardwareBuffer);
153 if (ret != AMEDIA_OK || hardwareBuffer == nullptr) {
154 ALOGE("%s: get hardware buffer for image %p failed! ret: %d",
155 __FUNCTION__, img, ret);
156 return ret;
157 }
158
159 mAcquiredBuffer[idx].mBufferPointer = data;
160
161 mAlloc[idx]->mHal.drvState.lod[0].mallocPtr = data;
162 mAlloc[idx]->mHal.drvState.lod[0].stride = rowstride;
163 mAlloc[idx]->mHal.state.nativeBuffer = hardwareBuffer;
164 mAlloc[idx]->mHal.state.timestamp = timestamp;
165
166 if (format == AIMAGE_FORMAT_YUV_420_888) {
167 const int yWidth = mAlloc[idx]->mHal.drvState.lod[0].dimX;
168 const int yHeight = mAlloc[idx]->mHal.drvState.lod[0].dimY;
169
170 const int cWidth = yWidth / 2;
171 const int cHeight = yHeight / 2;
172
173 uint8_t *uData = nullptr;
174 int uDataLength = 0;
175 ret = AImage_getPlaneData(img, 1, &uData, &uDataLength);
176 if (ret != AMEDIA_OK || uData == nullptr || uDataLength <= 0) {
177 ALOGE("%s: get U data for image %p failed! ret: %d, data %p, len %d",
178 __FUNCTION__, img, ret, uData, uDataLength);
179 return ret;
180 }
181
182 uint8_t *vData = nullptr;
183 int vDataLength = 0;
184 ret = AImage_getPlaneData(img, 2, &vData, &vDataLength);
185 if (ret != AMEDIA_OK || vData == nullptr || vDataLength <= 0) {
186 ALOGE("%s: get V data for image %p failed! ret: %d, data %p, len %d",
187 __FUNCTION__, img, ret, vData, vDataLength);
188 return ret;
189 }
190
191 int32_t uRowStride = -1;
192 ret = AImage_getPlaneRowStride(img, 1, &uRowStride);
193 if (ret != AMEDIA_OK || uRowStride == -1) {
194 ALOGE("%s: get U row stride for image %p failed! ret: %d, uRowStride %d",
195 __FUNCTION__, img, ret, uRowStride);
196 return ret;
197 }
198
199 int32_t vRowStride = -1;
200 ret = AImage_getPlaneRowStride(img, 2, &vRowStride);
201 if (ret != AMEDIA_OK || vRowStride == -1) {
202 ALOGE("%s: get V row stride for image %p failed! ret: %d, vRowStride %d",
203 __FUNCTION__, img, ret, vRowStride);
204 return ret;
205 }
206
207 int32_t uPixStride = -1;
208 ret = AImage_getPlanePixelStride(img, 1, &uPixStride);
209 if (ret != AMEDIA_OK || uPixStride == -1) {
210 ALOGE("%s: get U pixel stride for image %p failed! ret: %d, uPixStride %d",
211 __FUNCTION__, img, ret, uPixStride);
212 return ret;
213 }
214
215 mAlloc[idx]->mHal.drvState.lod[1].dimX = cWidth;
216 mAlloc[idx]->mHal.drvState.lod[1].dimY = cHeight;
217 mAlloc[idx]->mHal.drvState.lod[2].dimX = cWidth;
218 mAlloc[idx]->mHal.drvState.lod[2].dimY = cHeight;
219
220 mAlloc[idx]->mHal.drvState.lod[1].mallocPtr = uData;
221 mAlloc[idx]->mHal.drvState.lod[2].mallocPtr = vData;
222
223 mAlloc[idx]->mHal.drvState.lod[1].stride = uRowStride;
224 mAlloc[idx]->mHal.drvState.lod[2].stride = vRowStride;
225
226 mAlloc[idx]->mHal.drvState.yuv.shift = 1;
227 mAlloc[idx]->mHal.drvState.yuv.step = uPixStride;
228 mAlloc[idx]->mHal.drvState.lodCount = 3;
229 }
230
231 return AMEDIA_OK;
232 }
233
unlockBuffer(uint32_t idx)234 media_status_t GrallocConsumer::unlockBuffer(uint32_t idx) {
235 media_status_t ret;
236
237 if (idx >= mNumAlloc) {
238 ALOGE("Invalid buffer index: %d", idx);
239 return AMEDIA_ERROR_INVALID_PARAMETER;
240 }
241 if (mAcquiredBuffer[idx].mImg == nullptr) {
242 return AMEDIA_OK;
243 }
244
245 AImage_delete(mAcquiredBuffer[idx].mImg);
246 mAcquiredBuffer[idx].mImg = nullptr;
247 return AMEDIA_OK;
248 }
249
getNextAvailableIdx(Allocation * a)250 uint32_t GrallocConsumer::getNextAvailableIdx(Allocation *a) {
251 for (uint32_t i = 0; i < mNumAlloc; i++) {
252 if (isIdxUsed[i] == false) {
253 mAlloc[i] = a;
254 isIdxUsed[i] = true;
255 return i;
256 }
257 }
258 return mNumAlloc;
259 }
260
releaseIdx(uint32_t idx)261 bool GrallocConsumer::releaseIdx(uint32_t idx) {
262 if (idx >= mNumAlloc) {
263 ALOGE("Invalid buffer index: %d", idx);
264 return false;
265 }
266 if (isIdxUsed[idx] == false) {
267 ALOGV("Buffer index already released: %d", idx);
268 return true;
269 }
270 media_status_t ret;
271 ret = unlockBuffer(idx);
272 if (ret != OK) {
273 ALOGE("Unable to unlock graphic buffer");
274 return false;
275 }
276 mAlloc[idx] = nullptr;
277 isIdxUsed[idx] = false;
278 return true;
279 }
280
isActive()281 bool GrallocConsumer::isActive() {
282 for (uint32_t i = 0; i < mNumAlloc; i++) {
283 if (isIdxUsed[i]) {
284 return true;
285 }
286 }
287 return false;
288 }
289
290 } // namespace renderscript
291 } // namespace android
292