DRM_PlanesCompositor - SweerItTer/utilsCore GitHub Wiki

PlanesCompositor API 文档

概述

PlanesCompositor 是 utilsCore DRM 模块的核心类,提供 DRM Plane 的组合和原子提交功能,用于多图层合成显示。

职责

  • 管理 DRM Plane 的添加和移除
  • 提供图层属性更新
  • 执行原子提交(atomic commit)
  • 支持 Fence 同步机制

适用场景

  • 多图层合成显示
  • 视频叠加
  • UI 层显示
  • 硬件加速的图层合成

依赖关系

  • 依赖: DeviceController, DrmLayer
  • 被依赖: DisplayManager, VisionPipeline 等上层模块

类分析

PlanesCompositor 类

职责与用途

PlanesCompositor 是 DRM Plane 组合器的封装类,提供:

  • 图层管理(添加、移除、更新)
  • 原子提交
  • Fence 同步
  • 属性配置

设计模式

  • 组合模式: 管理多个 DrmLayer
  • 命令模式: 原子提交请求

公共 API 方法

create() - 创建组合器

static std::unique_ptr<PlanesCompositor> create();

参数说明: 无

返回值:

  • 成功: 返回 PlanesCompositor 的智能指针
  • 失败: 抛出异常

所有权归属:

  • 返回的 unique_ptr 持有 PlanesCompositor 的所有权
  • PlanesCompositor 自身不持有 DeviceController 的所有权

注意事项:

  1. 静态工厂方法
  2. 每次调用创建新实例
  3. 单线程使用或外部同步

使用例程:

// 创建组合器
auto compositor = PlanesCompositor::create();

addLayer() - 添加图层

bool addLayer(const DrmLayerPtr& layer);

参数说明:

  • layer (输入): DrmLayer 智能指针(shared_ptr)

返回值:

  • true: 成功
  • false: 失败

所有权归属:

  • DrmLayer 的所有权由调用者管理
  • PlanesCompositor 不持有 DrmLayer 的所有权

注意事项:

  1. 使用 shared_ptr 引用(不转移所有权)
  2. 图层会被添加到组合器中
  3. 需要调用 commit() 才能生效

使用例程:

// 创建图层
auto layer = std::make_shared<DrmLayer>(buffers, 2);

// 添加图层
if (compositor->addLayer(layer)) {
    printf("Layer added successfully\n");
}

// 提交变更
int fence;
compositor->commit(fence);

removeLayer() - 移除图层

void removeLayer(const DrmLayerPtr& layer);

参数说明:

  • layer (输入): DrmLayer 智能指针

返回值: 无

所有权归属:

  • 无所有权转移

注意事项:

  1. 从组合器中移除图层
  2. 需要调用 commit() 才能生效
  3. 如果图层不存在,不做任何操作

使用例程:

// 移除图层
compositor->removeLayer(layer);

// 提交变更
int fence;
compositor->commit(fence);

removeAllLayer() - 移除所有图层

void removeAllLayer();

参数说明: 无

返回值: 无

注意事项:

  1. 移除所有图层
  2. 需要调用 commit() 才能生效

updateLayer() - 更新图层

bool updateLayer(const DrmLayerPtr& layer);

参数说明:

  • layer (输入): DrmLayer 智能指针

返回值:

  • true: 成功
  • false: 失败

注意事项:

  1. 更新图层的属性
  2. 需要调用 commit() 才能生效
  3. 如果图层不存在,返回 false

updatePropertyForLayer() - 更新图层属性

bool updatePropertyForLayer(const DrmLayerPtr& layer);

参数说明:

  • layer (输入): DrmLayer 智能指针

返回值:

  • true: 成功
  • false: 失败

注意事项:

  1. 更新图层的 DRM 属性
  2. 需要调用 commit() 才能生效

updateLayer() - 更新图层(带 fb_id)

void updateLayer(const DrmLayerPtr& layer, const uint32_t fb_id);

参数说明:

  • layer (输入): DrmLayer 智能指针
  • fb_id (输入): Framebuffer ID

返回值: 无

注意事项:

  1. 更新图层的 framebuffer ID
  2. 需要调用 commit() 才能生效

commit() - 原子提交

int commit(int& fence);

参数说明:

  • fence (输出): 输出参数,接收 fence 文件描述符

返回值:

  • 成功: 返回 0
  • 失败: 返回 -1

所有权归属:

  • fence 的所有权由调用者管理
  • 返回的 fence fd 可以传递给 FenceWatcher

