ConsumerBase.h revision ed059a8d754770c3cf28b78dba30f7a6ba475dbe
1/*
2 * Copyright (C) 2010 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_CONSUMERBASE_H
18#define ANDROID_GUI_CONSUMERBASE_H
19
20#include <gui/BufferQueue.h>
21
22#include <ui/GraphicBuffer.h>
23
24#include <utils/String8.h>
25#include <utils/Vector.h>
26#include <utils/threads.h>
27
28namespace android {
29// ----------------------------------------------------------------------------
30
31class String8;
32
33// ConsumerBase is a base class for BufferQueue consumer end-points. It
34// handles common tasks like management of the connection to the BufferQueue
35// and the buffer pool.
36class ConsumerBase : public virtual RefBase,
37        protected BufferQueue::ConsumerListener {
38public:
39    struct FrameAvailableListener : public virtual RefBase {
40        // onFrameAvailable() is called each time an additional frame becomes
41        // available for consumption. This means that frames that are queued
42        // while in asynchronous mode only trigger the callback if no previous
43        // frames are pending. Frames queued while in synchronous mode always
44        // trigger the callback.
45        //
46        // This is called without any lock held and can be called concurrently
47        // by multiple threads.
48        virtual void onFrameAvailable() = 0;
49    };
50
51    virtual ~ConsumerBase();
52
53    // abandon frees all the buffers and puts the ConsumerBase into the
54    // 'abandoned' state.  Once put in this state the ConsumerBase can never
55    // leave it.  When in the 'abandoned' state, all methods of the
56    // ISurfaceTexture interface will fail with the NO_INIT error.
57    //
58    // Note that while calling this method causes all the buffers to be freed
59    // from the perspective of the the ConsumerBase, if there are additional
60    // references on the buffers (e.g. if a buffer is referenced by a client
61    // or by OpenGL ES as a texture) then those buffer will remain allocated.
62    void abandon();
63
64    // set the name of the ConsumerBase that will be used to identify it in
65    // log messages.
66    void setName(const String8& name);
67
68    // getBufferQueue returns the BufferQueue object to which this
69    // ConsumerBase is connected.
70    sp<BufferQueue> getBufferQueue() const;
71
72    // dump writes the current state to a string.  These methods should NOT be
73    // overridden by child classes.  Instead they should override the
74    // dumpLocked method, which is called by these methods after locking the
75    // mutex.
76    void dump(String8& result) const;
77    void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
78
79    // setFrameAvailableListener sets the listener object that will be notified
80    // when a new frame becomes available.
81    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
82
83private:
84    ConsumerBase(const ConsumerBase&);
85    void operator=(const ConsumerBase&);
86
87protected:
88
89    // TODO: Fix this comment
90    // ConsumerBase constructs a new ConsumerBase object. tex indicates the
91    // name of the OpenGL ES texture to which images are to be streamed.
92    // allowSynchronousMode specifies whether or not synchronous mode can be
93    // enabled. texTarget specifies the OpenGL ES texture target to which the
94    // texture will be bound in updateTexImage. useFenceSync specifies whether
95    // fences should be used to synchronize access to buffers if that behavior
96    // is enabled at compile-time. A custom bufferQueue can be specified
97    // if behavior for queue/dequeue/connect etc needs to be customized.
98    // Otherwise a default BufferQueue will be created and used.
99    //
100    // For legacy reasons, the ConsumerBase is created in a state where it is
101    // considered attached to an OpenGL ES context for the purposes of the
102    // attachToContext and detachFromContext methods. However, despite being
103    // considered "attached" to a context, the specific OpenGL ES context
104    // doesn't get latched until the first call to updateTexImage. After that
105    // point, all calls to updateTexImage must be made with the same OpenGL ES
106    // context current.
107    //
108    // A ConsumerBase may be detached from one OpenGL ES context and then
109    // attached to a different context using the detachFromContext and
110    // attachToContext methods, respectively. The intention of these methods is
111    // purely to allow a ConsumerBase to be transferred from one consumer
112    // context to another. If such a transfer is not needed there is no
113    // requirement that either of these methods be called.
114    ConsumerBase(const sp<BufferQueue> &bufferQueue);
115
116    // Implementation of the BufferQueue::ConsumerListener interface.  These
117    // calls are used to notify the ConsumerBase of asynchronous events in the
118    // BufferQueue.
119    virtual void onFrameAvailable();
120    virtual void onBuffersReleased();
121
122    // freeBufferLocked frees up the given buffer slot.  If the slot has been
123    // initialized this will release the reference to the GraphicBuffer in that
124    // slot and destroy the EGLImage in that slot.  Otherwise it has no effect.
125    //
126    // This method must be called with mMutex locked.
127    virtual void freeBufferLocked(int slotIndex);
128
129    // abandonLocked puts the BufferQueue into the abandoned state, causing
130    // all future operations on it to fail. This method rather than the public
131    // abandon method should be overridden by child classes to add abandon-
132    // time behavior.
133    //
134    // This method must be called with mMutex locked.
135    virtual void abandonLocked();
136
137    virtual void dumpLocked(String8& result, const char* prefix, char* buffer,
138            size_t SIZE) const;
139
140    // acquireBufferLocked fetches the next buffer from the BufferQueue and
141    // updates the buffer slot for the buffer returned.
142    virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item);
143
144    // releaseBufferLocked relinquishes control over a buffer, returning that
145    // control to the BufferQueue.
146    virtual status_t releaseBufferLocked(int buf, EGLDisplay display,
147           EGLSyncKHR eglFence, const sp<Fence>& fence);
148
149    // Slot contains the information and object references that
150    // ConsumerBase maintains about a BufferQueue buffer slot.
151    struct Slot {
152        // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if
153        // no Gralloc buffer is in the slot.
154        sp<GraphicBuffer> mGraphicBuffer;
155
156        // mFence is a fence which will signal when the buffer associated with
157        // this buffer slot is no longer being used by the consumer and can be
158        // overwritten. The buffer can be dequeued before the fence signals;
159        // the producer is responsible for delaying writes until it signals.
160        sp<Fence> mFence;
161    };
162
163    // mSlots stores the buffers that have been allocated by the BufferQueue
164    // for each buffer slot.  It is initialized to null pointers, and gets
165    // filled in with the result of BufferQueue::acquire when the
166    // client dequeues a buffer from a
167    // slot that has not yet been used. The buffer allocated to a slot will also
168    // be replaced if the requested buffer usage or geometry differs from that
169    // of the buffer allocated to a slot.
170    Slot mSlots[BufferQueue::NUM_BUFFER_SLOTS];
171
172    // mAbandoned indicates that the BufferQueue will no longer be used to
173    // consume images buffers pushed to it using the ISurfaceTexture
174    // interface. It is initialized to false, and set to true in the abandon
175    // method.  A BufferQueue that has been abandoned will return the NO_INIT
176    // error from all IConsumerBase methods capable of returning an error.
177    bool mAbandoned;
178
179    // mName is a string used to identify the ConsumerBase in log messages.
180    // It can be set by the setName method.
181    String8 mName;
182
183    // mFrameAvailableListener is the listener object that will be called when a
184    // new frame becomes available. If it is not NULL it will be called from
185    // queueBuffer.
186    sp<FrameAvailableListener> mFrameAvailableListener;
187
188    // The ConsumerBase has-a BufferQueue and is responsible for creating this object
189    // if none is supplied
190    sp<BufferQueue> mBufferQueue;
191
192    // mMutex is the mutex used to prevent concurrent access to the member
193    // variables of ConsumerBase objects. It must be locked whenever the
194    // member variables are accessed.
195    mutable Mutex mMutex;
196};
197
198// ----------------------------------------------------------------------------
199}; // namespace android
200
201#endif // ANDROID_GUI_CONSUMERBASE_H
202