1/* 2 * Copyright (C) 2012 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 LOG_NDEBUG 0 18#define LOG_TAG "CpuConsumer" 19//#define ATRACE_TAG ATRACE_TAG_GRAPHICS 20 21#include <gui/CpuConsumer.h> 22 23#include <gui/BufferItem.h> 24#include <utils/Log.h> 25 26#define CC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__) 27//#define CC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__) 28//#define CC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__) 29#define CC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__) 30#define CC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__) 31 32namespace android { 33 34CpuConsumer::CpuConsumer(const sp<IGraphicBufferConsumer>& bq, 35 size_t maxLockedBuffers, bool controlledByApp) : 36 ConsumerBase(bq, controlledByApp), 37 mMaxLockedBuffers(maxLockedBuffers), 38 mCurrentLockedBuffers(0) 39{ 40 // Create tracking entries for locked buffers 41 mAcquiredBuffers.insertAt(0, maxLockedBuffers); 42 43 mConsumer->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); 44 mConsumer->setMaxAcquiredBufferCount(static_cast<int32_t>(maxLockedBuffers)); 45} 46 47size_t CpuConsumer::findAcquiredBufferLocked(uintptr_t id) const { 48 for (size_t i = 0; i < mMaxLockedBuffers; i++) { 49 const auto& ab = mAcquiredBuffers[i]; 50 // note that this finds AcquiredBuffer::kUnusedId as well 51 if (ab.mLockedBufferId == id) { 52 return i; 53 } 54 } 55 return mMaxLockedBuffers; // an invalid index 56} 57 58static uintptr_t getLockedBufferId(const CpuConsumer::LockedBuffer& buffer) { 59 return reinterpret_cast<uintptr_t>(buffer.data); 60} 61 62static bool isPossiblyYUV(PixelFormat format) { 63 switch (static_cast<int>(format)) { 64 case HAL_PIXEL_FORMAT_RGBA_8888: 65 case HAL_PIXEL_FORMAT_RGBX_8888: 66 case HAL_PIXEL_FORMAT_RGBA_FP16: 67 case HAL_PIXEL_FORMAT_RGBA_1010102: 68 case HAL_PIXEL_FORMAT_RGB_888: 69 case HAL_PIXEL_FORMAT_RGB_565: 70 case HAL_PIXEL_FORMAT_BGRA_8888: 71 case HAL_PIXEL_FORMAT_Y8: 72 case HAL_PIXEL_FORMAT_Y16: 73 case HAL_PIXEL_FORMAT_RAW16: 74 case HAL_PIXEL_FORMAT_RAW10: 75 case HAL_PIXEL_FORMAT_RAW_OPAQUE: 76 case HAL_PIXEL_FORMAT_BLOB: 77 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: 78 return false; 79 80 case HAL_PIXEL_FORMAT_YV12: 81 case HAL_PIXEL_FORMAT_YCbCr_420_888: 82 case HAL_PIXEL_FORMAT_YCbCr_422_SP: 83 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 84 case HAL_PIXEL_FORMAT_YCbCr_422_I: 85 default: 86 return true; 87 } 88} 89 90status_t CpuConsumer::lockBufferItem(const BufferItem& item, LockedBuffer* outBuffer) const { 91 android_ycbcr ycbcr = android_ycbcr(); 92 93 PixelFormat format = item.mGraphicBuffer->getPixelFormat(); 94 PixelFormat flexFormat = format; 95 if (isPossiblyYUV(format)) { 96 int fenceFd = item.mFence.get() ? item.mFence->dup() : -1; 97 status_t err = item.mGraphicBuffer->lockAsyncYCbCr(GraphicBuffer::USAGE_SW_READ_OFTEN, 98 item.mCrop, &ycbcr, fenceFd); 99 if (err == OK) { 100 flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888; 101 if (format != HAL_PIXEL_FORMAT_YCbCr_420_888) { 102 CC_LOGV("locking buffer of format %#x as flex YUV", format); 103 } 104 } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) { 105 CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)", strerror(-err), err); 106 return err; 107 } 108 } 109 110 if (ycbcr.y != nullptr) { 111 outBuffer->data = reinterpret_cast<uint8_t*>(ycbcr.y); 112 outBuffer->stride = static_cast<uint32_t>(ycbcr.ystride); 113 outBuffer->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb); 114 outBuffer->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr); 115 outBuffer->chromaStride = static_cast<uint32_t>(ycbcr.cstride); 116 outBuffer->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step); 117 } else { 118 // not flexible YUV; try lockAsync 119 void* bufferPointer = nullptr; 120 int fenceFd = item.mFence.get() ? item.mFence->dup() : -1; 121 status_t err = item.mGraphicBuffer->lockAsync(GraphicBuffer::USAGE_SW_READ_OFTEN, 122 item.mCrop, &bufferPointer, fenceFd); 123 if (err != OK) { 124 CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)", strerror(-err), err); 125 return err; 126 } 127 128 outBuffer->data = reinterpret_cast<uint8_t*>(bufferPointer); 129 outBuffer->stride = item.mGraphicBuffer->getStride(); 130 outBuffer->dataCb = nullptr; 131 outBuffer->dataCr = nullptr; 132 outBuffer->chromaStride = 0; 133 outBuffer->chromaStep = 0; 134 } 135 136 outBuffer->width = item.mGraphicBuffer->getWidth(); 137 outBuffer->height = item.mGraphicBuffer->getHeight(); 138 outBuffer->format = format; 139 outBuffer->flexFormat = flexFormat; 140 141 outBuffer->crop = item.mCrop; 142 outBuffer->transform = item.mTransform; 143 outBuffer->scalingMode = item.mScalingMode; 144 outBuffer->timestamp = item.mTimestamp; 145 outBuffer->dataSpace = item.mDataSpace; 146 outBuffer->frameNumber = item.mFrameNumber; 147 148 return OK; 149} 150 151status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { 152 status_t err; 153 154 if (!nativeBuffer) return BAD_VALUE; 155 156 Mutex::Autolock _l(mMutex); 157 158 if (mCurrentLockedBuffers == mMaxLockedBuffers) { 159 CC_LOGW("Max buffers have been locked (%zd), cannot lock anymore.", 160 mMaxLockedBuffers); 161 return NOT_ENOUGH_DATA; 162 } 163 164 BufferItem b; 165 err = acquireBufferLocked(&b, 0); 166 if (err != OK) { 167 if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 168 return BAD_VALUE; 169 } else { 170 CC_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err); 171 return err; 172 } 173 } 174 175 if (b.mGraphicBuffer == nullptr) { 176 b.mGraphicBuffer = mSlots[b.mSlot].mGraphicBuffer; 177 } 178 179 err = lockBufferItem(b, nativeBuffer); 180 if (err != OK) { 181 return err; 182 } 183 184 // find an unused AcquiredBuffer 185 size_t lockedIdx = findAcquiredBufferLocked(AcquiredBuffer::kUnusedId); 186 ALOG_ASSERT(lockedIdx < mMaxLockedBuffers); 187 AcquiredBuffer& ab = mAcquiredBuffers.editItemAt(lockedIdx); 188 189 ab.mSlot = b.mSlot; 190 ab.mGraphicBuffer = b.mGraphicBuffer; 191 ab.mLockedBufferId = getLockedBufferId(*nativeBuffer); 192 193 mCurrentLockedBuffers++; 194 195 return OK; 196} 197 198status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) { 199 Mutex::Autolock _l(mMutex); 200 201 uintptr_t id = getLockedBufferId(nativeBuffer); 202 size_t lockedIdx = 203 (id != AcquiredBuffer::kUnusedId) ? findAcquiredBufferLocked(id) : mMaxLockedBuffers; 204 if (lockedIdx == mMaxLockedBuffers) { 205 CC_LOGE("%s: Can't find buffer to free", __FUNCTION__); 206 return BAD_VALUE; 207 } 208 209 AcquiredBuffer& ab = mAcquiredBuffers.editItemAt(lockedIdx); 210 211 int fenceFd = -1; 212 status_t err = ab.mGraphicBuffer->unlockAsync(&fenceFd); 213 if (err != OK) { 214 CC_LOGE("%s: Unable to unlock graphic buffer %zd", __FUNCTION__, 215 lockedIdx); 216 return err; 217 } 218 219 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE); 220 addReleaseFenceLocked(ab.mSlot, ab.mGraphicBuffer, fence); 221 releaseBufferLocked(ab.mSlot, ab.mGraphicBuffer); 222 223 ab.reset(); 224 225 mCurrentLockedBuffers--; 226 227 return OK; 228} 229 230} // namespace android 231