summaryrefslogtreecommitdiffstats
path: root/widget/gonk/nativewindow/GonkConsumerBaseJB.h
blob: 8f523af372a3335061ce09a41143fdaaa85e7767 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*
 * Copyright (C) 2010 The Android Open Source Project
 * Copyright (C) 2013 Mozilla Foundation
 *
 * 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 NATIVEWINDOW_GONKCONSUMERBASE_JB_H
#define NATIVEWINDOW_GONKCONSUMERBASE_JB_H

#include <ui/GraphicBuffer.h>

#include <utils/String8.h>
#include <utils/Vector.h>
#include <utils/threads.h>

#include "GonkBufferQueueJB.h"

namespace android {
// ----------------------------------------------------------------------------

class String8;

// GonkConsumerBase is a base class for GonkBufferQueue consumer end-points. It
// handles common tasks like management of the connection to the GonkBufferQueue
// and the buffer pool.
class GonkConsumerBase : public virtual RefBase,
        protected GonkBufferQueue::ConsumerListener {
public:
    struct FrameAvailableListener : public virtual RefBase {
        // onFrameAvailable() is called each time an additional frame becomes
        // available for consumption. This means that frames that are queued
        // while in asynchronous mode only trigger the callback if no previous
        // frames are pending. Frames queued while in synchronous mode always
        // trigger the callback.
        //
        // This is called without any lock held and can be called concurrently
        // by multiple threads.
        virtual void onFrameAvailable() = 0;
    };

    virtual ~GonkConsumerBase();

    // abandon frees all the buffers and puts the GonkConsumerBase into the
    // 'abandoned' state.  Once put in this state the GonkConsumerBase can never
    // leave it.  When in the 'abandoned' state, all methods of the
    // IGraphicBufferProducer interface will fail with the NO_INIT error.
    //
    // Note that while calling this method causes all the buffers to be freed
    // from the perspective of the the GonkConsumerBase, if there are additional
    // references on the buffers (e.g. if a buffer is referenced by a client
    // or by OpenGL ES as a texture) then those buffer will remain allocated.
    void abandon();

    // set the name of the GonkConsumerBase that will be used to identify it in
    // log messages.
    void setName(const String8& name);

    // getBufferQueue returns the GonkBufferQueue object to which this
    // GonkConsumerBase is connected.
    sp<GonkBufferQueue> getBufferQueue() const;

    // dump writes the current state to a string. Child classes should add
    // their state to the dump by overriding the dumpLocked method, which is
    // called by these methods after locking the mutex.
    void dump(String8& result) const;
    void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;

    // setFrameAvailableListener sets the listener object that will be notified
    // when a new frame becomes available.
#if ANDROID_VERSION == 17
    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
#else
    void setFrameAvailableListener(const wp<FrameAvailableListener>& listener);
#endif

private:
    GonkConsumerBase(const GonkConsumerBase&);
    void operator=(const GonkConsumerBase&);

protected:

    // GonkConsumerBase constructs a new GonkConsumerBase object to consume image
    // buffers from the given GonkBufferQueue.
    GonkConsumerBase(const sp<GonkBufferQueue> &bufferQueue);

    // onLastStrongRef gets called by RefBase just before the dtor of the most
    // derived class.  It is used to clean up the buffers so that GonkConsumerBase
    // can coordinate the clean-up by calling into virtual methods implemented
    // by the derived classes.  This would not be possible from the
    // ConsuemrBase dtor because by the time that gets called the derived
    // classes have already been destructed.
    //
    // This methods should not need to be overridden by derived classes, but
    // if they are overridden the GonkConsumerBase implementation must be called
    // from the derived class.
    virtual void onLastStrongRef(const void* id);

    // Implementation of the GonkBufferQueue::ConsumerListener interface.  These
    // calls are used to notify the GonkConsumerBase of asynchronous events in the
    // GonkBufferQueue.  These methods should not need to be overridden by derived
    // classes, but if they are overridden the GonkConsumerBase implementation
    // must be called from the derived class.
    virtual void onFrameAvailable();
    virtual void onBuffersReleased();

    // freeBufferLocked frees up the given buffer slot.  If the slot has been
    // initialized this will release the reference to the GraphicBuffer in that
    // slot.  Otherwise it has no effect.
    //
    // Derived classes should override this method to clean up any state they
    // keep per slot.  If it is overridden, the derived class's implementation
    // must call GonkConsumerBase::freeBufferLocked.
    //
    // This method must be called with mMutex locked.
    virtual void freeBufferLocked(int slotIndex);

    // abandonLocked puts the GonkBufferQueue into the abandoned state, causing
    // all future operations on it to fail. This method rather than the public
    // abandon method should be overridden by child classes to add abandon-
    // time behavior.
    //
    // Derived classes should override this method to clean up any object
    // state they keep (as opposed to per-slot state).  If it is overridden,
    // the derived class's implementation must call GonkConsumerBase::abandonLocked.
    //
    // This method must be called with mMutex locked.
    virtual void abandonLocked();

    // dumpLocked dumps the current state of the GonkConsumerBase object to the
    // result string.  Each line is prefixed with the string pointed to by the
    // prefix argument.  The buffer argument points to a buffer that may be
    // used for intermediate formatting data, and the size of that buffer is
    // indicated by the size argument.
    //
    // Derived classes should override this method to dump their internal
    // state.  If this method is overridden the derived class's implementation
    // should call GonkConsumerBase::dumpLocked.
    //
    // This method must be called with mMutex locked.
    virtual void dumpLocked(String8& result, const char* prefix, char* buffer,
            size_t size) const;

    // acquireBufferLocked fetches the next buffer from the GonkBufferQueue and
    // updates the buffer slot for the buffer returned.
    //
    // Derived classes should override this method to perform any
    // initialization that must take place the first time a buffer is assigned
    // to a slot.  If it is overridden the derived class's implementation must
    // call GonkConsumerBase::acquireBufferLocked.
    virtual status_t acquireBufferLocked(GonkBufferQueue::BufferItem *item);

    // releaseBufferLocked relinquishes control over a buffer, returning that
    // control to the GonkBufferQueue.
    //
    // Derived classes should override this method to perform any cleanup that
    // must take place when a buffer is released back to the GonkBufferQueue.  If
    // it is overridden the derived class's implementation must call
    // GonkConsumerBase::releaseBufferLocked.
    virtual status_t releaseBufferLocked(int buf);

    // addReleaseFence* adds the sync points associated with a fence to the set
    // of sync points that must be reached before the buffer in the given slot
    // may be used after the slot has been released.  This should be called by
    // derived classes each time some asynchronous work is kicked off that
    // references the buffer.
    status_t addReleaseFence(int slot, const sp<Fence>& fence);
    status_t addReleaseFenceLocked(int slot, const sp<Fence>& fence);

    // Slot contains the information and object references that
    // GonkConsumerBase maintains about a GonkBufferQueue buffer slot.
    struct Slot {
        // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if
        // no Gralloc buffer is in the slot.
        sp<GraphicBuffer> mGraphicBuffer;

        // mFence is a fence which will signal when the buffer associated with
        // this buffer slot is no longer being used by the consumer and can be
        // overwritten. The buffer can be dequeued before the fence signals;
        // the producer is responsible for delaying writes until it signals.
        sp<Fence> mFence;
    };

    // mSlots stores the buffers that have been allocated by the GonkBufferQueue
    // for each buffer slot.  It is initialized to null pointers, and gets
    // filled in with the result of GonkBufferQueue::acquire when the
    // client dequeues a buffer from a
    // slot that has not yet been used. The buffer allocated to a slot will also
    // be replaced if the requested buffer usage or geometry differs from that
    // of the buffer allocated to a slot.
    Slot mSlots[GonkBufferQueue::NUM_BUFFER_SLOTS];

    // mAbandoned indicates that the GonkBufferQueue will no longer be used to
    // consume images buffers pushed to it using the IGraphicBufferProducer
    // interface. It is initialized to false, and set to true in the abandon
    // method.  A GonkBufferQueue that has been abandoned will return the NO_INIT
    // error from all IGonkConsumerBase methods capable of returning an error.
    bool mAbandoned;

    // mName is a string used to identify the GonkConsumerBase in log messages.
    // It can be set by the setName method.
    String8 mName;

    // mFrameAvailableListener is the listener object that will be called when a
    // new frame becomes available. If it is not NULL it will be called from
    // queueBuffer.
#if ANDROID_VERSION == 17
    sp<FrameAvailableListener> mFrameAvailableListener;
#else
    wp<FrameAvailableListener> mFrameAvailableListener;
#endif

    // The GonkConsumerBase has-a GonkBufferQueue and is responsible for creating this object
    // if none is supplied
    sp<GonkBufferQueue> mBufferQueue;

    // mMutex is the mutex used to prevent concurrent access to the member
    // variables of GonkConsumerBase objects. It must be locked whenever the
    // member variables are accessed or when any of the *Locked methods are
    // called.
    //
    // This mutex is intended to be locked by derived classes.
    mutable Mutex mMutex;
};

// ----------------------------------------------------------------------------
}; // namespace android

#endif // NATIVEWINDOW_GONKCONSUMERBASE_H