Android drm-hwcomposer

软件环境:ubuntu20.04 aosp
硬件环境:X86 PC
模拟环境:在host ubuntu20.04启动支持图形(by virtio-gpu)的Android虚拟机

1. 介绍

  • HWC 会执行以下计算:

       1. SurfaceFlinger 向HWC 提供一个完整的层列表,并询问“您希望如何处理这些层?”
       2. Hwc的响应方式是将每个层标记为设备或客户端合成。
       3. SurfaceFlinger会处理所有客户端,将输出缓冲区传送到 HWC,并让HWC 处理其余部分。
       由于硬件供应商可以定制决策代码,因此可以在每台设备上实现最佳性能。
    

1.1 接口

#Hal接口定义,最新版本2.4
/hardware/interfaces/graphics/composer/
#谷歌定义的hwc接口
hardware/libhardware/include/hardware/hwcomposer.h 
#API 参考:
https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1861
  • API
#SF传递GPU图层buffer,保存client_layer_
SetClientTarget 
#针对每一个layer设置合成方式,保存sf_type_,值都为2
SetLayerCompositionType
#把内容呈现到屏幕上去
PresentDisplay 
#为每一个Layer选择合成方式
ValidateDisplay

1.2 实现

Surfaceflinger <----> HWC2 client <----> HWC server <----> Vendor impl

HWC三类接口:
1. Layer:合成工作
2. Display:与屏幕硬件交互
3. Vsync:Vsync控制以及对SF的回调,通知VSYNC时间
  • Cuttlefish实现

     每个厂商hwc实现可能不同如nxp,rockchip,drm-hwc,ranchu,也有很多厂商实现是闭源的如nxp,而谷歌的drm-hwc,ranchu是开源的
    
#swiftshader和gfxstream模式
androidboot.hardware.hwcomposer=ranchu //指定hwc为ranchu
hwcomposer.ranchu.so  
#3D drmvirgl模式
androidboot.hardware.gralloc=minigbm 
hwcomposer.drm_minigbm.so  

2. drm_hwcomposer

2. 1 线程

composer进程有1个主线程,几个HwBinder线程,几个vndbinder线程,vsync线程
thread #1: name = 'composer@2.4-se'
thread #2: name = 'vndbinder:413_1'
thread #3: name = 'uevent-listener'
thread #4: name = 'HwBinder:413_1'
thread #5: name = 'vndbinder:413_2'
thread #6: name = 'HwBinder:413_2'
thread #7: name = 'composer@2.4-se'
thread #8: name = 'vsync'
thread #9: name = 'composer@2.4-se'
thread #10: name = 'vsync'
thread #11: name = 'HwBinder:413_3' 

2. 2 模块构成

#启动配置文件
android.hardware.graphics.composer@2.1-service.rc
#main与cmd分解,ComposerCommandEngine.h
android.hardware.graphics.composer@2.4-service 
  #binder消息接收
  libhidlbase.so
  #cmd分解,ComposerCommandEngine.h
  android.hardware.graphics.composer@2.4-service
  #ComposerResources.cpp
  android.hardware.graphics.composer@2.1-resources.so 
  #对gralloc的处理,BsMapper.h
  android.hardware.graphics.mapper@4.0.so
  #mapper实现,如CrosGralloc4Mapper.cc
  android.hardware.graphics.mapper@4.0-impl.minigbm.so
  #minigbm实现,drv.c/drv_helpers.c如drv_bo_import
  libminigbm_gralloc.so
  #对libdrm的依赖,DRM_IOCTL_PRIME_FD_TO_HANDLE
  libdrm.so

2. 3 初始化

2. 4 SF交互

  • Hotplug
1. 检测到显示功能更改,onHotplug(display, connection=CONNECTED)通知SF
2. 收到通知后,SF会丢弃其显示状态,并通过getActiveConfig 、 getDisplayConfigs 、 getDisplayAttribute 、 
   getColorModes 、 getHdrCapabilities和getDisplayCapabilities重新创建
3. SF重新创建新的显示状态后,它会将onDisplayChanged回调发送到正在侦听此类事件的应用程序
  • SurfaceFlinger更新显示. 以2个display,每个display多个layer为例,介绍画面更新时SurfaceFlinger与hwc交互.

        SF首先让hwc更新display 0每个layer,然后PRESENT_OR_VALIDATE_DISPLAY,最后PRESENT_DISPLAY;
    然后让hwc更新display 1每个layer,然后PRESENT_OR_VALIDATE_DISPLAY,最后PRESENT_DISPLAY.
    
