Home | History | Annotate | Download | only in gui
      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 
     31 namespace android {
     32 
     33 CpuConsumer::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 
     46 CpuConsumer::~CpuConsumer() {
     47     // ConsumerBase destructor does all the work.
     48 }
     49 
     50 
     51 
     52 void CpuConsumer::setName(const String8& name) {
     53     Mutex::Autolock _l(mMutex);
     54     mName = name;
     55     mBufferQueue->setConsumerName(name);
     56 }
     57 
     58 status_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 
    159 status_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 
    176 status_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 
    204 void CpuConsumer::freeBufferLocked(int slotIndex) {
    205     ConsumerBase::freeBufferLocked(slotIndex);
    206 }
    207 
    208 } // namespace android
    209