Android Surfaceflinger服务(一) ----- BufferQueue分析

生产者和消费者模型是编程中运用比较广泛的模型。在SurfaceFlinger图像绘制、合成、显示也用到了该模型。利用该模型合理的管理图像缓冲区buffer。让整个android系统从绘制到显示的过程有条不紊的进行。

BufferQueue图像缓冲管理者。其成员函数createBufferQueue创建一个缓冲区队列。

void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
        sp<IGraphicBufferConsumer>* outConsumer,
        const sp<IGraphicBufferAlloc>& allocator) {
    LOG_ALWAYS_FATAL_IF(outProducer == NULL,
            "BufferQueue: outProducer must not be NULL");
    LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
            "BufferQueue: outConsumer must not be NULL");                                                                                                                                    

    sp<BufferQueueCore> core(new BufferQueueCore(allocator));
    LOG_ALWAYS_FATAL_IF(core == NULL,
            "BufferQueue: failed to create BufferQueueCore");                                                                                                                                

    sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));
    LOG_ALWAYS_FATAL_IF(producer == NULL,
            "BufferQueue: failed to create BufferQueueProducer");                                                                                                                            

    sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
    LOG_ALWAYS_FATAL_IF(consumer == NULL,
            "BufferQueue: failed to create BufferQueueConsumer");                                                                                                                            

    *outProducer = producer;
    *outConsumer = consumer;
}
  • outProducer outConsumer为输出参数,输出对应的生产者接口,和消费者接口
  • allocator为输入参数,输入一个图像缓冲区内存分配接口,用于内存的申请
  • 首先通用allocator构造一个BufferQueueCore对象,然后在用该对象构造生产者对象(BufferQueueProducer)和消费者对象(BufferQueueConsumer)
class BufferQueueCore : public virtual RefBase {

    friend class BufferQueueProducer;
    friend class BufferQueueConsumer;

public:
    // Used as a placeholder slot number when the value isn‘t pointing to an
    // existing buffer.
    enum { INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT };

    // We reserve two slots in order to guarantee that the producer and
    // consumer can run asynchronously.
    enum { MAX_MAX_ACQUIRED_BUFFERS = BufferQueueDefs::NUM_BUFFER_SLOTS - 2 };

    // The default API number used to indicate that no producer is connected
    enum { NO_CONNECTED_API = 0 };

    typedef Vector<BufferItem> Fifo;

    // BufferQueueCore manages a pool of gralloc memory slots to be used by
    // producers and consumers. allocator is used to allocate all the needed
    // gralloc buffers.
    BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator = NULL);
    virtual ~BufferQueueCore();

