1、概述

Android Graphics Overview :https://lucmann.github.io/gfx/hal/

【Android】硬件合成器 HWC :https://blog.csdn.net/lijian2017/article/details/147565151

Android P 图形显示系统(一)硬件合成HWC2 :https://www.cnblogs.com/hellokitty2/p/17637480.html

Android drm-hwcomposer:https://blog.csdn.net/stray2b/article/details/130291840

1)硬件类型:DPU(Data processing Unit) 或 2D渲染芯片,HWC和GPU一样,由于HWC模块有一定的自主性,因此厂家一般闭源;

2)HWC的任务:合成、送显、产生vsync信号(可以是软件也可以是硬件产生);

3)composer任务可以由OpenGL-ES完成(CPU或GPU),也可以是HWC完成;

为什么需要合成?

1、如果一帧图片所有内容都是顺序绘制,那显示延迟会非常大,为了加速显示 不同部分的绘制同步进行,绘制完后再合在一起 送显;

2、合成过程:当Android显示一个应用时,通常有三个图层(Layer) :顶部状态栏、APP区域、底部状态栏,它们由不同应用绘制渲染,在绘制时各应用(系统应用、用户应用)利用GPU生成自身的图像信息(Bitmap),随后HWC将多个Surface按照一定的顺序和透明度进行合成(CPU\GPU\HWC均可完成),最后送显,完成后产生vsync信息通知surfaceflinger开始下一帧的处理;

在这里插入图片描述

在这里插入图片描述

为什么要使用两种方式进行合成?

HWC 合成效率更高,而 GPU 可以合成更复杂的图层,二者可以搭配着使用,能显著提高合成效率。

在这里插入图片描述

1)部分图层会先利用GPU合成,一来硬件HWC合成层数有限,二来合成能力有限,因此需要借助GPU完成;

2)GPU合成和HWCOMPOSER合成统一由HWC软件模块管理;

3)HWC降级为GPU合成的原因分析?HWC硬件加速器不支持某些图像格式或合成方式。

GPU合成方式

在这里插入图片描述

1)GPU合成本质上是在同一个FB上依次绘制图形;

2)如果没有GPU硬件,则纯软件实现(即使用CPU绘制,效率低);

图层合成的顺序?

1)由WindowManagerService根据各个界面的Z值决定前后顺序;

2)最后将这些排序好的buffer送往HardwareComposer;

2、HWC硬件介绍

1)RK3568 HWC - VOP2

调试说明 - Rockchip Graphics - DRM Hardware Composer

在这里插入图片描述

合成方式
在这里插入图片描述

注意HWC支持的层数是有限的

RK3588 VOP图层分配介绍:https://blog.csdn.net/weixin_43245753/article/details/139000705

2)4412 HWC

在这里插入图片描述

3、HWC架构

1)HWC的层次结构

在这里插入图片描述

2)HWC Composition处理流程

在这里插入图片描述

1)使用CPU/GPU硬件 :HWC_FRAMEBUFFER -> OpenGL ES -> CPU/GPU

2)合成专用硬件:HWC_OVERLAY -> HWC HAL -> VOP2…

4、源码分析

1)数据结构

在这里插入图片描述

2)client-Surfaceflinger

1、概况

1、AN13上使用HAL库,采用AIDL方式远程调用HAL进程;
2、AN9上使用HAL库,采用HIDL方式远程调用HAL进程;

HWC1和HWC2使用分布:
Android 9以前使用
/android/frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
Android 9以以上使用
/android/frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h

1、Layer父类
/android/frameworks/native/services/surfaceflinger/Layer.cpp
2、Layer子类
/android/frameworks/native/services/surfaceflinger/BufferLayer.cpp
/android/frameworks/native/services/surfaceflinger/ColorLayer.cpp
/android/frameworks/native/services/surfaceflinger/ContainerLayer.cpp

下面针对两个系统分别介绍,SurfaceFlinger如何使用HWC
源码目录
/android/frameworks/native/services/surfaceflinger/DisplayHardware

2、低版本的使用opengl合成的代码流程

