Home | History | Annotate | Download | only in rs
      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 
     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 
     64 GrallocConsumer::~GrallocConsumer() {
     65     delete[] mAlloc;
     66     delete[] mAcquiredBuffer;
     67     delete[] isIdxUsed;
     68 }
     69 
     70 
     71 
     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 
    237 status_t GrallocConsumer::unlockBuffer(uint32_t idx) {
    238     Mutex::Autolock _l(mMutex);
    239     return releaseAcquiredBufferLocked(idx);
    240 }
    241 
    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 
    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 
    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