CpuConsumer.cpp revision e232fdca2a62dc5e81b550f5be8710e36174e7a6
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#include <utils/Log.h>
21
22#include <gui/CpuConsumer.h>
23
24#define CC_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
25#define CC_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
26#define CC_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
27#define CC_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
28#define CC_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
29
30namespace android {
31
32CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) :
33    ConsumerBase(new BufferQueue(true, maxLockedBuffers) ),
34    mMaxLockedBuffers(maxLockedBuffers),
35    mCurrentLockedBuffers(0)
36{
37
38    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
39        mBufferPointers[i] = NULL;
40    }
41
42    mBufferQueue->setSynchronousMode(true);
43    mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
44}
45
46CpuConsumer::~CpuConsumer() {
47}
48
49void CpuConsumer::setName(const String8& name) {
50    Mutex::Autolock _l(mMutex);
51    mName = name;
52    mBufferQueue->setConsumerName(name);
53}
54
55status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
56    status_t err;
57
58    if (!nativeBuffer) return BAD_VALUE;
59    if (mCurrentLockedBuffers == mMaxLockedBuffers) {
60        return INVALID_OPERATION;
61    }
62
63    BufferQueue::BufferItem b;
64
65    Mutex::Autolock _l(mMutex);
66
67    err = acquireBufferLocked(&b);
68    if (err != OK) {
69        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
70            return BAD_VALUE;
71        } else {
72            CC_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
73            return err;
74        }
75    }
76
77    int buf = b.mBuf;
78
79    if (b.mFence.get()) {
80        err = b.mFence->wait(Fence::TIMEOUT_NEVER);
81        if (err != OK) {
82            CC_LOGE("Failed to wait for fence of acquired buffer: %s (%d)",
83                    strerror(-err), err);
84            return err;
85        }
86    }
87
88    err = mSlots[buf].mGraphicBuffer->lock(
89        GraphicBuffer::USAGE_SW_READ_OFTEN,
90        b.mCrop,
91        &mBufferPointers[buf]);
92
93    if (mBufferPointers[buf] != NULL && err != OK) {
94        CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)", strerror(-err),
95                err);
96        return err;
97    }
98
99    nativeBuffer->data   = reinterpret_cast<uint8_t*>(mBufferPointers[buf]);
100    nativeBuffer->width  = mSlots[buf].mGraphicBuffer->getWidth();
101    nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight();
102    nativeBuffer->format = mSlots[buf].mGraphicBuffer->getPixelFormat();
103    nativeBuffer->stride = mSlots[buf].mGraphicBuffer->getStride();
104
105    nativeBuffer->crop        = b.mCrop;
106    nativeBuffer->transform   = b.mTransform;
107    nativeBuffer->scalingMode = b.mScalingMode;
108    nativeBuffer->timestamp   = b.mTimestamp;
109    nativeBuffer->frameNumber = b.mFrameNumber;
110
111    mCurrentLockedBuffers++;
112
113    return OK;
114}
115
116status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
117    Mutex::Autolock _l(mMutex);
118    int slotIndex = 0;
119    status_t err;
120
121    void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data);
122    for (; slotIndex < BufferQueue::NUM_BUFFER_SLOTS; slotIndex++) {
123        if (bufPtr == mBufferPointers[slotIndex]) break;
124    }
125    if (slotIndex == BufferQueue::NUM_BUFFER_SLOTS) {
126        CC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
127        return BAD_VALUE;
128    }
129
130    mBufferPointers[slotIndex] = NULL;
131    err = mSlots[slotIndex].mGraphicBuffer->unlock();
132    if (err != OK) {
133        CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, slotIndex);
134        return err;
135    }
136    releaseBufferLocked(slotIndex, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
137
138    mCurrentLockedBuffers--;
139
140    return OK;
141}
142
143void CpuConsumer::freeBufferLocked(int slotIndex) {
144    if (mBufferPointers[slotIndex] != NULL) {
145        status_t err;
146        CC_LOGW("Buffer %d freed while locked by consumer", slotIndex);
147        mBufferPointers[slotIndex] = NULL;
148        err = mSlots[slotIndex].mGraphicBuffer->unlock();
149        if (err != OK) {
150            CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__,
151                    slotIndex);
152        }
153        mCurrentLockedBuffers--;
154    }
155    ConsumerBase::freeBufferLocked(slotIndex);
156}
157
158} // namespace android
159