display适配

简介

本仓用于存放展锐Spreadtrum芯片display适配内容。

显示适配需要完成的工作:LCD驱动适配、图形服务HDI接口适配、GPU适配。

WUKONG100的LCD驱动适配使用linux原生驱动,具体参考内核适配过程。

显示HDI适配

显示HDI对图形服务提供显示驱动能力,包括显示图层的管理、显示内存的管理及硬件加速等。 显示HDI需要适配两部分:gralloc 和 display_device。其中display_device也包括硬件合成管理display_gfx等。整体架构如图所示:

目录结构如图所示:

display
├── BUILD.gn
├── include
└── src
    ├── display_device         # 显示设备管理、layer管理等
    │   ├── core
    │   ├── drm
    │   ├── fbdev
    │   └── vsync
    ├── display_gfx            # gsp硬件合成
    │   ├── display_gfx.cpp
    │   └── gsp
    │       ├── include
    │       └── src
    ├── display_gralloc        # allocator显示内存管理
    ├── display_layer_video
    └── utils

gralloc适配

gralloc模块提供显示内存管理功能,OpenHarmony提供了使用与Hi3516DV300参考实现,厂商可根据实际情况参考适配,该实现基于drm开发,源码链接

展锐P7885的显示内存管理参考RK3568的实现,依赖展锐私有的allocator实现,对展锐私有的allocator进行封装,提供libdisplay_buffer_vdi_impl.z.so供allocator_host服务调用。

display device适配

display device模块提供显示设备管理、layer管理、硬件加速等功能。

OpenHarmony提供了基于drm的Hi3516DV300芯片的参考实现,该实现默认支持硬件合成;

展锐P7885的display device模块参考RK3568的实现,默认支持硬件合成。

OpenHarmony初步实现了展锐P7885的GSP、DPU等硬件合成,GPU硬件合成尚未支持。硬件合成策略参考

//drivers_peripheral/display/hal/default_standard/src/display_device/hdi_gfx_composition.cpp文件中修改set_layers方法。

int32_t HdiGfxComposition::SetLayers(std::vector<HdiLayer *> &layers, HdiLayer &clientLayer)
{
    DISPLAY_LOGD("layers size %{public}zd", layers.size());
    mClientLayer = &clientLayer;
    mCompLayers.clear();
    int32_t mask = CheckLayers(layers, 0);
    mClientLayer->SetAcceleratorType(ACCELERATOR_NON);
    HdiLayer *layer;
    uint32_t dpuSize = 0;
    for (uint32_t i = 0; i < layers.size(); i++) {
        layer = layers[i];
        if (CanHandle(*layer)) {
            if ((layer->GetCompositionType() != COMPOSITION_VIDEO) &&
                (layer->GetCompositionType() != COMPOSITION_POINTER)) {
#ifdef SPRD_7863
                if(!(mask & 0x03) && (layers.size() < 4))
#else
                if((mask == 0) && (layers.size() < 4))//直接给DPU处理
#endif
                {
                    layer->SetAcceleratorType(ACCELERATOR_DPU);
                    layer->SetDeviceSelect(COMPOSITION_DEVICE);
                    dpuSize++;
                    continue;
                }
#ifdef SPRD_7863
                else if ((mask & 0x07) == 0x03)
                {   
                    layer->SetAcceleratorType(ACCELERATOR_GPU);
                    layer->SetDeviceSelect(COMPOSITION_CLIENT);
                    if(mClientLayer->GetAcceleratorType() == ACCELERATOR_NON)
                    {
                        dpuSize++;
                        mClientLayer->SetAcceleratorType(ACCELERATOR_DPU);//输出结果给DPU显示
                    }
                    continue;
                }
#endif
                else
                {
                    //GSP+DPU
                    int32_t tempMask = CheckLayers(layers, i);
                    uint32_t tempSize = layers.size() - i;
#ifdef SPRD_7863
                    if(tempMask & 0x03)
#else
                    if(tempMask)//复杂场景交给GSP
#endif
                    {
                        layer->SetAcceleratorType(ACCELERATOR_GSP);
                        layer->SetDeviceSelect(COMPOSITION_DEVICE);
                        if(mClientLayer->GetAcceleratorType() == ACCELERATOR_NON)
                        {
                            dpuSize++;
                            mClientLayer->SetAcceleratorType(ACCELERATOR_DPU);//输出结果给DPU显示
                        }
                    }
                    else
                    {
#ifdef SPRD_7863
                        if((dpuSize + tempSize) < 5)
#else
                        if((dpuSize + tempSize) < 7)//dpu支持6个layer
#endif
                        {
                            layer->SetAcceleratorType(ACCELERATOR_DPU);
                            layer->SetDeviceSelect(COMPOSITION_DEVICE);
                            dpuSize++;
                            continue;
                        }
                        else
                        {
                            layer->SetAcceleratorType(ACCELERATOR_GSP);
                            layer->SetDeviceSelect(COMPOSITION_DEVICE);
                            if(mClientLayer->GetAcceleratorType() == ACCELERATOR_NON)
                            {
                                dpuSize++;
                                mClientLayer->SetAcceleratorType(ACCELERATOR_DPU);//输出结果给DPU显示
                            }
                        }
                    }
                }
                
            } else {
                layer->SetDeviceSelect(layer->GetCompositionType());
            }
            mCompLayers.push_back(layer);
        } else {
            layer->SetDeviceSelect(COMPOSITION_CLIENT);
            mClientLayer->SetAcceleratorType(ACCELERATOR_DPU);
            dpuSize = 1;
        }
    }
    DISPLAY_LOGD("composer layers size %{public}zd dpuSize=%{public}d mask=%{public}d", mCompLayers.size(), dpuSize, mask);
    return DISPLAY_SUCCESS;
}

