michael@0: /* michael@0: * Copyright (C) 2010 The Android Open Source Project michael@0: * Copyright (C) 2013 Mozilla Foundation michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: #ifndef NATIVEWINDOW_GONKCONSUMERBASE_KK_H michael@0: #define NATIVEWINDOW_GONKCONSUMERBASE_KK_H michael@0: michael@0: #include michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include "GonkBufferQueueKK.h" michael@0: michael@0: namespace android { michael@0: // ---------------------------------------------------------------------------- michael@0: michael@0: class String8; michael@0: michael@0: // GonkConsumerBase is a base class for GonkBufferQueue consumer end-points. It michael@0: // handles common tasks like management of the connection to the GonkBufferQueue michael@0: // and the buffer pool. michael@0: class GonkConsumerBase : public virtual RefBase, michael@0: protected ConsumerListener { michael@0: public: michael@0: struct FrameAvailableListener : public virtual RefBase { michael@0: // onFrameAvailable() is called each time an additional frame becomes michael@0: // available for consumption. This means that frames that are queued michael@0: // while in asynchronous mode only trigger the callback if no previous michael@0: // frames are pending. Frames queued while in synchronous mode always michael@0: // trigger the callback. michael@0: // michael@0: // This is called without any lock held and can be called concurrently michael@0: // by multiple threads. michael@0: virtual void onFrameAvailable() = 0; michael@0: }; michael@0: michael@0: virtual ~GonkConsumerBase(); michael@0: michael@0: // abandon frees all the buffers and puts the GonkConsumerBase into the michael@0: // 'abandoned' state. Once put in this state the GonkConsumerBase can never michael@0: // leave it. When in the 'abandoned' state, all methods of the michael@0: // IGraphicBufferProducer interface will fail with the NO_INIT error. michael@0: // michael@0: // Note that while calling this method causes all the buffers to be freed michael@0: // from the perspective of the the GonkConsumerBase, if there are additional michael@0: // references on the buffers (e.g. if a buffer is referenced by a client michael@0: // or by OpenGL ES as a texture) then those buffer will remain allocated. michael@0: void abandon(); michael@0: michael@0: // set the name of the GonkConsumerBase that will be used to identify it in michael@0: // log messages. michael@0: void setName(const String8& name); michael@0: michael@0: // getBufferQueue returns the GonkBufferQueue object to which this michael@0: // GonkConsumerBase is connected. michael@0: sp getBufferQueue() const; michael@0: michael@0: // dump writes the current state to a string. Child classes should add michael@0: // their state to the dump by overriding the dumpLocked method, which is michael@0: // called by these methods after locking the mutex. michael@0: void dump(String8& result) const; michael@0: void dump(String8& result, const char* prefix) const; michael@0: michael@0: // setFrameAvailableListener sets the listener object that will be notified michael@0: // when a new frame becomes available. michael@0: void setFrameAvailableListener(const wp& listener); michael@0: michael@0: private: michael@0: GonkConsumerBase(const GonkConsumerBase&); michael@0: void operator=(const GonkConsumerBase&); michael@0: michael@0: protected: michael@0: michael@0: // GonkConsumerBase constructs a new GonkConsumerBase object to consume image michael@0: // buffers from the given GonkBufferQueue. michael@0: GonkConsumerBase(const sp& bufferQueue, bool controlledByApp = false); michael@0: michael@0: // onLastStrongRef gets called by RefBase just before the dtor of the most michael@0: // derived class. It is used to clean up the buffers so that GonkConsumerBase michael@0: // can coordinate the clean-up by calling into virtual methods implemented michael@0: // by the derived classes. This would not be possible from the michael@0: // ConsuemrBase dtor because by the time that gets called the derived michael@0: // classes have already been destructed. michael@0: // michael@0: // This methods should not need to be overridden by derived classes, but michael@0: // if they are overridden the GonkConsumerBase implementation must be called michael@0: // from the derived class. michael@0: virtual void onLastStrongRef(const void* id); michael@0: michael@0: // Implementation of the GonkBufferQueue::ConsumerListener interface. These michael@0: // calls are used to notify the GonkConsumerBase of asynchronous events in the michael@0: // GonkBufferQueue. These methods should not need to be overridden by derived michael@0: // classes, but if they are overridden the GonkConsumerBase implementation michael@0: // must be called from the derived class. michael@0: virtual void onFrameAvailable(); michael@0: virtual void onBuffersReleased(); michael@0: michael@0: // freeBufferLocked frees up the given buffer slot. If the slot has been michael@0: // initialized this will release the reference to the GraphicBuffer in that michael@0: // slot. Otherwise it has no effect. michael@0: // michael@0: // Derived classes should override this method to clean up any state they michael@0: // keep per slot. If it is overridden, the derived class's implementation michael@0: // must call GonkConsumerBase::freeBufferLocked. michael@0: // michael@0: // This method must be called with mMutex locked. michael@0: virtual void freeBufferLocked(int slotIndex); michael@0: michael@0: // abandonLocked puts the GonkBufferQueue into the abandoned state, causing michael@0: // all future operations on it to fail. This method rather than the public michael@0: // abandon method should be overridden by child classes to add abandon- michael@0: // time behavior. michael@0: // michael@0: // Derived classes should override this method to clean up any object michael@0: // state they keep (as opposed to per-slot state). If it is overridden, michael@0: // the derived class's implementation must call GonkConsumerBase::abandonLocked. michael@0: // michael@0: // This method must be called with mMutex locked. michael@0: virtual void abandonLocked(); michael@0: michael@0: // dumpLocked dumps the current state of the GonkConsumerBase object to the michael@0: // result string. Each line is prefixed with the string pointed to by the michael@0: // prefix argument. The buffer argument points to a buffer that may be michael@0: // used for intermediate formatting data, and the size of that buffer is michael@0: // indicated by the size argument. michael@0: // michael@0: // Derived classes should override this method to dump their internal michael@0: // state. If this method is overridden the derived class's implementation michael@0: // should call GonkConsumerBase::dumpLocked. michael@0: // michael@0: // This method must be called with mMutex locked. michael@0: virtual void dumpLocked(String8& result, const char* prefix) const; michael@0: michael@0: // acquireBufferLocked fetches the next buffer from the GonkBufferQueue and michael@0: // updates the buffer slot for the buffer returned. michael@0: // michael@0: // Derived classes should override this method to perform any michael@0: // initialization that must take place the first time a buffer is assigned michael@0: // to a slot. If it is overridden the derived class's implementation must michael@0: // call GonkConsumerBase::acquireBufferLocked. michael@0: virtual status_t acquireBufferLocked(IGonkGraphicBufferConsumer::BufferItem *item, michael@0: nsecs_t presentWhen); michael@0: michael@0: // releaseBufferLocked relinquishes control over a buffer, returning that michael@0: // control to the GonkBufferQueue. michael@0: // michael@0: // Derived classes should override this method to perform any cleanup that michael@0: // must take place when a buffer is released back to the GonkBufferQueue. If michael@0: // it is overridden the derived class's implementation must call michael@0: // GonkConsumerBase::releaseBufferLocked. michael@0: virtual status_t releaseBufferLocked(int slot, const sp graphicBuffer); michael@0: michael@0: // returns true iff the slot still has the graphicBuffer in it. michael@0: bool stillTracking(int slot, const sp graphicBuffer); michael@0: michael@0: // addReleaseFence* adds the sync points associated with a fence to the set michael@0: // of sync points that must be reached before the buffer in the given slot michael@0: // may be used after the slot has been released. This should be called by michael@0: // derived classes each time some asynchronous work is kicked off that michael@0: // references the buffer. michael@0: status_t addReleaseFence(int slot, michael@0: const sp graphicBuffer, const sp& fence); michael@0: status_t addReleaseFenceLocked(int slot, michael@0: const sp graphicBuffer, const sp& fence); michael@0: michael@0: // Slot contains the information and object references that michael@0: // GonkConsumerBase maintains about a GonkBufferQueue buffer slot. michael@0: struct Slot { michael@0: // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if michael@0: // no Gralloc buffer is in the slot. michael@0: sp mGraphicBuffer; michael@0: michael@0: // mFence is a fence which will signal when the buffer associated with michael@0: // this buffer slot is no longer being used by the consumer and can be michael@0: // overwritten. The buffer can be dequeued before the fence signals; michael@0: // the producer is responsible for delaying writes until it signals. michael@0: sp mFence; michael@0: michael@0: // the frame number of the last acquired frame for this slot michael@0: uint64_t mFrameNumber; michael@0: }; michael@0: michael@0: // mSlots stores the buffers that have been allocated by the GonkBufferQueue michael@0: // for each buffer slot. It is initialized to null pointers, and gets michael@0: // filled in with the result of GonkBufferQueue::acquire when the michael@0: // client dequeues a buffer from a michael@0: // slot that has not yet been used. The buffer allocated to a slot will also michael@0: // be replaced if the requested buffer usage or geometry differs from that michael@0: // of the buffer allocated to a slot. michael@0: Slot mSlots[GonkBufferQueue::NUM_BUFFER_SLOTS]; michael@0: michael@0: // mAbandoned indicates that the GonkBufferQueue will no longer be used to michael@0: // consume images buffers pushed to it using the IGraphicBufferProducer michael@0: // interface. It is initialized to false, and set to true in the abandon michael@0: // method. A GonkBufferQueue that has been abandoned will return the NO_INIT michael@0: // error from all IGonkConsumerBase methods capable of returning an error. michael@0: bool mAbandoned; michael@0: michael@0: // mName is a string used to identify the GonkConsumerBase in log messages. michael@0: // It can be set by the setName method. michael@0: String8 mName; michael@0: michael@0: // mFrameAvailableListener is the listener object that will be called when a michael@0: // new frame becomes available. If it is not NULL it will be called from michael@0: // queueBuffer. michael@0: wp mFrameAvailableListener; michael@0: michael@0: // The GonkConsumerBase has-a GonkBufferQueue and is responsible for creating this object michael@0: // if none is supplied michael@0: sp mConsumer; michael@0: michael@0: // mMutex is the mutex used to prevent concurrent access to the member michael@0: // variables of GonkConsumerBase objects. It must be locked whenever the michael@0: // member variables are accessed or when any of the *Locked methods are michael@0: // called. michael@0: // michael@0: // This mutex is intended to be locked by derived classes. michael@0: mutable Mutex mMutex; michael@0: }; michael@0: michael@0: // ---------------------------------------------------------------------------- michael@0: }; // namespace android michael@0: michael@0: #endif // NATIVEWINDOW_GONKCONSUMERBASE_H