SurfaceFlinger之绘图缓冲区

486 阅读3分钟

SurfaceFlinger是GUI系统的核心服务,它主要负责图层的合成任务,同时它为每个应用程序维护一个Client,Client又是由多个Layer组成,Layer对应应用端的Window,这样SurfaceFlinger就能通过Layer来明白各个应用的绘图需求,从而将其合成显示。本篇将从SurfaceFlinger的角度来分析系统是如何通过Layer来管理绘图缓冲区。

缓冲队列

绘图缓冲区是通过BufferQueeu进行管理的,它是一个缓冲区队列,从生产消费的角度来说它同时为消费者和生产者,这里看看它的结构便可以知道

class BufferQueue : public BnGraphicBufferProducer,
                    public BnGraphicBufferConsumer,
                    private IBinder::DeathRecipient 

BufferQueue同时是一个Binder,因此它也就具有跨进程的能力。本篇将会根据具体的使用来分析BufferQueue是如何同时作为消费者和生产者的。

BufferQueue的构成

BufferQueue内部是一个BufferSlot数组,大小为32,BufferSlot即Buffer槽用来描述一块缓冲区,需要注意的是BufferQueue在初始情况下并未分配缓冲区,只有当用户进行申请时才真正的分配缓冲区。一个缓冲区一旦被分配它便具有了状态,分别是:

FREE 表明该Buffer空闲,可以dequeue被生产者使用,此时它的拥有者为BufferQueue。

DEQUEUED 表示该Buffer已经被生产者dequeue,但还未入队或者取消,此时生产者是它的拥有者

QUEUED 表明这个Buffer已经被生产者填充好内容,等待消费者进行消费,此时它的拥有者为BufferQueue

ACQUIRED 表示该Buffer块被消费者获取到,此时消费者作为其拥有者。

enum BufferState {
    // FREE indicates that the buffer is available to be dequeued
    // by the producer.  The buffer may be in use by the consumer for
    // a finite time, so the buffer must not be modified until the
    // associated fence is signaled.
    //
    // The slot is "owned" by BufferQueue.  It transitions to DEQUEUED
    // when dequeueBuffer is called.
    FREE = 0,

    // DEQUEUED indicates that the buffer has been dequeued by the
    // producer, but has not yet been queued or canceled.  The
    // producer may modify the buffer's contents as soon as the
    // associated ready fence is signaled.
    //
    // The slot is "owned" by the producer.  It can transition to
    // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).
    DEQUEUED = 1,

    // QUEUED indicates that the buffer has been filled by the
    // producer and queued for use by the consumer.  The buffer
    // contents may continue to be modified for a finite time, so
    // the contents must not be accessed until the associated fence
    // is signaled.
    //
    // The slot is "owned" by BufferQueue.  It can transition to
    // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is
    // queued in asynchronous mode).
    QUEUED = 2,

    // ACQUIRED indicates that the buffer has been acquired by the
    // consumer.  As with QUEUED, the contents must not be accessed
    // by the consumer until the fence is signaled.
    //
    // The slot is "owned" by the consumer.  It transitions to FREE
    // when releaseBuffer is called.
    ACQUIRED = 3
};

BufferQueue作为消费者

View在第一次进行绘制时会从WMS请求一个Surface绘图表面,这个绘图表面实际上会通过IGrpahicBufferProducer来请求绘图缓冲区,它实际上是一个IBinder Client,它的服务端即BufferQueue是在为WMS对应的Window对象创建SF端的Layer对象时创建

void Layer::onFirstRef() {
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    mBufferQueue = new SurfaceTextureLayer(mFlinger);
    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mBufferQueue, mTextureName);
    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
    mSurfaceFlingerConsumer->setFrameAvailableListener(this);
    mSurfaceFlingerConsumer->setName(mName);

#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
#warning "disabling triple buffering"
    mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
#else
    mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
#endif

    const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
    updateTransformHint(hw);
}

这里的SurfaceTextureLayer是BufferQueue的子类,它在Layer对象被创建后第一次引用时创建。

status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
    // initialize the surfaces
    switch (format) {
    case PIXEL_FORMAT_TRANSPARENT:
    case PIXEL_FORMAT_TRANSLUCENT:
        format = PIXEL_FORMAT_RGBA_8888;
        break;
    case PIXEL_FORMAT_OPAQUE:
#ifdef NO_RGBX_8888
        format = PIXEL_FORMAT_RGB_565;
#else
        format = PIXEL_FORMAT_RGBX_8888;
#endif
        break;
    }

#ifdef NO_RGBX_8888
    if (format == PIXEL_FORMAT_RGBX_8888)
        format = PIXEL_FORMAT_RGBA_8888;
#endif

    *outLayer = new Layer(this, client, name, w, h, flags);
    status_t err = (*outLayer)->setBuffers(w, h, format, flags);
    if (err == NO_ERROR) {
        *handle = (*outLayer)->getHandle();
        *gbp = (*outLayer)->getBufferQueue();
    }

    return err;
}

可以看到Layer被创建后,通过getBufferQueue得到该缓冲队列,这个队列是以一个Binder代理返回给应用端的,应用端最终是通过该BufferQueue来请求缓冲区,从而通过该缓冲区构造SkCanvas最终提交给上层使用的。从这个角度来讲BufferQueue是作为生产者的。