先看低版本的使用opengl合成的代码流程
1、低版本的AOSP(Android 10及以下) 合成流程,Android9的代码
// frameworks/native/services/surfaceflinger/Surfaceflinger.cpp
void SurfaceFlinger::handleMessageRefresh() {
    preComposition();
    rebuildLayerStacks();
    // 判断哪些图层使用 GPU合成、哪些使用 硬件合成
    setUpHWComposer();
    doDebugFlashRegions(display, repaintEverything);
    // 使用GPU合成、送显
    doComposition();
    //后处理
    postComposition();
}

void SurfaceFlinger::setUpHWComposer() {
    // ...
    for (size_t i = 0; i < currentLayers.size(); i++) {
        const auto& layer = currentLayers[i];
        // 请求HWC判断合成方式
        if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) {
            // 标记该图层使用GPU合成
            layer->forceClientComposition(hwcId);
            continue;
        }
    }
}

void SurfaceFlinger::doComposition() {
    // 使用GPU合成部分Layer
    doDisplayComposition(hw, dirtyRegion);
    // 委托HWC合成所有Layer,并送显
    postFramebuffer();
}

2、核心方法doDisplayComposition详细流程
/android/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
doDisplayComposition(hw, dirtyRegion);
--doComposeSurfaces()
----doComposeSurfaces() //绘图(将所有的Layer绘成一个画面,即合成过程)
/android/frameworks/native/services/surfaceflinger/Layer.cpp
------layer->draw(renderArea,clip);
/android/frameworks/native/services/surfaceflinger/BufferLayer.cpp
--------onDraw(); //使用GL库来绘图
----------drawWithOpenGL(renderArea, useIdentityTransform);
/android/frameworks/native/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
------------engine.drawMesh(getBE().mMesh);
/android/frameworks/native/opengl/libagl/array.cpp  //使用Android GL库
--------------glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
/android/frameworks/native/services/surfaceflinger/DisplayDevice.cpp
----displayDevice->swapBuffers(getHwComposer())  //送显
/android/frameworks/native/services/surfaceflinger/RenderEngine/Surface.cpp
------mSurface->swapBuffers();
--------eglSwapBuffers(mEGLDisplay, mEGLSurface)
/android/frameworks/native/opengl/libagl/egl.cpp
------------d->swapBuffers(); // post the surface
/android/frameworks/native/opengl/libagl/egl.cpp
--------------struct egl_window_surface_v2_t : public egl_surface_t
/android/frameworks/native/libs/nativewindow/include/system/window.h
/android/frameworks/native/libs/gui/Surface.cpp
----------------nativeWindow->queueBuffer(nativeWindow, buffer, -1);
------------------mGraphicBufferProducer->queueBuffer()
/android/frameworks/native/libs/gui/BufferQueue.cpp
/frameworks/native/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
--------------------listener->onFrameAvailable();
/frameworks/native/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
----------------------mHwc.fbPost(mDisplayType, acquireFence, buf); //Android 8
/frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
------------------------fFbDev->post(mFbDev, buffer->handle) //调用fb驱动进行显示,Android 8,Android 9没有此方法


3、Android13 SurfaceFlinger composite流程分析

https://blog.csdn.net/liuning1985622/article/details/138465549
Android13代码相对Android9更加模块化,抽象出更多的“对象”,让其更加健壮但也更复杂,各个流程相对分散 不好分析;
对比着学习能掌握Android的变化趋势,也让我们更好地应对项目上的变化;

1)初始化
SurfaceFlinger::SurfaceFlinger(Factory& factory,)
mCompositionEngine(mFactory.createCompositionEngine()),

HWComposer& SurfaceFlinger::getHwComposer() const {
    return mCompositionEngine->getHwComposer();
}

1)关键参数
android/frameworks/native/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
struct CompositionRefreshArgs {
    Outputs outputs;  //等于display
    Layers layers;
    Layers layersWithQueuedFrames;
    std::vector<uint64_t> bufferIdsToUncache;
}

/android/frameworks/native/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
class Output {

}

/android/frameworks/native/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
class LayerFE : public virtual RefBase {
public:
    virtual const LayerFECompositionState* getCompositionState() const = 0;
    virtual void onLayerDisplayed(ftl::SharedFuture<FenceResult>) = 0;
}


mFlinger->createDisplay(displayName, secure);
mFlinger->mCompositionEngine->setHwComposer(std::make_unique<impl::HWComposer>(std::move(composer)));