#SF通知hwc更新display 0 layer 1-6的COMPOSITION_TYPE;设置SURFACE_DAMAGE;设置LAYER_BUFFER
setVsyncEnabled(display=0, enabled=ENABLE)
SET_LAYER_COMPOSITION_TYPE
SetLayerCompositionType(display=0 layer=6, type=2)
SET_LAYER_COMPOSITION_TYPE
SetLayerCompositionType(display=0 layer=5, type=2)
SET_LAYER_SURFACE_DAMAGE
setLayerSurfaceDamage(display=0, layer=4, damage=size=1)
SET_LAYER_BUFFER
setLayerBuffer(display=0, layer=4, buffer=0xeb882a00, acquireFence=15)
SET_LAYER_COMPOSITION_TYPE
setLayerCompositionType(display=0, layer=3, type=2)
SET_LAYER_COMPOSITION_TYPE
setLayerCompositionType(display=0, layer=2, type=2)
SET_LAYER_COMPOSITION_TYPE
setLayerCompositionType(display=0, layer=1, type=2)
...
#显示校验
PRESENT_OR_VALIDATE_DISPLAY
  #Hwchal.h:327
  validateDisplay_2_4(display=0, ...)
    GetChangedCompositionTypes
    GetChangedCompositionTypes
    getDisplayRequests
    getDisplayRequests

#hwc接收修改
ACCEPT_DISPLAY_CHANGES
  acceptDisplayChanges(display=0)

#GPU合成后设置到Hwc
SET_CLIENT_TARGET
  setClientTarget(display=0, target=0xe6781820, acquireFence=-1, dataspace=0, damage=size=0)

#显示到屏幕
PRESENT_DISPLAY
  presentDisplay(display=0, ... )   
  getReleaseFences(display=0, ...)
  getReleaseFences
#display 1重复上述操作.更新layer 7-11的COMPOSITION_TYPE,SURFACE_DAMAGE,LAYER_BUFFER
#循环给display1所有layer进行处理
SET_LAYER_COMPOSITION_TYPE
SetLayerCompositionType(display=1, layer=13, type=2)
SET_LAYER_COMPOSITION_TYPE
SetLayerCompositionType(display=1, layer=12, type=2)
SET_LAYER_SURFACE_DAMAGE
setLayerSurfaceDamage(display=1, layer=11, damage=size=1)
SET_LAYER_BUFFER
setLayerBuffer(display=1, layer=11, buffer=0xea943240, acquireFence=17)
SET_LAYER_COMPOSITION_TYPE
setLayerCompositionType(display=1, layer=11, type=2)
SET_LAYER_COMPOSITION_TYPE
setLayerCompositionType(display=1, layer=10, type=2)
SET_LAYER_COMPOSITION_TYPE
setLayerCompositionType(display=1, layer=8, type=2)
SET_LAYER_COMPOSITION_TYPE
setLayerCompositionType(display=1, layer=7, type=2)
... #开始校验和显示

2. 5 drm交互

    drm_hwcomposer与libdrm交互接口和流程.
  • 不更新画面. drm_hwc周期性drmModeAtomicCommit提交
#drm_hwcomposer向drm提交显示
PRESENT_DISPLAY
PresentDisplay 
  CreateComposition
    DrmAtomicStateManager::ExecuteAtomicCommit
      CommitFrame
        drmModeAtomicCommit
  • 更新画面. drm_hwc不断import buffer,创建framebuffer object,AtomicCommit提交显示
#SurfaceFlinger设置一个layerBuffer,最终依赖minigbm import
SET_LAYER_BUFFER #composer@2.4-service
  executeSetLayerBuffer
    getLayerBuffer #composer@2.1-resources.so
      getHandle
        importBuffer #该实现从composer@2.1-resources.so调用graphics.mapper@4.0.so,再调用graphics.mapper@4.0-impl.minigbm.so
          CrosGralloc4Mapper::importBuffer
            cros_gralloc_driver::retain
              drv_bo_import
                drv_prime_bo_import
                  DRM_IOCTL_PRIME_FD_TO_HANDLE
#SurfaceFlinger调用PRESENT_OR_VALIDATE_DISPLAY
PRESENT_OR_VALIDATE_DISPLAY  #composer@2.4-service
  executePresentOrValidateDisplay
    executeValidateDisplayInternal
      validateDisplay #hwcomposer.drm.so
        CreateComposition
          PopulateLayerData
            ImportFb
              GetOrCreateFbId
                #创建FBO需要gem handle
                drmPrimeFDToHandle
                #Import dmabufs and register FB
                DrmFbIdHandle::CreateInstance
                  #创建Framebuffer object
                  drmModeAddFB2(width=400, height=600,..)
#drm_hwcomposer向drm提交显示
PRESENT_DISPLAY
PresentDisplay 
  CreateComposition
    DrmAtomicStateManager::ExecuteAtomicCommit
      CommitFrame
        drmModeAtomicCommit
#SurfaceFlinger销毁Layer
_hidl_destroyLayer #销毁一个layer,最终依赖minigbm
  #composer@2.1-resources.so
  ComposerResources::removeLayer
  ComposerLayerResource::~ComposerLayerResource
  ComposerHandleCache::~ComposerHandleCache
    BsMapper::freeBuffer #mapper@4.0.so
      #libminigbm_gralloc.so
      cros_gralloc_buffer::~cros_gralloc_buffer
        drv_bo_destroy
          virgl_bo_destroy
            drv_gem_bo_destroy
              DRM_IOCTL_GEM_CLOSE

2.6 bufferinfo

2.7 用例与demo

  • hwc-drm-tests
    在这里插入图片描述
  • demo
