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