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, ×tamp); 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