Change BufferQueue into producer/consumer wrapper

Now that BufferQueue has been split into core + producer + consumer,
rewrite BufferQueue to be a thin layer over a producer and consumer
interface. Eventually, this layer will be deprecated in favor of
only using either the producer or consumer interface, as applicable.

Change-Id: I340ae5f5b633b244fb594615ff52ba50b9e2f7e4
This commit is contained in:
Dan Stoza 2014-03-03 10:16:19 -08:00
parent 289ade165e
commit 3e96f1982f
11 changed files with 371 additions and 1510 deletions

View File

@ -17,23 +17,16 @@
#ifndef ANDROID_GUI_BUFFERQUEUE_H
#define ANDROID_GUI_BUFFERQUEUE_H
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <gui/BufferQueueProducer.h>
#include <gui/BufferQueueConsumer.h>
#include <gui/IConsumerListener.h>
// These are only required to keep other parts of the framework with incomplete
// dependencies building successfully
#include <gui/IGraphicBufferAlloc.h>
#include <binder/IBinder.h>
#include <gui/IConsumerListener.h>
#include <gui/IGraphicBufferAlloc.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/IGraphicBufferConsumer.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
#include <utils/String8.h>
#include <utils/Vector.h>
#include <utils/threads.h>
namespace android {
// ----------------------------------------------------------------------------
@ -317,264 +310,8 @@ public:
virtual void dump(String8& result, const char* prefix) const;
private:
// The default API number used to indicate no producer client is connected.
enum { NO_CONNECTED_API = 0 };
// Aliases for using enums from <IGraphicBufferConsumer.h>
enum { STALE_BUFFER_SLOT = IGraphicBufferConsumer::STALE_BUFFER_SLOT };
// freeBufferLocked frees the GraphicBuffer and sync resources for the
// given slot.
void freeBufferLocked(int index);
// freeAllBuffersLocked frees the GraphicBuffer and sync resources for
// all slots.
void freeAllBuffersLocked();
// setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
// that will be used if the producer does not override the buffer slot
// count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
// The initial default is 2.
status_t setDefaultMaxBufferCountLocked(int count);
// getMinUndequeuedBufferCount returns the minimum number of buffers
// that must remain in a state other than DEQUEUED.
// The async parameter tells whether we're in asynchronous mode.
int getMinUndequeuedBufferCount(bool async) const;
// getMinBufferCountLocked returns the minimum number of buffers allowed
// given the current BufferQueue state.
// The async parameter tells whether we're in asynchronous mode.
int getMinMaxBufferCountLocked(bool async) const;
// getMaxBufferCountLocked returns the maximum number of buffers that can
// be allocated at once. This value depends upon the following member
// variables:
//
// mDequeueBufferCannotBlock
// mMaxAcquiredBufferCount
// mDefaultMaxBufferCount
// mOverrideMaxBufferCount
// async parameter
//
// Any time one of these member variables is changed while a producer is
// connected, mDequeueCondition must be broadcast.
int getMaxBufferCountLocked(bool async) const;
// stillTracking returns true iff the buffer item is still being tracked
// in one of the slots.
bool stillTracking(const BufferItem *item) const;
struct BufferSlot {
BufferSlot()
: mEglDisplay(EGL_NO_DISPLAY),
mBufferState(BufferSlot::FREE),
mRequestBufferCalled(false),
mFrameNumber(0),
mEglFence(EGL_NO_SYNC_KHR),
mAcquireCalled(false),
mNeedsCleanupOnRelease(false) {
}
// mGraphicBuffer points to the buffer allocated for this slot or is NULL
// if no buffer has been allocated.
sp<GraphicBuffer> mGraphicBuffer;
// mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects.
EGLDisplay mEglDisplay;
// BufferState represents the different states in which a buffer slot
// can be. All slots are initially FREE.
enum BufferState {
// FREE indicates that the buffer is available to be dequeued
// by the producer. The buffer may be in use by the consumer for
// a finite time, so the buffer must not be modified until the
// associated fence is signaled.
//
// The slot is "owned" by BufferQueue. It transitions to DEQUEUED
// when dequeueBuffer is called.
FREE = 0,
// DEQUEUED indicates that the buffer has been dequeued by the
// producer, but has not yet been queued or canceled. The
// producer may modify the buffer's contents as soon as the
// associated ready fence is signaled.
//
// The slot is "owned" by the producer. It can transition to
// QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).
DEQUEUED = 1,
// QUEUED indicates that the buffer has been filled by the
// producer and queued for use by the consumer. The buffer
// contents may continue to be modified for a finite time, so
// the contents must not be accessed until the associated fence
// is signaled.
//
// The slot is "owned" by BufferQueue. It can transition to
// ACQUIRED (via acquireBuffer) or to FREE (if another buffer is
// queued in asynchronous mode).
QUEUED = 2,
// ACQUIRED indicates that the buffer has been acquired by the
// consumer. As with QUEUED, the contents must not be accessed
// by the consumer until the fence is signaled.
//
// The slot is "owned" by the consumer. It transitions to FREE
// when releaseBuffer is called.
ACQUIRED = 3
};
// mBufferState is the current state of this buffer slot.
BufferState mBufferState;
// mRequestBufferCalled is used for validating that the producer did
// call requestBuffer() when told to do so. Technically this is not
// needed but useful for debugging and catching producer bugs.
bool mRequestBufferCalled;
// mFrameNumber is the number of the queued frame for this slot. This
// is used to dequeue buffers in LRU order (useful because buffers
// may be released before their release fence is signaled).
uint64_t mFrameNumber;
// mEglFence is the EGL sync object that must signal before the buffer
// associated with this buffer slot may be dequeued. It is initialized
// to EGL_NO_SYNC_KHR when the buffer is created and may be set to a
// new sync object in releaseBuffer. (This is deprecated in favor of
// mFence, below.)
EGLSyncKHR mEglFence;
// mFence is a fence which will signal when work initiated by the
// previous owner of the buffer is finished. When the buffer is FREE,
// the fence indicates when the consumer has finished reading
// from the buffer, or when the producer has finished writing if it
// called cancelBuffer after queueing some writes. When the buffer is
// QUEUED, it indicates when the producer has finished filling the
// buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been
// passed to the consumer or producer along with ownership of the
// buffer, and mFence is set to NO_FENCE.
sp<Fence> mFence;
// Indicates whether this buffer has been seen by a consumer yet
bool mAcquireCalled;
// Indicates whether this buffer needs to be cleaned up by the
// consumer. This is set when a buffer in ACQUIRED state is freed.
// It causes releaseBuffer to return STALE_BUFFER_SLOT.
bool mNeedsCleanupOnRelease;
};
// mSlots is the array of buffer slots that must be mirrored on the
// producer side. This allows buffer ownership to be transferred between
// the producer and consumer without sending a GraphicBuffer over binder.
// The entire array is initialized to NULL at construction time, and
// buffers are allocated for a slot when requestBuffer is called with
// that slot's index.
BufferSlot mSlots[NUM_BUFFER_SLOTS];
// mDefaultWidth holds the default width of allocated buffers. It is used
// in dequeueBuffer() if a width and height of zero is specified.
uint32_t mDefaultWidth;
// mDefaultHeight holds the default height of allocated buffers. It is used
// in dequeueBuffer() if a width and height of zero is specified.
uint32_t mDefaultHeight;
// mMaxAcquiredBufferCount is the number of buffers that the consumer may
// acquire at one time. It defaults to 1 and can be changed by the
// consumer via the setMaxAcquiredBufferCount method, but this may only be
// done when no producer is connected to the BufferQueue.
//
// This value is used to derive the value returned for the
// MIN_UNDEQUEUED_BUFFERS query by the producer.
int mMaxAcquiredBufferCount;
// mDefaultMaxBufferCount is the default limit on the number of buffers
// that will be allocated at one time. This default limit is set by the
// consumer. The limit (as opposed to the default limit) may be
// overridden by the producer.
int mDefaultMaxBufferCount;
// mOverrideMaxBufferCount is the limit on the number of buffers that will
// be allocated at one time. This value is set by the image producer by
// calling setBufferCount. The default is zero, which means the producer
// doesn't care about the number of buffers in the pool. In that case
// mDefaultMaxBufferCount is used as the limit.
int mOverrideMaxBufferCount;
// mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
// allocate new GraphicBuffer objects.
sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
// mConsumerListener is used to notify the connected consumer of
// asynchronous events that it may wish to react to. It is initially set
// to NULL and is written by consumerConnect and consumerDisconnect.
sp<IConsumerListener> mConsumerListener;
// mConsumerControlledByApp whether the connected consumer is controlled by the
// application.
bool mConsumerControlledByApp;
// mDequeueBufferCannotBlock whether dequeueBuffer() isn't allowed to block.
// this flag is set during connect() when both consumer and producer are controlled
// by the application.
bool mDequeueBufferCannotBlock;
// mUseAsyncBuffer whether an extra buffer is used in async mode to prevent
// dequeueBuffer() from ever blocking.
bool mUseAsyncBuffer;
// mConnectedApi indicates the producer API that is currently connected
// to this BufferQueue. It defaults to NO_CONNECTED_API (= 0), and gets
// updated by the connect and disconnect methods.
int mConnectedApi;
// mDequeueCondition condition used for dequeueBuffer in synchronous mode
mutable Condition mDequeueCondition;
// mQueue is a FIFO of queued buffers used in synchronous mode
typedef Vector<BufferItem> Fifo;
Fifo mQueue;
// mAbandoned indicates that the BufferQueue will no longer be used to
// consume image buffers pushed to it using the IGraphicBufferProducer
// interface. It is initialized to false, and set to true in the
// consumerDisconnect method. A BufferQueue that has been abandoned will
// return the NO_INIT error from all IGraphicBufferProducer methods
// capable of returning an error.
bool mAbandoned;
// mConsumerName is a string used to identify the BufferQueue in log
// messages. It is set by the setConsumerName method.
String8 mConsumerName;
// mMutex is the mutex used to prevent concurrent access to the member
// variables of BufferQueue objects. It must be locked whenever the
// member variables are accessed.
mutable Mutex mMutex;
// mFrameCounter is the free running counter, incremented on every
// successful queueBuffer call, and buffer allocation.
uint64_t mFrameCounter;
// mBufferHasBeenQueued is true once a buffer has been queued. It is
// reset when something causes all buffers to be freed (e.g. changing the
// buffer count).
bool mBufferHasBeenQueued;
// mDefaultBufferFormat can be set so it will override
// the buffer format when it isn't specified in dequeueBuffer
uint32_t mDefaultBufferFormat;
// mConsumerUsageBits contains flags the consumer wants for GraphicBuffers
uint32_t mConsumerUsageBits;
// mTransformHint is used to optimize for screen rotations
uint32_t mTransformHint;
// mConnectedProducerToken is used to set a binder death notification on the producer
sp<IBinder> mConnectedProducerToken;
sp<BufferQueueProducer> mProducer;
sp<BufferQueueConsumer> mConsumer;
};
// ----------------------------------------------------------------------------