private:
    // Dump our state in a string
    void dump(String8& result, const char* prefix) const;

    // getMinUndequeuedBufferCountLocked returns the minimum number of buffers
    // that must remain in a state other than DEQUEUED. The async parameter
    // tells whether we‘re in asynchronous mode.
    int getMinUndequeuedBufferCountLocked(bool async) const;

    // getMinMaxBufferCountLocked returns the minimum number of buffers allowed
    // given the current BufferQueue state. The async parameter tells whether
    // we‘re in asynchonous mode.
    int getMinMaxBufferCountLocked(bool async) const;

    // getMaxBufferCountLocked returns the maximum number of buffers that can be
    // allocated at once. This value depends on the following member variables:
    //
    //     mDequeueBufferCannotBlock
    //     mMaxAcquiredBufferCount
    //     mDefaultMaxBufferCount
    //     mOverrideMaxBufferCount
    //     async parameter
    //
    // Any time one of these member variables is changed while a producer is
    // connected, mDequeueCondition must be broadcast.
    int getMaxBufferCountLocked(bool async) const;

    // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
    // that will be used if the producer does not override the buffer slot
    // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. The
    // initial default is 2.
    status_t setDefaultMaxBufferCountLocked(int count);

    // freeBufferLocked frees the GraphicBuffer and sync resources for the
    // given slot.
    void freeBufferLocked(int slot);

    // freeAllBuffersLocked frees the GraphicBuffer and sync resources for
    // all slots.
    void freeAllBuffersLocked();

    // stillTracking returns true iff the buffer item is still being tracked
    // in one of the slots.
    bool stillTracking(const BufferItem* item) const;

    // waitWhileAllocatingLocked blocks until mIsAllocating is false.
    void waitWhileAllocatingLocked() const;

    // validateConsistencyLocked ensures that the free lists are in sync with
    // the information stored in mSlots
    void validateConsistencyLocked() const;

    // mAllocator is the connection to SurfaceFlinger that is used to allocate
    // new GraphicBuffer objects.
    sp<IGraphicBufferAlloc> mAllocator;

    // mMutex is the mutex used to prevent concurrent access to the member
    // variables of BufferQueueCore objects. It must be locked whenever any
    // member variable is accessed.
    mutable Mutex mMutex;

    // mIsAbandoned indicates that the BufferQueue will no longer be used to
    // consume image buffers pushed to it using the IGraphicBufferProducer
    // interface. It is initialized to false, and set to true in the
    // consumerDisconnect method. A BufferQueue that is abandoned will return
    // the NO_INIT error from all IGraphicBufferProducer methods capable of
    // returning an error.
    bool mIsAbandoned;

    // mConsumerControlledByApp indicates whether the connected consumer is
    // controlled by the application.
    bool mConsumerControlledByApp;

    // mConsumerName is a string used to identify the BufferQueue in log
    // messages. It is set by the IGraphicBufferConsumer::setConsumerName
    // method.
    String8 mConsumerName;

    // mConsumerListener is used to notify the connected consumer of
    // asynchronous events that it may wish to react to. It is initially
    // set to NULL and is written by consumerConnect and consumerDisconnect.
    sp<IConsumerListener> mConsumerListener;

    // mConsumerUsageBits contains flags that the consumer wants for
    // GraphicBuffers.
    uint32_t mConsumerUsageBits;

    // mConnectedApi indicates the producer API that is currently connected
    // to this BufferQueue. It defaults to NO_CONNECTED_API, and gets updated
    // by the connect and disconnect methods.
    int mConnectedApi;

    // mConnectedProducerToken is used to set a binder death notification on
    // the producer.
    sp<IProducerListener> mConnectedProducerListener;

    // mSlots is an array of buffer slots that must be mirrored on the producer
    // side. This allows buffer ownership to be transferred between the producer
    // and consumer without sending a GraphicBuffer over Binder. The entire
    // array is initialized to NULL at construction time, and buffers are
    // allocated for a slot when requestBuffer is called with that slot‘s index.
    BufferQueueDefs::SlotsType mSlots;

    // mQueue is a FIFO of queued buffers used in synchronous mode.
    Fifo mQueue;

    // mFreeSlots contains all of the slots which are FREE and do not currently
    // have a buffer attached
    std::set<int> mFreeSlots;

    // mFreeBuffers contains all of the slots which are FREE and currently have
    // a buffer attached
    std::list<int> mFreeBuffers;

    // mOverrideMaxBufferCount is the limit on the number of buffers that will
    // be allocated at one time. This value is set by the producer by calling
    // setBufferCount. The default is 0, which means that the producer doesn‘t
    // care about the number of buffers in the pool. In that case,
    // mDefaultMaxBufferCount is used as the limit.
    int mOverrideMaxBufferCount;

    // mDequeueCondition is a condition variable used for dequeueBuffer in
    // synchronous mode.
    mutable Condition mDequeueCondition;

    // mUseAsyncBuffer indicates whether an extra buffer is used in async mode
    // to prevent dequeueBuffer from blocking.
    bool mUseAsyncBuffer;

    // mDequeueBufferCannotBlock indicates whether dequeueBuffer is allowed to
    // block. This flag is set during connect when both the producer and
    // consumer are controlled by the application.
    bool mDequeueBufferCannotBlock;

    // mDefaultBufferFormat can be set so it will override the buffer format
    // when it isn‘t specified in dequeueBuffer.
    PixelFormat mDefaultBufferFormat;

    // mDefaultWidth holds the default width of allocated buffers. It is used
    // in dequeueBuffer if a width and height of 0 are specified.
    uint32_t mDefaultWidth;

    // mDefaultHeight holds the default height of allocated buffers. It is used
    // in dequeueBuffer if a width and height of 0 are specified.
    uint32_t mDefaultHeight;

    // mDefaultBufferDataSpace holds the default dataSpace of queued buffers.
    // It is used in queueBuffer if a dataspace of 0 (HAL_DATASPACE_UNKNOWN)
    // is specified.
    android_dataspace mDefaultBufferDataSpace;

    // mDefaultMaxBufferCount is the default limit on the number of buffers that
    // will be allocated at one time. This default limit is set by the consumer.
    // The limit (as opposed to the default limit) may be overriden by the
    // producer.
    int mDefaultMaxBufferCount;

    // mMaxAcquiredBufferCount is the number of buffers that the consumer may
    // acquire at one time. It defaults to 1, and can be changed by the consumer
    // via setMaxAcquiredBufferCount, but this may only be done while no
    // producer is connected to the BufferQueue. This value is used to derive
    // the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer.
    int mMaxAcquiredBufferCount;

    // mBufferHasBeenQueued is true once a buffer has been queued. It is reset
    // when something causes all buffers to be freed (e.g., changing the buffer
    // count).
    bool mBufferHasBeenQueued;

    // mFrameCounter is the free running counter, incremented on every
    // successful queueBuffer call and buffer allocation.
    uint64_t mFrameCounter;

    // mTransformHint is used to optimize for screen rotations.
    uint32_t mTransformHint;

    // mSidebandStream is a handle to the sideband buffer stream, if any
    sp<NativeHandle> mSidebandStream;

    // mIsAllocating indicates whether a producer is currently trying to allocate buffers (which
    // releases mMutex while doing the allocation proper). Producers should not modify any of the
    // FREE slots while this is true. mIsAllocatingCondition is signaled when this value changes to
    // false.
    bool mIsAllocating;

    // mIsAllocatingCondition is a condition variable used by producers to wait until mIsAllocating
    // becomes false.
    mutable Condition mIsAllocatingCondition;

    // mAllowAllocation determines whether dequeueBuffer is allowed to allocate
    // new buffers
    bool mAllowAllocation;

    // mBufferAge tracks the age of the contents of the most recently dequeued
    // buffer as the number of frames that have elapsed since it was last queued
    uint64_t mBufferAge;

    // mGenerationNumber stores the current generation number of the attached
    // producer. Any attempt to attach a buffer with a different generation
    // number will fail.
    uint32_t mGenerationNumber;

}; // class BufferQueueCore
  • 这个类是一个比较关键的类
  • 成员变量mSlots管理着队列中各个缓冲区的状态