当前旋转或缩放的Layer使用GSP硬件进行串行合成,可能影响性能。

GSP合成的实现依赖展锐闭源库,gfx_composition实现了对闭源库的调用,参考

//drivers_peripheral/display/hal/default_standard/src/display_device/hdi_gfx_composition.cpp文件中的GfxModuleInit方法。

int32_t HdiGfxComposition::GfxModuleInit(void)
{
    DISPLAY_LOGD();
    mGfxModule = dlopen(LIB_HDI_GFX_NAME, RTLD_NOW | RTLD_NOLOAD);
    if (mGfxModule != nullptr) {
        DISPLAY_LOGI("Module '%{public}s' already loaded", LIB_HDI_GFX_NAME);
    } else {
        DISPLAY_LOGI("Loading module '%{public}s'", LIB_HDI_GFX_NAME);
        mGfxModule = dlopen(LIB_HDI_GFX_NAME, RTLD_NOW);
        if (mGfxModule == nullptr) {
            DISPLAY_LOGE("Failed to load module: %{public}s", dlerror());
            return DISPLAY_FAILURE;
        }
    }

    using InitFunc = int32_t (*)(GfxFuncs **funcs);
    InitFunc func = reinterpret_cast<InitFunc>(dlsym(mGfxModule, LIB_GFX_FUNC_INIT));
    if (func == nullptr) {
        DISPLAY_LOGE("Failed to lookup %{public}s function: %s", LIB_GFX_FUNC_INIT, dlerror());
        dlclose(mGfxModule);
        return DISPLAY_FAILURE;
    }
    return func(&mGfxFuncs);
}

测试验证

hello_composer测试模块:Rosen图形框架提供的测试程序,主要显示流程,HDI接口等功能是否正常。默认随系统编译。

代码路径:

foundation/graphic/graphic_2d/rosen/samples/composer
├── BUILD.gn
├── hello_composer.cpp
├── hello_composer.h
├── layer_context.cpp
├── layer_context.h
└── main.cpp

具体验证如下:

  1. 关闭render service
service_control stop render_service
  1. 关闭 foundation进程
service_control stop foundation
  1. 运行hello_composer 测试相关接口
./hello_composer

GPU适配

展锐P7885提供了GPU驱动的闭源实现,参考RK3568的实现,对闭源库进行链接,参考如下:

ohos_prebuilt_shared_library( "GLES_mali" ){
    source = "${GPU_LIB_PATH}/lib64/libGLES_mali.z.so"
    relative_install_dir = "chipsetsdk"
    symlink_target_name = [
        "libEGL_impl.so",
        "libGLESv1_impl.so",
        "libGLESv2_impl.so",
        "libGLESv3_impl.so",
        "libmali.so.0",
        "libmali.so.1",
    ]
    install_enable = true
    install_images = [ chipset_base_dir ]
    part_name = "${PART_NAME}"
    subsystem_name = "${SUBSYSTEM_NAME}"
}