Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright (C) 2010 The Android Open Source Project |
michael@0 | 3 | * Copyright (C) 2013 Mozilla Foundation |
michael@0 | 4 | * |
michael@0 | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
michael@0 | 6 | * you may not use this file except in compliance with the License. |
michael@0 | 7 | * You may obtain a copy of the License at |
michael@0 | 8 | * |
michael@0 | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
michael@0 | 10 | * |
michael@0 | 11 | * Unless required by applicable law or agreed to in writing, software |
michael@0 | 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
michael@0 | 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
michael@0 | 14 | * See the License for the specific language governing permissions and |
michael@0 | 15 | * limitations under the License. |
michael@0 | 16 | */ |
michael@0 | 17 | |
michael@0 | 18 | #ifndef NATIVEWINDOW_GONKCONSUMERBASE_KK_H |
michael@0 | 19 | #define NATIVEWINDOW_GONKCONSUMERBASE_KK_H |
michael@0 | 20 | |
michael@0 | 21 | #include <ui/GraphicBuffer.h> |
michael@0 | 22 | |
michael@0 | 23 | #include <utils/String8.h> |
michael@0 | 24 | #include <utils/Vector.h> |
michael@0 | 25 | #include <utils/threads.h> |
michael@0 | 26 | #include <gui/IConsumerListener.h> |
michael@0 | 27 | |
michael@0 | 28 | #include "GonkBufferQueueKK.h" |
michael@0 | 29 | |
michael@0 | 30 | namespace android { |
michael@0 | 31 | // ---------------------------------------------------------------------------- |
michael@0 | 32 | |
michael@0 | 33 | class String8; |
michael@0 | 34 | |
michael@0 | 35 | // GonkConsumerBase is a base class for GonkBufferQueue consumer end-points. It |
michael@0 | 36 | // handles common tasks like management of the connection to the GonkBufferQueue |
michael@0 | 37 | // and the buffer pool. |
michael@0 | 38 | class GonkConsumerBase : public virtual RefBase, |
michael@0 | 39 | protected ConsumerListener { |
michael@0 | 40 | public: |
michael@0 | 41 | struct FrameAvailableListener : public virtual RefBase { |
michael@0 | 42 | // onFrameAvailable() is called each time an additional frame becomes |
michael@0 | 43 | // available for consumption. This means that frames that are queued |
michael@0 | 44 | // while in asynchronous mode only trigger the callback if no previous |
michael@0 | 45 | // frames are pending. Frames queued while in synchronous mode always |
michael@0 | 46 | // trigger the callback. |
michael@0 | 47 | // |
michael@0 | 48 | // This is called without any lock held and can be called concurrently |
michael@0 | 49 | // by multiple threads. |
michael@0 | 50 | virtual void onFrameAvailable() = 0; |
michael@0 | 51 | }; |
michael@0 | 52 | |
michael@0 | 53 | virtual ~GonkConsumerBase(); |
michael@0 | 54 | |
michael@0 | 55 | // abandon frees all the buffers and puts the GonkConsumerBase into the |
michael@0 | 56 | // 'abandoned' state. Once put in this state the GonkConsumerBase can never |
michael@0 | 57 | // leave it. When in the 'abandoned' state, all methods of the |
michael@0 | 58 | // IGraphicBufferProducer interface will fail with the NO_INIT error. |
michael@0 | 59 | // |
michael@0 | 60 | // Note that while calling this method causes all the buffers to be freed |
michael@0 | 61 | // from the perspective of the the GonkConsumerBase, if there are additional |
michael@0 | 62 | // references on the buffers (e.g. if a buffer is referenced by a client |
michael@0 | 63 | // or by OpenGL ES as a texture) then those buffer will remain allocated. |
michael@0 | 64 | void abandon(); |
michael@0 | 65 | |
michael@0 | 66 | // set the name of the GonkConsumerBase that will be used to identify it in |
michael@0 | 67 | // log messages. |
michael@0 | 68 | void setName(const String8& name); |
michael@0 | 69 | |
michael@0 | 70 | // getBufferQueue returns the GonkBufferQueue object to which this |
michael@0 | 71 | // GonkConsumerBase is connected. |
michael@0 | 72 | sp<GonkBufferQueue> getBufferQueue() const; |
michael@0 | 73 | |
michael@0 | 74 | // dump writes the current state to a string. Child classes should add |
michael@0 | 75 | // their state to the dump by overriding the dumpLocked method, which is |
michael@0 | 76 | // called by these methods after locking the mutex. |
michael@0 | 77 | void dump(String8& result) const; |
michael@0 | 78 | void dump(String8& result, const char* prefix) const; |
michael@0 | 79 | |
michael@0 | 80 | // setFrameAvailableListener sets the listener object that will be notified |
michael@0 | 81 | // when a new frame becomes available. |
michael@0 | 82 | void setFrameAvailableListener(const wp<FrameAvailableListener>& listener); |
michael@0 | 83 | |
michael@0 | 84 | private: |
michael@0 | 85 | GonkConsumerBase(const GonkConsumerBase&); |
michael@0 | 86 | void operator=(const GonkConsumerBase&); |
michael@0 | 87 | |
michael@0 | 88 | protected: |
michael@0 | 89 | |
michael@0 | 90 | // GonkConsumerBase constructs a new GonkConsumerBase object to consume image |
michael@0 | 91 | // buffers from the given GonkBufferQueue. |
michael@0 | 92 | GonkConsumerBase(const sp<GonkBufferQueue>& bufferQueue, bool controlledByApp = false); |
michael@0 | 93 | |
michael@0 | 94 | // onLastStrongRef gets called by RefBase just before the dtor of the most |
michael@0 | 95 | // derived class. It is used to clean up the buffers so that GonkConsumerBase |
michael@0 | 96 | // can coordinate the clean-up by calling into virtual methods implemented |
michael@0 | 97 | // by the derived classes. This would not be possible from the |
michael@0 | 98 | // ConsuemrBase dtor because by the time that gets called the derived |
michael@0 | 99 | // classes have already been destructed. |
michael@0 | 100 | // |
michael@0 | 101 | // This methods should not need to be overridden by derived classes, but |
michael@0 | 102 | // if they are overridden the GonkConsumerBase implementation must be called |
michael@0 | 103 | // from the derived class. |
michael@0 | 104 | virtual void onLastStrongRef(const void* id); |
michael@0 | 105 | |
michael@0 | 106 | // Implementation of the GonkBufferQueue::ConsumerListener interface. These |
michael@0 | 107 | // calls are used to notify the GonkConsumerBase of asynchronous events in the |
michael@0 | 108 | // GonkBufferQueue. These methods should not need to be overridden by derived |
michael@0 | 109 | // classes, but if they are overridden the GonkConsumerBase implementation |
michael@0 | 110 | // must be called from the derived class. |
michael@0 | 111 | virtual void onFrameAvailable(); |
michael@0 | 112 | virtual void onBuffersReleased(); |
michael@0 | 113 | |
michael@0 | 114 | // freeBufferLocked frees up the given buffer slot. If the slot has been |
michael@0 | 115 | // initialized this will release the reference to the GraphicBuffer in that |
michael@0 | 116 | // slot. Otherwise it has no effect. |
michael@0 | 117 | // |
michael@0 | 118 | // Derived classes should override this method to clean up any state they |
michael@0 | 119 | // keep per slot. If it is overridden, the derived class's implementation |
michael@0 | 120 | // must call GonkConsumerBase::freeBufferLocked. |
michael@0 | 121 | // |
michael@0 | 122 | // This method must be called with mMutex locked. |
michael@0 | 123 | virtual void freeBufferLocked(int slotIndex); |
michael@0 | 124 | |
michael@0 | 125 | // abandonLocked puts the GonkBufferQueue into the abandoned state, causing |
michael@0 | 126 | // all future operations on it to fail. This method rather than the public |
michael@0 | 127 | // abandon method should be overridden by child classes to add abandon- |
michael@0 | 128 | // time behavior. |
michael@0 | 129 | // |
michael@0 | 130 | // Derived classes should override this method to clean up any object |
michael@0 | 131 | // state they keep (as opposed to per-slot state). If it is overridden, |
michael@0 | 132 | // the derived class's implementation must call GonkConsumerBase::abandonLocked. |
michael@0 | 133 | // |
michael@0 | 134 | // This method must be called with mMutex locked. |
michael@0 | 135 | virtual void abandonLocked(); |
michael@0 | 136 | |
michael@0 | 137 | // dumpLocked dumps the current state of the GonkConsumerBase object to the |
michael@0 | 138 | // result string. Each line is prefixed with the string pointed to by the |
michael@0 | 139 | // prefix argument. The buffer argument points to a buffer that may be |
michael@0 | 140 | // used for intermediate formatting data, and the size of that buffer is |
michael@0 | 141 | // indicated by the size argument. |
michael@0 | 142 | // |
michael@0 | 143 | // Derived classes should override this method to dump their internal |
michael@0 | 144 | // state. If this method is overridden the derived class's implementation |
michael@0 | 145 | // should call GonkConsumerBase::dumpLocked. |
michael@0 | 146 | // |
michael@0 | 147 | // This method must be called with mMutex locked. |
michael@0 | 148 | virtual void dumpLocked(String8& result, const char* prefix) const; |
michael@0 | 149 | |
michael@0 | 150 | // acquireBufferLocked fetches the next buffer from the GonkBufferQueue and |
michael@0 | 151 | // updates the buffer slot for the buffer returned. |
michael@0 | 152 | // |
michael@0 | 153 | // Derived classes should override this method to perform any |
michael@0 | 154 | // initialization that must take place the first time a buffer is assigned |
michael@0 | 155 | // to a slot. If it is overridden the derived class's implementation must |
michael@0 | 156 | // call GonkConsumerBase::acquireBufferLocked. |
michael@0 | 157 | virtual status_t acquireBufferLocked(IGonkGraphicBufferConsumer::BufferItem *item, |
michael@0 | 158 | nsecs_t presentWhen); |
michael@0 | 159 | |
michael@0 | 160 | // releaseBufferLocked relinquishes control over a buffer, returning that |
michael@0 | 161 | // control to the GonkBufferQueue. |
michael@0 | 162 | // |
michael@0 | 163 | // Derived classes should override this method to perform any cleanup that |
michael@0 | 164 | // must take place when a buffer is released back to the GonkBufferQueue. If |
michael@0 | 165 | // it is overridden the derived class's implementation must call |
michael@0 | 166 | // GonkConsumerBase::releaseBufferLocked. |
michael@0 | 167 | virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer); |
michael@0 | 168 | |
michael@0 | 169 | // returns true iff the slot still has the graphicBuffer in it. |
michael@0 | 170 | bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer); |
michael@0 | 171 | |
michael@0 | 172 | // addReleaseFence* adds the sync points associated with a fence to the set |
michael@0 | 173 | // of sync points that must be reached before the buffer in the given slot |
michael@0 | 174 | // may be used after the slot has been released. This should be called by |
michael@0 | 175 | // derived classes each time some asynchronous work is kicked off that |
michael@0 | 176 | // references the buffer. |
michael@0 | 177 | status_t addReleaseFence(int slot, |
michael@0 | 178 | const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence); |
michael@0 | 179 | status_t addReleaseFenceLocked(int slot, |
michael@0 | 180 | const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence); |
michael@0 | 181 | |
michael@0 | 182 | // Slot contains the information and object references that |
michael@0 | 183 | // GonkConsumerBase maintains about a GonkBufferQueue buffer slot. |
michael@0 | 184 | struct Slot { |
michael@0 | 185 | // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if |
michael@0 | 186 | // no Gralloc buffer is in the slot. |
michael@0 | 187 | sp<GraphicBuffer> mGraphicBuffer; |
michael@0 | 188 | |
michael@0 | 189 | // mFence is a fence which will signal when the buffer associated with |
michael@0 | 190 | // this buffer slot is no longer being used by the consumer and can be |
michael@0 | 191 | // overwritten. The buffer can be dequeued before the fence signals; |
michael@0 | 192 | // the producer is responsible for delaying writes until it signals. |
michael@0 | 193 | sp<Fence> mFence; |
michael@0 | 194 | |
michael@0 | 195 | // the frame number of the last acquired frame for this slot |
michael@0 | 196 | uint64_t mFrameNumber; |
michael@0 | 197 | }; |
michael@0 | 198 | |
michael@0 | 199 | // mSlots stores the buffers that have been allocated by the GonkBufferQueue |
michael@0 | 200 | // for each buffer slot. It is initialized to null pointers, and gets |
michael@0 | 201 | // filled in with the result of GonkBufferQueue::acquire when the |
michael@0 | 202 | // client dequeues a buffer from a |
michael@0 | 203 | // slot that has not yet been used. The buffer allocated to a slot will also |
michael@0 | 204 | // be replaced if the requested buffer usage or geometry differs from that |
michael@0 | 205 | // of the buffer allocated to a slot. |
michael@0 | 206 | Slot mSlots[GonkBufferQueue::NUM_BUFFER_SLOTS]; |
michael@0 | 207 | |
michael@0 | 208 | // mAbandoned indicates that the GonkBufferQueue will no longer be used to |
michael@0 | 209 | // consume images buffers pushed to it using the IGraphicBufferProducer |
michael@0 | 210 | // interface. It is initialized to false, and set to true in the abandon |
michael@0 | 211 | // method. A GonkBufferQueue that has been abandoned will return the NO_INIT |
michael@0 | 212 | // error from all IGonkConsumerBase methods capable of returning an error. |
michael@0 | 213 | bool mAbandoned; |
michael@0 | 214 | |
michael@0 | 215 | // mName is a string used to identify the GonkConsumerBase in log messages. |
michael@0 | 216 | // It can be set by the setName method. |
michael@0 | 217 | String8 mName; |
michael@0 | 218 | |
michael@0 | 219 | // mFrameAvailableListener is the listener object that will be called when a |
michael@0 | 220 | // new frame becomes available. If it is not NULL it will be called from |
michael@0 | 221 | // queueBuffer. |
michael@0 | 222 | wp<FrameAvailableListener> mFrameAvailableListener; |
michael@0 | 223 | |
michael@0 | 224 | // The GonkConsumerBase has-a GonkBufferQueue and is responsible for creating this object |
michael@0 | 225 | // if none is supplied |
michael@0 | 226 | sp<GonkBufferQueue> mConsumer; |
michael@0 | 227 | |
michael@0 | 228 | // mMutex is the mutex used to prevent concurrent access to the member |
michael@0 | 229 | // variables of GonkConsumerBase objects. It must be locked whenever the |
michael@0 | 230 | // member variables are accessed or when any of the *Locked methods are |
michael@0 | 231 | // called. |
michael@0 | 232 | // |
michael@0 | 233 | // This mutex is intended to be locked by derived classes. |
michael@0 | 234 | mutable Mutex mMutex; |
michael@0 | 235 | }; |
michael@0 | 236 | |
michael@0 | 237 | // ---------------------------------------------------------------------------- |
michael@0 | 238 | }; // namespace android |
michael@0 | 239 | |
michael@0 | 240 | #endif // NATIVEWINDOW_GONKCONSUMERBASE_H |