2)合成流程
/android/frameworks/native/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
mFlinger->composite(commit(frameTime, vsyncId, expectedVsyncTime), kVsyncId);
--mCompositionEngine->present(refreshArgs);
/android/frameworks/native/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
----preComposition(args);//layer预合成
------layer->onPreComposition(mRefreshStartTime); //遍历所有的layer,进行layer预合成
/android/frameworks/native/services/surfaceflinger/BufferLayer.cpp
--------hasReadyFrame(); //判断是否需要更新
/android/frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
----output->prepare(args, latchedLayers); //output的预合成
------rebuildLayerStacks(refreshArgs, geomSnapshots); //重新计算Layer的visibility和coverage(相对复杂)
----output->present(args); //output的Layer合成
------updateCompositionState()
--------getOutputLayersOrderedByZ() 
----------layer->updateCompositionState()
------planComposition()
--------mPlanner->plan(getOutputLayerOrderedByZ()) //根据Z轴来进行排序计算layer的合成
/android/frameworks/native/services/surfaceflinger/CompositionEngin/src/Planner.cpp
----------Planner::plan()
------writeCompositionState()
------beginFrame()
/android/frameworks/native/services/surfaceflinger/CompositionEngin/src/Output.cpp
--------mRenderSurface->beginFrame(mustRecompose);
----------mDisplaySurface->beginFrame(mustRecompose);
/androidframeworks/native/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
------------refreshOutputBuffer();
--------------mHwc.setOutputBuffer(*halDisplayId, Fence::NO_FENCE, mProducerBUffers[mOutputProducerSlot])
frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
--------------std::unique_ptr<HWC2::Display> hwcDisplay; //调用HWC2::Display的setOutputBuffer方法
--------------displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
------prepareFrameAsync() //准备帧数据以进行显示(Async方式)
------postFramebuffer() //将帧缓冲区(framebuffer)的内容发送到显示设备进行显示
/android/frameworks/native/libs/ui/Region.cpp
--------outputState.dirtyRegion.clear(); //清除脏的区域
--------mRenderSurface->flip();
--------mRenderSurface->onPresentDisplayCompleted();
--------layer->onLayerDisplayed();
------renderCachedSets(refreshArgs); //进行渲染缓存设置
--------mPlanner->renderCachedSets()
--mScheduler->onPostComposition() //通知调度器
--postFrame(); //触发后续的帧提交
--postComposition(); //合成后处理

present会使用合成引擎(CompositionEngine),完成以下工作
1)根据图层类型、硬件能力等因素,为每个图层决定合成策略(使用GPU“客户端合成”,还是使用显示硬件“设备合成”)。
2)执行实际的混合、变换等操作,生成最终帧。
3)通过 present 操作将最终帧提交给显示硬件(如通过HWC模块)。

关键参数
1)outputs:遍历 mDisplays 列表(系统当前所有显示设备,如主屏、副屏),收集每个显示设备的 CompositionDisplay 对象。这是合成操作的目标。
2)layers:遍历 mDrawingState 中的所有图层(Layer),并获取其合成引擎前端接口 LayerFE。这代表了所有需要被合成的图形内容。
3)layersWithQueuedFrames:这是一个重要优化,它记录了那些有新帧(新图形数据)等待合成的图层。在合成时,系统可以优先或只处理这些“脏”图层,避免不必要的重复计算。
4)输出与颜色设置:如 outputColorSetting、forceOutputColorMode 等,用于控制色彩管理、是否强制使用GPU合成(客户端合成)等调试或特性开关。
5)时间参数:这是合成同步的关键,函数计算并传递了一系列精确的时间点:
earliestPresentTime:合成结果可以被提交给硬件的最早时间。
expectedPresentTime:预期本帧图像被显示的时间。
previousPresentFence:上一帧的显示栅栏(Fence),用于同步GPU/硬件工作,确保前一帧已显示完毕。


3)如何确定使用哪个HWComposer?
/android/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
--mCompositionEngine(mFactory.createCompositionEngine()),
//通过属性名来确定使用哪个aidl-hwc
--mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)), 


SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,..)
--auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
--sp<compositionengine::DisplaySurface> displaySurface;
--sp<IGraphicBufferProducer> producer;
--sp<IGraphicBufferProducer> bqProducer;
--sp<IGraphicBufferConsumer> bqConsumer;
--auto surface = ap<VirualDisplaySurface>::make(getHwComposer(),...)

HWComposer& SurfaceFlinger::getHwComposer() const {
    return mCompositionEngine->getHwComposer();
}

/android/frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.h
namespace android {
class HWComposer {
    virtual std::shared_ptr<HWC2::Layer> createLayer(HalDisplayId) = 0;
}
}

//对HWComposer进一步扩展
namespace impl {
class HWComposer final : public android::HWComposer {
    explicit HWComposer(std::unique_ptr<Hwc2::Composer> composer);
    explicit HWComposer(const std::string& composerServiceName);
}
}

4、mFlinger->composite 函数流程图
在这里插入图片描述

3)service-hwcomposer

1、service-hwcomposer
Service的职责是去load对应的hal库,并与client通信

2、AIDL-AML厂商的实现
/android/hardware/amlogic/hwcomposer/service/3.0/Main.cpp
main()
--ALOGI("meson (HWComposer3) starting up...");
--auto composer = ndk::ShareRefBase::make<Composer>();
--AServiceManager_addService(composer->asBinder().get(), instance.c_str());

/android/hardware/amlogic/hwcomposer/service/3.0/HwcHal.cpp
HwcHal::init()
--const hw_module_t* module;
--hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
--hwc2_open(module, &mDevice)
--initCapabilities() //
--initDispatch()
----mDevice->getFunction(mDevice, desc) //获取hal的函数

3、不同厂商的hwcomposer HAL是闭源的

4、但也有开源HAL库;基于drm驱动实现的开源hwcomposer HAL库。
/android/external/drm_hwcomposer
/android/external/drm_hwcomposer/Android.bp //hwcomposer.drm.so

4)hwcomposer HAL

概述

HAL hwcomposer 组件通常是由各个设备厂商根据自己的硬件特性实现的,有开源的,也有闭源的,闭源也情有可原,毕竟厂家的核心实现,这也是HAL产生的原因,但导致架构相对繁杂,代码分支多!HAL的分支:
在这里插入图片描述

在 AOSP 中有一个通用的基础的 HAL hwcomposer demo实现,主要用于那些不需要特别硬件加速或优化的设备,类似 xserver 中的 modesetting.

我们重点关注开源HAL实现drm-hwcomposer -> arm drm-hwcomposer

1、libhardware
1、各个厂商需要实现HAL libhardware规定的接口

/android/hardware/amlogic/hwcomposer
/android/hardware/libhardware/modules/hwcomposer

/android/hardware/amlogic/hwcomposer/service/3.0/HwcHal.cpp
#define HWC_HARDWARE_MODULE_ID "hwcomposer"

2、HAL接口有多个版本 HWC1和HWC2
/android/hardware/libhardware/include/hardware/hwcomposer_defs.h

HWC1功能相对单一
/android/hardware/libhardware/include/hardware/hwcomposer.h
HWC2功能则丰富很多
/android/hardware/libhardware/include/hardware/hwcomposer2.h

1)HW1
/android/hardware/libhardware/include/hardware/hwcomposer.h
typedef struct hwc_composer_device_1 {
    struct hw_device_t common;
    int (*prepare)(struct hwc_composer_device_1 *dev, size_t numDisplays, ...);
    int (*set)(struct hwc_composer_device_1 *dev, size_t numDisplays, ...);
    int (*eventControl)(struct hwc_comoser_device_q* dev, int disp, ...);
    int (*blank)(struct hwc_comoser_device_1* dev, int disp, ...);
    int (*setPowerMode)(struct hwc_composer_device_1* dev, int disp, ...);
    int (*query)(struct hwc_composer_device_1*, int what, ...);
    int (*registerProcs)(struct hwc_composer_device_1*);
    int (*dump)()
    int (*getDisplayConfigs)()
    int (*getDisplayAttributes)()
    int (*getActiveConfig)()
    int (*setAcitveConfig)()
    int (*setCursorPositionAsync)()
}

hwc_open_1(struct hw_module_t* module, hwc_composer_device_1_t** device) {
    return module->methods-open(module, HWC_HARDWARE_COMPOSER, TO_HW_DEVICE_T_OPEN(device))
}

