1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gonk/nativewindow/GonkBufferQueueJB.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1042 @@ 1.4 +/* 1.5 + * Copyright (C) 2012 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 "GonkBufferQueue" 1.22 +#define ATRACE_TAG ATRACE_TAG_GRAPHICS 1.23 +#define LOG_NDEBUG 0 1.24 + 1.25 +#define GL_GLEXT_PROTOTYPES 1.26 +#define EGL_EGLEXT_PROTOTYPES 1.27 + 1.28 +#include <utils/Log.h> 1.29 + 1.30 +#include "mozilla/layers/GrallocTextureClient.h" 1.31 +#include "mozilla/layers/ImageBridgeChild.h" 1.32 + 1.33 +#include "GonkBufferQueueJB.h" 1.34 + 1.35 +// Macros for including the GonkBufferQueue name in log messages 1.36 +#define ST_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) 1.37 +#define ST_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) 1.38 +#define ST_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 1.39 +#define ST_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) 1.40 +#define ST_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 1.41 + 1.42 +#define ATRACE_BUFFER_INDEX(index) 1.43 + 1.44 +using namespace mozilla; 1.45 +using namespace mozilla::gfx; 1.46 +using namespace mozilla::layers; 1.47 + 1.48 +namespace android { 1.49 + 1.50 +// Get an ID that's unique within this process. 1.51 +static int32_t createProcessUniqueId() { 1.52 + static volatile int32_t globalCounter = 0; 1.53 + return android_atomic_inc(&globalCounter); 1.54 +} 1.55 + 1.56 +static const char* scalingModeName(int scalingMode) { 1.57 + switch (scalingMode) { 1.58 + case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE"; 1.59 + case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW"; 1.60 + case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP"; 1.61 + default: return "Unknown"; 1.62 + } 1.63 +} 1.64 + 1.65 +class nsProxyReleaseTask : public Task 1.66 +{ 1.67 +public: 1.68 + nsProxyReleaseTask(TextureClient* aClient) 1.69 + : mTextureClient(aClient) { 1.70 + } 1.71 + 1.72 + virtual void Run() MOZ_OVERRIDE 1.73 + { 1.74 + mTextureClient = nullptr; 1.75 + } 1.76 + 1.77 +private: 1.78 + mozilla::RefPtr<TextureClient> mTextureClient; 1.79 +}; 1.80 + 1.81 +GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode, 1.82 + const sp<IGraphicBufferAlloc>& allocator) : 1.83 + mDefaultWidth(1), 1.84 + mDefaultHeight(1), 1.85 + mMaxAcquiredBufferCount(1), 1.86 + mDefaultMaxBufferCount(2), 1.87 + mOverrideMaxBufferCount(0), 1.88 + mSynchronousMode(true), // GonkBufferQueue always works in sync mode. 1.89 + mAllowSynchronousMode(allowSynchronousMode), 1.90 + mConnectedApi(NO_CONNECTED_API), 1.91 + mAbandoned(false), 1.92 + mFrameCounter(0), 1.93 + mBufferHasBeenQueued(false), 1.94 + mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), 1.95 + mConsumerUsageBits(0), 1.96 + mTransformHint(0) 1.97 +{ 1.98 + // Choose a name using the PID and a process-unique ID. 1.99 + mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); 1.100 + 1.101 + ST_LOGV("GonkBufferQueue"); 1.102 +} 1.103 + 1.104 +GonkBufferQueue::~GonkBufferQueue() { 1.105 + ST_LOGV("~GonkBufferQueue"); 1.106 +} 1.107 + 1.108 +status_t GonkBufferQueue::setDefaultMaxBufferCountLocked(int count) { 1.109 + if (count < 2 || count > NUM_BUFFER_SLOTS) 1.110 + return BAD_VALUE; 1.111 + 1.112 + mDefaultMaxBufferCount = count; 1.113 + mDequeueCondition.broadcast(); 1.114 + 1.115 + return NO_ERROR; 1.116 +} 1.117 + 1.118 +bool GonkBufferQueue::isSynchronousMode() const { 1.119 + Mutex::Autolock lock(mMutex); 1.120 + return mSynchronousMode; 1.121 +} 1.122 + 1.123 +void GonkBufferQueue::setConsumerName(const String8& name) { 1.124 + Mutex::Autolock lock(mMutex); 1.125 + mConsumerName = name; 1.126 +} 1.127 + 1.128 +status_t GonkBufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) { 1.129 + Mutex::Autolock lock(mMutex); 1.130 + mDefaultBufferFormat = defaultFormat; 1.131 + return NO_ERROR; 1.132 +} 1.133 + 1.134 +status_t GonkBufferQueue::setConsumerUsageBits(uint32_t usage) { 1.135 + Mutex::Autolock lock(mMutex); 1.136 + mConsumerUsageBits = usage; 1.137 + return NO_ERROR; 1.138 +} 1.139 + 1.140 +status_t GonkBufferQueue::setTransformHint(uint32_t hint) { 1.141 + ST_LOGV("setTransformHint: %02x", hint); 1.142 + Mutex::Autolock lock(mMutex); 1.143 + mTransformHint = hint; 1.144 + return NO_ERROR; 1.145 +} 1.146 + 1.147 +TemporaryRef<TextureClient> 1.148 +GonkBufferQueue::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) 1.149 +{ 1.150 + Mutex::Autolock _l(mMutex); 1.151 + if (buffer == NULL) { 1.152 + ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer"); 1.153 + return nullptr; 1.154 + } 1.155 + 1.156 + for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 1.157 + if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) { 1.158 + return mSlots[i].mTextureClient; 1.159 + } 1.160 + } 1.161 + ST_LOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle); 1.162 + return nullptr; 1.163 +} 1.164 + 1.165 +int GonkBufferQueue::getSlotFromTextureClientLocked( 1.166 + TextureClient* client) const 1.167 +{ 1.168 + if (client == NULL) { 1.169 + ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer"); 1.170 + return BAD_VALUE; 1.171 + } 1.172 + 1.173 + for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 1.174 + if (mSlots[i].mTextureClient == client) { 1.175 + return i; 1.176 + } 1.177 + } 1.178 + ST_LOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client); 1.179 + return BAD_VALUE; 1.180 +} 1.181 + 1.182 + 1.183 +status_t GonkBufferQueue::setBufferCount(int bufferCount) { 1.184 + ST_LOGV("setBufferCount: count=%d", bufferCount); 1.185 + 1.186 + sp<ConsumerListener> listener; 1.187 + { 1.188 + Mutex::Autolock lock(mMutex); 1.189 + 1.190 + if (mAbandoned) { 1.191 + ST_LOGE("setBufferCount: GonkBufferQueue has been abandoned!"); 1.192 + return NO_INIT; 1.193 + } 1.194 + if (bufferCount > NUM_BUFFER_SLOTS) { 1.195 + ST_LOGE("setBufferCount: bufferCount too large (max %d)", 1.196 + NUM_BUFFER_SLOTS); 1.197 + return BAD_VALUE; 1.198 + } 1.199 + 1.200 + // Error out if the user has dequeued buffers 1.201 + int maxBufferCount = getMaxBufferCountLocked(); 1.202 + for (int i=0 ; i<maxBufferCount; i++) { 1.203 + if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { 1.204 + ST_LOGE("setBufferCount: client owns some buffers"); 1.205 + return -EINVAL; 1.206 + } 1.207 + } 1.208 + 1.209 + const int minBufferSlots = getMinMaxBufferCountLocked(); 1.210 + if (bufferCount == 0) { 1.211 + mOverrideMaxBufferCount = 0; 1.212 + mDequeueCondition.broadcast(); 1.213 + return NO_ERROR; 1.214 + } 1.215 + 1.216 + if (bufferCount < minBufferSlots) { 1.217 + ST_LOGE("setBufferCount: requested buffer count (%d) is less than " 1.218 + "minimum (%d)", bufferCount, minBufferSlots); 1.219 + return BAD_VALUE; 1.220 + } 1.221 + 1.222 + // here we're guaranteed that the client doesn't have dequeued buffers 1.223 + // and will release all of its buffer references. 1.224 + // 1.225 + // XXX: Should this use drainQueueAndFreeBuffersLocked instead? 1.226 + freeAllBuffersLocked(); 1.227 + mOverrideMaxBufferCount = bufferCount; 1.228 + mBufferHasBeenQueued = false; 1.229 + mDequeueCondition.broadcast(); 1.230 + listener = mConsumerListener; 1.231 + } // scope for lock 1.232 + 1.233 + if (listener != NULL) { 1.234 + listener->onBuffersReleased(); 1.235 + } 1.236 + 1.237 + return NO_ERROR; 1.238 +} 1.239 + 1.240 +int GonkBufferQueue::query(int what, int* outValue) 1.241 +{ 1.242 + Mutex::Autolock lock(mMutex); 1.243 + 1.244 + if (mAbandoned) { 1.245 + ST_LOGE("query: GonkBufferQueue has been abandoned!"); 1.246 + return NO_INIT; 1.247 + } 1.248 + 1.249 + int value; 1.250 + switch (what) { 1.251 + case NATIVE_WINDOW_WIDTH: 1.252 + value = mDefaultWidth; 1.253 + break; 1.254 + case NATIVE_WINDOW_HEIGHT: 1.255 + value = mDefaultHeight; 1.256 + break; 1.257 + case NATIVE_WINDOW_FORMAT: 1.258 + value = mDefaultBufferFormat; 1.259 + break; 1.260 + case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 1.261 + value = getMinUndequeuedBufferCountLocked(); 1.262 + break; 1.263 + case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: 1.264 + value = (mQueue.size() >= 2); 1.265 + break; 1.266 + default: 1.267 + return BAD_VALUE; 1.268 + } 1.269 + outValue[0] = value; 1.270 + return NO_ERROR; 1.271 +} 1.272 + 1.273 +status_t GonkBufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) { 1.274 + ST_LOGV("requestBuffer: slot=%d", slot); 1.275 + Mutex::Autolock lock(mMutex); 1.276 + if (mAbandoned) { 1.277 + ST_LOGE("requestBuffer: GonkBufferQueue has been abandoned!"); 1.278 + return NO_INIT; 1.279 + } 1.280 + int maxBufferCount = getMaxBufferCountLocked(); 1.281 + if (slot < 0 || maxBufferCount <= slot) { 1.282 + ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d", 1.283 + maxBufferCount, slot); 1.284 + return BAD_VALUE; 1.285 + } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { 1.286 + // XXX: I vaguely recall there was some reason this can be valid, but 1.287 + // for the life of me I can't recall under what circumstances that's 1.288 + // the case. 1.289 + ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)", 1.290 + slot, mSlots[slot].mBufferState); 1.291 + return BAD_VALUE; 1.292 + } 1.293 + mSlots[slot].mRequestBufferCalled = true; 1.294 + *buf = mSlots[slot].mGraphicBuffer; 1.295 + return NO_ERROR; 1.296 +} 1.297 + 1.298 +status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, 1.299 + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { 1.300 + ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage); 1.301 + 1.302 + if ((w && !h) || (!w && h)) { 1.303 + ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); 1.304 + return BAD_VALUE; 1.305 + } 1.306 + 1.307 + status_t returnFlags(OK); 1.308 + int buf = INVALID_BUFFER_SLOT; 1.309 + 1.310 + { // Scope for the lock 1.311 + Mutex::Autolock lock(mMutex); 1.312 + 1.313 + if (format == 0) { 1.314 + format = mDefaultBufferFormat; 1.315 + } 1.316 + // turn on usage bits the consumer requested 1.317 + usage |= mConsumerUsageBits; 1.318 + 1.319 + int found = -1; 1.320 + int dequeuedCount = 0; 1.321 + bool tryAgain = true; 1.322 + while (tryAgain) { 1.323 + if (mAbandoned) { 1.324 + ST_LOGE("dequeueBuffer: GonkBufferQueue has been abandoned!"); 1.325 + return NO_INIT; 1.326 + } 1.327 + 1.328 + const int maxBufferCount = getMaxBufferCountLocked(); 1.329 + 1.330 + // Free up any buffers that are in slots beyond the max buffer 1.331 + // count. 1.332 + //for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) { 1.333 + // assert(mSlots[i].mBufferState == BufferSlot::FREE); 1.334 + // if (mSlots[i].mGraphicBuffer != NULL) { 1.335 + // freeBufferLocked(i); 1.336 + // returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS; 1.337 + // } 1.338 + //} 1.339 + 1.340 + // look for a free buffer to give to the client 1.341 + found = INVALID_BUFFER_SLOT; 1.342 + dequeuedCount = 0; 1.343 + for (int i = 0; i < maxBufferCount; i++) { 1.344 + const int state = mSlots[i].mBufferState; 1.345 + if (state == BufferSlot::DEQUEUED) { 1.346 + dequeuedCount++; 1.347 + } 1.348 + 1.349 + if (state == BufferSlot::FREE) { 1.350 + /* We return the oldest of the free buffers to avoid 1.351 + * stalling the producer if possible. This is because 1.352 + * the consumer may still have pending reads of the 1.353 + * buffers in flight. 1.354 + */ 1.355 + if ((found < 0) || 1.356 + mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) { 1.357 + found = i; 1.358 + } 1.359 + } 1.360 + } 1.361 + 1.362 + // clients are not allowed to dequeue more than one buffer 1.363 + // if they didn't set a buffer count. 1.364 + if (!mOverrideMaxBufferCount && dequeuedCount) { 1.365 + ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without " 1.366 + "setting the buffer count"); 1.367 + return -EINVAL; 1.368 + } 1.369 + 1.370 + // See whether a buffer has been queued since the last 1.371 + // setBufferCount so we know whether to perform the min undequeued 1.372 + // buffers check below. 1.373 + if (mBufferHasBeenQueued) { 1.374 + // make sure the client is not trying to dequeue more buffers 1.375 + // than allowed. 1.376 + const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1); 1.377 + const int minUndequeuedCount = getMinUndequeuedBufferCountLocked(); 1.378 + if (newUndequeuedCount < minUndequeuedCount) { 1.379 + ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) " 1.380 + "exceeded (dequeued=%d undequeudCount=%d)", 1.381 + minUndequeuedCount, dequeuedCount, 1.382 + newUndequeuedCount); 1.383 + return -EBUSY; 1.384 + } 1.385 + } 1.386 + 1.387 + // If no buffer is found, wait for a buffer to be released or for 1.388 + // the max buffer count to change. 1.389 + tryAgain = found == INVALID_BUFFER_SLOT; 1.390 + if (tryAgain) { 1.391 + mDequeueCondition.wait(mMutex); 1.392 + } 1.393 + } 1.394 + 1.395 + 1.396 + if (found == INVALID_BUFFER_SLOT) { 1.397 + // This should not happen. 1.398 + ST_LOGE("dequeueBuffer: no available buffer slots"); 1.399 + return -EBUSY; 1.400 + } 1.401 + 1.402 + buf = found; 1.403 + *outBuf = found; 1.404 + 1.405 + const bool useDefaultSize = !w && !h; 1.406 + if (useDefaultSize) { 1.407 + // use the default size 1.408 + w = mDefaultWidth; 1.409 + h = mDefaultHeight; 1.410 + } 1.411 + 1.412 + mSlots[buf].mBufferState = BufferSlot::DEQUEUED; 1.413 + 1.414 + const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); 1.415 + if ((buffer == NULL) || 1.416 + (uint32_t(buffer->width) != w) || 1.417 + (uint32_t(buffer->height) != h) || 1.418 + (uint32_t(buffer->format) != format) || 1.419 + ((uint32_t(buffer->usage) & usage) != usage)) 1.420 + { 1.421 + mSlots[buf].mAcquireCalled = false; 1.422 + mSlots[buf].mGraphicBuffer = NULL; 1.423 + mSlots[buf].mRequestBufferCalled = false; 1.424 + mSlots[buf].mFence = Fence::NO_FENCE; 1.425 + if (mSlots[buf].mTextureClient) { 1.426 + mSlots[buf].mTextureClient->ClearRecycleCallback(); 1.427 + // release TextureClient in ImageBridge thread 1.428 + nsProxyReleaseTask* task = new nsProxyReleaseTask(mSlots[buf].mTextureClient); 1.429 + mSlots[buf].mTextureClient = NULL; 1.430 + ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(FROM_HERE, task); 1.431 + } 1.432 + returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION; 1.433 + } 1.434 + 1.435 + *outFence = mSlots[buf].mFence; 1.436 + mSlots[buf].mFence = Fence::NO_FENCE; 1.437 + } // end lock scope 1.438 + 1.439 + sp<GraphicBuffer> graphicBuffer; 1.440 + if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) { 1.441 + RefPtr<GrallocTextureClientOGL> textureClient = 1.442 + new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(), 1.443 + gfx::SurfaceFormat::UNKNOWN, 1.444 + gfx::BackendType::NONE, 1.445 + TEXTURE_DEALLOCATE_CLIENT); 1.446 + usage |= GraphicBuffer::USAGE_HW_TEXTURE; 1.447 + bool result = textureClient->AllocateGralloc(IntSize(w, h), format, usage); 1.448 + sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer(); 1.449 + if (!result || !graphicBuffer.get()) { 1.450 + ST_LOGE("dequeueBuffer: failed to alloc gralloc buffer"); 1.451 + return -ENOMEM; 1.452 + } 1.453 + 1.454 + { // Scope for the lock 1.455 + Mutex::Autolock lock(mMutex); 1.456 + 1.457 + if (mAbandoned) { 1.458 + ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); 1.459 + return NO_INIT; 1.460 + } 1.461 + 1.462 + mSlots[buf].mGraphicBuffer = graphicBuffer; 1.463 + mSlots[buf].mTextureClient = textureClient; 1.464 + ST_LOGD("dequeueBuffer: returning slot=%d buf=%p ", buf, 1.465 + mSlots[buf].mGraphicBuffer->handle); 1.466 + //mSlots[*outBuf].mGraphicBuffer = graphicBuffer; 1.467 + } 1.468 + } 1.469 + 1.470 + ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf, 1.471 + mSlots[*outBuf].mGraphicBuffer->handle, returnFlags); 1.472 + 1.473 + return returnFlags; 1.474 +} 1.475 + 1.476 +status_t GonkBufferQueue::setSynchronousMode(bool enabled) { 1.477 + return NO_ERROR; 1.478 +} 1.479 + 1.480 +status_t GonkBufferQueue::queueBuffer(int buf, 1.481 + const QueueBufferInput& input, QueueBufferOutput* output) { 1.482 + 1.483 + Rect crop; 1.484 + uint32_t transform; 1.485 + int scalingMode; 1.486 + int64_t timestamp; 1.487 + sp<Fence> fence; 1.488 + 1.489 + input.deflate(×tamp, &crop, &scalingMode, &transform, &fence); 1.490 + 1.491 +#if ANDROID_VERSION >= 18 1.492 + if (fence == NULL) { 1.493 + ST_LOGE("queueBuffer: fence is NULL"); 1.494 + return BAD_VALUE; 1.495 + } 1.496 +#endif 1.497 + 1.498 + ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x " 1.499 + "scale=%s", 1.500 + buf, timestamp, crop.left, crop.top, crop.right, crop.bottom, 1.501 + transform, scalingModeName(scalingMode)); 1.502 + 1.503 + sp<ConsumerListener> listener; 1.504 + 1.505 + { // scope for the lock 1.506 + Mutex::Autolock lock(mMutex); 1.507 + if (mAbandoned) { 1.508 + ST_LOGE("queueBuffer: GonkBufferQueue has been abandoned!"); 1.509 + return NO_INIT; 1.510 + } 1.511 + int maxBufferCount = getMaxBufferCountLocked(); 1.512 + if (buf < 0 || buf >= maxBufferCount) { 1.513 + ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d", 1.514 + maxBufferCount, buf); 1.515 + return -EINVAL; 1.516 + } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 1.517 + ST_LOGE("queueBuffer: slot %d is not owned by the client " 1.518 + "(state=%d)", buf, mSlots[buf].mBufferState); 1.519 + return -EINVAL; 1.520 + } else if (!mSlots[buf].mRequestBufferCalled) { 1.521 + ST_LOGE("queueBuffer: slot %d was enqueued without requesting a " 1.522 + "buffer", buf); 1.523 + return -EINVAL; 1.524 + } 1.525 + 1.526 + const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer); 1.527 + Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); 1.528 + Rect croppedCrop; 1.529 + crop.intersect(bufferRect, &croppedCrop); 1.530 + if (croppedCrop != crop) { 1.531 + ST_LOGE("queueBuffer: crop rect is not contained within the " 1.532 + "buffer in slot %d", buf); 1.533 + return -EINVAL; 1.534 + } 1.535 + 1.536 + if (mSynchronousMode) { 1.537 + // In synchronous mode we queue all buffers in a FIFO. 1.538 + mQueue.push_back(buf); 1.539 + 1.540 + // Synchronous mode always signals that an additional frame should 1.541 + // be consumed. 1.542 + listener = mConsumerListener; 1.543 + } else { 1.544 + // In asynchronous mode we only keep the most recent buffer. 1.545 + if (mQueue.empty()) { 1.546 + mQueue.push_back(buf); 1.547 + 1.548 + // Asynchronous mode only signals that a frame should be 1.549 + // consumed if no previous frame was pending. If a frame were 1.550 + // pending then the consumer would have already been notified. 1.551 + listener = mConsumerListener; 1.552 + } else { 1.553 + Fifo::iterator front(mQueue.begin()); 1.554 + // buffer currently queued is freed 1.555 + mSlots[*front].mBufferState = BufferSlot::FREE; 1.556 + // and we record the new buffer index in the queued list 1.557 + *front = buf; 1.558 + } 1.559 + } 1.560 + 1.561 + mSlots[buf].mTimestamp = timestamp; 1.562 + mSlots[buf].mCrop = crop; 1.563 + mSlots[buf].mTransform = transform; 1.564 + mSlots[buf].mFence = fence; 1.565 + 1.566 + switch (scalingMode) { 1.567 + case NATIVE_WINDOW_SCALING_MODE_FREEZE: 1.568 + case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 1.569 + case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: 1.570 + break; 1.571 + default: 1.572 + ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode); 1.573 + scalingMode = mSlots[buf].mScalingMode; 1.574 + break; 1.575 + } 1.576 + 1.577 + mSlots[buf].mBufferState = BufferSlot::QUEUED; 1.578 + mSlots[buf].mScalingMode = scalingMode; 1.579 + mFrameCounter++; 1.580 + mSlots[buf].mFrameNumber = mFrameCounter; 1.581 + 1.582 + mBufferHasBeenQueued = true; 1.583 + mDequeueCondition.broadcast(); 1.584 + 1.585 + output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, 1.586 + mQueue.size()); 1.587 + } // scope for the lock 1.588 + 1.589 + // call back without lock held 1.590 + if (listener != 0) { 1.591 + listener->onFrameAvailable(); 1.592 + } 1.593 + return NO_ERROR; 1.594 +} 1.595 + 1.596 +#if ANDROID_VERSION == 17 1.597 +void GonkBufferQueue::cancelBuffer(int buf, sp<Fence> fence) { 1.598 +#else 1.599 +void GonkBufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) { 1.600 +#endif 1.601 + 1.602 + ST_LOGV("cancelBuffer: slot=%d", buf); 1.603 + Mutex::Autolock lock(mMutex); 1.604 + 1.605 + if (mAbandoned) { 1.606 + ST_LOGW("cancelBuffer: GonkBufferQueue has been abandoned!"); 1.607 + return; 1.608 + } 1.609 + 1.610 + int maxBufferCount = getMaxBufferCountLocked(); 1.611 + if (buf < 0 || buf >= maxBufferCount) { 1.612 + ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d", 1.613 + maxBufferCount, buf); 1.614 + return; 1.615 + } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 1.616 + ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", 1.617 + buf, mSlots[buf].mBufferState); 1.618 + return; 1.619 +#if ANDROID_VERSION >= 18 1.620 + } else if (fence == NULL) { 1.621 + ST_LOGE("cancelBuffer: fence is NULL"); 1.622 + return; 1.623 +#endif 1.624 + } 1.625 + mSlots[buf].mBufferState = BufferSlot::FREE; 1.626 + mSlots[buf].mFrameNumber = 0; 1.627 + mSlots[buf].mFence = fence; 1.628 + mDequeueCondition.broadcast(); 1.629 +} 1.630 + 1.631 +status_t GonkBufferQueue::connect(int api, QueueBufferOutput* output) { 1.632 + ST_LOGV("connect: api=%d", api); 1.633 + Mutex::Autolock lock(mMutex); 1.634 + 1.635 + if (mAbandoned) { 1.636 + ST_LOGE("connect: GonkBufferQueue has been abandoned!"); 1.637 + return NO_INIT; 1.638 + } 1.639 + 1.640 + if (mConsumerListener == NULL) { 1.641 + ST_LOGE("connect: GonkBufferQueue has no consumer!"); 1.642 + return NO_INIT; 1.643 + } 1.644 + 1.645 + int err = NO_ERROR; 1.646 + switch (api) { 1.647 + case NATIVE_WINDOW_API_EGL: 1.648 + case NATIVE_WINDOW_API_CPU: 1.649 + case NATIVE_WINDOW_API_MEDIA: 1.650 + case NATIVE_WINDOW_API_CAMERA: 1.651 + if (mConnectedApi != NO_CONNECTED_API) { 1.652 + ST_LOGE("connect: already connected (cur=%d, req=%d)", 1.653 + mConnectedApi, api); 1.654 + err = -EINVAL; 1.655 + } else { 1.656 + mConnectedApi = api; 1.657 + output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, 1.658 + mQueue.size()); 1.659 + } 1.660 + break; 1.661 + default: 1.662 + err = -EINVAL; 1.663 + break; 1.664 + } 1.665 + 1.666 + mBufferHasBeenQueued = false; 1.667 + 1.668 + return err; 1.669 +} 1.670 + 1.671 +status_t GonkBufferQueue::disconnect(int api) { 1.672 + ST_LOGV("disconnect: api=%d", api); 1.673 + 1.674 + int err = NO_ERROR; 1.675 + sp<ConsumerListener> listener; 1.676 + 1.677 + { // Scope for the lock 1.678 + Mutex::Autolock lock(mMutex); 1.679 + 1.680 + if (mAbandoned) { 1.681 + // it is not really an error to disconnect after the surface 1.682 + // has been abandoned, it should just be a no-op. 1.683 + return NO_ERROR; 1.684 + } 1.685 + 1.686 + switch (api) { 1.687 + case NATIVE_WINDOW_API_EGL: 1.688 + case NATIVE_WINDOW_API_CPU: 1.689 + case NATIVE_WINDOW_API_MEDIA: 1.690 + case NATIVE_WINDOW_API_CAMERA: 1.691 + if (mConnectedApi == api) { 1.692 + freeAllBuffersLocked(); 1.693 + mConnectedApi = NO_CONNECTED_API; 1.694 + mDequeueCondition.broadcast(); 1.695 + listener = mConsumerListener; 1.696 + } else { 1.697 + ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)", 1.698 + mConnectedApi, api); 1.699 + err = -EINVAL; 1.700 + } 1.701 + break; 1.702 + default: 1.703 + ST_LOGE("disconnect: unknown API %d", api); 1.704 + err = -EINVAL; 1.705 + break; 1.706 + } 1.707 + } 1.708 + 1.709 + if (listener != NULL) { 1.710 + listener->onBuffersReleased(); 1.711 + } 1.712 + 1.713 + return err; 1.714 +} 1.715 + 1.716 +void GonkBufferQueue::dump(String8& result) const 1.717 +{ 1.718 + char buffer[1024]; 1.719 + GonkBufferQueue::dump(result, "", buffer, 1024); 1.720 +} 1.721 + 1.722 +void GonkBufferQueue::dump(String8& result, const char* prefix, 1.723 + char* buffer, size_t SIZE) const 1.724 +{ 1.725 + Mutex::Autolock _l(mMutex); 1.726 + 1.727 + String8 fifo; 1.728 + int fifoSize = 0; 1.729 + Fifo::const_iterator i(mQueue.begin()); 1.730 + while (i != mQueue.end()) { 1.731 + snprintf(buffer, SIZE, "%02d ", *i++); 1.732 + fifoSize++; 1.733 + fifo.append(buffer); 1.734 + } 1.735 + 1.736 + int maxBufferCount = getMaxBufferCountLocked(); 1.737 + 1.738 + snprintf(buffer, SIZE, 1.739 + "%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " 1.740 + "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n", 1.741 + prefix, maxBufferCount, mSynchronousMode, mDefaultWidth, 1.742 + mDefaultHeight, mDefaultBufferFormat, mTransformHint, 1.743 + fifoSize, fifo.string()); 1.744 + result.append(buffer); 1.745 + 1.746 + 1.747 + struct { 1.748 + const char * operator()(int state) const { 1.749 + switch (state) { 1.750 + case BufferSlot::DEQUEUED: return "DEQUEUED"; 1.751 + case BufferSlot::QUEUED: return "QUEUED"; 1.752 + case BufferSlot::FREE: return "FREE"; 1.753 + case BufferSlot::ACQUIRED: return "ACQUIRED"; 1.754 + default: return "Unknown"; 1.755 + } 1.756 + } 1.757 + } stateName; 1.758 + 1.759 + for (int i=0 ; i<maxBufferCount ; i++) { 1.760 + const BufferSlot& slot(mSlots[i]); 1.761 + snprintf(buffer, SIZE, 1.762 + "%s%s[%02d] " 1.763 + "state=%-8s, crop=[%d,%d,%d,%d], " 1.764 + "xform=0x%02x, time=%#llx, scale=%s", 1.765 + prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, 1.766 + stateName(slot.mBufferState), 1.767 + slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, 1.768 + slot.mCrop.bottom, slot.mTransform, slot.mTimestamp, 1.769 + scalingModeName(slot.mScalingMode) 1.770 + ); 1.771 + result.append(buffer); 1.772 + 1.773 + const sp<GraphicBuffer>& buf(slot.mGraphicBuffer); 1.774 + if (buf != NULL) { 1.775 + snprintf(buffer, SIZE, 1.776 + ", %p [%4ux%4u:%4u,%3X]", 1.777 + buf->handle, buf->width, buf->height, buf->stride, 1.778 + buf->format); 1.779 + result.append(buffer); 1.780 + } 1.781 + result.append("\n"); 1.782 + } 1.783 +} 1.784 + 1.785 +void GonkBufferQueue::freeAllBuffersLocked() 1.786 +{ 1.787 + ALOGW_IF(!mQueue.isEmpty(), 1.788 + "freeAllBuffersLocked called but mQueue is not empty"); 1.789 + mQueue.clear(); 1.790 + mBufferHasBeenQueued = false; 1.791 + for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 1.792 + mSlots[i].mGraphicBuffer = 0; 1.793 + if (mSlots[i].mTextureClient) { 1.794 + mSlots[i].mTextureClient->ClearRecycleCallback(); 1.795 + // release TextureClient in ImageBridge thread 1.796 + nsProxyReleaseTask* task = new nsProxyReleaseTask(mSlots[i].mTextureClient); 1.797 + mSlots[i].mTextureClient = NULL; 1.798 + ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(FROM_HERE, task); 1.799 + } 1.800 + if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) { 1.801 + mSlots[i].mNeedsCleanupOnRelease = true; 1.802 + } 1.803 + mSlots[i].mBufferState = BufferSlot::FREE; 1.804 + mSlots[i].mFrameNumber = 0; 1.805 + mSlots[i].mAcquireCalled = false; 1.806 + // destroy fence as GonkBufferQueue now takes ownership 1.807 + mSlots[i].mFence = Fence::NO_FENCE; 1.808 + } 1.809 +} 1.810 + 1.811 +status_t GonkBufferQueue::acquireBuffer(BufferItem *buffer) { 1.812 + Mutex::Autolock _l(mMutex); 1.813 + 1.814 + // Check that the consumer doesn't currently have the maximum number of 1.815 + // buffers acquired. We allow the max buffer count to be exceeded by one 1.816 + // buffer, so that the consumer can successfully set up the newly acquired 1.817 + // buffer before releasing the old one. 1.818 + int numAcquiredBuffers = 0; 1.819 + for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 1.820 + if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) { 1.821 + numAcquiredBuffers++; 1.822 + } 1.823 + } 1.824 + if (numAcquiredBuffers >= mMaxAcquiredBufferCount+1) { 1.825 + ST_LOGE("acquireBuffer: max acquired buffer count reached: %d (max=%d)", 1.826 + numAcquiredBuffers, mMaxAcquiredBufferCount); 1.827 + return INVALID_OPERATION; 1.828 + } 1.829 + 1.830 + // check if queue is empty 1.831 + // In asynchronous mode the list is guaranteed to be one buffer 1.832 + // deep, while in synchronous mode we use the oldest buffer. 1.833 + if (!mQueue.empty()) { 1.834 + Fifo::iterator front(mQueue.begin()); 1.835 + int buf = *front; 1.836 + 1.837 + // In android, when the buffer is aquired by BufferConsumer, 1.838 + // BufferQueue releases a reference to the buffer and 1.839 + // it's ownership moves to the BufferConsumer. 1.840 + // In b2g, GonkBufferQueue continues to have a buffer ownership. 1.841 + // It is necessary to free buffer via ImageBridgeChild. 1.842 + 1.843 + //if (mSlots[buf].mAcquireCalled) { 1.844 + // buffer->mGraphicBuffer = NULL; 1.845 + //} else { 1.846 + // buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer; 1.847 + //} 1.848 + buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer; 1.849 + buffer->mCrop = mSlots[buf].mCrop; 1.850 + buffer->mTransform = mSlots[buf].mTransform; 1.851 + buffer->mScalingMode = mSlots[buf].mScalingMode; 1.852 + buffer->mFrameNumber = mSlots[buf].mFrameNumber; 1.853 + buffer->mTimestamp = mSlots[buf].mTimestamp; 1.854 + buffer->mBuf = buf; 1.855 + buffer->mFence = mSlots[buf].mFence; 1.856 + 1.857 + mSlots[buf].mAcquireCalled = true; 1.858 + mSlots[buf].mNeedsCleanupOnRelease = false; 1.859 + mSlots[buf].mBufferState = BufferSlot::ACQUIRED; 1.860 + mSlots[buf].mFence = Fence::NO_FENCE; 1.861 + 1.862 + mQueue.erase(front); 1.863 + mDequeueCondition.broadcast(); 1.864 + } else { 1.865 + return NO_BUFFER_AVAILABLE; 1.866 + } 1.867 + 1.868 + return NO_ERROR; 1.869 +} 1.870 + 1.871 +status_t GonkBufferQueue::releaseBuffer(int buf, const sp<Fence>& fence) { 1.872 + Mutex::Autolock _l(mMutex); 1.873 + 1.874 +#if ANDROID_VERSION == 17 1.875 + if (buf == INVALID_BUFFER_SLOT) { 1.876 +#else 1.877 + if (buf == INVALID_BUFFER_SLOT || fence == NULL) { 1.878 +#endif 1.879 + return BAD_VALUE; 1.880 + } 1.881 + 1.882 + mSlots[buf].mFence = fence; 1.883 + 1.884 + // The buffer can now only be released if its in the acquired state 1.885 + if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) { 1.886 + mSlots[buf].mBufferState = BufferSlot::FREE; 1.887 + } else if (mSlots[buf].mNeedsCleanupOnRelease) { 1.888 + ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState); 1.889 + mSlots[buf].mNeedsCleanupOnRelease = false; 1.890 + return STALE_BUFFER_SLOT; 1.891 + } else { 1.892 + ST_LOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState); 1.893 + return -EINVAL; 1.894 + } 1.895 + 1.896 + mDequeueCondition.broadcast(); 1.897 + return NO_ERROR; 1.898 +} 1.899 + 1.900 +status_t GonkBufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) { 1.901 + ST_LOGV("consumerConnect"); 1.902 + Mutex::Autolock lock(mMutex); 1.903 + 1.904 + if (mAbandoned) { 1.905 + ST_LOGE("consumerConnect: GonkBufferQueue has been abandoned!"); 1.906 + return NO_INIT; 1.907 + } 1.908 + if (consumerListener == NULL) { 1.909 + ST_LOGE("consumerConnect: consumerListener may not be NULL"); 1.910 + return BAD_VALUE; 1.911 + } 1.912 + 1.913 + mConsumerListener = consumerListener; 1.914 + 1.915 + return NO_ERROR; 1.916 +} 1.917 + 1.918 +status_t GonkBufferQueue::consumerDisconnect() { 1.919 + ST_LOGV("consumerDisconnect"); 1.920 + Mutex::Autolock lock(mMutex); 1.921 + 1.922 + if (mConsumerListener == NULL) { 1.923 + ST_LOGE("consumerDisconnect: No consumer is connected!"); 1.924 + return -EINVAL; 1.925 + } 1.926 + 1.927 + mAbandoned = true; 1.928 + mConsumerListener = NULL; 1.929 + mQueue.clear(); 1.930 + freeAllBuffersLocked(); 1.931 + mDequeueCondition.broadcast(); 1.932 + return NO_ERROR; 1.933 +} 1.934 + 1.935 +status_t GonkBufferQueue::getReleasedBuffers(uint32_t* slotMask) { 1.936 + ST_LOGV("getReleasedBuffers"); 1.937 + Mutex::Autolock lock(mMutex); 1.938 + 1.939 + if (mAbandoned) { 1.940 + ST_LOGE("getReleasedBuffers: GonkBufferQueue has been abandoned!"); 1.941 + return NO_INIT; 1.942 + } 1.943 + 1.944 + uint32_t mask = 0; 1.945 + for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 1.946 + if (!mSlots[i].mAcquireCalled) { 1.947 + mask |= 1 << i; 1.948 + } 1.949 + } 1.950 + *slotMask = mask; 1.951 + 1.952 + ST_LOGV("getReleasedBuffers: returning mask %#x", mask); 1.953 + return NO_ERROR; 1.954 +} 1.955 + 1.956 +status_t GonkBufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) 1.957 +{ 1.958 + ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h); 1.959 + if (!w || !h) { 1.960 + ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", 1.961 + w, h); 1.962 + return BAD_VALUE; 1.963 + } 1.964 + 1.965 + Mutex::Autolock lock(mMutex); 1.966 + mDefaultWidth = w; 1.967 + mDefaultHeight = h; 1.968 + return NO_ERROR; 1.969 +} 1.970 + 1.971 +status_t GonkBufferQueue::setDefaultMaxBufferCount(int bufferCount) { 1.972 + Mutex::Autolock lock(mMutex); 1.973 + return setDefaultMaxBufferCountLocked(bufferCount); 1.974 +} 1.975 + 1.976 +status_t GonkBufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { 1.977 + Mutex::Autolock lock(mMutex); 1.978 + if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) { 1.979 + ST_LOGE("setMaxAcquiredBufferCount: invalid count specified: %d", 1.980 + maxAcquiredBuffers); 1.981 + return BAD_VALUE; 1.982 + } 1.983 + if (mConnectedApi != NO_CONNECTED_API) { 1.984 + return INVALID_OPERATION; 1.985 + } 1.986 + mMaxAcquiredBufferCount = maxAcquiredBuffers; 1.987 + return NO_ERROR; 1.988 +} 1.989 + 1.990 +int GonkBufferQueue::getMinMaxBufferCountLocked() const { 1.991 + return getMinUndequeuedBufferCountLocked() + 1; 1.992 +} 1.993 + 1.994 +int GonkBufferQueue::getMinUndequeuedBufferCountLocked() const { 1.995 + return mSynchronousMode ? mMaxAcquiredBufferCount : 1.996 + mMaxAcquiredBufferCount + 1; 1.997 +} 1.998 + 1.999 +int GonkBufferQueue::getMaxBufferCountLocked() const { 1.1000 + int minMaxBufferCount = getMinMaxBufferCountLocked(); 1.1001 + 1.1002 + int maxBufferCount = mDefaultMaxBufferCount; 1.1003 + if (maxBufferCount < minMaxBufferCount) { 1.1004 + maxBufferCount = minMaxBufferCount; 1.1005 + } 1.1006 + if (mOverrideMaxBufferCount != 0) { 1.1007 + assert(mOverrideMaxBufferCount >= minMaxBufferCount); 1.1008 + maxBufferCount = mOverrideMaxBufferCount; 1.1009 + } 1.1010 + 1.1011 + // Any buffers that are dequeued by the producer or sitting in the queue 1.1012 + // waiting to be consumed need to have their slots preserved. Such 1.1013 + // buffers will temporarily keep the max buffer count up until the slots 1.1014 + // no longer need to be preserved. 1.1015 + for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) { 1.1016 + BufferSlot::BufferState state = mSlots[i].mBufferState; 1.1017 + if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) { 1.1018 + maxBufferCount = i + 1; 1.1019 + } 1.1020 + } 1.1021 + 1.1022 + return maxBufferCount; 1.1023 +} 1.1024 + 1.1025 +GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener( 1.1026 + const wp<GonkBufferQueue::ConsumerListener>& consumerListener): 1.1027 + mConsumerListener(consumerListener) {} 1.1028 + 1.1029 +GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} 1.1030 + 1.1031 +void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() { 1.1032 + sp<GonkBufferQueue::ConsumerListener> listener(mConsumerListener.promote()); 1.1033 + if (listener != NULL) { 1.1034 + listener->onFrameAvailable(); 1.1035 + } 1.1036 +} 1.1037 + 1.1038 +void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() { 1.1039 + sp<GonkBufferQueue::ConsumerListener> listener(mConsumerListener.promote()); 1.1040 + if (listener != NULL) { 1.1041 + listener->onBuffersReleased(); 1.1042 + } 1.1043 +} 1.1044 + 1.1045 +}; // namespace android