Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 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 | |
| 28 | namespace android { |
| 29 | // ---------------------------------------------------------------------------- |
| 30 | |
| 31 | class 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. |
| 36 | class ConsumerBase : public virtual RefBase, |
| 37 | protected BufferQueue::ConsumerListener { |
| 38 | public: |
| 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 |
Andy McFadden | 2adaf04 | 2012-12-18 09:49:45 -0800 | [diff] [blame] | 56 | // IGraphicBufferProducer interface will fail with the NO_INIT error. |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 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 | |
Jesse Hall | 7adb0f8 | 2013-03-06 16:13:49 -0800 | [diff] [blame] | 72 | // dump writes the current state to a string. Child classes should add |
| 73 | // their state to the dump by overriding the dumpLocked method, which is |
| 74 | // called by these methods after locking the mutex. |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 75 | void dump(String8& result) const; |
Mathias Agopian | 74d211a | 2013-04-22 16:55:35 +0200 | [diff] [blame] | 76 | void dump(String8& result, const char* prefix) const; |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 77 | |
| 78 | // setFrameAvailableListener sets the listener object that will be notified |
| 79 | // when a new frame becomes available. |
Igor Murashkin | a4a3149 | 2012-10-29 13:36:11 -0700 | [diff] [blame] | 80 | void setFrameAvailableListener(const wp<FrameAvailableListener>& listener); |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 81 | |
| 82 | private: |
| 83 | ConsumerBase(const ConsumerBase&); |
| 84 | void operator=(const ConsumerBase&); |
| 85 | |
| 86 | protected: |
| 87 | |
Jamie Gennis | 9fea342 | 2012-08-07 18:03:04 -0700 | [diff] [blame] | 88 | // ConsumerBase constructs a new ConsumerBase object to consume image |
| 89 | // buffers from the given BufferQueue. |
Mathias Agopian | 595264f | 2013-07-16 22:56:09 -0700 | [diff] [blame^] | 90 | // The controlledByApp flag indicates that this consumer is under the application's |
| 91 | // control. |
| 92 | ConsumerBase(const sp<BufferQueue> &bufferQueue, bool controlledByApp = false); |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 93 | |
Jamie Gennis | ad669b0 | 2013-04-05 16:41:27 -0700 | [diff] [blame] | 94 | // onLastStrongRef gets called by RefBase just before the dtor of the most |
| 95 | // derived class. It is used to clean up the buffers so that ConsumerBase |
| 96 | // can coordinate the clean-up by calling into virtual methods implemented |
| 97 | // by the derived classes. This would not be possible from the |
| 98 | // ConsuemrBase dtor because by the time that gets called the derived |
| 99 | // classes have already been destructed. |
| 100 | // |
| 101 | // This methods should not need to be overridden by derived classes, but |
| 102 | // if they are overridden the ConsumerBase implementation must be called |
| 103 | // from the derived class. |
| 104 | virtual void onLastStrongRef(const void* id); |
| 105 | |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 106 | // Implementation of the BufferQueue::ConsumerListener interface. These |
| 107 | // calls are used to notify the ConsumerBase of asynchronous events in the |
Jamie Gennis | 9fea342 | 2012-08-07 18:03:04 -0700 | [diff] [blame] | 108 | // BufferQueue. These methods should not need to be overridden by derived |
| 109 | // classes, but if they are overridden the ConsumerBase implementation |
| 110 | // must be called from the derived class. |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 111 | virtual void onFrameAvailable(); |
| 112 | virtual void onBuffersReleased(); |
| 113 | |
| 114 | // freeBufferLocked frees up the given buffer slot. If the slot has been |
| 115 | // initialized this will release the reference to the GraphicBuffer in that |
Jamie Gennis | 9fea342 | 2012-08-07 18:03:04 -0700 | [diff] [blame] | 116 | // slot. Otherwise it has no effect. |
| 117 | // |
| 118 | // Derived classes should override this method to clean up any state they |
| 119 | // keep per slot. If it is overridden, the derived class's implementation |
| 120 | // must call ConsumerBase::freeBufferLocked. |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 121 | // |
| 122 | // This method must be called with mMutex locked. |
| 123 | virtual void freeBufferLocked(int slotIndex); |
| 124 | |
| 125 | // abandonLocked puts the BufferQueue into the abandoned state, causing |
| 126 | // all future operations on it to fail. This method rather than the public |
| 127 | // abandon method should be overridden by child classes to add abandon- |
| 128 | // time behavior. |
| 129 | // |
Jamie Gennis | 9fea342 | 2012-08-07 18:03:04 -0700 | [diff] [blame] | 130 | // Derived classes should override this method to clean up any object |
| 131 | // state they keep (as opposed to per-slot state). If it is overridden, |
| 132 | // the derived class's implementation must call ConsumerBase::abandonLocked. |
| 133 | // |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 134 | // This method must be called with mMutex locked. |
| 135 | virtual void abandonLocked(); |
| 136 | |
Jamie Gennis | 9fea342 | 2012-08-07 18:03:04 -0700 | [diff] [blame] | 137 | // dumpLocked dumps the current state of the ConsumerBase object to the |
| 138 | // result string. Each line is prefixed with the string pointed to by the |
| 139 | // prefix argument. The buffer argument points to a buffer that may be |
| 140 | // used for intermediate formatting data, and the size of that buffer is |
| 141 | // indicated by the size argument. |
| 142 | // |
| 143 | // Derived classes should override this method to dump their internal |
| 144 | // state. If this method is overridden the derived class's implementation |
| 145 | // should call ConsumerBase::dumpLocked. |
| 146 | // |
| 147 | // This method must be called with mMutex locked. |
Mathias Agopian | 74d211a | 2013-04-22 16:55:35 +0200 | [diff] [blame] | 148 | virtual void dumpLocked(String8& result, const char* prefix) const; |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 149 | |
| 150 | // acquireBufferLocked fetches the next buffer from the BufferQueue and |
| 151 | // updates the buffer slot for the buffer returned. |
Jamie Gennis | 9fea342 | 2012-08-07 18:03:04 -0700 | [diff] [blame] | 152 | // |
| 153 | // Derived classes should override this method to perform any |
| 154 | // initialization that must take place the first time a buffer is assigned |
| 155 | // to a slot. If it is overridden the derived class's implementation must |
| 156 | // call ConsumerBase::acquireBufferLocked. |
Andy McFadden | 1585c4d | 2013-06-28 13:52:40 -0700 | [diff] [blame] | 157 | virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item, |
| 158 | nsecs_t presentWhen); |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 159 | |
| 160 | // releaseBufferLocked relinquishes control over a buffer, returning that |
| 161 | // control to the BufferQueue. |
Jamie Gennis | 9fea342 | 2012-08-07 18:03:04 -0700 | [diff] [blame] | 162 | // |
| 163 | // Derived classes should override this method to perform any cleanup that |
| 164 | // must take place when a buffer is released back to the BufferQueue. If |
| 165 | // it is overridden the derived class's implementation must call |
Lajos Molnar | c5d7b7d | 2013-05-03 14:50:50 -0700 | [diff] [blame] | 166 | // ConsumerBase::releaseBufferLocked.e |
| 167 | virtual status_t releaseBufferLocked(int slot, |
| 168 | const sp<GraphicBuffer> graphicBuffer, |
| 169 | EGLDisplay display, EGLSyncKHR eglFence); |
| 170 | |
| 171 | // returns true iff the slot still has the graphicBuffer in it. |
| 172 | bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer); |
Jamie Gennis | b272541 | 2012-09-05 20:09:05 -0700 | [diff] [blame] | 173 | |
Jesse Hall | 9504eb9 | 2012-10-05 14:34:21 -0700 | [diff] [blame] | 174 | // addReleaseFence* adds the sync points associated with a fence to the set |
Jamie Gennis | b272541 | 2012-09-05 20:09:05 -0700 | [diff] [blame] | 175 | // of sync points that must be reached before the buffer in the given slot |
| 176 | // may be used after the slot has been released. This should be called by |
| 177 | // derived classes each time some asynchronous work is kicked off that |
| 178 | // references the buffer. |
Lajos Molnar | c5d7b7d | 2013-05-03 14:50:50 -0700 | [diff] [blame] | 179 | status_t addReleaseFence(int slot, |
| 180 | const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence); |
| 181 | status_t addReleaseFenceLocked(int slot, |
| 182 | const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence); |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 183 | |
| 184 | // Slot contains the information and object references that |
| 185 | // ConsumerBase maintains about a BufferQueue buffer slot. |
| 186 | struct Slot { |
| 187 | // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if |
| 188 | // no Gralloc buffer is in the slot. |
| 189 | sp<GraphicBuffer> mGraphicBuffer; |
| 190 | |
| 191 | // mFence is a fence which will signal when the buffer associated with |
| 192 | // this buffer slot is no longer being used by the consumer and can be |
| 193 | // overwritten. The buffer can be dequeued before the fence signals; |
| 194 | // the producer is responsible for delaying writes until it signals. |
| 195 | sp<Fence> mFence; |
Lajos Molnar | c5d7b7d | 2013-05-03 14:50:50 -0700 | [diff] [blame] | 196 | |
| 197 | // the frame number of the last acquired frame for this slot |
| 198 | uint64_t mFrameNumber; |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 199 | }; |
| 200 | |
| 201 | // mSlots stores the buffers that have been allocated by the BufferQueue |
| 202 | // for each buffer slot. It is initialized to null pointers, and gets |
| 203 | // filled in with the result of BufferQueue::acquire when the |
| 204 | // client dequeues a buffer from a |
| 205 | // slot that has not yet been used. The buffer allocated to a slot will also |
| 206 | // be replaced if the requested buffer usage or geometry differs from that |
| 207 | // of the buffer allocated to a slot. |
| 208 | Slot mSlots[BufferQueue::NUM_BUFFER_SLOTS]; |
| 209 | |
| 210 | // mAbandoned indicates that the BufferQueue will no longer be used to |
Andy McFadden | 2adaf04 | 2012-12-18 09:49:45 -0800 | [diff] [blame] | 211 | // consume images buffers pushed to it using the IGraphicBufferProducer |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 212 | // interface. It is initialized to false, and set to true in the abandon |
| 213 | // method. A BufferQueue that has been abandoned will return the NO_INIT |
| 214 | // error from all IConsumerBase methods capable of returning an error. |
| 215 | bool mAbandoned; |
| 216 | |
| 217 | // mName is a string used to identify the ConsumerBase in log messages. |
| 218 | // It can be set by the setName method. |
| 219 | String8 mName; |
| 220 | |
| 221 | // mFrameAvailableListener is the listener object that will be called when a |
| 222 | // new frame becomes available. If it is not NULL it will be called from |
| 223 | // queueBuffer. |
Igor Murashkin | a4a3149 | 2012-10-29 13:36:11 -0700 | [diff] [blame] | 224 | wp<FrameAvailableListener> mFrameAvailableListener; |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 225 | |
| 226 | // The ConsumerBase has-a BufferQueue and is responsible for creating this object |
| 227 | // if none is supplied |
| 228 | sp<BufferQueue> mBufferQueue; |
| 229 | |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 230 | // mMutex is the mutex used to prevent concurrent access to the member |
| 231 | // variables of ConsumerBase objects. It must be locked whenever the |
Jamie Gennis | 9fea342 | 2012-08-07 18:03:04 -0700 | [diff] [blame] | 232 | // member variables are accessed or when any of the *Locked methods are |
| 233 | // called. |
| 234 | // |
| 235 | // This mutex is intended to be locked by derived classes. |
Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 236 | mutable Mutex mMutex; |
| 237 | }; |
| 238 | |
| 239 | // ---------------------------------------------------------------------------- |
| 240 | }; // namespace android |
| 241 | |
| 242 | #endif // ANDROID_GUI_CONSUMERBASE_H |