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 #include "rsAllocation.h"
     18 #include "rsContext.h"
     19 #include "rsGrallocConsumer.h"
     20 #include "rs_hal.h"
     21 
     22 namespace android {
     23 namespace renderscript {
     24 
     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 
     68 GrallocConsumer::~GrallocConsumer() {
     69     AImageReader_delete(mImgReader);
     70     delete[] mAlloc;
     71     delete[] mAcquiredBuffer;
     72     delete[] isIdxUsed;
     73 }
     74 
     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 
     86 ANativeWindow* GrallocConsumer::getNativeWindow() {
     87     return mNativeWindow;
     88 }
     89 
     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, &timestamp);
    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 
    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 
    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 
    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 
    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