View File

@ -20,7 +20,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueDefs.h>
#include <gui/IGraphicBufferConsumer.h>
namespace android {
@ -136,10 +136,34 @@ public:
// dump our state in a String
virtual void dump(String8& result, const char* prefix) const;
// Functions required for backwards compatibility.
// These will be modified/renamed in IGraphicBufferConsumer and will be
// removed from this class at that time. See b/13306289.
virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
EGLDisplay display, EGLSyncKHR fence,
const sp<Fence>& releaseFence) {
return releaseBuffer(buf, frameNumber, releaseFence, display, fence);
}
virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
bool controlledByApp) {
return connect(consumer, controlledByApp);
}
virtual status_t consumerDisconnect() { return disconnect(); }
// End functions required for backwards compatibility
private:
sp<BufferQueueCore> mCore;
BufferQueueCore::SlotsType& mSlots;
String8 mConsumerName; // Cached from mCore. Updated on setConsumerName.
// This references mCore->mSlots. Lock mCore->mMutex while accessing.
BufferQueueDefs::SlotsType& mSlots;
// This is a cached copy of the name stored in the BufferQueueCore.
// It's updated during setConsumerName.
String8 mConsumerName;
}; // class BufferQueueConsumer

View File

@ -17,6 +17,7 @@
#ifndef ANDROID_GUI_BUFFERQUEUECORE_H
#define ANDROID_GUI_BUFFERQUEUECORE_H
#include <gui/BufferQueueDefs.h>
#include <gui/BufferSlot.h>
#include <utils/Condition.h>
@ -54,22 +55,17 @@ class BufferQueueCore : public virtual RefBase {
friend class BufferQueueConsumer;
public:
// BufferQueue will keep track of at most this value of buffers. Attempts
// at runtime to increase the number of buffers past this will fail.
enum { NUM_BUFFER_SLOTS = 32 };
// Used as a placeholder slot number when the value isn't pointing to an
// existing buffer.
enum { INVALID_BUFFER_SLOT = -1 }; // TODO: Extract from IGBC::BufferItem
// We reserve two slots in order to guarantee that the producer and
// consumer can run asynchronously.
enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 };
enum { MAX_MAX_ACQUIRED_BUFFERS = BufferQueueDefs::NUM_BUFFER_SLOTS - 2 };
// The default API number used to indicate that no producer is connected
enum { NO_CONNECTED_API = 0 };
typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
typedef Vector<BufferItem> Fifo;
// BufferQueueCore manages a pool of gralloc memory slots to be used by
@ -79,38 +75,159 @@ public:
virtual ~BufferQueueCore();
private:
// Dump our state in a string
void dump(String8& result, const char* prefix) const;
// getMinUndequeuedBufferCountLocked returns the minimum number of buffers
// that must remain in a state other than DEQUEUED. The async parameter
// tells whether we're in asynchronous mode.
int getMinUndequeuedBufferCountLocked(bool async) const;
// getMinMaxBufferCountLocked returns the minimum number of buffers allowed
// given the current BufferQueue state. The async parameter tells whether
// we're in asynchonous mode.
int getMinMaxBufferCountLocked(bool async) const;
// getMaxBufferCountLocked returns the maximum number of buffers that can be
// allocated at once. This value depends on the following member variables:
//
// mDequeueBufferCannotBlock
// mMaxAcquiredBufferCount
// mDefaultMaxBufferCount
// mOverrideMaxBufferCount
// async parameter
//
// Any time one of these member variables is changed while a producer is
// connected, mDequeueCondition must be broadcast.
int getMaxBufferCountLocked(bool async) const;
// setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
// that will be used if the producer does not override the buffer slot
// count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. The
// initial default is 2.
status_t setDefaultMaxBufferCountLocked(int count);
// freeBufferLocked frees the GraphicBuffer and sync resources for the
// given slot.
void freeBufferLocked(int slot);
// freeAllBuffersLocked frees the GraphicBuffer and sync resources for
// all slots.
void freeAllBuffersLocked();
// stillTracking returns true iff the buffer item is still being tracked
// in one of the slots.
bool stillTracking(const BufferItem* item) const;
const sp<IGraphicBufferAlloc>& mAllocator;
// mAllocator is the connection to SurfaceFlinger that is used to allocate
// new GraphicBuffer objects.
sp<IGraphicBufferAlloc> mAllocator;
// mMutex is the mutex used to prevent concurrent access to the member
// variables of BufferQueueCore objects. It must be locked whenever any
// member variable is accessed.
mutable Mutex mMutex;
// mIsAbandoned indicates that the BufferQueue will no longer be used to
// consume image buffers pushed to it using the IGraphicBufferProducer
// interface. It is initialized to false, and set to true in the
// consumerDisconnect method. A BufferQueue that is abandoned will return
// the NO_INIT error from all IGraphicBufferProducer methods capable of
// returning an error.
bool mIsAbandoned;
// mConsumerControlledByApp indicates whether the connected consumer is
// controlled by the application.
bool mConsumerControlledByApp;
// mConsumerName is a string used to identify the BufferQueue in log
// messages. It is set by the IGraphicBufferConsumer::setConsumerName
// method.
String8 mConsumerName;
// mConsumerListener is used to notify the connected consumer of
// asynchronous events that it may wish to react to. It is initially
// set to NULL and is written by consumerConnect and consumerDisconnect.
sp<IConsumerListener> mConsumerListener;
// mConsumerUsageBits contains flags that the consumer wants for
// GraphicBuffers.
uint32_t mConsumerUsageBits;
// mConnectedApi indicates the producer API that is currently connected
// to this BufferQueue. It defaults to NO_CONNECTED_API, and gets updated
// by the connect and disconnect methods.
int mConnectedApi;
// mConnectedProducerToken is used to set a binder death notification on
// the producer.
sp<IBinder> mConnectedProducerToken;
BufferSlot mSlots[NUM_BUFFER_SLOTS];
// mSlots is an array of buffer slots that must be mirrored on the producer
// side. This allows buffer ownership to be transferred between the producer
// and consumer without sending a GraphicBuffer over Binder. The entire
// array is initialized to NULL at construction time, and buffers are
// allocated for a slot when requestBuffer is called with that slot's index.
BufferQueueDefs::SlotsType mSlots;
// mQueue is a FIFO of queued buffers used in synchronous mode.
Fifo mQueue;
// mOverrideMaxBufferCount is the limit on the number of buffers that will
// be allocated at one time. This value is set by the producer by calling
// setBufferCount. The default is 0, which means that the producer doesn't
// care about the number of buffers in the pool. In that case,
// mDefaultMaxBufferCount is used as the limit.
int mOverrideMaxBufferCount;
// mDequeueCondition is a condition variable used for dequeueBuffer in
// synchronous mode.
mutable Condition mDequeueCondition;
// mUseAsyncBuffer indicates whether an extra buffer is used in async mode
// to prevent dequeueBuffer from blocking.
bool mUseAsyncBuffer;
// mDequeueBufferCannotBlock indicates whether dequeueBuffer is allowed to
// block. This flag is set during connect when both the producer and
// consumer are controlled by the application.
bool mDequeueBufferCannotBlock;
// mDefaultBufferFormat can be set so it will override the buffer format
// when it isn't specified in dequeueBuffer.
uint32_t mDefaultBufferFormat;
// mDefaultWidth holds the default width of allocated buffers. It is used
// in dequeueBuffer if a width and height of 0 are specified.
int mDefaultWidth;
// mDefaultHeight holds the default height of allocated buffers. It is used
// in dequeueBuffer if a width and height of 0 are specified.
int mDefaultHeight;
// mDefaultMaxBufferCount is the default limit on the number of buffers that
// will be allocated at one time. This default limit is set by the consumer.
// The limit (as opposed to the default limit) may be overriden by the
// producer.
int mDefaultMaxBufferCount;
// mMaxAcquiredBufferCount is the number of buffers that the consumer may
// acquire at one time. It defaults to 1, and can be changed by the consumer
// via setMaxAcquiredBufferCount, but this may only be done while no
// producer is connected to the BufferQueue. This value is used to derive
// the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer.
int mMaxAcquiredBufferCount;
// mBufferHasBeenQueued is true once a buffer has been queued. It is reset
// when something causes all buffers to be freed (e.g., changing the buffer
// count).
bool mBufferHasBeenQueued;
// mFrameCounter is the free running counter, incremented on every
// successful queueBuffer call and buffer allocation.
uint64_t mFrameCounter;
// mTransformHint is used to optimize for screen rotations.
uint32_t mTransformHint;
}; // class BufferQueueCore

