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