struct BufferSlot {

    BufferSlot()
    : mEglDisplay(EGL_NO_DISPLAY),
      mBufferState(BufferSlot::FREE),
      mRequestBufferCalled(false),
      mFrameNumber(0),
      mEglFence(EGL_NO_SYNC_KHR),
      mAcquireCalled(false),
      mNeedsCleanupOnRelease(false),
      mAttachedByConsumer(false) {
    }

    // mGraphicBuffer points to the buffer allocated for this slot or is NULL
    // if no buffer has been allocated.
    sp<GraphicBuffer> mGraphicBuffer;

    // mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects.
    EGLDisplay mEglDisplay;

    // BufferState represents the different states in which a buffer slot
    // can be.  All slots are initially FREE.
    enum BufferState {
        FREE = 0,
        DEQUEUED = 1,
        QUEUED = 2,
        ACQUIRED = 3
    };

    static const char* bufferStateName(BufferState state);

    // mBufferState is the current state of this buffer slot.
    BufferState mBufferState;

    // mRequestBufferCalled is used for validating that the producer did
    // call requestBuffer() when told to do so. Technically this is not
    // needed but useful for debugging and catching producer bugs.
    bool mRequestBufferCalled;

    // mFrameNumber is the number of the queued frame for this slot.  This
    // is used to dequeue buffers in LRU order (useful because buffers
    // may be released before their release fence is signaled).
    uint64_t mFrameNumber;

