GUI系统--SurfaceFlinger

GUI即是图形用户界面,可以说任何操作系统中都占据非常重要的位置,因为它是用户对操作系统最直接的感官体验。一款优秀的图形界面系统至少满足以下几个条件。

流畅性 :评判GUI系统重要准则之一。 

友好性:GUI直接面向用户,操作友好直接影响用户体验。 

可拓展性 :意味着用户或者开发者可以在原来基础上延伸,添加新的界面和交互方式。 

因为Android的GUI系统是基于OpenGL/EGL来实现的,所以掌握一定OpenGL基础只是对于分析Android系统源码会有帮助。 

一、OpenGL ES 与EGL 

SurfaceFlinger是GUI的核心,从OpenGL角度来讲算是一个应用程序。 

按照上图分析

1. Linux内核提供了统一的framebuffer显示驱动。设备节点在/dev/graphics/fb* 或者/dev/fb* ,其中fb0表示一个Monitor。 

2. Android的HAL提供了Gralloc,包括fb和gralloc两个设备 。gralloc负责打开内核中的framebuffer、初始化配置、提供post、setSwapInterval等操作接口 。 说明上层元素只能通过Gralloc来间接访问帧缓冲区,从而保证系统对framebuffer有序使用和统一管理。 

3. OpenGL是一个通用的函数库。 不同平台需要与具体平台窗口系统建立关联,保证正常工作,从图中FrameBufferNativeWindow可以看出,它是扶着OpenGL ES与Android系统中介 。 

4. OpenGL只是一个协议,具体实现采用软件,也可以依托硬件。 通过读取efl.cfg这个配置文件,然后用户设定动态加载libagl 或者libhgl 。 

5. SurfaceFlinger中有一个显示设备

6.很多模块可以调用OpenGL ES提供的API。包括SurfaceFlinger,DisplayDevice等。 

7.与OpenGL ES相关的模块分以下几类:  配置类、依赖类、使用类 

二、Android的硬件接口---HAL

2.1硬件接口抽象 

这里抽象涉及了继承关系,让子结构地一个成员变量是父类结构即可。 觉里Grolloc 

  /**
   * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
   * and the fields of this data structure must begin with hw_module_t
   * followed by module specific information.
   */
  typedef struct gralloc_module_t {
      struct hw_module_t common;
  
      /*
       * (*registerBuffer)() must be called before a buffer_handle_t that has not
       * been created with (*alloc_device_t::alloc)() can be used.
       *
       * This is intended to be used with buffer_handle_t's that have been
       * received in this process through IPC.
       *
       * This function checks that the handle is indeed a valid one and prepares
       * it for use with (*lock)() and (*unlock)().
       *
       * It is not necessary to call (*registerBuffer)() on a handle created
       * with (*alloc_device_t::alloc)().
       *
       * returns an error if this buffer_handle_t is not valid.
       */
      int (*registerBuffer)(struct gralloc_module_t const* module,
              buffer_handle_t handle);

从函数的注释可以看出,每一个硬件必须有一个名称为HAL_MODULE_INFO_SYM的变量。 其次变量的数据结构要以hw_module_t开头,后面才是硬件模块持有的部分,这就体现了继承关系。 

2.2 接口稳定性 

对于硬件设备商来说,它所提供的HAL接口必须是稳定不变的----android系统已经预先定义好了这些接口,硬件设备商只需要按照要求来实现即可。 HAL各硬件接口的定义统一放置在工程源码中:

2.3 灵活使用方法 

比如说Androis手机设备A和B,分别采用了GPS1和GPS2两个厂家GPS。那么需要考虑那些问题呢?

对于GPS硬件厂家来说 ,只需要按照Android的要求来实现HAL接口。

对于Android手机开发商来说,只需要移植硬件厂家提供的HAL库即可。 

对于Android团队来说,Android系统必须提供完整、可靠并且稳定的HAL机制。 

三、Android终端显示设备的化身

3.1Gralloc与Framebuffer 

Gralloc读应模块是有FramebuffNativeWindow的构造函数中加载的。

举例Gralloc

 struct private_module_t HAL_MODULE_INFO_SYM = {
      .base = {
          .common = {
              .tag = HARDWARE_MODULE_TAG,
              .version_major = 1,
              .version_minor = 0,
              .id = GRALLOC_HARDWARE_MODULE_ID,
              .name = "Graphics Memory Allocator Module",
              .author = "The Android Open Source Project",
              .methods = &gralloc_module_methods
          },
          .registerBuffer = gralloc_register_buffer,
          .unregisterBuffer = gralloc_unregister_buffer,
          .lock = gralloc_lock,
          .unlock = gralloc_unlock,
      },
      .framebuffer = 0,
      .flags = 0,
      .numBuffers = 0,
      .bufferMask = 0,
      .lock = PTHREAD_MUTEX_INITIALIZER,
      .currentBuffer = 0,
  };

可以看到针对Gralloc的硬件模块ID为  GRALLOC_HARDWARE_MODULE_ID ,按照hw_get_module的做法,它会在如下路径查找与ID值匹配的库。 

#define HAL_LIBRARY PATH1  "/system/lib/hw" 

#define HAL_LIBRARY PATH2  "/vendor/lib/hw" 

lib库有以下几种形式  gralloc.[ro.hardware].so 、gralloc.[ro.product.board].so  、

gralloc.[ro.board.platform].so   、 gralloc.[ro.arch].so  或者上诉系统属性组成的文件名都不存在时,使用默认的 gralloc.default.so  

这个gralloc库是Android原生态实现的,

源位置在 /hardware/libhardware/modules/gralloc/

2. Gralloc提供接口 

Gralloc对应的HAL库被成功加载后,看下有哪些提供的重要接口。 

源码位置: /hardware/libhardware/include/hardware/hardware.h

typedef struct hw_module_t {

          ... 
      /** Modules methods */
      struct hw_module_methods_t* methods;
         ... 
  
  } hw_module_t;


typedef struct hw_module_methods_t {
      /** Open a specific device */
      int (*open)(const struct hw_module_t* module, const char* id,
              struct hw_device_t** device);
  
  } hw_module_methods_t;

也就说任何硬件设备HAL 库都必须实现hw_module_methods_t。Andriod原生态实现的gralloc会发现除了hw_module_t和gralloc_module_t外,各硬件厂商还定义了一个private_moudle_t ,可以看出整个继承关系如下: 

继承关系: private_module_t  -->  gralloc_module_t --->  hw_module_t 

open方法对应实现:

/hardware/libhardware/modules/gralloc/gralloc.cpp

 int gralloc_device_open(const hw_module_t* module, const char* name,
292          hw_device_t** device)
293  {
294      int status = -EINVAL;
295      if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
296          gralloc_context_t *dev;
297          dev = (gralloc_context_t*)malloc(sizeof(*dev));
298  
299          /* initialize our state here */
300          memset(dev, 0, sizeof(*dev));
301  
302          /* initialize the procs */
303          dev->device.common.tag = HARDWARE_DEVICE_TAG;
304          dev->device.common.version = 0;
305          dev->device.common.module = const_cast<hw_module_t*>(module);
306          dev->device.common.close = gralloc_close;
307  
308          dev->device.alloc   = gralloc_alloc;
309          dev->device.free    = gralloc_free;
310  
311          *device = &dev->device.common;
312          status = 0;
313      } else {
314          status = fb_device_open(module, name, device);
315      }
316      return status;
317  }

 这个函数根据设备名打开fb设备还是gralloc设备。 

