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 <cutils/compiler.h> 22#include <utils/Log.h> 23#include <gui/CpuConsumer.h> 24 25#define CC_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__) 26#define CC_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__) 27#define CC_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__) 28#define CC_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) 29#define CC_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) 30 31namespace android { 32 33CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers, bool synchronousMode) : 34 ConsumerBase(new BufferQueue(true) ), 35 mMaxLockedBuffers(maxLockedBuffers), 36 mCurrentLockedBuffers(0) 37{ 38 // Create tracking entries for locked buffers 39 mAcquiredBuffers.insertAt(0, maxLockedBuffers); 40 41 mBufferQueue->setSynchronousMode(synchronousMode); 42 mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); 43 mBufferQueue->setMaxAcquiredBufferCount(maxLockedBuffers); 44} 45 46CpuConsumer::~CpuConsumer() { 47 // ConsumerBase destructor does all the work. 48} 49 50 51 52void CpuConsumer::setName(const String8& name) { 53 Mutex::Autolock _l(mMutex); 54 mName = name; 55 mBufferQueue->setConsumerName(name); 56} 57 58status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { 59 status_t err; 60 61 if (!nativeBuffer) return BAD_VALUE; 62 if (mCurrentLockedBuffers == mMaxLockedBuffers) { 63 return INVALID_OPERATION; 64 } 65 66 BufferQueue::BufferItem b; 67 68 Mutex::Autolock _l(mMutex); 69 70 err = acquireBufferLocked(&b); 71 if (err != OK) { 72 if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 73 return BAD_VALUE; 74 } else { 75 CC_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err); 76 return err; 77 } 78 } 79 80 int buf = b.mBuf; 81 82 if (b.mFence.get()) { 83 err = b.mFence->waitForever("CpuConsumer::lockNextBuffer"); 84 if (err != OK) { 85 CC_LOGE("Failed to wait for fence of acquired buffer: %s (%d)", 86 strerror(-err), err); 87 return err; 88 } 89 } 90 91 void *bufferPointer = NULL; 92 android_ycbcr ycbcr = android_ycbcr(); 93 94 if (mSlots[buf].mGraphicBuffer->getPixelFormat() == 95 HAL_PIXEL_FORMAT_YCbCr_420_888) { 96 err = mSlots[buf].mGraphicBuffer->lockYCbCr( 97 GraphicBuffer::USAGE_SW_READ_OFTEN, 98 b.mCrop, 99 &ycbcr); 100 101 if (err != OK) { 102 CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)", 103 strerror(-err), err); 104 return err; 105 } 106 bufferPointer = ycbcr.y; 107 } else { 108 err = mSlots[buf].mGraphicBuffer->lock( 109 GraphicBuffer::USAGE_SW_READ_OFTEN, 110 b.mCrop, 111 &bufferPointer); 112 113 if (err != OK) { 114 CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)", 115 strerror(-err), err); 116 return err; 117 } 118 } 119 120 size_t lockedIdx = 0; 121 for (; lockedIdx < mMaxLockedBuffers; lockedIdx++) { 122 if (mAcquiredBuffers[lockedIdx].mSlot == 123 BufferQueue::INVALID_BUFFER_SLOT) { 124 break; 125 } 126 } 127 assert(lockedIdx < mMaxLockedBuffers); 128 129 AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx); 130 ab.mSlot = buf; 131 ab.mBufferPointer = bufferPointer; 132 ab.mGraphicBuffer = mSlots[buf].mGraphicBuffer; 133 134 nativeBuffer->data = 135 reinterpret_cast<uint8_t*>(bufferPointer); 136 nativeBuffer->width = mSlots[buf].mGraphicBuffer->getWidth(); 137 nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight(); 138 nativeBuffer->format = mSlots[buf].mGraphicBuffer->getPixelFormat(); 139 nativeBuffer->stride = (ycbcr.y != NULL) ? 140 ycbcr.ystride : 141 mSlots[buf].mGraphicBuffer->getStride(); 142 143 nativeBuffer->crop = b.mCrop; 144 nativeBuffer->transform = b.mTransform; 145 nativeBuffer->scalingMode = b.mScalingMode; 146 nativeBuffer->timestamp = b.mTimestamp; 147 nativeBuffer->frameNumber = b.mFrameNumber; 148 149 nativeBuffer->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb); 150 nativeBuffer->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr); 151 nativeBuffer->chromaStride = ycbcr.cstride; 152 nativeBuffer->chromaStep = ycbcr.chroma_step; 153 154 mCurrentLockedBuffers++; 155 156 return OK; 157} 158 159status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) { 160 Mutex::Autolock _l(mMutex); 161 size_t lockedIdx = 0; 162 status_t err; 163 164 void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data); 165 for (; lockedIdx < mMaxLockedBuffers; lockedIdx++) { 166 if (bufPtr == mAcquiredBuffers[lockedIdx].mBufferPointer) break; 167 } 168 if (lockedIdx == mMaxLockedBuffers) { 169 CC_LOGE("%s: Can't find buffer to free", __FUNCTION__); 170 return BAD_VALUE; 171 } 172 173 return releaseAcquiredBufferLocked(lockedIdx); 174} 175 176status_t CpuConsumer::releaseAcquiredBufferLocked(int lockedIdx) { 177 status_t err; 178 179 err = mAcquiredBuffers[lockedIdx].mGraphicBuffer->unlock(); 180 if (err != OK) { 181 CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, 182 lockedIdx); 183 return err; 184 } 185 int buf = mAcquiredBuffers[lockedIdx].mSlot; 186 187 // release the buffer if it hasn't already been freed by the BufferQueue. 188 // This can happen, for example, when the producer of this buffer 189 // disconnected after this buffer was acquired. 190 if (CC_LIKELY(mAcquiredBuffers[lockedIdx].mGraphicBuffer == 191 mSlots[buf].mGraphicBuffer)) { 192 releaseBufferLocked(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); 193 } 194 195 AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx); 196 ab.mSlot = BufferQueue::INVALID_BUFFER_SLOT; 197 ab.mBufferPointer = NULL; 198 ab.mGraphicBuffer.clear(); 199 200 mCurrentLockedBuffers--; 201 return OK; 202} 203 204void CpuConsumer::freeBufferLocked(int slotIndex) { 205 ConsumerBase::freeBufferLocked(slotIndex); 206} 207 208} // namespace android 209