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