android p图形显示系统,Android图形显示系统——下层显示3:窗口系统

Android之窗口系统

要点

1.Android窗口系统通过C-S架构和一套Buffer循环机制实现,在保证安全稳定的前提下基本上做到了极致性能(无大块内存拷贝,IPC通信内容最少)。

2.SurfaceFlinger创建Layer,将其中的BufferQueueProducer作为IGraphicBufferProducer传给应用侧的Surface,因而构成窗口。

3.Surface是皮,BufferQueue是肉,通过这样的皮肉关系构建了Buffer循环机制。Buffer循环机制不仅用于窗口系统,也用于视频播放解码流,相机拍照数据流等(Camera2.0架构)。

注:代码基于Android 5.0

窗口系统接口

作为一个应用,绘图是自由的,基本上也是平台无关的。但如果要把绘图的结果显示出来,就必须依赖平台提供的窗口系统。好比我们写篇文章出来容易,要投到杂志上发表,就必须按杂志社的格式,并通过审校等一堆流程,不然每个人都随便发,肯定乱套了。

Android的窗口系统设计

0818b9ca8b590ca3270a3433284dd417.png

Android为应用层提供的窗口接口为ANativeWindow。这个接口可用来调整配置参数,获取图形内存并送还触发显示。应用层是Buffer的生产者。

对于非GPU绘图的应用,通过这个类去获取图形内存(dequeueBuffer),并在绘制完成之后送还(queueBuffer),让显示系统在合适的时机显示。

对于GPU绘图(严格来说,是使用EGL标准)的应用,在创建OpenGL上下文时将ANativeWindow的指针传入,GPU的驱动会在合适的时候完成获取内存和送还的操作。应用层只需要调用eglSwapBuffers换缓存即可。

Android的Windows接口

对应用层开放的windows接口定义在

system/core/include/system/windows.h

主要接口函数如下:

struct ANativeWindow

{

/*......*/

int (*setSwapInterval)(struct ANativeWindow* window, int interval);//设置Buffer失效期限,当应用生产Buffer快于消费者(一般是显示系统)的消费时,这个参数决定是否丢弃之前没来得及消费的Buffer。

int (*query)(const struct ANativeWindow* window, int what, int* value);//查询参数

int (*perform)(struct ANativeWindow* window,int operation, ... );//设置参数,其中也包括做连接

int (*dequeueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer, int* fenceFd);//从队列中取出一块Buffer用于生产(一般是图形渲染),若是第一次调用,会触发Buffer的申请

int (*queueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd);//将生产完成的Buffer送还

int (*cancelBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd);//释放Buffer队列中的Buffer,一般是disconnect时调用

};

用于perform和query接口的一些宏定义如下:

/*用于perform和query接口的宏*/

enum {

NATIVE_WINDOW_SET_USAGE = 0,

NATIVE_WINDOW_CONNECT = 1, /* deprecated */

NATIVE_WINDOW_DISCONNECT = 2, /* deprecated */

NATIVE_WINDOW_SET_CROP = 3, /* private */

NATIVE_WINDOW_SET_BUFFER_COUNT = 4,

NATIVE_WINDOW_SET_BUFFERS_GEOMETRY = 5, /* deprecated */

NATIVE_WINDOW_SET_BUFFERS_TRANSFORM = 6,

NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP = 7,

NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS = 8,

NATIVE_WINDOW_SET_BUFFERS_FORMAT = 9,

NATIVE_WINDOW_SET_SCALING_MODE = 10, /* private */

NATIVE_WINDOW_LOCK = 11, /* private */

NATIVE_WINDOW_UNLOCK_AND_POST = 12, /* private */

NATIVE_WINDOW_API_CONNECT = 13, /* private */

NATIVE_WINDOW_API_DISCONNECT = 14, /* private */

NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */

NATIVE_WINDOW_SET_POST_TRANSFORM_CROP = 16, /* private */

NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM = 17,/* private */

NATIVE_WINDOW_SET_SIDEBAND_STREAM = 18,

NATIVE_WINDOW_SET_BUFFERS_DATASPACE = 19

};

窗口的创建与使用

Surface

自Android 4.2之后,FramebufferNativeWindow被废弃,所有窗口均继承Surface。Surface本身是一种ANativeWindow。

class Surface

: public ANativeObjectBase/*Surface继承于ANativeWindow*/

