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