软件环境: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结构