Home | History | Annotate | Download | only in gui
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ANDROID_GUI_BUFFERQUEUE_H
     18 #define ANDROID_GUI_BUFFERQUEUE_H
     19 
     20 #include <EGL/egl.h>
     21 #include <EGL/eglext.h>
     22 
     23 #include <gui/IGraphicBufferAlloc.h>
     24 #include <gui/ISurfaceTexture.h>
     25 
     26 #include <ui/GraphicBuffer.h>
     27 
     28 #include <utils/String8.h>
     29 #include <utils/Vector.h>
     30 #include <utils/threads.h>
     31 
     32 namespace android {
     33 // ----------------------------------------------------------------------------
     34 
     35 class BufferQueue : public BnSurfaceTexture {
     36 public:
     37     enum { MIN_UNDEQUEUED_BUFFERS = 2 };
     38     enum { NUM_BUFFER_SLOTS = 32 };
     39     enum { NO_CONNECTED_API = 0 };
     40     enum { INVALID_BUFFER_SLOT = -1 };
     41     enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE };
     42 
     43     // ConsumerListener is the interface through which the BufferQueue notifies
     44     // the consumer of events that the consumer may wish to react to.  Because
     45     // the consumer will generally have a mutex that is locked during calls from
     46     // teh consumer to the BufferQueue, these calls from the BufferQueue to the
     47     // consumer *MUST* be called only when the BufferQueue mutex is NOT locked.
     48     struct ConsumerListener : public virtual RefBase {
     49         // onFrameAvailable is called from queueBuffer each time an additional
     50         // frame becomes available for consumption. This means that frames that
     51         // are queued while in asynchronous mode only trigger the callback if no
     52         // previous frames are pending. Frames queued while in synchronous mode
     53         // always trigger the callback.
     54         //
     55         // This is called without any lock held and can be called concurrently
     56         // by multiple threads.
     57         virtual void onFrameAvailable() = 0;
     58 
     59         // onBuffersReleased is called to notify the buffer consumer that the
     60         // BufferQueue has released its references to one or more GraphicBuffers
     61         // contained in its slots.  The buffer consumer should then call
     62         // BufferQueue::getReleasedBuffers to retrieve the list of buffers
     63         //
     64         // This is called without any lock held and can be called concurrently
     65         // by multiple threads.
     66         virtual void onBuffersReleased() = 0;
     67     };
     68 
     69     // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak
     70     // reference to the actual consumer object.  It forwards all calls to that
     71     // consumer object so long as it exists.
     72     //
     73     // This class exists to avoid having a circular reference between the
     74     // BufferQueue object and the consumer object.  The reason this can't be a weak
     75     // reference in the BufferQueue class is because we're planning to expose the
     76     // consumer side of a BufferQueue as a binder interface, which doesn't support
     77     // weak references.
     78     class ProxyConsumerListener : public BufferQueue::ConsumerListener {
     79     public:
     80 
     81         ProxyConsumerListener(const wp<BufferQueue::ConsumerListener>& consumerListener);
     82         virtual ~ProxyConsumerListener();
     83         virtual void onFrameAvailable();
     84         virtual void onBuffersReleased();
     85 
     86     private:
     87 
     88         // mConsumerListener is a weak reference to the ConsumerListener.  This is
     89         // the raison d'etre of ProxyConsumerListener.
     90         wp<BufferQueue::ConsumerListener> mConsumerListener;
     91     };
     92 
     93 
     94     // BufferQueue manages a pool of gralloc memory slots to be used
     95     // by producers and consumers.
     96     // allowSynchronousMode specifies whether or not synchronous mode can be
     97     // enabled.
     98     // bufferCount sets the minimum number of undequeued buffers for this queue
     99     BufferQueue(  bool allowSynchronousMode = true, int bufferCount = MIN_UNDEQUEUED_BUFFERS);
    100     virtual ~BufferQueue();
    101 
    102     virtual int query(int what, int* value);
    103 
    104     // setBufferCount updates the number of available buffer slots.  After
    105     // calling this all buffer slots are both unallocated and owned by the
    106     // BufferQueue object (i.e. they are not owned by the client).
    107     virtual status_t setBufferCount(int bufferCount);
    108 
    109     virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
    110 
    111     // dequeueBuffer gets the next buffer slot index for the client to use. If a
    112     // buffer slot is available then that slot index is written to the location
    113     // pointed to by the buf argument and a status of OK is returned.  If no
    114     // slot is available then a status of -EBUSY is returned and buf is
    115     // unmodified.
    116     // The width and height parameters must be no greater than the minimum of
    117     // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
    118     // An error due to invalid dimensions might not be reported until
    119     // updateTexImage() is called.
    120     virtual status_t dequeueBuffer(int *buf, uint32_t width, uint32_t height,
    121             uint32_t format, uint32_t usage);
    122 
    123     // queueBuffer returns a filled buffer to the BufferQueue. In addition, a
    124     // timestamp must be provided for the buffer. The timestamp is in
    125     // nanoseconds, and must be monotonically increasing. Its other semantics
    126     // (zero point, etc) are client-dependent and should be documented by the
    127     // client.
    128     virtual status_t queueBuffer(int buf,
    129             const QueueBufferInput& input, QueueBufferOutput* output);
    130 
    131     virtual void cancelBuffer(int buf);
    132 
    133     // setSynchronousMode set whether dequeueBuffer is synchronous or
    134     // asynchronous. In synchronous mode, dequeueBuffer blocks until
    135     // a buffer is available, the currently bound buffer can be dequeued and
    136     // queued buffers will be retired in order.
    137     // The default mode is asynchronous.
    138     virtual status_t setSynchronousMode(bool enabled);
    139 
    140     // connect attempts to connect a producer client API to the BufferQueue.
    141     // This must be called before any other ISurfaceTexture methods are called
    142     // except for getAllocator.
    143     //
    144     // This method will fail if the connect was previously called on the
    145     // BufferQueue and no corresponding disconnect call was made.
    146     virtual status_t connect(int api, QueueBufferOutput* output);
    147 
    148     // disconnect attempts to disconnect a producer client API from the
    149     // BufferQueue. Calling this method will cause any subsequent calls to other
    150     // ISurfaceTexture methods to fail except for getAllocator and connect.
    151     // Successfully calling connect after this will allow the other methods to
    152     // succeed again.
    153     //
    154     // This method will fail if the the BufferQueue is not currently
    155     // connected to the specified client API.
    156     virtual status_t disconnect(int api);
    157 
    158     // dump our state in a String
    159     virtual void dump(String8& result) const;
    160     virtual void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
    161 
    162     // public facing structure for BufferSlot
    163     struct BufferItem {
    164 
    165         BufferItem()
    166          :
    167            mTransform(0),
    168            mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
    169            mTimestamp(0),
    170            mFrameNumber(0),
    171            mBuf(INVALID_BUFFER_SLOT) {
    172              mCrop.makeInvalid();
    173          }
    174         // mGraphicBuffer points to the buffer allocated for this slot or is NULL
    175         // if no buffer has been allocated.
    176         sp<GraphicBuffer> mGraphicBuffer;
    177 
    178         // mCrop is the current crop rectangle for this buffer slot.
    179         Rect mCrop;
    180 
    181         // mTransform is the current transform flags for this buffer slot.
    182         uint32_t mTransform;
    183 
    184         // mScalingMode is the current scaling mode for this buffer slot.
    185         uint32_t mScalingMode;
    186 
    187         // mTimestamp is the current timestamp for this buffer slot. This gets
    188         // to set by queueBuffer each time this slot is queued.
    189         int64_t mTimestamp;
    190 
    191         // mFrameNumber is the number of the queued frame for this slot.
    192         uint64_t mFrameNumber;
    193 
    194         // mBuf is the slot index of this buffer
    195         int mBuf;
    196     };
    197 
    198     // The following public functions is the consumer facing interface
    199 
    200     // acquireBuffer attempts to acquire ownership of the next pending buffer in
    201     // the BufferQueue.  If no buffer is pending then it returns -EINVAL.  If a
    202     // buffer is successfully acquired, the information about the buffer is
    203     // returned in BufferItem.  If the buffer returned had previously been
    204     // acquired then the BufferItem::mGraphicBuffer field of buffer is set to
    205     // NULL and it is assumed that the consumer still holds a reference to the
    206     // buffer.
    207     status_t acquireBuffer(BufferItem *buffer);
    208 
    209     // releaseBuffer releases a buffer slot from the consumer back to the
    210     // BufferQueue pending a fence sync.
    211     //
    212     // Note that the dependencies on EGL will be removed once we switch to using
    213     // the Android HW Sync HAL.
    214     status_t releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence);
    215 
    216     // consumerConnect connects a consumer to the BufferQueue.  Only one
    217     // consumer may be connected, and when that consumer disconnects the
    218     // BufferQueue is placed into the "abandoned" state, causing most
    219     // interactions with the BufferQueue by the producer to fail.
    220     status_t consumerConnect(const sp<ConsumerListener>& consumer);
    221 
    222     // consumerDisconnect disconnects a consumer from the BufferQueue. All
    223     // buffers will be freed and the BufferQueue is placed in the "abandoned"
    224     // state, causing most interactions with the BufferQueue by the producer to
    225     // fail.
    226     status_t consumerDisconnect();
    227 
    228     // getReleasedBuffers sets the value pointed to by slotMask to a bit mask
    229     // indicating which buffer slots the have been released by the BufferQueue
    230     // but have not yet been released by the consumer.
    231     status_t getReleasedBuffers(uint32_t* slotMask);
    232 
    233     // setDefaultBufferSize is used to set the size of buffers returned by
    234     // requestBuffers when a with and height of zero is requested.
    235     status_t setDefaultBufferSize(uint32_t w, uint32_t h);
    236 
    237     // setBufferCountServer set the buffer count. If the client has requested
    238     // a buffer count using setBufferCount, the server-buffer count will
    239     // take effect once the client sets the count back to zero.
    240     status_t setBufferCountServer(int bufferCount);
    241 
    242     // isSynchronousMode returns whether the SurfaceTexture is currently in
    243     // synchronous mode.
    244     bool isSynchronousMode() const;
    245 
    246     // setConsumerName sets the name used in logging
    247     void setConsumerName(const String8& name);
    248 
    249     // setDefaultBufferFormat allows the BufferQueue to create
    250     // GraphicBuffers of a defaultFormat if no format is specified
    251     // in dequeueBuffer
    252     status_t setDefaultBufferFormat(uint32_t defaultFormat);
    253 
    254     // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer
    255     status_t setConsumerUsageBits(uint32_t usage);
    256 
    257     // setTransformHint bakes in rotation to buffers so overlays can be used
    258     status_t setTransformHint(uint32_t hint);
    259 
    260 private:
    261     // freeBufferLocked frees the resources (both GraphicBuffer and EGLImage)
    262     // for the given slot.
    263     void freeBufferLocked(int index);
    264 
    265     // freeAllBuffersLocked frees the resources (both GraphicBuffer and
    266     // EGLImage) for all slots.
    267     void freeAllBuffersLocked();
    268 
    269     // freeAllBuffersExceptHeadLocked frees the resources (both GraphicBuffer
    270     // and EGLImage) for all slots except the head of mQueue
    271     void freeAllBuffersExceptHeadLocked();
    272 
    273     // drainQueueLocked drains the buffer queue if we're in synchronous mode
    274     // returns immediately otherwise. It returns NO_INIT if the BufferQueue
    275     // became abandoned or disconnected during this call.
    276     status_t drainQueueLocked();
    277 
    278     // drainQueueAndFreeBuffersLocked drains the buffer queue if we're in
    279     // synchronous mode and free all buffers. In asynchronous mode, all buffers
    280     // are freed except the current buffer.
    281     status_t drainQueueAndFreeBuffersLocked();
    282 
    283     status_t setBufferCountServerLocked(int bufferCount);
    284 
    285     struct BufferSlot {
    286 
    287         BufferSlot()
    288         : mEglDisplay(EGL_NO_DISPLAY),
    289           mBufferState(BufferSlot::FREE),
    290           mRequestBufferCalled(false),
    291           mTransform(0),
    292           mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
    293           mTimestamp(0),
    294           mFrameNumber(0),
    295           mFence(EGL_NO_SYNC_KHR),
    296           mAcquireCalled(false),
    297           mNeedsCleanupOnRelease(false) {
    298             mCrop.makeInvalid();
    299         }
    300 
    301         // mGraphicBuffer points to the buffer allocated for this slot or is NULL
    302         // if no buffer has been allocated.
    303         sp<GraphicBuffer> mGraphicBuffer;
    304 
    305         // mEglDisplay is the EGLDisplay used to create mEglImage.
    306         EGLDisplay mEglDisplay;
    307 
    308         // BufferState represents the different states in which a buffer slot
    309         // can be.
    310         enum BufferState {
    311             // FREE indicates that the buffer is not currently being used and
    312             // will not be used in the future until it gets dequeued and
    313             // subsequently queued by the client.
    314             // aka "owned by BufferQueue, ready to be dequeued"
    315             FREE = 0,
    316 
    317             // DEQUEUED indicates that the buffer has been dequeued by the
    318             // client, but has not yet been queued or canceled. The buffer is
    319             // considered 'owned' by the client, and the server should not use
    320             // it for anything.
    321             //
    322             // Note that when in synchronous-mode (mSynchronousMode == true),
    323             // the buffer that's currently attached to the texture may be
    324             // dequeued by the client.  That means that the current buffer can
    325             // be in either the DEQUEUED or QUEUED state.  In asynchronous mode,
    326             // however, the current buffer is always in the QUEUED state.
    327             // aka "owned by producer, ready to be queued"
    328             DEQUEUED = 1,
    329 
    330             // QUEUED indicates that the buffer has been queued by the client,
    331             // and has not since been made available for the client to dequeue.
    332             // Attaching the buffer to the texture does NOT transition the
    333             // buffer away from the QUEUED state. However, in Synchronous mode
    334             // the current buffer may be dequeued by the client under some
    335             // circumstances. See the note about the current buffer in the
    336             // documentation for DEQUEUED.
    337             // aka "owned by BufferQueue, ready to be acquired"
    338             QUEUED = 2,
    339 
    340             // aka "owned by consumer, ready to be released"
    341             ACQUIRED = 3
    342         };
    343 
    344         // mBufferState is the current state of this buffer slot.
    345         BufferState mBufferState;
    346 
    347         // mRequestBufferCalled is used for validating that the client did
    348         // call requestBuffer() when told to do so. Technically this is not
    349         // needed but useful for debugging and catching client bugs.
    350         bool mRequestBufferCalled;
    351 
    352         // mCrop is the current crop rectangle for this buffer slot.
    353         Rect mCrop;
    354 
    355         // mTransform is the current transform flags for this buffer slot.
    356         uint32_t mTransform;
    357 
    358         // mScalingMode is the current scaling mode for this buffer slot.
    359         uint32_t mScalingMode;
    360 
    361         // mTimestamp is the current timestamp for this buffer slot. This gets
    362         // to set by queueBuffer each time this slot is queued.
    363         int64_t mTimestamp;
    364 
    365         // mFrameNumber is the number of the queued frame for this slot.
    366         uint64_t mFrameNumber;
    367 
    368         // mFence is the EGL sync object that must signal before the buffer
    369         // associated with this buffer slot may be dequeued. It is initialized
    370         // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
    371         // on a compile-time option) set to a new sync object in updateTexImage.
    372         EGLSyncKHR mFence;
    373 
    374         // Indicates whether this buffer has been seen by a consumer yet
    375         bool mAcquireCalled;
    376 
    377         // Indicates whether this buffer needs to be cleaned up by consumer
    378         bool mNeedsCleanupOnRelease;
    379     };
    380 
    381     // mSlots is the array of buffer slots that must be mirrored on the client
    382     // side. This allows buffer ownership to be transferred between the client
    383     // and server without sending a GraphicBuffer over binder. The entire array
    384     // is initialized to NULL at construction time, and buffers are allocated
    385     // for a slot when requestBuffer is called with that slot's index.
    386     BufferSlot mSlots[NUM_BUFFER_SLOTS];
    387 
    388     // mDefaultWidth holds the default width of allocated buffers. It is used
    389     // in requestBuffers() if a width and height of zero is specified.
    390     uint32_t mDefaultWidth;
    391 
    392     // mDefaultHeight holds the default height of allocated buffers. It is used
    393     // in requestBuffers() if a width and height of zero is specified.
    394     uint32_t mDefaultHeight;
    395 
    396     // mPixelFormat holds the pixel format of allocated buffers. It is used
    397     // in requestBuffers() if a format of zero is specified.
    398     uint32_t mPixelFormat;
    399 
    400     // mMinUndequeuedBuffers is a constraint on the number of buffers
    401     // not dequeued at any time
    402     int mMinUndequeuedBuffers;
    403 
    404     // mMinAsyncBufferSlots is a constraint on the minimum mBufferCount
    405     // when this BufferQueue is in asynchronous mode
    406     int mMinAsyncBufferSlots;
    407 
    408     // mMinSyncBufferSlots is a constraint on the minimum mBufferCount
    409     // when this BufferQueue is in synchronous mode
    410     int mMinSyncBufferSlots;
    411 
    412     // mBufferCount is the number of buffer slots that the client and server
    413     // must maintain. It defaults to MIN_ASYNC_BUFFER_SLOTS and can be changed
    414     // by calling setBufferCount or setBufferCountServer
    415     int mBufferCount;
    416 
    417     // mClientBufferCount is the number of buffer slots requested by the client.
    418     // The default is zero, which means the client doesn't care how many buffers
    419     // there is.
    420     int mClientBufferCount;
    421 
    422     // mServerBufferCount buffer count requested by the server-side
    423     int mServerBufferCount;
    424 
    425     // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
    426     // allocate new GraphicBuffer objects.
    427     sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
    428 
    429     // mConsumerListener is used to notify the connected consumer of
    430     // asynchronous events that it may wish to react to.  It is initially set
    431     // to NULL and is written by consumerConnect and consumerDisconnect.
    432     sp<ConsumerListener> mConsumerListener;
    433 
    434     // mSynchronousMode whether we're in synchronous mode or not
    435     bool mSynchronousMode;
    436 
    437     // mAllowSynchronousMode whether we allow synchronous mode or not
    438     const bool mAllowSynchronousMode;
    439 
    440     // mConnectedApi indicates the API that is currently connected to this
    441     // BufferQueue.  It defaults to NO_CONNECTED_API (= 0), and gets updated
    442     // by the connect and disconnect methods.
    443     int mConnectedApi;
    444 
    445     // mDequeueCondition condition used for dequeueBuffer in synchronous mode
    446     mutable Condition mDequeueCondition;
    447 
    448     // mQueue is a FIFO of queued buffers used in synchronous mode
    449     typedef Vector<int> Fifo;
    450     Fifo mQueue;
    451 
    452     // mAbandoned indicates that the BufferQueue will no longer be used to
    453     // consume images buffers pushed to it using the ISurfaceTexture interface.
    454     // It is initialized to false, and set to true in the abandon method.  A
    455     // BufferQueue that has been abandoned will return the NO_INIT error from
    456     // all ISurfaceTexture methods capable of returning an error.
    457     bool mAbandoned;
    458 
    459     // mName is a string used to identify the BufferQueue in log messages.
    460     // It is set by the setName method.
    461     String8 mConsumerName;
    462 
    463     // mMutex is the mutex used to prevent concurrent access to the member
    464     // variables of BufferQueue objects. It must be locked whenever the
    465     // member variables are accessed.
    466     mutable Mutex mMutex;
    467 
    468     // mFrameCounter is the free running counter, incremented for every buffer queued
    469     // with the surface Texture.
    470     uint64_t mFrameCounter;
    471 
    472     // mBufferHasBeenQueued is true once a buffer has been queued.  It is reset
    473     // by changing the buffer count.
    474     bool mBufferHasBeenQueued;
    475 
    476     // mDefaultBufferFormat can be set so it will override
    477     // the buffer format when it isn't specified in dequeueBuffer
    478     uint32_t mDefaultBufferFormat;
    479 
    480     // mConsumerUsageBits contains flags the consumer wants for GraphicBuffers
    481     uint32_t mConsumerUsageBits;
    482 
    483     // mTransformHint is used to optimize for screen rotations
    484     uint32_t mTransformHint;
    485 };
    486 
    487 // ----------------------------------------------------------------------------
    488 }; // namespace android
    489 
    490 #endif // ANDROID_GUI_BUFFERQUEUE_H
    491