    // mEglFence is the EGL sync object that must signal before the buffer
    // associated with this buffer slot may be dequeued. It is initialized
    // to EGL_NO_SYNC_KHR when the buffer is created and may be set to a
    // new sync object in releaseBuffer.  (This is deprecated in favor of
    // mFence, below.)
    EGLSyncKHR mEglFence;

    // mFence is a fence which will signal when work initiated by the
    // previous owner of the buffer is finished. When the buffer is FREE,
    // the fence indicates when the consumer has finished reading
    // from the buffer, or when the producer has finished writing if it
    // called cancelBuffer after queueing some writes. When the buffer is
    // QUEUED, it indicates when the producer has finished filling the
    // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been
    // passed to the consumer or producer along with ownership of the
    // buffer, and mFence is set to NO_FENCE.
    sp<Fence> mFence;

    // Indicates whether this buffer has been seen by a consumer yet
    bool mAcquireCalled;

    // Indicates whether this buffer needs to be cleaned up by the
    // consumer.  This is set when a buffer in ACQUIRED state is freed.
    // It causes releaseBuffer to return STALE_BUFFER_SLOT.
    bool mNeedsCleanupOnRelease;

    // Indicates whether the buffer was attached on the consumer side.
    // If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when dequeued
    // to prevent the producer from using a stale cached buffer.
    bool mAttachedByConsumer;
};
  • BufferState定义了缓冲区的五种状态
  • 该结构体描述了每个缓冲区的状态与属性

BufferQueue的生产步骤(生产者接口BufferQueueProducer):

  1. dequeueBuffer
  2. requestBuffer
  3. queueBuffer

BufferQueue消费步骤(消费者接口BufferQueueConsumer):

  1. acquireBuffer
  2. releaseBuffer

生产者在缓冲区填充完成后,调用queueBuffer方法将缓冲区加入队列,并且通知消费者。

status_t BufferQueueProducer::queueBuffer(int slot,
        const QueueBufferInput &input, QueueBufferOutput *output) {
    .......

    frameAvailableListener = mCore->mConsumerListener;

    ......

    frameAvailableListener->onFrameAvailable(item);

    ......
}
  • 获取BufferQueueCore内的成员变量mConsumerListener(消费者监听接口)
  • 回调接口方法onFrameAvailable

那么问题又来了,mConsumerListener又是在哪里给设置的呢?

status_t BufferQueueConsumer::connect(
        const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
    ATRACE_CALL();                      

    if (consumerListener == NULL) {
        BQ_LOGE("connect(C): consumerListener may not be NULL");
        return BAD_VALUE;
    }

    BQ_LOGV("connect(C): controlledByApp=%s",
            controlledByApp ? "true" : "false");     

    Mutex::Autolock lock(mCore->mMutex);

    if (mCore->mIsAbandoned) {
        BQ_LOGE("connect(C): BufferQueue has been abandoned");
        return NO_INIT;
    }  

    mCore->mConsumerListener = consumerListener;
    mCore->mConsumerControlledByApp = controlledByApp;

    return NO_ERROR;
}
  • BufferQueueConsumer::connect函数中会传入consumerListener接口指针,并设置给mCore->mConsumerListener
  • 最终决定在哪消费就那BufferQueueConsumer接口调用connect函数时传入的接口对象类型

原文地址:https://www.cnblogs.com/jonnezhang/p/8657683.html

时间: 2024-08-02 02:58:12

Android Surfaceflinger服务(一) ----- BufferQueue分析的相关文章

Android SurfaceFlinger服务(三) ----- 本地图层Layer创建

在上一篇文章中,主要分析了Surface的创建过程,对于Layer图层的创建并没有深入跟踪分析.这篇文章将分析Layer图层的创建,并分析handle gbp这两个变量的来源. 在SurfaceFlinger中会根据flags的值创建不同的layer.这里主要以创建普通layer为例进行分析. status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, const String8& name, uin

