1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gonk/nativewindow/GonkConsumerBaseJB.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,245 @@ 1.4 +/* 1.5 + * Copyright (C) 2010 The Android Open Source Project 1.6 + * Copyright (C) 2013 Mozilla Foundation 1.7 + * 1.8 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.9 + * you may not use this file except in compliance with the License. 1.10 + * You may obtain a copy of the License at 1.11 + * 1.12 + * http://www.apache.org/licenses/LICENSE-2.0 1.13 + * 1.14 + * Unless required by applicable law or agreed to in writing, software 1.15 + * distributed under the License is distributed on an "AS IS" BASIS, 1.16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.17 + * See the License for the specific language governing permissions and 1.18 + * limitations under the License. 1.19 + */ 1.20 + 1.21 +#define LOG_TAG "GonkConsumerBase" 1.22 +#define ATRACE_TAG ATRACE_TAG_GRAPHICS 1.23 +//#define LOG_NDEBUG 0 1.24 + 1.25 +#define EGL_EGLEXT_PROTOTYPES 1.26 + 1.27 +#include <hardware/hardware.h> 1.28 + 1.29 +#include <gui/IGraphicBufferAlloc.h> 1.30 +#include <utils/Log.h> 1.31 +#include <utils/String8.h> 1.32 + 1.33 +#include "GonkConsumerBaseJB.h" 1.34 + 1.35 +// Macros for including the GonkConsumerBase name in log messages 1.36 +#define CB_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) 1.37 +#define CB_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) 1.38 +#define CB_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 1.39 +#define CB_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) 1.40 +#define CB_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 1.41 + 1.42 +namespace android { 1.43 + 1.44 +// Get an ID that's unique within this process. 1.45 +static int32_t createProcessUniqueId() { 1.46 + static volatile int32_t globalCounter = 0; 1.47 + return android_atomic_inc(&globalCounter); 1.48 +} 1.49 + 1.50 +GonkConsumerBase::GonkConsumerBase(const sp<GonkBufferQueue>& bufferQueue) : 1.51 + mAbandoned(false), 1.52 + mBufferQueue(bufferQueue) { 1.53 + // Choose a name using the PID and a process-unique ID. 1.54 + mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); 1.55 + 1.56 + // Note that we can't create an sp<...>(this) in a ctor that will not keep a 1.57 + // reference once the ctor ends, as that would cause the refcount of 'this' 1.58 + // dropping to 0 at the end of the ctor. Since all we need is a wp<...> 1.59 + // that's what we create. 1.60 + wp<GonkBufferQueue::ConsumerListener> listener; 1.61 + sp<GonkBufferQueue::ConsumerListener> proxy; 1.62 + listener = static_cast<GonkBufferQueue::ConsumerListener*>(this); 1.63 + proxy = new GonkBufferQueue::ProxyConsumerListener(listener); 1.64 + 1.65 + status_t err = mBufferQueue->consumerConnect(proxy); 1.66 + if (err != NO_ERROR) { 1.67 + CB_LOGE("GonkConsumerBase: error connecting to GonkBufferQueue: %s (%d)", 1.68 + strerror(-err), err); 1.69 + } else { 1.70 + mBufferQueue->setConsumerName(mName); 1.71 + } 1.72 +} 1.73 + 1.74 +GonkConsumerBase::~GonkConsumerBase() { 1.75 + CB_LOGV("~GonkConsumerBase"); 1.76 + Mutex::Autolock lock(mMutex); 1.77 + 1.78 + // Verify that abandon() has been called before we get here. This should 1.79 + // be done by GonkConsumerBase::onLastStrongRef(), but it's possible for a 1.80 + // derived class to override that method and not call 1.81 + // GonkConsumerBase::onLastStrongRef(). 1.82 + LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~GonkConsumerBase was called, but the " 1.83 + "consumer is not abandoned!", mName.string()); 1.84 +} 1.85 + 1.86 +void GonkConsumerBase::onLastStrongRef(const void* id) { 1.87 + abandon(); 1.88 +} 1.89 + 1.90 +void GonkConsumerBase::freeBufferLocked(int slotIndex) { 1.91 + CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); 1.92 + mSlots[slotIndex].mGraphicBuffer = 0; 1.93 + mSlots[slotIndex].mFence = Fence::NO_FENCE; 1.94 +} 1.95 + 1.96 +// Used for refactoring, should not be in final interface 1.97 +sp<GonkBufferQueue> GonkConsumerBase::getBufferQueue() const { 1.98 + Mutex::Autolock lock(mMutex); 1.99 + return mBufferQueue; 1.100 +} 1.101 + 1.102 +void GonkConsumerBase::onFrameAvailable() { 1.103 + CB_LOGV("onFrameAvailable"); 1.104 + 1.105 + sp<FrameAvailableListener> listener; 1.106 + { // scope for the lock 1.107 + Mutex::Autolock lock(mMutex); 1.108 +#if ANDROID_VERSION == 17 1.109 + listener = mFrameAvailableListener; 1.110 +#else 1.111 + listener = mFrameAvailableListener.promote(); 1.112 +#endif 1.113 + } 1.114 + 1.115 + if (listener != NULL) { 1.116 + CB_LOGV("actually calling onFrameAvailable"); 1.117 + listener->onFrameAvailable(); 1.118 + } 1.119 +} 1.120 + 1.121 +void GonkConsumerBase::onBuffersReleased() { 1.122 + Mutex::Autolock lock(mMutex); 1.123 + 1.124 + CB_LOGV("onBuffersReleased"); 1.125 + 1.126 + if (mAbandoned) { 1.127 + // Nothing to do if we're already abandoned. 1.128 + return; 1.129 + } 1.130 + 1.131 + uint32_t mask = 0; 1.132 + mBufferQueue->getReleasedBuffers(&mask); 1.133 + for (int i = 0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) { 1.134 + if (mask & (1 << i)) { 1.135 + freeBufferLocked(i); 1.136 + } 1.137 + } 1.138 +} 1.139 + 1.140 +void GonkConsumerBase::abandon() { 1.141 + CB_LOGV("abandon"); 1.142 + Mutex::Autolock lock(mMutex); 1.143 + 1.144 + if (!mAbandoned) { 1.145 + abandonLocked(); 1.146 + mAbandoned = true; 1.147 + } 1.148 +} 1.149 + 1.150 +void GonkConsumerBase::abandonLocked() { 1.151 + CB_LOGV("abandonLocked"); 1.152 + for (int i =0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) { 1.153 + freeBufferLocked(i); 1.154 + } 1.155 + // disconnect from the GonkBufferQueue 1.156 + mBufferQueue->consumerDisconnect(); 1.157 + mBufferQueue.clear(); 1.158 +} 1.159 + 1.160 +void GonkConsumerBase::setFrameAvailableListener( 1.161 +#if ANDROID_VERSION == 17 1.162 + const sp<FrameAvailableListener>& listener) { 1.163 +#else 1.164 + const wp<FrameAvailableListener>& listener) { 1.165 +#endif 1.166 + CB_LOGV("setFrameAvailableListener"); 1.167 + Mutex::Autolock lock(mMutex); 1.168 + mFrameAvailableListener = listener; 1.169 +} 1.170 + 1.171 +void GonkConsumerBase::dump(String8& result) const { 1.172 + char buffer[1024]; 1.173 + dump(result, "", buffer, 1024); 1.174 +} 1.175 + 1.176 +void GonkConsumerBase::dump(String8& result, const char* prefix, 1.177 + char* buffer, size_t size) const { 1.178 + Mutex::Autolock _l(mMutex); 1.179 + dumpLocked(result, prefix, buffer, size); 1.180 +} 1.181 + 1.182 +void GonkConsumerBase::dumpLocked(String8& result, const char* prefix, 1.183 + char* buffer, size_t SIZE) const { 1.184 + snprintf(buffer, SIZE, "%smAbandoned=%d\n", prefix, int(mAbandoned)); 1.185 + result.append(buffer); 1.186 + 1.187 + if (!mAbandoned) { 1.188 + mBufferQueue->dump(result, prefix, buffer, SIZE); 1.189 + } 1.190 +} 1.191 + 1.192 +status_t GonkConsumerBase::acquireBufferLocked(GonkBufferQueue::BufferItem *item) { 1.193 + status_t err = mBufferQueue->acquireBuffer(item); 1.194 + if (err != NO_ERROR) { 1.195 + return err; 1.196 + } 1.197 + 1.198 + if (item->mGraphicBuffer != NULL) { 1.199 + mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer; 1.200 + } 1.201 + 1.202 + mSlots[item->mBuf].mFence = item->mFence; 1.203 + 1.204 + CB_LOGV("acquireBufferLocked: -> slot=%d", item->mBuf); 1.205 + 1.206 + return OK; 1.207 +} 1.208 + 1.209 +status_t GonkConsumerBase::addReleaseFence(int slot, const sp<Fence>& fence) { 1.210 + Mutex::Autolock lock(mMutex); 1.211 + return addReleaseFenceLocked(slot, fence); 1.212 +} 1.213 + 1.214 +status_t GonkConsumerBase::addReleaseFenceLocked(int slot, const sp<Fence>& fence) { 1.215 + CB_LOGV("addReleaseFenceLocked: slot=%d", slot); 1.216 + 1.217 + if (!mSlots[slot].mFence.get()) { 1.218 + mSlots[slot].mFence = fence; 1.219 + } else { 1.220 + sp<Fence> mergedFence = Fence::merge( 1.221 + String8::format("%.28s:%d", mName.string(), slot), 1.222 + mSlots[slot].mFence, fence); 1.223 + if (!mergedFence.get()) { 1.224 + CB_LOGE("failed to merge release fences"); 1.225 + // synchronization is broken, the best we can do is hope fences 1.226 + // signal in order so the new fence will act like a union 1.227 + mSlots[slot].mFence = fence; 1.228 + return BAD_VALUE; 1.229 + } 1.230 + mSlots[slot].mFence = mergedFence; 1.231 + } 1.232 + 1.233 + return OK; 1.234 +} 1.235 + 1.236 +status_t GonkConsumerBase::releaseBufferLocked(int slot) { 1.237 + CB_LOGV("releaseBufferLocked: slot=%d", slot); 1.238 + status_t err = mBufferQueue->releaseBuffer(slot, mSlots[slot].mFence); 1.239 + if (err == GonkBufferQueue::STALE_BUFFER_SLOT) { 1.240 + freeBufferLocked(slot); 1.241 + } 1.242 + 1.243 + mSlots[slot].mFence = Fence::NO_FENCE; 1.244 + 1.245 + return err; 1.246 +} 1.247 + 1.248 +} // namespace android