• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
BufferItemBufferItem165         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 
BufferSlotBufferSlot287         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