SurfaceFlinger and HWComposer

本文介绍了HWComposer在SurfaceFlinger中的作用及其实现流程,包括如何决定将哪些层交给GPU处理,哪些交给显示硬件处理,以及关键的hwcset接口如何工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Introduction

In the beginning, people believes that GPU composition is fast and power effiecent compared with CPU composition. Then, people find that in most usage scenarios, GPU can be kept sleep with the introduction of more display planes. This is where HWComposer comes into play. It is linked into SurfaceFlinger as a library, and works as a judge to decide when to offload work from GPU to display hardware.

General flow

handleMessageRefresh
     |—> preComposition
     |—> rebuildLayerStacks
     |—> setUpHWComposer
          |—> HWComposer::createWorkList <== hwc structures are allocated
          |—> Layer::setGeometry()
          |—  set per frame data
          |—  HWComposer::prepare
               |—> hwc prepare
     |—> doComposition
          |---- skip composition on external display if condition meets
          |—> doDisplayComposition
          |    |—> doComposeSurfaces
          |     |—> DisplayDevice::swapBuffers
          |          |—> eglSwapBuffers
          |          |—> FramebufferSurface::advanceFrame
          |—> DisplayDevice::flip(…)     <== just update statistics count
          |--> Call DisplayDevice::compositionComplete(), notify each display
               |--> DisplaySurface::compositionComplete()
                    |--> FramebufferSurface::compositionComplete()
                         |--> HWComposer::fbCompositionComplete()
                              |--> NoOP if HWC >= 1.1
                              |--> used only in framebuffer device case.
          |—> postFrameBuffer
               |—> HWComposer::commit
                    |—> hwc set
                    |—> update retireFenceFd of hwc_display_contents_1
               |—> DisplayDevice::onSwapBuffersCompleted
                    |—> FramebufferSurface::onFrameComitted
               |—> Layer::onLayerDisplayed
               |—   update some statistics
     |—> postComposition 

Recap of the draw-a-frame flow

  • SurfaceFlinger::setUpHWComposer
    • beginFrame
    • hwc prepare
    • prepareFrame
  • DisplayDevice::swapBuffers
    • eglSwapBuffer
    • advanceFrame
  • DisplayDevice::onSwapBuffers
    • hwc set
    • onFrameComitted

hwc prepare

One of the major interfaces of hwc, decision is made in this phase if a layer should belended by GPU or display. Generally speaking, a layer that can be blended by display should be marked as HWC_OVERLAY, other layers marked as HWC_FRAMEBUFFER, though other complicated cases exist.

hwc set

Another major interface of hwc, hwc set callback is used to replace eglSwapBuffers for frames with mixed GLES and HWC layers. Before hwc set happens, GLES layers already composed to framebuffer target, while not the other layers marked as HWC_OVERLAY. These HWC_OVERLAY layers and framebuffer tareget will be sent to hardware for blend. On my platform, in the parameters of hwc set, the Displays is 3,which includes 0 (primary display),1(external display - like HDMI),2(virtual display), mLists contains all the layers of all displays. The layers in a display is called layer stack.

Events from HWC to SF

Setup SF callback to HWC in HWComposer constructor

mHwc->registerProcs(mHwc, &mCBContext->procs);

hotplug:

HWC -> HWComposer::hook_hotplug -> HWComposer::hotplug -> SurfaceFlinger::onHotplugReceived

hardware vsync:

HWC -> HWComposer::hook_vsync -> HWComposer::vsync -> SurfaceFlinger::onVSyncReceived

Do not confuse these two callbacks with similar functions in EventThread, like EventThread::onHotplugReceived and EventThread::onVsyncEvent, these functions are used to notify client.

How layer maps to plane

The process that software layers map to display plane is driver and framework dependent, and different between implementations. PVR and GEN are lot diffrent. On PVR,DRM pageflip ioctl is not used, dc_plane_ctx structure is allocated instead,specific dc_device_post function is called to parse parameter to kernel. No more detailed explanation here, but for GEN which uses drm and i915 open source implementation, more articles will be written later.

### vsync信号变化与帧绘制的关系 #### 帧绘制的基本原理 Vsync(垂直同步)信号是一种定时脉冲信号,其核心目的是确保显示器的刷新率与图形渲染速度保持一致[^5]。这种同步可以有效避免图像撕裂现象的发生,提升用户体验。 在 Android 系统中,Vsync 信号不仅用于驱动屏幕刷新,还参与应用层和合成层的任务调度。具体来说: - **硬件层面**:由 HWComposer 提供真实的 VSync 信号[^3]。 - **虚拟化层面**:通过 DispSyncThread 将真实 VSync 信号转化为多个虚拟化的 VSync 信号,分别服务于 App 和 SurfaceFlinger[^1]。 - **任务触发**:当 VSync 信号到来时,Choreographer 在应用层负责协调动画更新、输入事件处理以及视图重绘;SurfaceFlinger 则在原生层完成最终的画面合成并提交给显示屏[^4]。 #### vsync信号状态转换及其意义 Vsync 信号是一个周期性的高低电平切换信号,在一个完整的周期内经历两次重要的状态转变——从低到高(上升沿)和从高到低(下降沿)。以下是这两种状态变换的具体含义及它们如何映射至帧绘制过程中的各个阶段: 1. **从0到1 (上升沿)** 上升沿通常标志着一个新的显示周期开始的时间点。对于帧绘制而言,这代表了当前帧计算启动的关键时刻: - 在此瞬间,Android 系统会通知应用程序该准备下一帧的内容了。 - 对于应用层,这意味着 Choreographer 可能会被唤醒以安排新的任务队列执行,比如调用 `doFrame` 方法来处理动画或者重新布局界面元素。 - 同时也意味着 SurfaceFlinger 开始考虑是否需要读取最新的缓冲区数据以便稍后进行画面组合工作[^2]。 2. **从1到0 (下降沿)** 下降沿则往往指示着本周期即将结束,并接近实际物理屏幕上像素更新发生的那一刻之前不久的位置。在这个时间窗口附近会发生如下动作: - 如果一切顺利的话,则此时应该已经完成了所有必要的准备工作,包括但不限于应用端生成的新图像内容已经被写入共享内存区域等待进一步传输。 - 接下来便是 SurfaceFlinger 把这些预处理完毕的数据按照既定顺序排列好之后发送出去让 GPU 或者专用显示控制器去加载进而展示出来形成可见的一帧画面^。 - 随即进入下一个循环继续重复上述步骤直到程序终止运行为止。 值得注意的是,尽管理论上每次遇到边沿都会引发相应行为但是实际情况可能因为各种因素存在差异例如负载过高可能导致丢弃部分帧等情况发生. ```python def frame_drawing_process(vsync_signal): if vsync_signal == 'rising_edge': # From 0 to 1 print("Start preparing next frame.") choreographer_schedule_tasks() # Application layer task scheduling. elif vsync_signal == 'falling_edge': # From 1 to 0 surface_flinger_composite_and_display() print("Display the prepared frame on screen.") def choreographer_schedule_tasks(): pass # Placeholder for application-level tasks like animations or layout updates. def surface_flinger_composite_and_display(): pass # Placeholder for native-layer composition and display submission. ``` ### 结论 综上所述,Vsync 信号的状态改变直接关联到了每帧图像生产的各个环节当中起到了至关重要的节奏把控角色;其中,"0转1"(上升沿)侧重于开启新一轮制作流程而"1变回0"(下降沿)更偏向于是最后呈现成果前的最后一刻确认节点.[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值