可以看到frameBuffer设备打开过程 :

/hardware/libhardware/modules/gralloc/framebuffer.cpp 

 int fb_device_open(hw_module_t const* module, const char* name,
300          hw_device_t** device)
301  {
302      int status = -EINVAL;
303      if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
304          /* initialize our state here */
305          fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
306          memset(dev, 0, sizeof(*dev));
307  
308          /* initialize the procs */
309          dev->device.common.tag = HARDWARE_DEVICE_TAG;
310          dev->device.common.version = 0;
311          dev->device.common.module = const_cast<hw_module_t*>(module);
312          dev->device.common.close = fb_close;
313          dev->device.setSwapInterval = fb_setSwapInterval;
314          dev->device.post            = fb_post;
315          dev->device.setUpdateRect = 0;
316  
317          private_module_t* m = (private_module_t*)module;
318          status = mapFrameBuffer(m); // 内存映射
319          if (status >= 0) {
320               ....  
334              *device = &dev->device.common;
335          } else {
336              free(dev);
337          }
338      }
339      return status;

其中fb_context_t是framebuffer内部使用的一个类,它包含了众多信息,而参数函数device 的内容只是其内部的device.common。

struct fb_context_t {
      framebuffer_device_t  device;
};

类型fb_context_t里的唯一成员就是framebuffer_device_t,这是对framebuffer设备统一描述。一个标准的fb设备通常提供如下接口实现:

1.  int(*post)(struct framebuffer_device_t * dev,buffer_handlet buffer) 

将buffer数据post到显示屏上。要求buffer必须与屏幕尺寸一致,并且没有被locked,这样buffer内容将在下一次VSYNC中被显示出来。 

2. int(*setSwapInterval)(struct framebuffer_device_t* window, int interval)

设置两个缓冲区交换的时间间隔 

3. int(*setUpdateRect)(struct framebuffer_device_t* window , int left, int top ,int width, int height )

设置刷新区域,需要framebuffer驱动支持 update-on-demand 。也就是会所在这个区域外数据是可能被认为是无效的。 

framebuffer_device_t重要的成员变量

变量描述
uint32_t  flags 标记位,指示framebuffer的属性配置

uint32_t  width 

uint32_t height 