2)HW2
/android/hardware/libhardware/include/hardware/hwcomposer2.h
typedef enum {
    HWC2_FUNCTION_CREATE_LAYER,
    HWC2_FUNCTION_PRESENT_DISPLAY,
    HWC2_FUNCTION_REGISTER_CALLBACK,
    HWC2_FUNCTION_SET_ACTIVE_CONFIG,
    HWC2_FUNCTION_SET_CLIENT_TARGET,
    HWC2_FUNCTION_SET_COLOR_MODE,
    HWC2_FUNCTION_SET_COLOR_TRANSFORM,
    HWC2_FUNCTION_SET_CURSOR_POSITION,
    HWC2_FUNCTION_SET_LAYER_BLEND_MODE,
    HWC2_FUNCTION_SET_LAYER_BUFFER,
    
    // composer 2.3
    HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA,
    HWC2_FUNCTION_GET_DISPLAY_CAPABILITIES,
    HWC2_FUNCTION_SET_LAYER_COLOR_TRANSFORM,
    HWC2_FUNCTION_GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
    HWC2_FUNCTION_SET_DISPLAYED_CONTENT_SAMPLING_ENABLED,
    HWC2_FUNCTION_GET_DISPLAYED_CONTENT_SAMPLE,
    HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA_BLOBS,
    HWC2_FUNCTION_GET_DISPLAY_BRIGHTNESS_SUPPORT,
    HWC2_FUNCTION_SET_DISPLAY_BRIGHTNESS,
    
    // composer 2.4
    HWC2_FUNCTION_GET_DISPLAY_CONNECTION_TYPE,
    HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD,
    HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS,
    HWC2_FUNCTION_SET_AUTO_LOW_LATENCY_MODE,
    HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES,
    HWC2_FUNCTION_SET_CONTENT_TYPE,
    HWC2_FUNCTION_GET_CLIENT_TARGET_PROPERTY,
    HWC2_FUNCTION_SET_LAYER_GENERIC_METADATA,
    HWC2_FUNCTION_GET_LAYER_GENERIC_METADATA_KEY,
} hwc2_function_descriptor_t;

static inline int hwc2_open(struct hw_module_t* module, hwc2_device_t** device){
    return module->methods->open(module, HWC_HARDWARE_COMPOSER, TO_HW_DEVICE_T_OPEN(device))
}
2、hwcomposer demo
1、Android官方开源HAL模版,各个厂商可以基于此demo完成自己的接口
/android/hardware/libhardware/modules/hwcomposer/hwcomposer.cpp
hwc_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .methods = &hwc_module_methods,
    }
}

static struct hw_module_methods_t hwc_module_methods = {
    .open = hwc_device_open
};

hwc_device_open(hw_module_t* module, char *name, hw_device_t** device)
--if (!strcmp(name, HWC_HARDWARE_COMPOSER))
----dev->device.prepare = hwc_prepare;
----dev->device.set = hwc_set;

hwc_prepare
--displays[0]->hwLayers[i].compositionType = HWC_FRAMEBUFFER;

hwc_set
1)实现1
/android/frameworks/native/opengl/libs/eglApi.cpp
--eglSwapBuffers((EGLDisplay)displays[0]->dpy, (EGLSurface)displays[0]->sur); //使用OpenGL-ES合成并显示
----gEGLImpl->platform.eglSwapBUffers(dpy, surface)  //最终导致Gralloc hal:post调用
------queueBuffer()
--------surfaceFLinger->onFrameAvailable()

struct egl_connection_t gEGLImpl
--struct platform_impl_t
----/android/frameworks/native/opengl/libs/platform_entries.in

2)
/android/external/mesa3d/src/egl/main/eglapi.c
eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
--disp->Driver->SwapBuffers(disp, surf);

3、drm-hwcomposer
1、基于drm驱动实现的开源hal hwcomposer

2、libdrm的关系?
drm-hwcomposer通过libdrm与驱动交互

3、
drm-kernel有hwcomposer驱动的实现?
hwc的驱动需要按照drm框架,注册对应的component

5)driver

android/common-5.15/common/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
android/common-5.15/common/drivers/gpu/drm/meson/meson_overlay.c
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