/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_GUI_CONSUMERBASE_H #define ANDROID_GUI_CONSUMERBASE_H #include #include #include #include #include namespace android { // ---------------------------------------------------------------------------- class String8; // ConsumerBase is a base class for BufferQueue consumer end-points. It // handles common tasks like management of the connection to the BufferQueue // and the buffer pool. class ConsumerBase : public virtual RefBase, protected BufferQueue::ConsumerListener { public: struct FrameAvailableListener : public virtual RefBase { // onFrameAvailable() is called each time an additional frame becomes // available for consumption. This means that frames that are queued // while in asynchronous mode only trigger the callback if no previous // frames are pending. Frames queued while in synchronous mode always // trigger the callback. // // This is called without any lock held and can be called concurrently // by multiple threads. virtual void onFrameAvailable() = 0; }; virtual ~ConsumerBase(); // abandon frees all the buffers and puts the ConsumerBase into the // 'abandoned' state. Once put in this state the ConsumerBase can never // leave it. When in the 'abandoned' state, all methods of the // ISurfaceTexture interface will fail with the NO_INIT error. // // Note that while calling this method causes all the buffers to be freed // from the perspective of the the ConsumerBase, if there are additional // references on the buffers (e.g. if a buffer is referenced by a client // or by OpenGL ES as a texture) then those buffer will remain allocated. void abandon(); // set the name of the ConsumerBase that will be used to identify it in // log messages. void setName(const String8& name); // getBufferQueue returns the BufferQueue object to which this // ConsumerBase is connected. sp getBufferQueue() const; // dump writes the current state to a string. These methods should NOT be // overridden by child classes. Instead they should override the // dumpLocked method, which is called by these methods after locking the // mutex. void dump(String8& result) const; void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const; // setFrameAvailableListener sets the listener object that will be notified // when a new frame becomes available. void setFrameAvailableListener(const sp& listener); private: ConsumerBase(const ConsumerBase&); void operator=(const ConsumerBase&); protected: // TODO: Fix this comment // ConsumerBase constructs a new ConsumerBase object. tex indicates the // name of the OpenGL ES texture to which images are to be streamed. // allowSynchronousMode specifies whether or not synchronous mode can be // enabled. texTarget specifies the OpenGL ES texture target to which the // texture will be bound in updateTexImage. useFenceSync specifies whether // fences should be used to synchronize access to buffers if that behavior // is enabled at compile-time. A custom bufferQueue can be specified // if behavior for queue/dequeue/connect etc needs to be customized. // Otherwise a default BufferQueue will be created and used. // // For legacy reasons, the ConsumerBase is created in a state where it is // considered attached to an OpenGL ES context for the purposes of the // attachToContext and detachFromContext methods. However, despite being // considered "attached" to a context, the specific OpenGL ES context // doesn't get latched until the first call to updateTexImage. After that // point, all calls to updateTexImage must be made with the same OpenGL ES // context current. // // A ConsumerBase may be detached from one OpenGL ES context and then // attached to a different context using the detachFromContext and // attachToContext methods, respectively. The intention of these methods is // purely to allow a ConsumerBase to be transferred from one consumer // context to another. If such a transfer is not needed there is no // requirement that either of these methods be called. ConsumerBase(const sp &bufferQueue); // Implementation of the BufferQueue::ConsumerListener interface. These // calls are used to notify the ConsumerBase of asynchronous events in the // BufferQueue. virtual void onFrameAvailable(); virtual void onBuffersReleased(); // freeBufferLocked frees up the given buffer slot. If the slot has been // initialized this will release the reference to the GraphicBuffer in that // slot and destroy the EGLImage in that slot. Otherwise it has no effect. // // This method must be called with mMutex locked. virtual void freeBufferLocked(int slotIndex); // abandonLocked puts the BufferQueue into the abandoned state, causing // all future operations on it to fail. This method rather than the public // abandon method should be overridden by child classes to add abandon- // time behavior. // // This method must be called with mMutex locked. virtual void abandonLocked(); virtual void dumpLocked(String8& result, const char* prefix, char* buffer, size_t SIZE) const; // acquireBufferLocked fetches the next buffer from the BufferQueue and // updates the buffer slot for the buffer returned. virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item); // releaseBufferLocked relinquishes control over a buffer, returning that // control to the BufferQueue. virtual status_t releaseBufferLocked(int buf, EGLDisplay display, EGLSyncKHR eglFence, const sp& fence); // Slot contains the information and object references that // ConsumerBase maintains about a BufferQueue buffer slot. struct Slot { // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if // no Gralloc buffer is in the slot. sp mGraphicBuffer; // mFence is a fence which will signal when the buffer associated with // this buffer slot is no longer being used by the consumer and can be // overwritten. The buffer can be dequeued before the fence signals; // the producer is responsible for delaying writes until it signals. sp mFence; }; // mSlots stores the buffers that have been allocated by the BufferQueue // for each buffer slot. It is initialized to null pointers, and gets // filled in with the result of BufferQueue::acquire when the // client dequeues a buffer from a // slot that has not yet been used. The buffer allocated to a slot will also // be replaced if the requested buffer usage or geometry differs from that // of the buffer allocated to a slot. Slot mSlots[BufferQueue::NUM_BUFFER_SLOTS]; // mAbandoned indicates that the BufferQueue will no longer be used to // consume images buffers pushed to it using the ISurfaceTexture // interface. It is initialized to false, and set to true in the abandon // method. A BufferQueue that has been abandoned will return the NO_INIT // error from all IConsumerBase methods capable of returning an error. bool mAbandoned; // mName is a string used to identify the ConsumerBase in log messages. // It can be set by the setName method. String8 mName; // mFrameAvailableListener is the listener object that will be called when a // new frame becomes available. If it is not NULL it will be called from // queueBuffer. sp mFrameAvailableListener; // The ConsumerBase has-a BufferQueue and is responsible for creating this object // if none is supplied sp mBufferQueue; // mMutex is the mutex used to prevent concurrent access to the member // variables of ConsumerBase objects. It must be locked whenever the // member variables are accessed. mutable Mutex mMutex; }; // ---------------------------------------------------------------------------- }; // namespace android #endif // ANDROID_GUI_CONSUMERBASE_H