View File

@ -0,0 +1,35 @@
/*
* Copyright 2014 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.
*/
#ifndef ANDROID_GUI_BUFFERQUEUECOREDEFS_H
#define ANDROID_GUI_BUFFERQUEUECOREDEFS_H
#include <gui/BufferSlot.h>
namespace android {
class BufferQueueCore;
namespace BufferQueueDefs {
// BufferQueue will keep track of at most this value of buffers.
// Attempts at runtime to increase the number of buffers past this
// will fail.
enum { NUM_BUFFER_SLOTS = 32 };
typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
} // namespace BufferQueueDefs
} // namespace android
#endif

View File

@ -17,7 +17,7 @@
#ifndef ANDROID_GUI_BUFFERQUEUEPRODUCER_H
#define ANDROID_GUI_BUFFERQUEUEPRODUCER_H
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueDefs.h>
#include <gui/IGraphicBufferProducer.h>
namespace android {
@ -26,8 +26,9 @@ class BufferSlot;
class BufferQueueProducer : public BnGraphicBufferProducer,
private IBinder::DeathRecipient {
public:
friend class BufferQueue; // Needed to access binderDied
BufferQueueProducer(const sp<BufferQueueCore>& core);
virtual ~BufferQueueProducer();
@ -151,7 +152,9 @@ private:
virtual void binderDied(const wp<IBinder>& who);
sp<BufferQueueCore> mCore;
BufferQueueCore::SlotsType& mSlots;
// This references mCore->mSlots. Lock mCore->mMutex while accessing.
BufferQueueDefs::SlotsType& mSlots;
// This is a cached copy of the name stored in the BufferQueueCore.
// It's updated during connect and dequeueBuffer (which should catch

View File

@ -38,6 +38,9 @@ BufferItem::BufferItem() :
BufferItem::operator IGraphicBufferConsumer::BufferItem() const {
IGraphicBufferConsumer::BufferItem bufferItem;
bufferItem.mGraphicBuffer = mGraphicBuffer;
bufferItem.mFence = mFence;
bufferItem.mCrop = mCrop;
bufferItem.mTransform = mTransform;
bufferItem.mScalingMode = mScalingMode;
bufferItem.mTimestamp = mTimestamp;
@ -47,7 +50,6 @@ BufferItem::operator IGraphicBufferConsumer::BufferItem() const {
bufferItem.mIsDroppable = mIsDroppable;
bufferItem.mAcquireCalled = mAcquireCalled;
bufferItem.mTransformToDisplayInverse = mTransformToDisplayInverse;
bufferItem.mCrop = mCrop;
return bufferItem;
}

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,10 @@
* limitations under the License.
*/
#define LOG_TAG "BufferQueueConsumer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
//#define LOG_NDEBUG 0
#include <gui/BufferItem.h>
#include <gui/BufferQueueConsumer.h>
#include <gui/BufferQueueCore.h>
@ -38,7 +42,7 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
// buffer so that the consumer can successfully set up the newly acquired
// buffer before releasing the old one.
int numAcquiredBuffers = 0;
for (int s = 0; s < BufferQueueCore::NUM_BUFFER_SLOTS; ++s) {
for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
++numAcquiredBuffers;
}
@ -275,7 +279,7 @@ status_t BufferQueueConsumer::getReleasedBuffers(uint32_t *outSlotMask) {
}
uint32_t mask = 0;
for (int s = 0; s < BufferQueueCore::NUM_BUFFER_SLOTS; ++s) {
for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
if (!mSlots[s].mAcquireCalled) {
mask |= (1u << s);
}

View File

@ -14,11 +14,18 @@
* limitations under the License.
*/
#define LOG_TAG "BufferQueueCore"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
//#define LOG_NDEBUG 0
#define EGL_EGLEXT_PROTOTYPES
#include <gui/BufferItem.h>
#include <gui/BufferQueueCore.h>
#include <gui/IConsumerListener.h>
#include <gui/IGraphicBufferAlloc.h>
#include <gui/ISurfaceComposer.h>
#include <private/gui/ComposerService.h>
template <typename T>
static inline T max(T a, T b) { return a > b ? a : b; }
@ -54,7 +61,16 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
mMaxAcquiredBufferCount(1),
mBufferHasBeenQueued(false),
mFrameCounter(0),
mTransformHint(0) {}
mTransformHint(0)
{
if (allocator == NULL) {
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
mAllocator = composer->createGraphicBufferAlloc();
if (mAllocator == NULL) {
BQ_LOGE("createGraphicBufferAlloc failed");
}
}
}
BufferQueueCore::~BufferQueueCore() {}
@ -82,7 +98,7 @@ void BufferQueueCore::dump(String8& result, const char* prefix) const {
// Trim the free buffers so as to not spam the dump
int maxBufferCount = 0;
for (int s = NUM_BUFFER_SLOTS - 1; s >= 0; --s) {
for (int s = BufferQueueDefs::NUM_BUFFER_SLOTS - 1; s >= 0; --s) {
const BufferSlot& slot(mSlots[s]);
if (slot.mBufferState != BufferSlot::FREE ||
slot.mGraphicBuffer != NULL) {
@ -140,7 +156,7 @@ int BufferQueueCore::getMaxBufferCountLocked(bool async) const {
// waiting to be consumed need to have their slots preserved. Such buffers
// will temporarily keep the max buffer count up until the slots no longer
// need to be preserved.
for (int s = maxBufferCount; s < NUM_BUFFER_SLOTS; ++s) {
for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
BufferSlot::BufferState state = mSlots[s].mBufferState;
if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) {
maxBufferCount = s + 1;
@ -152,9 +168,9 @@ int BufferQueueCore::getMaxBufferCountLocked(bool async) const {
status_t BufferQueueCore::setDefaultMaxBufferCountLocked(int count) {
const int minBufferCount = mUseAsyncBuffer ? 2 : 1;
if (count < minBufferCount || count > NUM_BUFFER_SLOTS) {
if (count < minBufferCount || count > BufferQueueDefs::NUM_BUFFER_SLOTS) {
BQ_LOGV("setDefaultMaxBufferCount: invalid count %d, should be in "
"[%d, %d]", minBufferCount, NUM_BUFFER_SLOTS);
"[%d, %d]", minBufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
return BAD_VALUE;
}
@ -185,7 +201,7 @@ void BufferQueueCore::freeBufferLocked(int slot) {
void BufferQueueCore::freeAllBuffersLocked() {
mBufferHasBeenQueued = false;
for (int s = 0; s < NUM_BUFFER_SLOTS; ++s) {
for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
freeBufferLocked(s);
}
}

View File

@ -14,6 +14,10 @@
* limitations under the License.
*/
#define LOG_TAG "BufferQueueProducer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
//#define LOG_NDEBUG 0
#define EGL_EGLEXT_PROTOTYPES
#include <gui/BufferItem.h>
@ -44,9 +48,9 @@ status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
return NO_INIT;
}
if (slot < 0 || slot >= BufferQueueCore::NUM_BUFFER_SLOTS) {
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
slot, BufferQueueCore::NUM_BUFFER_SLOTS);
slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
return BAD_VALUE;
} else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
@ -72,14 +76,14 @@ status_t BufferQueueProducer::setBufferCount(int bufferCount) {
return NO_INIT;
}
if (bufferCount > BufferQueueCore::NUM_BUFFER_SLOTS) {
if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)",
bufferCount, BufferQueueCore::NUM_BUFFER_SLOTS);
bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
return BAD_VALUE;
}
// There must be no dequeued buffers when changing the buffer count.
for (int s = 0; s < BufferQueueCore::NUM_BUFFER_SLOTS; ++s) {
for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
BQ_LOGE("setBufferCount: buffer owned by producer");
return -EINVAL;
@ -169,7 +173,7 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
}
// Free up any buffers that are in slots beyond the max buffer count
for (int s = maxBufferCount; s < BufferQueueCore::NUM_BUFFER_SLOTS; ++s) {
for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
assert(mSlots[s].mBufferState == BufferSlot::FREE);
if (mSlots[s].mGraphicBuffer != NULL) {
mCore->freeBufferLocked(s);
@ -494,9 +498,9 @@ void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
return;
}
if (slot < 0 || slot >= BufferQueueCore::NUM_BUFFER_SLOTS) {
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
slot, BufferQueueCore::NUM_BUFFER_SLOTS);
slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
return;
} else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "

View File

@ -1,3 +1,19 @@
/*
* Copyright 2014 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.
*/
#include <gui/BufferSlot.h>
namespace android {