framebuffer的宽和高,象素单位 
int format framebuffer像素格式

float xdip 

float ydpi 

x和y轴密度
float fps 屏幕的每秒刷新频率,假如无法从设备获取这个值,Android系统会默认设置为60Hz 

int minSwapInterval 

int maxSwapInterval 

该framebuffer支持的最小和最大的u缓冲交换时间

fb设备和配置都是在mapFrameBuffer()中完成的,内部调用了方法mapFrameBufferLocked 。 

这个函数首先要尝试打开(调用open接口,权限为O_RDWR)如下路径的fb设备。 

    char const * const device_template[] = {
              "/dev/graphics/fb%u",
              "/dev/fb%u",
              0 };

成功打开fb后,通过方法: 

ioctl(fd, FBIOGET_FSCREENINFO, &finfo)

ioctl(fd, FBIOGET_VSCREENINFO, &info)

来的到显示屏的一系列参数,同时通过:ioctl(fd, FBIOPUT_VSCREENINFO, &info)来对底层fb进行配置 。

接下里在看下系统打开gralloc设备过程:

/hardware/libhardware/modules/gralloc/gralloc.cpp

int gralloc_device_open(const hw_module_t* module, const char* name,
292          hw_device_t** device)
293  {
294      int status = -EINVAL;
295      if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
296          gralloc_context_t *dev;
297          dev = (gralloc_context_t*)malloc(sizeof(*dev));
298  
299          /* initialize our state here */
300          memset(dev, 0, sizeof(*dev));
301  
302          /* initialize the procs */
303          dev->device.common.tag = HARDWARE_DEVICE_TAG;
304          dev->device.common.version = 0;
305          dev->device.common.module = const_cast<hw_module_t*>(module);
306          dev->device.common.close = gralloc_close;
307  
308          dev->device.alloc   = gralloc_alloc;
309          dev->device.free    = gralloc_free;
310  
311          *device = &dev->device.common;
312          status = 0;
313      } else {
314          status = fb_device_open(module, name, device);
315      }
316      return status;
317  }
318  

因为gralloc担负这图形缓冲区的分配与释放,所以它提供了两个最终要接口是alloc和free。  

Gralloc模块简图:

四、Andorid中的本地窗口

对于Android系统来说,如何将OpenGL ES本地化呢?

4.1FramebufferNativeWindow

EGL需要通过本地窗口来为OpenGL/OpenGL ES创建环境。 函数原型如下:

GELSurface  eglCreateWindowSurface (EGLDisplay dpy,  EGLConfig config,

NativeWindowTypeWindow , const EGLint *attrib_list) 

#elif defined(__ANDROID__) || defined(ANDROID)
99  
100  struct ANativeWindow;
101  struct egl_native_pixmap_t;
102  
103  typedef struct ANativeWindow*           EGLNativeWindowType;
104  typedef struct egl_native_pixmap_t*     EGLNativePixmapType;
105  typedef void*                           EGLNativeDisplayType;

由于OpenGL ES并不是针对某一个特定操作平台,这个EGLNativeWindowType在同系统对应不同数据类型,如上代码所示,Android中的就是ANativeWindow ,它就像是一份协议,规定了本地窗口的形态和功能。 

4.2应用程序端本地窗口---Surface 

正对应用程序端本地窗口是Surface和FramebufferNativeWindow一样必须集成AnativeWindow 

Surface是面向Android系统的所有UI应用程序,可以推测内部实现至少以下几点: 

1. 面向上层实现提供绘制图像的画板

2. 与SurfaceFlinger间如何分工。 

 Surface由SurfaceControl管理,而后又有SurfaceComposerClient创建。 代码如下:

47  status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
1348                                                       PixelFormat format,
1349                                                       sp<SurfaceControl>* outSurface, uint32_t flags,
1350                                                       SurfaceControl* parent,
1351                                                       LayerMetadata metadata) {
1352      sp<SurfaceControl> sur;
1353      status_t err = mStatus;
1354  
1355      if (mStatus == NO_ERROR) {
1356          sp<IBinder> handle;
1357          sp<IBinder> parentHandle;
1358          sp<IGraphicBufferProducer> gbp;
1359  
1360          if (parent != nullptr) {
1361              parentHandle = parent->getHandle();
1362          }
1363  
1364          err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),
1365                                       &handle, &gbp);
1366          ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
1367          if (err == NO_ERROR) {
1368              *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
1369          }
1370      }
1371      return err;
1372  }
1373  

上述代码中,mClient就是ISurfaceCompserClient的sp指针,程序通过它来生产一个Surface。

4.3 SurfaceFlingger

在createSurface的执行过程中,Client线程所在(即Binder线程)将进入wait状态,知道SurfaceFlinger成功完成业务后,它才被唤醒,然后发回最终结果给客户端,这一工作方式和postMessageSync所需要实现的同步他是一致的。 

4.4、VSync的产生和处理

1. 硬件源

2.软件源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值