{

public:

Surface(const sp& bufferProducer, bool controlledByApp = false);

/*......*/

private:

// ANativeWindow hooks

/*这几个hook函数对应于 window.h 中的接口函数*/

static int hook_cancelBuffer(ANativeWindow* window,

ANativeWindowBuffer* buffer, int fenceFd);

static int hook_dequeueBuffer(ANativeWindow* window,

ANativeWindowBuffer** buffer, int* fenceFd);

static int hook_perform(ANativeWindow* window, int operation, ...);

static int hook_query(const ANativeWindow* window, int what, int* value);

static int hook_queueBuffer(ANativeWindow* window,

ANativeWindowBuffer* buffer, int fenceFd);

static int hook_setSwapInterval(ANativeWindow* window, int interval);

static int hook_cancelBuffer_DEPRECATED(ANativeWindow* window,

ANativeWindowBuffer* buffer);

static int hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,

ANativeWindowBuffer** buffer);

static int hook_lockBuffer_DEPRECATED(ANativeWindow* window,

ANativeWindowBuffer* buffer);

static int hook_queueBuffer_DEPRECATED(ANativeWindow* window,

ANativeWindowBuffer* buffer);

/*.......*/

public:

/*这两个函数主要是CPU绘图时调用,除了获取,映射Buffer之外,额外将非脏区域从上一块Buffer拷贝到本块Buffer,以便渲染时只绘制脏区域*/

virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);

virtual int unlockAndPost();

/*.......*/

private:

struct BufferSlot {

sp buffer;

Region dirtyRegion;

};

/*Buffer生产者,Surface*/

sp mGraphicBufferProducer;

BufferSlot mSlots[NUM_BUFFER_SLOTS];

/*通过native_window_set_buffers_dimensions改变,用于在合适的时机改变GraphicBuffer的长宽*/

uint32_t mReqWidth;

uint32_t mReqHeight;

/*需求的GraphicBuffer格式,用于动态调整*/

PixelFormat mReqFormat;

/*需求Usage说明,影响GraphicBuffer的flags*/

uint32_t mReqUsage;

/*时间戳,用于判断Buffer是否过期*/

int64_t mTimestamp;

/*Buffer的使用范围*/

Rect mCrop;

/*Buffer后续变换需求,只包括水平、垂直翻转,90度旋转*/

uint32_t mTransformHint;

/*BufferProducer是否由使用Surface的App控制,这个主要是用来决定dequeueBuffer时是否堵塞*/

bool mProducerControlledByApp;

/*......*/

};

}; // namespace android

窗口的创建

用于图形显示的窗口,是由SurfaceFlinger进程负责创建的:

0818b9ca8b590ca3270a3433284dd417.png

为应用层创建Surface(窗口)时,SurfaceFlinger同步创建一个Layer,并将Layer的生产者关联到Surface上。这样,应用侧便可以通过Surface申请Buffer,作为生产者渲染图像,送显由Layer中的消费者负责。

Buffer循环机制

对于按一定帧率刷新的窗口系统,每一次渲染只有很有限的时间,频繁地申请/释放图形内存是不可接受的。Android的做法是维护一个Buffer队列,按生产者——消费者模式循环利用。这个Buffer就是上一章所述的GraphicBuffer。

Buffer的状态

Buffer队列池中持有固定数量的Buffer(由setBufferCount函数决定,一般是3块),每个Buffer有四种状态,决定其是否可以被生产者/消费者访问。

0818b9ca8b590ca3270a3433284dd417.png

Buffer的生产

序号化

由于Layer位于SurfaceFlinger进程中,GraphicBuffer是在SurfaceFlinger进程中创建的。应用层作为生产者,使用时需要将其映射到自己的进程空间。在每次申请Buffer时都做一次映射很不明智。

很容易想到的一个方法是在应用层建一个GraphicBuffer队列,和SurfaceFlinger中的Buffer队列对应地映射起来,每次申请和返还时,以序号代替真实的GraphicBuffer传替。Android也正是这么做的。

dequeueBuffer

Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd)

这接口用于申请内存进行生产(渲染)。

于Surface侧,它获取Buffer的序列号,然后检查是否已经同步过,若没有同步过调用requestBuffer同步(映射共享内存)。

于BufferQueue侧,它检查是否有 FREE 标志的Buffer,如果没有,根据 mProducerControlledByApp 标志决定返回错误码或者等待。

fenceFd是BufferQueue返回给Surface的,生产者有义务去等fence。

queueBuffer

int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd)

于Surface侧,它将Buffer送还给BufferQueue,但这不一定表示生产者用完了,消费者获取到Buffer之后仍有义务等fence。

于BufferQueue侧,接收到Buffer,将其放到一个可用队列中,修改状态,并且触发监听器的onFrameAvailable函数。

Buffer的消费

acquireBuffer

消费者获取buffer,由于在queueBuffer时,会将Buffer放到一个队列中,这时便从那个队列去取。

releaseBuffer

消费者释放buffer。

你可能感兴趣的:(android,p图形显示系统)