Android SurfaceFlinger服务(六) ----- VSync信号的分发

HWComposer模块产生VSync信号后要经过分发才能送达到关心VSync事件的模块中去.VSync信号分发大致流程为HWComposer->SurfaceFlinger->DispSync->DispSyncSource->各个具体模块.下面具体分析下这个流程. 在上一篇文章中分析到硬件或者软件VSync信号产生时,会回调SurfaceFlinger的onVSyncReceived函数,来看看这个函数: void SurfaceFlinger::onVSyncReceived

Android SurfaceFlinger服务(八) ----- 图像的输出

SurfaceFlinger合成后就进行图像的输出的工作.在图像输出时,存在硬件合成器与不存在的情况有些差别.软件合成时用到图像缓冲区生产者与消费者模型.首先来看看图像缓冲区的初始化. void SurfaceFlinger::init() { ALOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); ...... // initialize our n

Android系统Surface机制的SurfaceFlinger服务的线程模型分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8062945 在前面两篇文章中,我们分析了SurfaceFlinger服务的启动过程以及SurfaceFlinger服务初始化硬件帧缓冲区的过程.从这两个过程可以知道,SurfaceFlinger服务在启动的过程中,一共涉及到了三种类型的线程,它们分别是Binder线程.UI渲染线程和控制台事件监控线程.在本文中,我们就将详细分SurfaceFl

Android系统Surface机制的SurfaceFlinger服务对帧缓冲区(Frame Buffer)的管理分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8046659 在前文中,我们分析了SurfaceFlinger服务的启动过程.SurfaceFlinger服务在启动的过程中,会对系统的硬件帧缓冲区进行初始化.由于系统的硬件帧缓冲区一般只有一个,并且不是谁都可以随便访问的,因此,它就需要由一个服务来统一管理.在Android系统中,这个服务便是SurfaceFlinger.在本文中,我们就详细分

Android应用程序与SurfaceFlinger服务之间的共享UI元数据(SharedClient)的创建过程分析 .

引自:http://blog.csdn.net/luoshengyang/article/details/7867340 在前面一篇文章中,我们分析了Android应用程序与SurfaceFlinger服务的连接过程.Android应用程序成功连接上SurfaceFlinger服务之后,还需要一块匿名共享内存来和SurfaceFlinger服务共享它的UI元数据, 以便使得SurfaceFlinger服务可以正确地为它创建以及渲染Surface.在本文中,我们将详细地分析这块用来保存UI元数据的

Android应用程序与SurfaceFlinger服务的连接过程分析

转自:http://blog.csdn.net/luoshengyang/article/details/7857163 前文在描述Android应用程序和SurfaceFlinger服务的关系时提到,每一个有UI的Android应用程序都需要与SurfaceFlinger服务建立一个连接,以便可以通过这个连接来请求SurfaceFlinger服务为它创建和渲染Surface. 在本文中,我们将以Android系统的开机动画应用程序为例,详细描述Android应用程序是如何与SurfaceFli

Android应用程序与SurfaceFlinger服务的关系概述和学习计划 .

转自:http://blog.csdn.net/luoshengyang/article/details/7846923 SurfaceFlinger服务:负责绘制Android应用程序的UI, SurfaceFlinger服务运行在Android系统的System进程中,它负责管理Android系统的帧缓冲区(Frame Buffer).Android系统的帧缓冲区的相关知识, Android应用程序为了能够将自己的UI绘制在系统的帧缓冲区上,它们就必须要与SurfaceFlinger服务进行

Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8079456 在前面的一系列文章中,我们学习了Android应用程序与SurfaceFlinger服务的关系,以及SurfaceFlinger服务的启动过程.初始化硬件帧缓冲区的过程.线程模型.SurfaceFlinger服务所做的一切都是为了给Android应用程序提服务的,即为Android应用程序渲染它们的UI.在本文中,我们就详细分析Su