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