注意事项:

  1. 执行 DRM 原子提交
  2. 所有变更一次性生效
  3. 返回的 fence 用于同步
  4. 阻塞操作,等待提交完成

使用例程:

// 添加图层
auto layer = std::make_shared<DrmLayer>(buffers, 2);
compositor->addLayer(layer);

// 更新图层属性
DrmLayer::LayerProperties props;
props.crtcwidth_ = 1920;
props.crtcheight_ = 1080;
props.srcwidth_ = 1920;
props.srcheight_ = 1080;
props.crtcX_ = 0;
props.crtcY_ = 0;
props.zOrder_ = 0;
props.alpha_ = 1.0f;
layer->setProperty(props);

// 提交所有变更
int fence;
int ret = compositor->commit(fence);
if (ret == 0) {
    // 监控 fence
    FenceWatcher::instance().watchFence(fence, [layer]() {
        layer->onFenceSignaled();
    });
}

内部实现

数据结构

struct PlaneProperty {
    uint32_t property_crtc_id = 0;
    uint32_t property_fb_id = 0;
    uint32_t property_crtc_x = 0;
    uint32_t property_crtc_y = 0;
    uint32_t property_crtc_w = 0;
    uint32_t property_crtc_h = 0;
    uint32_t property_src_x = 0;
    uintuint32_t property_src_y = 0;
    uint32_t property_src_w = 0;
    uint32_t property_src_h = 0;
    uint32_t property_zpos = 0;
};

struct LayerProperty {
    uint32_t plane_id = 0;
    uint32_t crtc_id = 0;
    uint32_t fb_id = 0;
    uint32_t crtc_x = 0;
    uint32_t crtc_y = 0;
    uint32_t crtc_w = 0;
    uint32_t crtc_h = 0;
    uint32_t src_x = 0;
    uint32_t src_y = 0;
    uint32_t src_w = 0;
    uint32_t src_h = 0;
    float alpha = 1.0f;
    uint32_t zpos = 0;
    int type = 0;
};

struct PropertyCache {
    PlaneProperty planeProperty;
    LayerProperty layerProperty;
};

图层管理

  • 使用 std::unordered_map<DrmLayerPtr, PropertyCache, SharedPtrHash, SharedPtrEqual> 管理图层
  • 自定义哈希和比较函数,支持 shared_ptr 作为键
  • 使用互斥锁保护图层操作

典型使用场景

场景 1: 创建和提交图层

// 创建组合器
auto compositor = PlanesCompositor::create();

// 准备缓冲区
std::vector<DmaBufferPtr> buffers;
buffers.push_back(dmaBufferY);
buffers.push_back(dmaBufferUV);

// 创建图层
auto layer = std::make_shared<DrmLayer>(buffers, 2);

// 设置属性
DrmLayer::LayerProperties props;
props.type_ = 0;  // overlay
props.crtcwidth_ = 1920;
props.crtcheight_ = 1080;
props.srcwidth_ = 1920;
props.srcheight_ = 1080;
props.crtcX_ = 0;
props.crtcY_ = 0;
props.zOrder_ = 0;
props.alpha_ = 1.0f;
layer->setProperty(props);

// 添加图层
compositor->addLayer(layer);

// 提交
int fence;
compositor->commit(fence);

// 监控 fence
FenceWatcher::instance().watchFence(fence, [layer]() {
    layer->onFenceSignaled();
});

场景 2: DisplayManager 中的使用

// src/pipeline/displayManager.cpp:229
void DisplayManager::Impl::mainLoop() {
    int drmFence{ -1 };
    while (running.load()) {
        // ...
        
        // 合成并提交
        drmFence = -1;
        if (compositor) compositor->commit(drmFence);

        FenceWatcher::instance().watchFence(drmFence, [this]() {
            for (auto& pf : planesVector) {
                pf.layer->onFenceSignaled();
            }
            cv.notify_one();
        });
    }
}

注意事项

  1. 构造方式: 使用静态工厂方法 create() 创建,不是构造函数
  2. 图层引用: 使用 shared_ptr 引用图层,不转移所有权
  3. commit 必要性: 所有变更都需要调用 commit() 才能生效
  4. Fence 同步: commit() 返回的 fence 需要使用 FenceWatcher 监控
  5. 线程安全: 多线程操作需要外部同步
  6. 图层复用: 同一个图层可以多次更新和提交
  7. 原子提交: commit() 是原子操作,所有变更一次性生效
  8. 错误处理: 失败时返回 -1,需要检查返回值

相关文档


参考资料

⚠️ **GitHub.com Fallback** ⚠️