external/drm_hwcomposer/tests

3 drm-hwc多屏

4 DPU合成

若Drm Plane个数不足,如没有OVERLAY_PALNE,就只能GPU合成
若Gralloc申请的仅是GPU内存,无法Convert为Drm格式,也只能GPU合成

4 .1.Usage

  • GraphicBuffer格式

    决定Layer能否被DPU使用.GRALLOC_USAGE_HW_FB格式的layer才能被drm-hwc ConvertBo,否则Layer只能被GPU合成
    
STANDARD_USAGE = GRALLOC_USAGE_SW_READ_MASK | /* 0x0FU */
GRALLOC_USAGE_SW_WRITE_MASK | /* 0xF0U */
GRALLOC_USAGE_HW_TEXTURE | /* 1U << 8 */
GRALLOC_USAGE_HW_RENDER | /* 1U << 9 */
GRALLOC_USAGE_HW_2D | /* 1U << 10 */
GRALLOC_USAGE_HW_COMPOSER | /* 1U << 11 */
GRALLOC_USAGE_HW_FB | /* 1U << 12 */
GRALLOC_USAGE_EXTERNAL_DISP | /* 1U << 13 */
GRALLOC_USAGE_PROTECTED | /* 1U << 14 */
GRALLOC_USAGE_CURSOR | /* 1U << 15 */
GRALLOC_USAGE_HW_VIDEO_ENCODER | /* 1U << 16 */
GRALLOC_USAGE_HW_CAMERA_WRITE | /* 1U << 17 */
GRALLOC_USAGE_HW_CAMERA_READ | /* 1U << 18 */
GRALLOC_USAGE_RENDERSCRIPT | /* 1U << 20 */
GRALLOC_USAGE_DECODER | /* 1U << 22 */
/* Producer and consumer usage are combined, but on Gralloc version 1
 - there is no way to differentiate these as they
 - are mapped to the same value (1U << 23). */
GRALLOC_USAGE_SENSOR_DIRECT_DATA | /* 1U << 23 */
GRALLOC_USAGE_GPU_DATA_BUFFER | /* 1U << 24 */
GRALLOC_USAGE_FRONTBUFFER; /* 1L << 32 */ 
  • Buffer申请
#申请buffer 带 GRALLOC_USAGE_HW_FB usage
  gralloc_alloc_framebuffer #从/dev/fb或/dev/graphic/fb申请
  gralloc_alloc_buffer #从dma_heap或ion(cma) 

4.2.Plane

  • 类型
#1. Drm plane共有3中格式
DRM_PLANE_TYPE_OVERLAY:
DRM_PLANE_TYPE_PRIMARY:
DRM_PLANE_TYPE_CURSOR: 
#2. Drm_hwc只使用了PRIMARY和OVERLAY,CURSOR忽略 
  • 数量. 决定了能否hwc合成,至少需要一个PRIMARY
#1. 至少1个PLANE PRIMARY
#2. Cuttlefish drmvirgl共4个PLANE,2PRIMARY和2CURSOR
  • Format
#1. HAL format与Drm format对应关系,参考ConvertHalFormatToDrm
HAL_PIXEL_FORMAT_RGB_888:3
 -> DRM_FORMAT_BGR888;
HAL_PIXEL_FORMAT_BGRA_8888:5
 -> DRM_FORMAT_ARGB8888;
HAL_PIXEL_FORMAT_RGBX_8888:2
 -> DRM_FORMAT_XBGR8888;
HAL_PIXEL_FORMAT_RGBA_8888:1 //常见于Android Layer
 -> DRM_FORMAT_ABGR8888;
HAL_PIXEL_FORMAT_RGB_565:4
 -> DRM_FORMAT_BGR565;
HAL_PIXEL_FORMAT_YV12:842094169
 -> DRM_FORMAT_YVU420;
HAL_PIXEL_FORMAT_RGBA_1010102:43
 -> DRM_FORMAT_ABGR2101010; 

#2. ConvertBo会将Layer转换为Drm支持格式
#3. 在createComposition也会检查layer格式是否是Drm支持的 

4.3.Property

vendor.hwc.drm.use_overlay_planes
vendor.hwc.drm.scale_with_gpu

4.4.数据结构

  • HwcLayer
(android::DrmHwcTwo::HwcLayer) layer = {
  acquire_fence_ = (fd_ = 36)
  release_fence_ = (fd_ = -1)
  sf_type_ = Device
  validated_type_ = Client
  blending_ = Premultiplied
  buffer_ = 0xb400e913f81c7630
  display_frame_ = (left = 0, top = 0, right = 1920, bottom = 1080)
  alpha_ = 1
  source_crop_ = (left = 0, top = 0, right = 1920, bottom = 1080)
  cursor_x_ = 0
  cursor_y_ = 0
  layer_color_ = (r = '\0', g = '\0', b = '\0', a = '\0')
  transform_ = None
  z_order_ = 0
  dataspace_ = HAL_DATASPACE_UNKNOWN
}
  • private_handle_t

    其中buffer_是一个gralloc申请的buffer_handle_t,转换为private_handle_t后可看到buffer结构
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值