diff options
author | Mathias Agopian <mathias@google.com> | 2013-07-20 01:02:47 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-07-20 01:02:47 +0000 |
commit | bdce8170479d0efb548514c1a290e1bfea711cfd (patch) | |
tree | 7cd97ee1e8d8842e3d229a531975f43f4502c75e /libs | |
parent | e5bb2a45e0861c7ed953373f86afe44f255f021c (diff) | |
parent | 26a6f37cc06b8014edcedbee8d5558ca7da9abe3 (diff) | |
download | frameworks_native-bdce8170479d0efb548514c1a290e1bfea711cfd.zip frameworks_native-bdce8170479d0efb548514c1a290e1bfea711cfd.tar.gz frameworks_native-bdce8170479d0efb548514c1a290e1bfea711cfd.tar.bz2 |
Merge changes Ic45929f3,Ic63f4f96,I1e703d36,I691f9507
* changes:
make sure to reset the framenumber when a buffer is marked FREE
Make ANW.setSwapInterval(0) work again
BuffferQueue disconnect is now always asynchrnous
BufferQueue improvements and APIs changes
Diffstat (limited to 'libs')
-rw-r--r-- | libs/gui/Android.mk | 1 | ||||
-rw-r--r-- | libs/gui/BufferItemConsumer.cpp | 5 | ||||
-rw-r--r-- | libs/gui/BufferQueue.cpp | 199 | ||||
-rw-r--r-- | libs/gui/ConsumerBase.cpp | 4 | ||||
-rw-r--r-- | libs/gui/CpuConsumer.cpp | 5 | ||||
-rw-r--r-- | libs/gui/DummyConsumer.cpp | 43 | ||||
-rw-r--r-- | libs/gui/GLConsumer.cpp | 16 | ||||
-rw-r--r-- | libs/gui/IGraphicBufferProducer.cpp | 35 | ||||
-rw-r--r-- | libs/gui/Surface.cpp | 16 | ||||
-rw-r--r-- | libs/gui/tests/BufferQueue_test.cpp | 14 | ||||
-rw-r--r-- | libs/gui/tests/SurfaceTextureClient_test.cpp | 10 | ||||
-rw-r--r-- | libs/gui/tests/SurfaceTexture_test.cpp | 42 |
12 files changed, 121 insertions, 269 deletions
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index c080f47..f627e5d 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -8,7 +8,6 @@ LOCAL_SRC_FILES:= \ ConsumerBase.cpp \ CpuConsumer.cpp \ DisplayEventReceiver.cpp \ - DummyConsumer.cpp \ GLConsumer.cpp \ GraphicBufferAlloc.cpp \ GuiConfig.cpp \ diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp index f5b2c7e..0f818b7 100644 --- a/libs/gui/BufferItemConsumer.cpp +++ b/libs/gui/BufferItemConsumer.cpp @@ -30,11 +30,10 @@ namespace android { BufferItemConsumer::BufferItemConsumer(const sp<BufferQueue>& bq, - uint32_t consumerUsage, int bufferCount, bool synchronousMode) : - ConsumerBase(bq) + uint32_t consumerUsage, int bufferCount, bool controlledByApp) : + ConsumerBase(bq, controlledByApp) { mBufferQueue->setConsumerUsageBits(consumerUsage); - mBufferQueue->setSynchronousMode(synchronousMode); mBufferQueue->setMaxAcquiredBufferCount(bufferCount); } diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 8d4b174..73bd488 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -30,6 +30,7 @@ #include <utils/Log.h> #include <utils/Trace.h> +#include <utils/CallStack.h> // Macros for including the BufferQueue name in log messages #define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__) @@ -63,15 +64,14 @@ static const char* scalingModeName(int scalingMode) { } } -BufferQueue::BufferQueue(bool allowSynchronousMode, - const sp<IGraphicBufferAlloc>& allocator) : +BufferQueue::BufferQueue(const sp<IGraphicBufferAlloc>& allocator) : mDefaultWidth(1), mDefaultHeight(1), mMaxAcquiredBufferCount(1), mDefaultMaxBufferCount(2), mOverrideMaxBufferCount(0), - mSynchronousMode(false), - mAllowSynchronousMode(allowSynchronousMode), + mConsumerControlledByApp(false), + mDequeueBufferCannotBlock(false), mConnectedApi(NO_CONNECTED_API), mAbandoned(false), mFrameCounter(0), @@ -109,11 +109,6 @@ status_t BufferQueue::setDefaultMaxBufferCountLocked(int count) { return NO_ERROR; } -bool BufferQueue::isSynchronousMode() const { - Mutex::Autolock lock(mMutex); - return mSynchronousMode; -} - void BufferQueue::setConsumerName(const String8& name) { Mutex::Autolock lock(mMutex); mConsumerName = name; @@ -156,21 +151,21 @@ status_t BufferQueue::setBufferCount(int bufferCount) { } // Error out if the user has dequeued buffers - int maxBufferCount = getMaxBufferCountLocked(); - for (int i=0 ; i<maxBufferCount; i++) { + for (int i=0 ; i<NUM_BUFFER_SLOTS; i++) { if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { ST_LOGE("setBufferCount: client owns some buffers"); return -EINVAL; } } - const int minBufferSlots = getMinMaxBufferCountLocked(); if (bufferCount == 0) { mOverrideMaxBufferCount = 0; mDequeueCondition.broadcast(); return NO_ERROR; } + // fine to assume async to false before we're setting the buffer count + const int minBufferSlots = getMinMaxBufferCountLocked(false); if (bufferCount < minBufferSlots) { ST_LOGE("setBufferCount: requested buffer count (%d) is less than " "minimum (%d)", bufferCount, minBufferSlots); @@ -215,7 +210,7 @@ int BufferQueue::query(int what, int* outValue) value = mDefaultBufferFormat; break; case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: - value = getMinUndequeuedBufferCountLocked(); + value = getMinUndequeuedBufferCount(false); break; case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: value = (mQueue.size() >= 2); @@ -235,15 +230,11 @@ status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) { ST_LOGE("requestBuffer: BufferQueue has been abandoned!"); return NO_INIT; } - int maxBufferCount = getMaxBufferCountLocked(); - if (slot < 0 || maxBufferCount <= slot) { + if (slot < 0 || slot >= NUM_BUFFER_SLOTS) { ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d", - maxBufferCount, slot); + NUM_BUFFER_SLOTS, slot); return BAD_VALUE; } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) { - // XXX: I vaguely recall there was some reason this can be valid, but - // for the life of me I can't recall under what circumstances that's - // the case. ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)", slot, mSlots[slot].mBufferState); return BAD_VALUE; @@ -253,7 +244,7 @@ status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) { return NO_ERROR; } -status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, +status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async, uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { ATRACE_CALL(); ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage); @@ -285,7 +276,16 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, return NO_INIT; } - const int maxBufferCount = getMaxBufferCountLocked(); + const int maxBufferCount = getMaxBufferCountLocked(async); + if (async && mOverrideMaxBufferCount) { + // FIXME: some drivers are manually setting the buffer-count (which they + // shouldn't), so we do this extra test here to handle that case. + // This is TEMPORARY, until we get this fixed. + if (mOverrideMaxBufferCount < maxBufferCount) { + ST_LOGE("dequeueBuffer: async mode is invalid with buffercount override"); + return BAD_VALUE; + } + } // Free up any buffers that are in slots beyond the max buffer // count. @@ -334,7 +334,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, // make sure the client is not trying to dequeue more buffers // than allowed. const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1); - const int minUndequeuedCount = getMinUndequeuedBufferCountLocked(); + const int minUndequeuedCount = getMinUndequeuedBufferCount(async); if (newUndequeuedCount < minUndequeuedCount) { ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) " "exceeded (dequeued=%d undequeudCount=%d)", @@ -348,6 +348,10 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, // the max buffer count to change. tryAgain = found == INVALID_BUFFER_SLOT; if (tryAgain) { + if (mDequeueBufferCannotBlock) { + ST_LOGE("dequeueBuffer: would block! returning an error instead."); + return WOULD_BLOCK; + } mDequeueCondition.wait(mMutex); } } @@ -441,38 +445,6 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, return returnFlags; } -status_t BufferQueue::setSynchronousMode(bool enabled) { - ATRACE_CALL(); - ST_LOGV("setSynchronousMode: enabled=%d", enabled); - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - ST_LOGE("setSynchronousMode: BufferQueue has been abandoned!"); - return NO_INIT; - } - - status_t err = OK; - if (!mAllowSynchronousMode && enabled) - return err; - - if (!enabled) { - // going to asynchronous mode, drain the queue - err = drainQueueLocked(); - if (err != NO_ERROR) - return err; - } - - if (mSynchronousMode != enabled) { - // - if we're going to asynchronous mode, the queue is guaranteed to be - // empty here - // - if the client set the number of buffers, we're guaranteed that - // we have at least 3 (because we don't allow less) - mSynchronousMode = enabled; - mDequeueCondition.broadcast(); - } - return err; -} - status_t BufferQueue::queueBuffer(int buf, const QueueBufferInput& input, QueueBufferOutput* output) { ATRACE_CALL(); @@ -482,9 +454,10 @@ status_t BufferQueue::queueBuffer(int buf, uint32_t transform; int scalingMode; int64_t timestamp; + bool async; sp<Fence> fence; - input.deflate(×tamp, &crop, &scalingMode, &transform, &fence); + input.deflate(×tamp, &crop, &scalingMode, &transform, &async, &fence); if (fence == NULL) { ST_LOGE("queueBuffer: fence is NULL"); @@ -511,7 +484,17 @@ status_t BufferQueue::queueBuffer(int buf, ST_LOGE("queueBuffer: BufferQueue has been abandoned!"); return NO_INIT; } - int maxBufferCount = getMaxBufferCountLocked(); + + const int maxBufferCount = getMaxBufferCountLocked(async); + if (async && mOverrideMaxBufferCount) { + // FIXME: some drivers are manually setting the buffer-count (which they + // shouldn't), so we do this extra test here to handle that case. + // This is TEMPORARY, until we get this fixed. + if (mOverrideMaxBufferCount < maxBufferCount) { + ST_LOGE("queueBuffer: async mode is invalid with buffercount override"); + return BAD_VALUE; + } + } if (buf < 0 || buf >= maxBufferCount) { ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d", maxBufferCount, buf); @@ -557,31 +540,30 @@ status_t BufferQueue::queueBuffer(int buf, item.mFrameNumber = mFrameCounter; item.mBuf = buf; item.mFence = fence; + item.mIsDroppable = mDequeueBufferCannotBlock || async; - if (mSynchronousMode) { - // In synchronous mode we queue all buffers in a FIFO. + if (mQueue.empty()) { + // when the queue is empty, we can ignore "mDequeueBufferCannotBlock", and + // simply queue this buffer. mQueue.push_back(item); - - // Synchronous mode always signals that an additional frame should - // be consumed. listener = mConsumerListener; } else { - // In asynchronous mode we only keep the most recent buffer. - if (mQueue.empty()) { - mQueue.push_back(item); - - // Asynchronous mode only signals that a frame should be - // consumed if no previous frame was pending. If a frame were - // pending then the consumer would have already been notified. - listener = mConsumerListener; - } else { - Fifo::iterator front(mQueue.begin()); + // when the queue is not empty, we need to look at the front buffer + // state and see if we need to replace it. + Fifo::iterator front(mQueue.begin()); + if (front->mIsDroppable) { // buffer slot currently queued is marked free if still tracked if (stillTracking(front)) { mSlots[front->mBuf].mBufferState = BufferSlot::FREE; + // reset the frame number of the freed buffer so that it is the first in + // line to be dequeued again. + mSlots[front->mBuf].mFrameNumber = 0; } - // and we record the new buffer index in the queued list + // and we record the new buffer in the queued list *front = item; + } else { + mQueue.push_back(item); + listener = mConsumerListener; } } @@ -611,10 +593,9 @@ void BufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) { return; } - int maxBufferCount = getMaxBufferCountLocked(); - if (buf < 0 || buf >= maxBufferCount) { + if (buf < 0 || buf >= NUM_BUFFER_SLOTS) { ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d", - maxBufferCount, buf); + NUM_BUFFER_SLOTS, buf); return; } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", @@ -630,7 +611,7 @@ void BufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) { mDequeueCondition.broadcast(); } -status_t BufferQueue::connect(int api, QueueBufferOutput* output) { +status_t BufferQueue::connect(int api, bool producerControlledByApp, QueueBufferOutput* output) { ATRACE_CALL(); ST_LOGV("connect: api=%d", api); Mutex::Autolock lock(mMutex); @@ -667,6 +648,7 @@ status_t BufferQueue::connect(int api, QueueBufferOutput* output) { } mBufferHasBeenQueued = false; + mDequeueBufferCannotBlock = mConsumerControlledByApp && producerControlledByApp; return err; } @@ -693,7 +675,7 @@ status_t BufferQueue::disconnect(int api) { case NATIVE_WINDOW_API_MEDIA: case NATIVE_WINDOW_API_CAMERA: if (mConnectedApi == api) { - drainQueueAndFreeBuffersLocked(); + freeAllBuffersLocked(); mConnectedApi = NO_CONNECTED_API; mDequeueCondition.broadcast(); listener = mConsumerListener; @@ -739,12 +721,11 @@ void BufferQueue::dump(String8& result, const char* prefix) const { fifoSize++; } - int maxBufferCount = getMaxBufferCountLocked(); result.appendFormat( - "%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " + "%s-BufferQueue mMaxAcquiredBufferCount=%d, mDequeueBufferCannotBlock=%d, default-size=[%dx%d], " "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n", - prefix, maxBufferCount, mSynchronousMode, mDefaultWidth, + prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, mDefaultWidth, mDefaultHeight, mDefaultBufferFormat, mTransformHint, fifoSize, fifo.string()); @@ -760,16 +741,25 @@ void BufferQueue::dump(String8& result, const char* prefix) const { } } stateName; + // just trim the free buffers to not spam the dump + int maxBufferCount = 0; + for (int i=NUM_BUFFER_SLOTS-1 ; i>=0 ; i--) { + const BufferSlot& slot(mSlots[i]); + if ((slot.mBufferState != BufferSlot::FREE) || (slot.mGraphicBuffer != NULL)) { + maxBufferCount = i+1; + break; + } + } + for (int i=0 ; i<maxBufferCount ; i++) { const BufferSlot& slot(mSlots[i]); + const sp<GraphicBuffer>& buf(slot.mGraphicBuffer); result.appendFormat( "%s%s[%02d:%p] state=%-8s", - prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, - slot.mGraphicBuffer.get(), + prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, buf.get(), stateName(slot.mBufferState) ); - const sp<GraphicBuffer>& buf(slot.mGraphicBuffer); if (buf != NULL) { result.appendFormat( ", %p [%4ux%4u:%4u,%3X]", @@ -799,8 +789,6 @@ void BufferQueue::freeBufferLocked(int slot) { } void BufferQueue::freeAllBuffersLocked() { - ALOGD_IF(!mQueue.isEmpty(), - "freeAllBuffersLocked called with non-empty mQueue"); mBufferHasBeenQueued = false; for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { freeBufferLocked(i); @@ -950,7 +938,8 @@ status_t BufferQueue::releaseBuffer( return NO_ERROR; } -status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) { +status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener, + bool controlledByApp) { ST_LOGV("consumerConnect"); Mutex::Autolock lock(mMutex); @@ -964,6 +953,7 @@ status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListen } mConsumerListener = consumerListener; + mConsumerControlledByApp = controlledByApp; return NO_ERROR; } @@ -1053,40 +1043,17 @@ status_t BufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { return NO_ERROR; } -status_t BufferQueue::drainQueueLocked() { - while (mSynchronousMode && mQueue.size() > 1) { - mDequeueCondition.wait(mMutex); - if (mAbandoned) { - ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!"); - return NO_INIT; - } - if (mConnectedApi == NO_CONNECTED_API) { - ST_LOGE("drainQueueLocked: BufferQueue is not connected!"); - return NO_INIT; - } - } - return NO_ERROR; -} - -status_t BufferQueue::drainQueueAndFreeBuffersLocked() { - status_t err = drainQueueLocked(); - if (err == NO_ERROR) { - freeAllBuffersLocked(); - } - return err; -} - -int BufferQueue::getMinMaxBufferCountLocked() const { - return getMinUndequeuedBufferCountLocked() + 1; +int BufferQueue::getMinUndequeuedBufferCount(bool async) const { + return (mDequeueBufferCannotBlock || async) ? + mMaxAcquiredBufferCount+1 : mMaxAcquiredBufferCount; } -int BufferQueue::getMinUndequeuedBufferCountLocked() const { - return mSynchronousMode ? mMaxAcquiredBufferCount : - mMaxAcquiredBufferCount + 1; +int BufferQueue::getMinMaxBufferCountLocked(bool async) const { + return getMinUndequeuedBufferCount(async) + 1; } -int BufferQueue::getMaxBufferCountLocked() const { - int minMaxBufferCount = getMinMaxBufferCountLocked(); +int BufferQueue::getMaxBufferCountLocked(bool async) const { + int minMaxBufferCount = getMinMaxBufferCountLocked(async); int maxBufferCount = mDefaultMaxBufferCount; if (maxBufferCount < minMaxBufferCount) { diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index deb2646..cd94ce1 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -51,7 +51,7 @@ static int32_t createProcessUniqueId() { return android_atomic_inc(&globalCounter); } -ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue) : +ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue, bool controlledByApp) : mAbandoned(false), mBufferQueue(bufferQueue) { // Choose a name using the PID and a process-unique ID. @@ -66,7 +66,7 @@ ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue) : listener = static_cast<BufferQueue::ConsumerListener*>(this); proxy = new BufferQueue::ProxyConsumerListener(listener); - status_t err = mBufferQueue->consumerConnect(proxy); + status_t err = mBufferQueue->consumerConnect(proxy, controlledByApp); if (err != NO_ERROR) { CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)", strerror(-err), err); diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp index adddfc2..b8c00af 100644 --- a/libs/gui/CpuConsumer.cpp +++ b/libs/gui/CpuConsumer.cpp @@ -31,15 +31,14 @@ namespace android { CpuConsumer::CpuConsumer(const sp<BufferQueue>& bq, - uint32_t maxLockedBuffers, bool synchronousMode) : - ConsumerBase(bq), + uint32_t maxLockedBuffers, bool controlledByApp) : + ConsumerBase(bq, controlledByApp), mMaxLockedBuffers(maxLockedBuffers), mCurrentLockedBuffers(0) { // Create tracking entries for locked buffers mAcquiredBuffers.insertAt(0, maxLockedBuffers); - mBufferQueue->setSynchronousMode(synchronousMode); mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); mBufferQueue->setMaxAcquiredBufferCount(maxLockedBuffers); } diff --git a/libs/gui/DummyConsumer.cpp b/libs/gui/DummyConsumer.cpp deleted file mode 100644 index be47e0e..0000000 --- a/libs/gui/DummyConsumer.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "DummyConsumer" -// #define LOG_NDEBUG 0 - -#include <gui/DummyConsumer.h> - -#include <utils/Log.h> -#include <utils/String8.h> - -namespace android { - -DummyConsumer::DummyConsumer() { - ALOGV("DummyConsumer"); -} - -DummyConsumer::~DummyConsumer() { - ALOGV("~DummyConsumer"); -} - -void DummyConsumer::onFrameAvailable() { - ALOGV("onFrameAvailable"); -} - -void DummyConsumer::onBuffersReleased() { - ALOGV("onBuffersReleased"); -} - -}; // namespace android diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index 07f27c3..92f07eb 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -79,8 +79,8 @@ static void mtxMul(float out[16], const float a[16], const float b[16]); GLConsumer::GLConsumer(const sp<BufferQueue>& bq, GLuint tex, - GLenum texTarget, bool useFenceSync) : - ConsumerBase(bq), + GLenum texTarget, bool useFenceSync, bool isControlledByApp) : + ConsumerBase(bq, isControlledByApp), mCurrentTransform(0), mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mCurrentFence(Fence::NO_FENCE), @@ -844,11 +844,6 @@ status_t GLConsumer::doGLFenceWaitLocked() const { return NO_ERROR; } -bool GLConsumer::isSynchronousMode() const { - Mutex::Autolock lock(mMutex); - return mBufferQueue->isSynchronousMode(); -} - void GLConsumer::freeBufferLocked(int slotIndex) { ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); if (slotIndex == mCurrentTexture) { @@ -891,13 +886,6 @@ status_t GLConsumer::setTransformHint(uint32_t hint) { return mBufferQueue->setTransformHint(hint); } -// Used for refactoring BufferQueue from GLConsumer -// Should not be in final interface once users of GLConsumer are clean up. -status_t GLConsumer::setSynchronousMode(bool enabled) { - Mutex::Autolock lock(mMutex); - return mBufferQueue->setSynchronousMode(enabled); -} - void GLConsumer::dumpLocked(String8& result, const char* prefix) const { result.appendFormat( diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 63d7628..2e561df 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -37,7 +37,6 @@ enum { QUEUE_BUFFER, CANCEL_BUFFER, QUERY, - SET_SYNCHRONOUS_MODE, CONNECT, DISCONNECT, }; @@ -81,10 +80,11 @@ public: return result; } - virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, + virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async, uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); + data.writeInt32(async); data.writeInt32(w); data.writeInt32(h); data.writeInt32(format); @@ -142,22 +142,11 @@ public: return result; } - virtual status_t setSynchronousMode(bool enabled) { - Parcel data, reply; - data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); - data.writeInt32(enabled); - status_t result = remote()->transact(SET_SYNCHRONOUS_MODE, data, &reply); - if (result != NO_ERROR) { - return result; - } - result = reply.readInt32(); - return result; - } - - virtual status_t connect(int api, QueueBufferOutput* output) { + virtual status_t connect(int api, bool producerControlledByApp, QueueBufferOutput* output) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); data.writeInt32(api); + data.writeInt32(producerControlledByApp); status_t result = remote()->transact(CONNECT, data, &reply); if (result != NO_ERROR) { return result; @@ -209,13 +198,14 @@ status_t BnGraphicBufferProducer::onTransact( } break; case DEQUEUE_BUFFER: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); + bool async = data.readInt32(); uint32_t w = data.readInt32(); uint32_t h = data.readInt32(); uint32_t format = data.readInt32(); uint32_t usage = data.readInt32(); int buf; sp<Fence> fence; - int result = dequeueBuffer(&buf, &fence, w, h, format, usage); + int result = dequeueBuffer(&buf, &fence, async, w, h, format, usage); reply->writeInt32(buf); reply->writeInt32(fence != NULL); if (fence != NULL) { @@ -252,20 +242,14 @@ status_t BnGraphicBufferProducer::onTransact( reply->writeInt32(res); return NO_ERROR; } break; - case SET_SYNCHRONOUS_MODE: { - CHECK_INTERFACE(IGraphicBufferProducer, data, reply); - bool enabled = data.readInt32(); - status_t res = setSynchronousMode(enabled); - reply->writeInt32(res); - return NO_ERROR; - } break; case CONNECT: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); int api = data.readInt32(); + bool producerControlledByApp = data.readInt32(); QueueBufferOutput* const output = reinterpret_cast<QueueBufferOutput *>( reply->writeInplace(sizeof(QueueBufferOutput))); - status_t res = connect(api, output); + status_t res = connect(api, producerControlledByApp, output); reply->writeInt32(res); return NO_ERROR; } break; @@ -292,6 +276,7 @@ size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const + sizeof(crop) + sizeof(scalingMode) + sizeof(transform) + + sizeof(async) + fence->getFlattenedSize(); } @@ -309,6 +294,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::flatten(void* buffer, size_t memcpy(p, &crop, sizeof(crop)); p += sizeof(crop); memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode); memcpy(p, &transform, sizeof(transform)); p += sizeof(transform); + memcpy(p, &async, sizeof(async)); p += sizeof(async); err = fence->flatten(p, size - (p - (char*)buffer), fds, count); return err; } @@ -322,6 +308,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten(void const* buffer, memcpy(&crop, p, sizeof(crop)); p += sizeof(crop); memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode); memcpy(&transform, p, sizeof(transform)); p += sizeof(transform); + memcpy(&async, p, sizeof(async)); p += sizeof(async); fence = new Fence(); err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count); return err; diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index a616c1e..998ea8a 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -37,7 +37,8 @@ namespace android { Surface::Surface( - const sp<IGraphicBufferProducer>& bufferProducer) + const sp<IGraphicBufferProducer>& bufferProducer, + bool controlledByApp) : mGraphicBufferProducer(bufferProducer) { // Initialize the ANativeWindow function pointers. @@ -71,6 +72,8 @@ Surface::Surface( mTransformHint = 0; mConsumerRunningBehind = false; mConnectedToCpu = false; + mProducerControlledByApp = true; + mSwapIntervalZero = false; } Surface::~Surface() { @@ -160,7 +163,6 @@ int Surface::setSwapInterval(int interval) { // EGL specification states: // interval is silently clamped to minimum and maximum implementation // dependent values before being stored. - // Although we don't have to, we apply the same logic here. if (interval < minSwapInterval) interval = minSwapInterval; @@ -168,9 +170,9 @@ int Surface::setSwapInterval(int interval) { if (interval > maxSwapInterval) interval = maxSwapInterval; - status_t res = mGraphicBufferProducer->setSynchronousMode(interval ? true : false); + mSwapIntervalZero = (interval == 0); - return res; + return NO_ERROR; } int Surface::dequeueBuffer(android_native_buffer_t** buffer, @@ -182,7 +184,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int reqW = mReqWidth ? mReqWidth : mUserWidth; int reqH = mReqHeight ? mReqHeight : mUserHeight; sp<Fence> fence; - status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, + status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, mSwapIntervalZero, reqW, reqH, mReqFormat, mReqUsage); if (result < 0) { ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d)" @@ -278,7 +280,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE); IGraphicBufferProducer::QueueBufferOutput output; IGraphicBufferProducer::QueueBufferInput input(timestamp, crop, mScalingMode, - mTransform, fence); + mTransform, mSwapIntervalZero, fence); status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output); if (err != OK) { ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err); @@ -486,7 +488,7 @@ int Surface::connect(int api) { ALOGV("Surface::connect"); Mutex::Autolock lock(mMutex); IGraphicBufferProducer::QueueBufferOutput output; - int err = mGraphicBufferProducer->connect(api, &output); + int err = mGraphicBufferProducer->connect(api, mProducerControlledByApp, &output); if (err == NO_ERROR) { uint32_t numPendingBuffers = 0; output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint, diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp index 9682987..b691fc1 100644 --- a/libs/gui/tests/BufferQueue_test.cpp +++ b/libs/gui/tests/BufferQueue_test.cpp @@ -62,21 +62,21 @@ struct DummyConsumer : public BufferQueue::ConsumerListener { TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) { sp<DummyConsumer> dc(new DummyConsumer); - mBQ->consumerConnect(dc); + mBQ->consumerConnect(dc, false); IGraphicBufferProducer::QueueBufferOutput qbo; - mBQ->connect(NATIVE_WINDOW_API_CPU, &qbo); + mBQ->connect(NATIVE_WINDOW_API_CPU, false, &qbo); mBQ->setBufferCount(4); int slot; sp<Fence> fence; sp<GraphicBuffer> buf; IGraphicBufferProducer::QueueBufferInput qbi(0, Rect(0, 0, 1, 1), - NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); + NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE); BufferQueue::BufferItem item; for (int i = 0; i < 2; i++) { ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, - mBQ->dequeueBuffer(&slot, &fence, 1, 1, 0, + mBQ->dequeueBuffer(&slot, &fence, false, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN)); ASSERT_EQ(OK, mBQ->requestBuffer(slot, &buf)); ASSERT_EQ(OK, mBQ->queueBuffer(slot, qbi, &qbo)); @@ -84,7 +84,7 @@ TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) { } ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, - mBQ->dequeueBuffer(&slot, &fence, 1, 1, 0, + mBQ->dequeueBuffer(&slot, &fence, false, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN)); ASSERT_EQ(OK, mBQ->requestBuffer(slot, &buf)); ASSERT_EQ(OK, mBQ->queueBuffer(slot, qbi, &qbo)); @@ -95,7 +95,7 @@ TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) { TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) { sp<DummyConsumer> dc(new DummyConsumer); - mBQ->consumerConnect(dc); + mBQ->consumerConnect(dc, false); ASSERT_EQ(BAD_VALUE, mBQ->setMaxAcquiredBufferCount(0)); ASSERT_EQ(BAD_VALUE, mBQ->setMaxAcquiredBufferCount(-3)); @@ -106,7 +106,7 @@ TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) { sp<DummyConsumer> dc(new DummyConsumer); - mBQ->consumerConnect(dc); + mBQ->consumerConnect(dc, false); ASSERT_EQ(OK, mBQ->setMaxAcquiredBufferCount(1)); ASSERT_EQ(OK, mBQ->setMaxAcquiredBufferCount(2)); diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp index 46bcb22..158c94b 100644 --- a/libs/gui/tests/SurfaceTextureClient_test.cpp +++ b/libs/gui/tests/SurfaceTextureClient_test.cpp @@ -338,7 +338,7 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) { TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) { android_native_buffer_t* buf[3]; - ASSERT_EQ(OK, mST->setSynchronousMode(false)); + ASSERT_EQ(OK, mANW->setSwapInterval(mANW.get(), 0)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); @@ -346,7 +346,7 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) { EXPECT_EQ(OK, mST->updateTexImage()); EXPECT_EQ(OK, mST->updateTexImage()); - ASSERT_EQ(OK, mST->setSynchronousMode(true)); + ASSERT_EQ(OK, mANW->setSwapInterval(mANW.get(), 1)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); @@ -361,7 +361,6 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) { TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) { android_native_buffer_t* buf[3]; - ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); @@ -382,7 +381,6 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) { TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) { android_native_buffer_t* buf[3]; - ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1])); @@ -403,7 +401,6 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) { TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) { android_native_buffer_t* buf[3]; - ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); @@ -429,7 +426,6 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) { TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) { android_native_buffer_t* buf[3]; android_native_buffer_t* firstBuf; - ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3)); ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &firstBuf)); ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), firstBuf, -1)); @@ -449,7 +445,6 @@ TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) { android_native_buffer_t* buf[3]; - ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3)); // We should be able to dequeue all the buffers before we've queued mANWy. @@ -528,7 +523,6 @@ TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeWaitRetire) { }; android_native_buffer_t* buf[3]; - ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3)); // dequeue/queue/update so we have a current buffer ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0])); diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp index d97521a..e6d87db 100644 --- a/libs/gui/tests/SurfaceTexture_test.cpp +++ b/libs/gui/tests/SurfaceTexture_test.cpp @@ -944,7 +944,6 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { enum { texHeight = 16 }; enum { numFrames = 1024 }; - ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true)); ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2)); ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); @@ -1211,10 +1210,8 @@ TEST_F(SurfaceTextureGLTest, DisconnectStressTest) { sp<ANativeWindow> mANW; }; - ASSERT_EQ(OK, mST->setSynchronousMode(true)); - sp<DisconnectWaiter> dw(new DisconnectWaiter()); - mST->getBufferQueue()->consumerConnect(dw); + mST->getBufferQueue()->consumerConnect(dw, false); sp<Thread> pt(new ProducerThread(mANW)); @@ -1237,8 +1234,6 @@ TEST_F(SurfaceTextureGLTest, DisconnectStressTest) { // when it is disconnected and reconnected. Otherwise it will // attempt to release a buffer that it does not owned TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) { - ASSERT_EQ(OK, mST->setSynchronousMode(true)); - ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_EGL)); @@ -1258,8 +1253,6 @@ TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) { ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_EGL)); - ASSERT_EQ(OK, mST->setSynchronousMode(true)); - EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); @@ -1272,8 +1265,6 @@ TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) { } TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) { - ASSERT_EQ(OK, mST->setSynchronousMode(true)); - ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)); @@ -1306,8 +1297,6 @@ TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) { // the image such that it has the same aspect ratio as the // default buffer size TEST_F(SurfaceTextureGLTest, CroppedScalingMode) { - ASSERT_EQ(OK, mST->setSynchronousMode(true)); - ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)); @@ -1417,7 +1406,6 @@ TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) { Mutex mMutex; }; - ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2)); sp<Thread> pt(new ProducerThread(mANW)); @@ -1810,32 +1798,6 @@ TEST_F(SurfaceTextureGLToGLTest, EglMakeCurrentAfterConsumerDeathUnrefsBuffers) EXPECT_EQ(1, buffer->getStrongCount()); } - -TEST_F(SurfaceTextureGLToGLTest, EglSurfaceDefaultsToSynchronousMode) { - // This test requires 3 buffers to run on a single thread. - mST->setDefaultMaxBufferCount(3); - - ASSERT_TRUE(mST->isSynchronousMode()); - - for (int i = 0; i < 10; i++) { - // Produce a frame - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, - mProducerEglSurface, mProducerEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - - // Consume a frame - EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, - mEglContext)); - ASSERT_EQ(EGL_SUCCESS, eglGetError()); - ASSERT_EQ(NO_ERROR, mST->updateTexImage()); - } - - ASSERT_TRUE(mST->isSynchronousMode()); -} - TEST_F(SurfaceTextureGLToGLTest, TexturingFromUserSizedGLFilledBuffer) { enum { texWidth = 64 }; enum { texHeight = 64 }; @@ -2285,7 +2247,6 @@ TEST_F(SurfaceTextureGLThreadToGLTest, } }; - ASSERT_EQ(OK, mST->setSynchronousMode(true)); ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2)); runProducerThread(new PT()); @@ -2826,7 +2787,6 @@ TEST_F(SurfaceTextureMultiContextGLTest, TEST_F(SurfaceTextureMultiContextGLTest, UpdateTexImageSucceedsForBufferConsumedBeforeDetach) { - ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true)); ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2)); // produce two frames and consume them both on the primary context |