现在的位置: 首页 > 综合 > 正文

android 绘图

2013年03月01日 ⁄ 综合 ⁄ 共 1621字 ⁄ 字号 评论关闭

    绘图系统的底层是对linux驱动提供的frambuffer内存进行读写,屏幕显示既是把显示内存搬运到屏幕缓冲区。在搬运的同时可能会做一些处理,比如点的格式的转换如rgb32转换为rgb16等,同时还有放大,缩小,旋转等操作。数据搬运一般可以用硬件加速来进行,此外屏幕缓冲区使用共享内存来实现进程间通迅。

 

    绘图系统上层是要提供Android.view.surface接口和Graphics绘图接口。在这个过程中首先进行的第一步抽象是Android Gralloc动态库的抽象,和其他对硬件的操作一样,这个抽象的目的是屏蔽硬件的差异向上层提供统一的接口,这里用到了hal驱动的设计。屏幕的绘图经过了以下几个阶段:先创建一个服务进程创建fb双缓冲内存,前端内存为显示的内存,后端内存用于缓冲,当后端内存准备好后切换到后端内存进行显示。应用程序进程如果要绘图则映射服务器的缓冲地址进行绘图。如何映射服务器的缓冲地址呢?首先通过一个结构体native_handle_t来传递数据,既服务器端定义一个native_handle_t的子类private_handle_t,然后在客户端定义一个native_handle_t类并获取服务器端private_handle_t的数据。再通过Graphic Mapper进行内存映射。

 

1. android的绘图过程为:

    首先创建buffer: 服务器端进程分配两段内存->客户端共享后端内存

 

    然后绘图:服务器端绘制bitmap到back buffer -> back buffer和front buffer互换

    另外还有以下两种可能的绘图模式:

        客户端输出图形数据到共享内存->(客户端或服务器端)把改变部分复制到前端内存。

        客户端直接使用前端内存来绘制图形。

 

2. 客户端如何计算输出要输出到fb内存中的数据:

普通界面绘图:

    首先创建Surface:Windows Manage Service生成activity的进程并在SurfaceFlinger服务器端创建Surface同时形成Layer的z-order时序。

    然后绘制到fb: 客户端view绘制或Graphics API调用 -> ViewRoot请求Surface返回一个Canvas -> 绘图到Canvas(LayerBuffer) -> view调用surface.unlockCanvasAndPost(canvas),并置标志  -> 服务器端调用surfaceFlinger::composeSurfaces()根据每个 layer 的 Z-order 把多个层组合为一个主Surface -> 从主Surface计算出输出到fb的数据。

 

surfaceFlinger的功能:

    threadLoop死循环:计算有无哪个Layer发生修改 (若有) -> 根据layer的z-order计算出每个layer的显示区域 -> 根据显示区域与需要刷新区域的交集绘制绘制到Surface -> 投递到屏幕。

 

opengl API的绘图:

     绘图API绘图到GGLBuffer ->  surfaceFlinger的opengl 服务响应,计算输出到frambuffer的数据。

 

另外opengl PAI 的 surfaceFlinger和Laye的surfaceFlinger是两个不同的对象。另外我觉得skia的一个重要功能是实现Surface的显示数据的存储与解析处理,另外skia会调用opengl和egl的api吗?早期的版本应该没有,而新版本越来越多的调用了opengles接口,因此没有opengles硬件加速时新版本的android的界面流畅度比老版本要差,部分原因可能是新版本调用了opengles的软件实现导致。而有opengles硬件加速时的情况真好相反。(个人见解,欢迎指正)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

抱歉!评论已关闭.