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(const sp<IGraphicBufferConsumer>& bq,
     34         uint32_t maxLockedBuffers, bool controlledByApp) :
     35     ConsumerBase(bq, controlledByApp),
     36     mMaxLockedBuffers(maxLockedBuffers),
     37     mCurrentLockedBuffers(0)
     38 {
     39     // Create tracking entries for locked buffers
     40     mAcquiredBuffers.insertAt(0, maxLockedBuffers);
     41 
     42     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
     43     mConsumer->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     mConsumer->setConsumerName(name);
     56 }
     57 
     58 status_t CpuConsumer::setDefaultBufferSize(uint32_t width, uint32_t height)
     59 {
     60     Mutex::Autolock _l(mMutex);
     61     return mConsumer->setDefaultBufferSize(width, height);
     62 }
     63 
     64 status_t CpuConsumer::setDefaultBufferFormat(uint32_t defaultFormat)
     65 {
     66     Mutex::Autolock _l(mMutex);
     67     return mConsumer->setDefaultBufferFormat(defaultFormat);
     68 }
     69 
     70 static bool isPossiblyYUV(PixelFormat format) {
     71     switch ((int)format) {
     72         case HAL_PIXEL_FORMAT_RGBA_8888:
     73         case HAL_PIXEL_FORMAT_RGBX_8888:
     74         case HAL_PIXEL_FORMAT_RGB_888:
     75         case HAL_PIXEL_FORMAT_RGB_565:
     76         case HAL_PIXEL_FORMAT_BGRA_8888:
     77         case HAL_PIXEL_FORMAT_sRGB_A_8888:
     78         case HAL_PIXEL_FORMAT_sRGB_X_8888:
     79         case HAL_PIXEL_FORMAT_Y8:
     80         case HAL_PIXEL_FORMAT_Y16:
     81         case HAL_PIXEL_FORMAT_RAW16: // same as HAL_PIXEL_FORMAT_RAW_SENSOR
     82         case HAL_PIXEL_FORMAT_RAW10:
     83         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
     84         case HAL_PIXEL_FORMAT_BLOB:
     85         case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
     86             return false;
     87 
     88         case HAL_PIXEL_FORMAT_YV12:
     89         case HAL_PIXEL_FORMAT_YCbCr_420_888:
     90         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
     91         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
     92         case HAL_PIXEL_FORMAT_YCbCr_422_I:
     93         default:
     94             return true;
     95     }
     96 }
     97 
     98 status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
     99     status_t err;
    100 
    101     if (!nativeBuffer) return BAD_VALUE;
    102     if (mCurrentLockedBuffers == mMaxLockedBuffers) {
    103         CC_LOGW("Max buffers have been locked (%d), cannot lock anymore.",
    104                 mMaxLockedBuffers);
    105         return NOT_ENOUGH_DATA;
    106     }
    107 
    108     BufferQueue::BufferItem b;
    109 
    110     Mutex::Autolock _l(mMutex);
    111 
    112     err = acquireBufferLocked(&b, 0);
    113     if (err != OK) {
    114         if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
    115             return BAD_VALUE;
    116         } else {
    117             CC_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
    118             return err;
    119         }
    120     }
    121 
    122     int buf = b.mBuf;
    123 
    124     void *bufferPointer = NULL;
    125     android_ycbcr ycbcr = android_ycbcr();
    126 
    127     PixelFormat format = mSlots[buf].mGraphicBuffer->getPixelFormat();
    128     PixelFormat flexFormat = format;
    129     if (isPossiblyYUV(format)) {
    130         if (b.mFence.get()) {
    131             err = mSlots[buf].mGraphicBuffer->lockAsyncYCbCr(
    132                 GraphicBuffer::USAGE_SW_READ_OFTEN,
    133                 b.mCrop,
    134                 &ycbcr,
    135                 b.mFence->dup());
    136         } else {
    137             err = mSlots[buf].mGraphicBuffer->lockYCbCr(
    138                 GraphicBuffer::USAGE_SW_READ_OFTEN,
    139                 b.mCrop,
    140                 &ycbcr);
    141         }
    142         if (err == OK) {
    143             bufferPointer = ycbcr.y;
    144             flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
    145             if (format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
    146                 CC_LOGV("locking buffer of format %#x as flex YUV", format);
    147             }
    148         } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
    149             CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
    150                     strerror(-err), err);
    151             return err;
    152         }
    153     }
    154 
    155     if (bufferPointer == NULL) { // not flexible YUV
    156         if (b.mFence.get()) {
    157             err = mSlots[buf].mGraphicBuffer->lockAsync(
    158                 GraphicBuffer::USAGE_SW_READ_OFTEN,
    159                 b.mCrop,
    160                 &bufferPointer,
    161                 b.mFence->dup());
    162         } else {
    163             err = mSlots[buf].mGraphicBuffer->lock(
    164                 GraphicBuffer::USAGE_SW_READ_OFTEN,
    165                 b.mCrop,
    166                 &bufferPointer);
    167         }
    168         if (err != OK) {
    169             CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)",
    170                     strerror(-err), err);
    171             return err;
    172         }
    173     }
    174 
    175     size_t lockedIdx = 0;
    176     for (; lockedIdx < mMaxLockedBuffers; lockedIdx++) {
    177         if (mAcquiredBuffers[lockedIdx].mSlot ==
    178                 BufferQueue::INVALID_BUFFER_SLOT) {
    179             break;
    180         }
    181     }
    182     assert(lockedIdx < mMaxLockedBuffers);
    183 
    184     AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx);
    185     ab.mSlot = buf;
    186     ab.mBufferPointer = bufferPointer;
    187     ab.mGraphicBuffer = mSlots[buf].mGraphicBuffer;
    188 
    189     nativeBuffer->data   =
    190             reinterpret_cast<uint8_t*>(bufferPointer);
    191     nativeBuffer->width  = mSlots[buf].mGraphicBuffer->getWidth();
    192     nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight();
    193     nativeBuffer->format = format;
    194     nativeBuffer->flexFormat = flexFormat;
    195     nativeBuffer->stride = (ycbcr.y != NULL) ?
    196             ycbcr.ystride :
    197             mSlots[buf].mGraphicBuffer->getStride();
    198 
    199     nativeBuffer->crop        = b.mCrop;
    200     nativeBuffer->transform   = b.mTransform;
    201     nativeBuffer->scalingMode = b.mScalingMode;
    202     nativeBuffer->timestamp   = b.mTimestamp;
    203     nativeBuffer->frameNumber = b.mFrameNumber;
    204 
    205     nativeBuffer->dataCb       = reinterpret_cast<uint8_t*>(ycbcr.cb);
    206     nativeBuffer->dataCr       = reinterpret_cast<uint8_t*>(ycbcr.cr);
    207     nativeBuffer->chromaStride = ycbcr.cstride;
    208     nativeBuffer->chromaStep   = ycbcr.chroma_step;
    209 
    210     mCurrentLockedBuffers++;
    211 
    212     return OK;
    213 }
    214 
    215 status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
    216     Mutex::Autolock _l(mMutex);
    217     size_t lockedIdx = 0;
    218     status_t err;
    219 
    220     void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data);
    221     for (; lockedIdx < mMaxLockedBuffers; lockedIdx++) {
    222         if (bufPtr == mAcquiredBuffers[lockedIdx].mBufferPointer) break;
    223     }
    224     if (lockedIdx == mMaxLockedBuffers) {
    225         CC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
    226         return BAD_VALUE;
    227     }
    228 
    229     return releaseAcquiredBufferLocked(lockedIdx);
    230 }
    231 
    232 status_t CpuConsumer::releaseAcquiredBufferLocked(int lockedIdx) {
    233     status_t err;
    234     int fd = -1;
    235 
    236     err = mAcquiredBuffers[lockedIdx].mGraphicBuffer->unlockAsync(&fd);
    237     if (err != OK) {
    238         CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__,
    239                 lockedIdx);
    240         return err;
    241     }
    242     int buf = mAcquiredBuffers[lockedIdx].mSlot;
    243     if (CC_LIKELY(fd != -1)) {
    244         sp<Fence> fence(new Fence(fd));
    245         addReleaseFenceLocked(
    246             mAcquiredBuffers[lockedIdx].mSlot,
    247             mSlots[buf].mGraphicBuffer,
    248             fence);
    249     }
    250 
    251     // release the buffer if it hasn't already been freed by the BufferQueue.
    252     // This can happen, for example, when the producer of this buffer
    253     // disconnected after this buffer was acquired.
    254     if (CC_LIKELY(mAcquiredBuffers[lockedIdx].mGraphicBuffer ==
    255             mSlots[buf].mGraphicBuffer)) {
    256         releaseBufferLocked(
    257                 buf, mAcquiredBuffers[lockedIdx].mGraphicBuffer,
    258                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
    259     }
    260 
    261     AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx);
    262     ab.mSlot = BufferQueue::INVALID_BUFFER_SLOT;
    263     ab.mBufferPointer = NULL;
    264     ab.mGraphicBuffer.clear();
    265 
    266     mCurrentLockedBuffers--;
    267     return OK;
    268 }
    269 
    270 void CpuConsumer::freeBufferLocked(int slotIndex) {
    271     ConsumerBase::freeBufferLocked(slotIndex);
    272 }
    273 
    274 } // namespace android
    275