blob: 45d8a8faae472e33f94a58a882fc7801fda06218 [file] [log] [blame]
Jason Samsddceab92013-08-07 13:02:32 -07001/*
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"
Jason Samsddceab92013-08-07 13:02:32 -070021#include "rs_hal.h"
22
23#include <cutils/compiler.h>
24#include <utils/Log.h>
25#include "rsGrallocConsumer.h"
Dan Stoza82659142015-03-12 15:15:58 -070026#include <gui/BufferItem.h>
Jason Samsddceab92013-08-07 13:02:32 -070027#include <ui/GraphicBuffer.h>
28
29
30namespace android {
31namespace renderscript {
32
Miao Wang75474682015-10-26 16:50:13 -070033GrallocConsumer::GrallocConsumer(Allocation *a, const sp<IGraphicBufferConsumer>& bq, int flags, uint32_t numAlloc) :
Jason Samsddceab92013-08-07 13:02:32 -070034 ConsumerBase(bq, true)
35{
Miao Wang75474682015-10-26 16:50:13 -070036 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;
Jason Sams1c19f052014-11-10 12:11:37 -080043 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);
Miao Wang75474682015-10-26 16:50:13 -070049 mConsumer->setMaxAcquiredBufferCount(numAlloc + 1);
Jason Samsddceab92013-08-07 13:02:32 -070050
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
Jason Sams61656a72013-09-03 16:21:18 -070055 if (a->mHal.state.yuv) {
56 bq->setDefaultBufferFormat(a->mHal.state.yuv);
57 }
Miao Wang75474682015-10-26 16:50:13 -070058 for (uint32_t i = 1; i < numAlloc; i++) {
59 isIdxUsed[i] = false;
60 }
Jason Samsddceab92013-08-07 13:02:32 -070061 //mBufferQueue->setConsumerName(name);
62}
63
64GrallocConsumer::~GrallocConsumer() {
Miao Wang75474682015-10-26 16:50:13 -070065 delete[] mAlloc;
66 delete[] mAcquiredBuffer;
67 delete[] isIdxUsed;
Jason Samsddceab92013-08-07 13:02:32 -070068}
69
70
71
Miao Wang75474682015-10-26 16:50:13 -070072status_t GrallocConsumer::lockNextBuffer(uint32_t idx) {
Jason Samsddceab92013-08-07 13:02:32 -070073 Mutex::Autolock _l(mMutex);
74 status_t err;
75
Miao Wang75474682015-10-26 16:50:13 -070076 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);
Jason Samsddceab92013-08-07 13:02:32 -070083 if (err) {
84 return err;
85 }
86 }
87
Dan Stoza82659142015-03-12 15:15:58 -070088 BufferItem b;
Jason Samsddceab92013-08-07 13:02:32 -070089
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
Miao Wangb4cb5ff2016-02-18 12:23:40 -0800100 int slot = b.mSlot;
Jason Samsddceab92013-08-07 13:02:32 -0700101
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
Chris Wailes44bef6f2014-08-12 13:51:10 -0700111 void *bufferPointer = nullptr;
Jason Samsddceab92013-08-07 13:02:32 -0700112 android_ycbcr ycbcr = android_ycbcr();
113
Miao Wangb4cb5ff2016-02-18 12:23:40 -0800114 if (mSlots[slot].mGraphicBuffer->getPixelFormat() ==
Jason Samsddceab92013-08-07 13:02:32 -0700115 HAL_PIXEL_FORMAT_YCbCr_420_888) {
Miao Wangb4cb5ff2016-02-18 12:23:40 -0800116 err = mSlots[slot].mGraphicBuffer->lockYCbCr(
Jason Samsddceab92013-08-07 13:02:32 -0700117 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 {
Miao Wangb4cb5ff2016-02-18 12:23:40 -0800128 err = mSlots[slot].mGraphicBuffer->lock(
Jason Samsddceab92013-08-07 13:02:32 -0700129 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;
Miao Wang75474682015-10-26 16:50:13 -0700141 rsAssert(mAcquiredBuffer[idx].mSlot == BufferQueue::INVALID_BUFFER_SLOT);
Jason Samsddceab92013-08-07 13:02:32 -0700142
Miao Wangb4cb5ff2016-02-18 12:23:40 -0800143 mAcquiredBuffer[idx].mSlot = slot;
Miao Wang75474682015-10-26 16:50:13 -0700144 mAcquiredBuffer[idx].mBufferPointer = bufferPointer;
Miao Wangb4cb5ff2016-02-18 12:23:40 -0800145 mAcquiredBuffer[idx].mGraphicBuffer = mSlots[slot].mGraphicBuffer;
Jason Samsddceab92013-08-07 13:02:32 -0700146
Miao Wang75474682015-10-26 16:50:13 -0700147 mAlloc[idx]->mHal.drvState.lod[0].mallocPtr = reinterpret_cast<uint8_t*>(bufferPointer);
Miao Wangb4cb5ff2016-02-18 12:23:40 -0800148 mAlloc[idx]->mHal.drvState.lod[0].stride = mSlots[slot].mGraphicBuffer->getStride() *
Miao Wang75474682015-10-26 16:50:13 -0700149 mAlloc[idx]->mHal.state.type->getElementSizeBytes();
150 mAlloc[idx]->mHal.state.nativeBuffer = mAcquiredBuffer[idx].mGraphicBuffer->getNativeBuffer();
151 mAlloc[idx]->mHal.state.timestamp = b.mTimestamp;
Jason Samsddceab92013-08-07 13:02:32 -0700152
Miao Wang75474682015-10-26 16:50:13 -0700153 rsAssert(mAlloc[idx]->mHal.drvState.lod[0].dimX ==
Miao Wangb4cb5ff2016-02-18 12:23:40 -0800154 mSlots[slot].mGraphicBuffer->getWidth());
Miao Wang75474682015-10-26 16:50:13 -0700155 rsAssert(mAlloc[idx]->mHal.drvState.lod[0].dimY ==
Miao Wangb4cb5ff2016-02-18 12:23:40 -0800156 mSlots[slot].mGraphicBuffer->getHeight());
Jason Samsddceab92013-08-07 13:02:32 -0700157
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
Miao Wang1aaf4fa2015-12-21 17:34:46 +0800165 // 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.
Miao Wang75474682015-10-26 16:50:13 -0700172 if (mAlloc[idx]->mHal.state.yuv == HAL_PIXEL_FORMAT_YCbCr_420_888) {
Miao Wang1aaf4fa2015-12-21 17:34:46 +0800173 const int yWidth = mAlloc[idx]->mHal.drvState.lod[0].dimX;
174 const int yHeight = mAlloc[idx]->mHal.drvState.lod[0].dimY;
Jason Samsddceab92013-08-07 13:02:32 -0700175
Miao Wangb4cb5ff2016-02-18 12:23:40 -0800176 if (mSlots[slot].mGraphicBuffer->getPixelFormat() ==
Miao Wang1aaf4fa2015-12-21 17:34:46 +0800177 HAL_PIXEL_FORMAT_YCbCr_420_888) {
178 const int cWidth = yWidth / 2;
179 const int cHeight = yHeight / 2;
Jason Sams61656a72013-09-03 16:21:18 -0700180
Miao Wang1aaf4fa2015-12-21 17:34:46 +0800181 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;
Miao Wangb4cb5ff2016-02-18 12:23:40 -0800197 } else if (mSlots[slot].mGraphicBuffer->getPixelFormat() ==
Miao Wang1aaf4fa2015-12-21 17:34:46 +0800198 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",
Miao Wangb4cb5ff2016-02-18 12:23:40 -0800230 mSlots[slot].mGraphicBuffer->getPixelFormat());
Miao Wang1aaf4fa2015-12-21 17:34:46 +0800231 }
Jason Samsddceab92013-08-07 13:02:32 -0700232 }
233
234 return OK;
235}
236
Miao Wang75474682015-10-26 16:50:13 -0700237status_t GrallocConsumer::unlockBuffer(uint32_t idx) {
Jason Samsddceab92013-08-07 13:02:32 -0700238 Mutex::Autolock _l(mMutex);
Miao Wang75474682015-10-26 16:50:13 -0700239 return releaseAcquiredBufferLocked(idx);
Jason Samsddceab92013-08-07 13:02:32 -0700240}
241
Miao Wang75474682015-10-26 16:50:13 -0700242status_t GrallocConsumer::releaseAcquiredBufferLocked(uint32_t idx) {
Jason Samsddceab92013-08-07 13:02:32 -0700243 status_t err;
244
Miao Wang75474682015-10-26 16:50:13 -0700245 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();
Jason Samsddceab92013-08-07 13:02:32 -0700254 if (err != OK) {
255 ALOGE("%s: Unable to unlock graphic buffer", __FUNCTION__);
256 return err;
257 }
Miao Wang75474682015-10-26 16:50:13 -0700258 int buf = mAcquiredBuffer[idx].mSlot;
Jason Samsddceab92013-08-07 13:02:32 -0700259
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.
Miao Wang75474682015-10-26 16:50:13 -0700263 if (CC_LIKELY(mAcquiredBuffer[idx].mGraphicBuffer ==
Jason Samsddceab92013-08-07 13:02:32 -0700264 mSlots[buf].mGraphicBuffer)) {
265 releaseBufferLocked(
Miao Wang75474682015-10-26 16:50:13 -0700266 buf, mAcquiredBuffer[idx].mGraphicBuffer,
Jason Samsddceab92013-08-07 13:02:32 -0700267 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
268 }
269
Miao Wang75474682015-10-26 16:50:13 -0700270 mAcquiredBuffer[idx].mSlot = BufferQueue::INVALID_BUFFER_SLOT;
271 mAcquiredBuffer[idx].mBufferPointer = nullptr;
272 mAcquiredBuffer[idx].mGraphicBuffer.clear();
Jason Samsddceab92013-08-07 13:02:32 -0700273 return OK;
274}
275
Miao Wang75474682015-10-26 16:50:13 -0700276uint32_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
287bool 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
Jason Samsddceab92013-08-07 13:02:32 -0700307} // namespace renderscript
308} // namespace android