当前位置: 首页 > article >正文

SurfaceFlinger 调用 libdrm 的详细代码流程分析

1. 整体架构图┌─────────────────────────────────────────────────────────────────┐ │ 应用层框架 │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ App应用 │ │ Activity │ │ View系统 │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ └─────────────────────┬───────────────────────────────────────────┘ │ Binder IPC ▼ ┌─────────────────────────────────────────────────────────────────┐ │ SurfaceFlinger服务 │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ SurfaceFlinger.cpp │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ │ │ - mHwc (std::unique_ptrHWComposer) │ │ │ │ │ │ - mDisplays (显示设备集合) │ │ │ │ │ │ - commit() - 合成提交 │ │ │ │ │ │ - postComposition() - 后处理 │ │ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ └─────────────────────┬───────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ HWComposer硬件组合器 │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ DisplayHardware/HWComposer.h/.cpp │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ │ │ std::unique_ptrHwc2::Composer mComposer │ │ │ │ │ │ mDisplayData (显示数据结构) │ │ │ │ │ │ │ │ │ │ │ │ 关键方法 │ │ │ │ │ │ - setCallback() - 设置回调 │ │ │ │ │ │ - getDeviceCompositionChanges() - 获取合成变更 │ │ │ │ │ │ - setClientTarget() - 设置客户端目标 │ │ │ │ │ │ - presentAndGetReleaseFences() - 显示和获取栅栏 │ │ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ └─────────────────────┬───────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Composer HAL抽象层 │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ DisplayHardware/ComposerHal.h │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ │ │ class Composer { │ │ │ │ │ │ public: │ │ │ │ │ │ virtual Error presentDisplay() 0; │ │ │ │ │ │ virtual Error setClientTarget() 0; │ │ │ │ │ │ virtual Error validateDisplay() 0; │ │ │ │ │ │ virtual Error createLayer() 0; │ │ │ │ │ │ // ... 更多接口 │ │ │ │ │ │ }; │ │ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ 具体实现AidlComposerHal/HidlComposerHal │ │ │ └──────────────────────────────────────────────────────────┘ │ └─────────────────────┬───────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ 硬件组合器HAL服务 (厂商实现) │ │ (位于vendor分区实现具体的显示输出逻辑) │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ 厂商实现的核心代码 │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ │ │ DrmDisplay.cpp (DRM显示管理) │ │ │ │ │ │ DrmConnector.cpp (连接器管理) │ │ │ │ │ │ DrmCrtc.cpp (CRTC管理) │ │ │ │ │ │ DrmPlane.cpp (平面管理) │ │ │ │ │ │ DrmDevice.cpp (DRM设备管理) │ │ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ └─────────────────────┬───────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ libdrm │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ libdrm核心接口 │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ │ │ 设备管理 (xf86drm.h) │ │ │ │ │ │ - drmOpen() - 打开DRM设备 │ │ │ │ │ │ - drmClose() - 关闭DRM设备 │ │ │ │ │ │ - drmGetVersion() - 获取驱动版本 │ │ │ │ │ │ - drmIoctl() - ioctl封装 │ │ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ │ │ KMS模式设置 (xf86drmMode.h) │ │ │ │ │ │ - drmModeGetResources() - 获取资源 │ │ │ │ │ │ - drmModeGetConnector() - 获取连接器 │ │ │ │ │ │ - drmModeSetCrtc() - 设置CRTC │ │ │ │ │ │ - drmModeAddFB() - 添加帧缓冲区 │ │ │ │ │ │ - drmModePageFlip() - 页面翻转 │ │ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ └─────────────────────┬───────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Linux Kernel DRM子系统 │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ DRM Core (drivers/gpu/drm/) │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ │ │ drm_dev.c - 设备管理 │ │ │ │ │ │ drm_mode_config.c - 模式配置 │ │ │ │ │ │ drm_connector.c - 连接器管理 │ │ │ │ │ │ drm_crtc.c - CRTC管理 │ │ │ │ │ │ drm_encoder.c - 编码器管理 │ │ │ │ │ │ drm_plane.c - 平面管理 │ │ │ │ │ │ drm_gem.c - GEM内存管理 │ │ │ │ │ │ drm_fb_helper.c - 帧缓冲区助手 │ │ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ GPU驱动实现 │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ i915 │ │ amdgpu │ │ 其他驱动 │ │ │ │ │ │ Intel GPU │ │ AMD GPU │ │ │ │ │ │ │ │ 驱动实现 │ │ 驱动实现 │ │ │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ └─────────────────────┬───────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ GPU硬件 / 显示控制器 │ │ ├─► GPU核心 (计算单元、着色器等) │ │ ├─► 显示控制器 (时序控制、信号输出) │ │ ├─► 显存 (VRAM/系统内存共享) │ │ ├─► 输出接口 (HDMI/DP/eDP/DSI/Mipi等) │ │ └─► 显示器 (实际显示设备) │ └─────────────────────────────────────────────────────────────────┘2. 初始化阶段详细代码流程SurfaceFlinger::init() │ │ 代码位置: native/services/surfaceflinger/SurfaceFlinger.cpp │ ├─► HWComposer构造函数 │ │ │ ├─► HWComposer::HWComposer(composerServiceName) │ │ │ │ │ └─► HWComposer::HWComposer(Hwc2::Composer::create(composerServiceName)) │ │ │ │ │ ├─► Hwc2::Composer::create() │ │ │ │ │ │ │ └─► 检查并连接到硬件服务 │ │ │ │ │ │ │ ├─► 检查AIDL服务 │ │ │ │ │ │ │ │ │ └─► AServiceManager_checkService( │ │ │ │ android.hardware.graphics.composer3) │ │ │ │ │ │ │ ├─► 检查HIDL服务 │ │ │ │ │ │ │ │ │ └─► IComposer::getService() │ │ │ │ │ │ │ └─► 创建Composer实例 │ │ │ │ │ │ │ └─► std::make_uniqueAidlComposerHal(halService) │ │ │ │ │ │ │ └─► 初始化AIDL连接 │ │ │ │ │ │ │ └─► 连接到硬件Composer服务 │ │ │ │ │ │ │ └─► 厂商HAL服务初始化 │ │ │ │ │ │ │ └─► libdrm初始化调用 │ │ │ │ │ │ │ ├─► drmOpen(/dev/dri/card0) │ │ │ │ │ │ │ │ │ └─► libdrm/xf86drm.c │ │ │ │ │ │ │ │ │ ├─► drmOpenDevice() │ │ │ │ │ ├─► 确定设备节点路径 │ │ │ │ │ ├─► open(/dev/dri/card0, O_RDWR) │ │ │ │ │ └─► 返回文件描述符 │ │ │ │ │ │ │ ├─► drmGetVersion(fd, version) │ │ │ │ │ │ │ │ │ └─► drmIoctl(fd, DRM_IOCTL_VERSION, version) │ │ │ │ │ │ │ │ │ └─► 内核处理并返回驱动版本 │ │ │ │ │ │ │ └─► drmModeGetResources(fd) │ │ │ │ │ │ │ └─► libdrm/xf86drmMode.c │ │ │ │ │ │ │ ├─► drmModeGetResources() │ │ │ │ │ │ │ │ │ ├─► 准备drm_mode_card_res结构 │ │ │ │ │ │ │ │ │ ├─► 第一次ioctl调用 │ │ │ │ │ └─► drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, res) │ │ │ │ │ ├─► 内核DRM处理 │ │ │ │ │ ├─► 返回资源数量 │ │ │ │ │ └─► res.count_crtcs, res.count_connectors等 │ │ │ │ │ │ │ │ │ ├─► 分配内存 │ │ │ │ │ ├─► res.fb_id_ptr malloc(count_fbs * sizeof(uint32_t)) │ │ │ │ │ ├─► res.crtc_id_ptr malloc(count_crtcs * sizeof(uint32_t)) │ │ │ │ │ └─► ... 分配其他资源数组 │ │ │ │ │ │ │ │ │ └─► 第二次ioctl调用 │ │ │ │ └─► drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, res) │ │ │ │ ├─► 内核填充资源ID数组 │ │ │ │ └─│ 返回完整的资源信息 │ │ │ │ │ │ │ └─► 构建drmModeRes结构返回 │ │ │ ├─► fbs: 帧缓冲区ID数组 │ │ │ ├─► crtcs: CRTC ID数组 │ │ │ ├─► connectors: 连接器ID数组 │ │ │ └─► encoders: 编码器ID数组 │ │ │ │ │ └─► 初始化HWComposer成员变量 │ │ ├─► mComposer std::move(composer) │ │ ├─► mRegisteredCallback false │ │ └─► mCapabilities 初始化能力集合 │ │ │ └─► 返回HWComposer实例 │ ├─► 设置回调函数 │ │ │ ├─► HWComposer::setCallback(callback) │ │ │ │ │ ├─► loadCapabilities() │ │ │ │ │ │ │ └─► mComposer-getCapabilities() │ │ │ │ │ │ │ └─► AidlComposerHal::getCapabilities() │ │ │ │ │ │ │ └─► mHal-getCapabilities(capabilities) │ │ │ │ │ │ │ └─► 硬件服务返回能力列表 │ │ │ ├─► SKIP_CLIENT_COLOR_TRANSFORM │ │ │ ├─► DOZE │ │ │ ├─► REFRESH_RATE_SWITCHING │ │ │ └─► 其他能力 │ │ │ │ │ ├─► loadLayerMetadataSupport() │ │ │ │ │ ├─► loadOverlayProperties() │ │ │ │ │ ├─► loadHdrConversionCapabilities() │ │ │ │ │ └─► 注册回调 │ │ │ │ │ └─► mComposer-registerCallback(callback) │ │ │ │ │ └─► AidlComposerHal::registerCallback() │ │ │ │ │ └─► mHal-registerCallback(callbackWrapper) │ │ │ │ │ └─► 硬件服务注册回调 │ │ │ │ │ └─► 启用热插拔、VSync等事件通知 │ │ ├─► onHotplug - 显示器热插拔 │ │ ├─► onVsync - 垂直同步信号 │ │ └─► onRefresh - 刷新请求 │ │ └─► 初始化显示设备 │ └─► SurfaceFlinger::initializeDisplays() │ ├─► 处理热插拔事件 │ │ │ └─► HWComposer::onHotplug(hwcDisplayId, connection) │ │ │ └─► onHotplugConnect(hwcDisplayId) │ │ │ ├─► 获取显示标识信息 │ │ │ │ │ └─► getDisplayIdentificationData(hwcDisplayId) │ │ │ │ │ └─► mComposer-getDisplayIdentificationData() │ │ │ │ │ └─► 硬件服务返回显示标识 │ │ ├─► EDID数据 │ │ ├─► 厂商信息 │ │ └─│ 设备ID │ │ │ ├─► 创建物理显示设备 │ │ │ │ │ └─► allocatePhysicalDisplay(hwcDisplayId, displayId) │ │ │ │ │ └─► 创建HWC2::Display实例 │ │ │ │ │ └─► std::make_uniqueHWC2::impl::Display( │ │ *mComposer.get(), │ │ mCapabilities, │ │ hwcDisplayId, │ │ hal::DisplayType::PHYSICAL) │ │ │ └─► 返回显示设备信息 │ ├─► 显示ID │ ├─► 分辨率 │ └─► 显示名称 │ └─► 创建DisplayDevice实例 │ └─► 创建DisplayDevice并添加到显示设备列表3. 帧显示和合成详细流程SurfaceFlinger::commit() │ │ 代码位置: native/services/surfaceflinger/SurfaceFlinger.cpp │ ├─► 准备合成 │ │ │ ├─► validateLayers() │ │ │ │ │ └─► 检查所有Layer的状态 │ │ ├─► 图层可见性 │ │ ├─│ 缓冲区状态 │ │ └─│ 合成类型 │ │ │ └─► buildLayerStacks() │ │ │ └─► 构建图层栈 │ ├─► 按Z顺序排序 │ ├─► 确定合成策略 │ └─► 准备合成参数 │ ├─► 获取硬件合成器建议 │ │ │ ├─► HWComposer::getDeviceCompositionChanges(displayId, frameUsesClientComposition, │ │ earliestPresentTime, expectedPresentTime, │ │ frameInterval, outChanges) │ │ │ │ │ └─► DeviceRequestedChanges获取流程 │ │ │ │ │ ├─► 检查显示有效性 │ │ │ │ │ │ │ └─► RETURN_IF_INVALID_DISPLAY(displayId, error) │ │ │ │ │ ├─► 获取显示数据 │ │ │ │ │ │ │ └─► auto displayData mDisplayData[displayId] │ │ │ │ │ │ │ └─► 获取HWC2::Display实例 │ │ │ │ │ │ │ └─► displayData.hwcDisplay │ │ │ │ │ ├─► 准备客户端目标 │ │ │ │ │ │ │ └─► prepareClientTarget(displayData, frameUsesClientComposition, │ │ │ earliestPresentTime, expectedPresentTime, │ │ │ frameInterval) │ │ │ │ │ ├─► 验证显示 │ │ │ │ │ │ │ └─► validateDisplay(displayData, earliestPresentTime, │ │ │ expectedPresentTime, frameInterval) │ │ │ │ │ │ │ ├─► HWC2::Display::validate() │ │ │ │ │ │ │ └─► ComposerHal::validateDisplay(display, expectedPresentTime, │ │ │ frameIntervalNs, outNumTypes, │ │ │ outNumRequests) │ │ │ │ │ │ │ └─► AidlComposerHal::validateDisplay() │ │ │ │ │ │ │ └─► mHal-validateDisplay(display, expectedPresentTime, │ │ │ frameIntervalNs, numTypes, │ │ │ numRequests) │ │ │ │ │ │ │ └─► 硬件服务验证 │ │ │ │ │ │ │ └─► 厂商实现调用libdrm │ │ │ │ │ │ │ ├─► drmModeGetConnector() │ │ │ │ │ │ │ │ │ └─► ioctl(DRM_IOCTL_MODE_GETCONNECTOR) │ │ │ │ ├─► 内核DRM处理 │ │ │ │ ├─► 检查连接状态 │ │ │ │ ├─► 获取支持的显示模式 │ │ │ │ └─│ 返回连接器信息 │ │ │ │ │ │ │ ├─► drmModeGetEncoder() │ │ │ │ │ │ │ │ │ └─► ioctl(DRM_IOCTL_MODE_GETENCODER) │ │ │ │ └─► 获取编码器信息 │ │ │ │ │ │ │ └─► drmModeGetCrtc() │ │ │ │ │ │ │ └─► ioctl(DRM_IOCTL_MODE_GETCRTC) │ │ │ ├─► 获取CRTC状态 │ │ │ └─│ 返回当前配置 │ │ │ │ │ ├─► 获取合成类型变更 │ │ │ │ │ │ │ └─► getChangedCompositionTypes() │ │ │ │ │ │ │ └─► ComposerHal::getChangedCompositionTypes(display, outLayers, │ │ │ outTypes) │ │ │ │ │ │ │ └─► 硬件服务返回合成类型建议 │ │ │ ├─► DEVICE - 硬件合成 │ │ │ ├─► CLIENT - 客户端合成 │ │ │ └─► CURSOR - 光标合成 │ │ │ │ │ ├─► 获取显示请求 │ │ │ │ │ │ │ └─► getDisplayRequests(display, outDisplayRequestMask, │ │ │ outLayers, outLayerRequestMasks) │ │ │ │ │ │ │ └─► 获取显示相关的合成请求 │ │ │ ├─► FLIP_CLIENT_TARGET - 翻转客户端目标 │ │ │ ├─► WRITE_CLIENT_TARGET_TO_OUTPUT - 写入客户端目标 │ │ │ └─► 其他显示请求 │ │ │ │ │ └─► 构建返回结果 │ │ │ │ │ └─► DeviceRequestedChanges │ │ ├─► changedTypes - 图层合成类型变更 │ │ ├─► displayRequests - 显示器请求 │ │ └─► layerRequests - 图层请求 │ │ └─► 执行合成操作 │ ├─► 根据合成类型选择合成方式 │ │ │ ├─► DEVICE合成 (硬件加速) │ │ │ │ │ └─► 直接由硬件合成器处理 │ │ │ │ │ └─► 设置图层层属性 │ │ │ │ │ ├─► setLayerBuffer() │ │ │ │ │ │ │ └─► ComposerHal::setLayerBuffer(display, layer, slot, │ │ │ buffer, acquireFence) │ │ │ │ │ │ │ └─► 硬件服务设置图层缓冲区 │ │ │ │ │ │ │ └─► 关联GEM句柄到图层 │ │ │ │ │ ├─► setLayerCompositionType() │ │ │ │ │ │ │ └─► 设置为DEVICE合成类型 │ │ │ │ │ └─► 其他图层属性设置 │ │ ├─► setLayerDisplayFrame() │ │ ├─► setLayerSourceCrop() │ │ ├─► setLayerBlendMode() │ │ └─► setLayerTransform() │ │ │ └─► CLIENT合成 (软件渲染) │ │ │ └─► GPU渲染流程 │ │ │ └─► RenderEngine::renderLayers() │ │ │ ├─► OpenGL ES渲染 │ │ │ │ │ └─► 使用GPU合成多个图层 │ │ ├─► 图层混合 │ │ ├─► 效果处理 │ │ └─► 生成最终图像 │ │ │ └─► 输出到GraphicBuffer │ │ │ └─► 作为客户端目标提交 │ ├─► 提交显示 │ │ │ └─► SurfaceFlinger::postComposition() │ │ │ └─► HWComposer::presentAndGetReleaseFences(displayId, earliestPresentTime) │ │ │ └─► 显示和获取释放栅栏的详细流程 │ │ │ ├─► 设置客户端目标 │ │ │ │ │ └─► setClientTarget(displayId, slot, acquireFence, target, │ │ dataspace, hdrSdrRatio) │ │ │ │ │ └─► ComposerHal::setClientTarget(display, slot, target, │ │ acquireFence, dataspace, damage, │ │ hdrSdrRatio) │ │ │ │ │ └─► 硬件服务处理客户端目标 │ │ │ │ │ └─► 调用libdrm分配GEM对象 │ │ │ │ │ ├─► 分配GEM缓冲对象 │ │ │ │ │ │ │ └─► drmIoctl(fd, DRM_IOCTL_GEM_CREATE, create) │ │ │ │ │ │ │ └─► 内核创建GEM对象 │ │ │ │ │ │ │ ├─► DRM Core: drm_gem_create() │ │ │ │ │ │ │ │ │ └─► GPU驱动: gem_create() │ │ │ │ ├─► 分配显存 │ │ │ │ ├─► 创建GEM对象 │ │ │ │ └─│ 返回GEM句柄 │ │ │ │ │ │ │ └─► 返回gem_handle │ │ │ │ │ ├─► 映射GEM对象到用户空间 │ │ │ │ │ │ │ └─► drmIoctl(fd, DRM_IOCTL_GEM_MMAP, map) │ │ │ │ │ │ │ └─► 内核处理映射请求 │ │ │ │ │ │ │ ├─► DRM Core: drm_gem_mmap() │ │ │ │ │ │ │ │ │ └─► GPU驱动: gem_mmap() │ │ │ │ ├─► 获取物理地址 │ │ │ │ ├─► 设置页表映射 │ │ │ │ └─│ 返回偏移量 │ │ │ │ │ │ │ └─► mmap()系统调用 │ │ │ │ │ │ │ └─► 映射到用户空间虚拟地址 │ │ │ │ │ │ │ └─► 返回用户空间地址 │ │ │ │ │ ├─► 复制像素数据 │ │ │ │ │ │ │ └─► memcpy(addr, buffer_data, size) │ │ │ │ │ │ │ └─► 将客户端合成的数据复制到GEM缓冲区 │ │ │ │ │ └─► 创建帧缓冲区 │ │ │ │ │ └─► drmModeAddFB(fd, width, height, depth, bpp, │ │ pitch, gem_handle, fb_id) │ │ │ │ │ └─► libdrm/xf86drmMode.c │ │ │ │ │ └─► drmModeAddFB() │ │ │ │ │ ├─► 准备drm_mode_fb_cmd结构 │ │ │ │ │ ├─► ioctl(DRM_IOCTL_MODE_ADDFB, fb_cmd) │ │ │ │ │ └─► 内核创建帧缓冲区 │ │ │ │ │ ├─► DRM Core: drm_mode_addfb() │ │ │ │ │ └─► GPU驱动: 用户空间帧缓冲区接口 │ │ │ │ │ ├─► 关联GEM对象到帧缓冲区 │ │ ├─► 设置帧缓冲区属性 │ │ └─│ 返回帧缓冲区ID │ │ │ │ │ └─► 返回fb_id │ │ │ └─► 显示到屏幕 │ │ │ └─► presentDisplay(displayId, earliestPresentTime) │ │ │ └─► ComposerHal::presentDisplay(display, outPresentFence) │ │ │ └─► AidlComposerHal::presentDisplay(display, outPresentFence) │ │ │ └─► mHal-presentDisplay(display, outPresentFence) │ │ │ └─► 硬件服务执行显示 │ │ │ └─► 厂商实现调用libdrm │ │ │ ├─► 设置显示模式 │ │ │ │ │ └─► drmModeSetCrtc(fd, crtc_id, fb_id, x, y, │ │ connectors, count, mode) │ │ │ │ │ └─► libdrm/xf86drmMode.c │ │ │ │ │ └─► drmModeSetCrtc() │ │ │ │ │ ├─► 准备drm_mode_crtc结构 │ │ │ ├─► 设置帧缓冲区ID │ │ │ ├─► 设置显示位置 │ │ │ ├─│ 设置连接器 │ │ │ └─│ 设置显示模式 │ │ │ │ │ ├─► ioctl(DRM_IOCTL_MODE_SETCRTC, crtc_req) │ │ │ │ │ └─► 内核配置CRTC │ │ │ │ │ ├─► DRM Core: drm_mode_setcrtc() │ │ │ │ │ │ │ └─► GPU驱动: 设置CRTC输出 │ │ │ │ │ │ │ ├─► 配置显示时序 │ │ │ │ ├─► 设置像素时钟 │ │ │ │ ├─│ 设置水平时序 │ │ │ │ ├─│ 设置垂直时序 │ │ │ │ └─│ 其他时序参数 │ │ │ │ │ │ │ ├─► 配置PLL │ │ │ │ ├─► 计算PLL参数 │ │ │ │ ├─│ 设置PLL频率 │ │ │ │ └─│ 锁定PLL │ │ │ │ │ │ │ ├─► 连接帧缓冲区 │ │ │ │ ├─│ 关联FB到CRTC │ │ │ │ └─│ 设置显示地址 │ │ │ │ │ │ │ ├─► 启用编码器 │ │ │ │ ├─│ 配置输出格式 │ │ │ │ ├─│ 设置信号电平 │ │ │ │ └─│ 启用输出驱动器 │ │ │ │ │ │ │ └─► 启用CRTC │ │ │ ├─│ 启用输出信号 │ │ │ ├─│ 开始扫描输出 │ │ │ └─│ 显示生效 │ │ │ │ │ └─► 硬件寄存器编程 │ │ ├─► 显示控制器编程 │ │ ├─► 时钟生成器配置 │ │ ├─► PLL配置 │ │ └─► 输出驱动器使能 │ │ │ └─► 页面翻转 │ │ │ └─► drmModePageFlip(fd, crtc_id, fb_id, flags, user_data) │ │ │ └─► libdrm/xf86drmMode.c │ │ │ └─► drmModePageFlip() │ │ │ ├─► 准备drm_mode_crtc_page_flip结构 │ │ ├─► 设置CRTC ID │ │ ├─► 设置新的帧缓冲区ID │ │ ├─► 设置翻转标志 │ │ │ ├─► DRM_MODE_PAGE_FLIP_EVENT - 事件通知 │ │ │ └─► DRM_MODE_PAGE_FLIP_ASYNC - 异步翻转 │ │ └─│ 设置用户数据 │ │ │ ├─► ioctl(DRM_IOCTL_MODE_PAGE_FLIP, flip_req) │ │ │ └─► 内核执行页面翻转 │ │ │ ├─► DRM Core: drm_mode_page_flip() │ │ │ └─► GPU驱动: 处理页面翻转 │ │ │ ├─► 双缓冲管理 │ │ ├─► 等待VBlank │ │ ├─► 切换前台/后台缓冲区 │ │ └─│ 交换缓冲区指针 │ │ │ ├─► 等待垂直同步 │ │ ├─► 阻塞等待VBlank信号 │ │ ├─│ 获取VBlank时间戳 │ │ └─│ 更新显示时间 │ │ │ └─► 生成释放栅栏 │ │ │ └─► 创建sync_file │ │ │ └─► 用于同步GPU操作 │ └─► 清理和释放资源 │ ├─► drmModeRmFB(fd, fb_id) │ │ │ └─► libdrm/xf86drmMode.c │ │ │ └─► drmModeRmFB() │ │ │ ├─► ioctl(DRM_IOCTL_MODE_RMFB, fb_id) │ │ │ └─► 内核删除帧缓冲区 │ │ │ └─► DRM Core: drm_mode_rmfb() │ │ │ └─► GPU驱动: 释放帧缓冲区资源 │ ├─│ 取消GEM对象关联 │ ├─│ 释放GEM对象 │ └─│ 更新资源状态 │ ├─► munmap(addr, size) │ │ │ └─► 解除用户空间映射 │ │ │ └─► 内核处理munmap │ │ │ └─► 释放页表映射 │ └─► drmClose(fd) │ └─► 关闭DRM设备文件描述符 │ └─► 释放设备资源4. 关键代码片段分析4.1 HWComposer 初始化代码片段// HWComposer.cpp 中的初始化代码HWComposer::HWComposer(std::unique_ptrHwc2::Composercomposer):mComposer(std::move(composer)),mMaxVirtualDisplayDimension(static_castsize_t(sysprop::max_virtual_display_dimension(0))),mUpdateDeviceProductInfoOnHotplugReconnect(sysprop::update_device_product_info_on_hotplug_reconnect(false)),mEnableVrrTimeout(base::GetBoolProperty(debug.sf.vrr_timeout_hint_enableds,true)){}HWComposer::HWComposer(conststd::stringcomposerServiceName):HWComposer(Hwc2::Composer::create(composerServiceName)){}voidHWComposer::setCallback(HWC2::ComposerCallbackcallback){loadCapabilities();loadLayerMetadataSupport();loadOverlayProperties();loadHdrConversionCapabilities();if(mRegisteredCallback){ALOGW(Callback already registered. Ignored extra registration attempt.);return;}mRegisteredCallbacktrue;mComposer-registerCallback(callback);}4.2 显示设备分配代码片段voidHWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId,PhysicalDisplayId displayId){mPhysicalDisplayIdMap[hwcDisplayId]displayId;if(!mPrimaryHwcDisplayId){mPrimaryHwcDisplayIdhwcDisplayId;}autodisplayDatamDisplayData[displayId];autonewDisplaystd::make_uniqueHWC2::impl::Display(*mComposer.get(),mCapabilities,hwcDisplayId,hal::DisplayType::PHYSICAL);newDisplay-setConnected(true);displayData.hwcDisplaystd::move(newDisplay);}4.3 设备组合变更获取代码片段status_tHWComposer::getDeviceCompositionChanges(HalDisplayId displayId,boolframeUsesClientComposition,std::optionalstd::chrono::steady_clock::time_pointearliestPresentTime,nsecs_t expectedPresentTime,Fps frameInterval,std::optionalDeviceRequestedChanges*outChanges){RETURN_IF_INVALID_DISPLAY(displayId,BAD_VALUE);autodisplayDatamDisplayData[displayId];prepareClientTarget(displayData,frameUsesClientComposition,earliestPresentTime,expectedPresentTime,frameInterval);std::vectorLayer*changedLayers;std::vectorCompositioncompositionTypes;uint32_tdisplayRequestMask0;std::vectorLayer*requestedLayers;std::vectoruint32_tlayerRequestMasks;autoerrordisplayData.hwcDisplay-validateAndGetChangedCompositionTypes(earliestPresentTime,expectedPresentTime,frameInterval,changedLayers,compositionTypes,displayRequestMask,requestedLayers,layerRequestMasks);if(errorhal::Error::NONE){DeviceRequestedChanges changes;changes.changedTypesbuildChangedTypesMap(changedLayers,compositionTypes);changes.displayRequestsdisplayRequestMask;changes.layerRequestsbuildLayerRequestsMap(requestedLayers,layerRequestMasks);// 获取客户端目标属性hal::V3_0::ClientTargetPropertyWithBrightness clientTargetProperty;errormComposer-getClientTargetProperty(displayData.hwcDisplay-getId(),clientTargetProperty);if(errorhal::Error::NONE){changes.clientTargetPropertyclientTargetProperty;}*outChangeschanges;}returnstatic_caststatus_t(error);}4.4 显示和栅栏获取代码片段status_tHWComposer::presentAndGetReleaseFences(HalDisplayId displayId,std::optionalstd::chrono::steady_clock::time_pointearliestPresentTime){RETURN_IF_INVALID_DISPLAY(displayId,BAD_VALUE);autodisplayDatamDisplayData[displayId];autoerrordisplayData.hwcDisplay-present(earliestPresentTime);if(error!hal::Error::NONE){RETURN_IF_HWC_ERROR(error,displayId,UNKNOWN_ERROR);}returnOK;}5. libdrm 调用序列图SurfaceFlinger HWComposer ComposerHal 硬件服务 libdrm 内核DRM │ │ │ │ │ │ │ │ │ │ │ │ ├─ init() │ │ │ │ │ │ │ │ │ │ │ │ ├─ create() ────────┤ │ │ │ │ │ │ ├─ create() ──────────┤ │ │ │ │ │ │ ├─ connect() ──────┤ │ │ │ │ │ │ ├─ drmOpen() ──────┤ │ │ │ │ │ │ ├─ open() │ │ │ │ │ │ │ ├─ 设备节点 │ │ │ │ │ │ └─ 返回fd │ │ │ │ │ ├─ 返回fd │ │ │ │ │ │ │ │ │ │ │ ├─ drmGetVersion() ─┤ │ │ │ │ │ │ ├─ ioctl(VERSION) │ │ │ │ │ │ │ ├─ 返回驱动信息 │ │ │ │ │ │ └─ 返回版本 │ │ │ │ │ ├─ 返回版本 │ │ │ │ │ │ │ │ │ │ │ ├─ drmModeGetResources() ────────────┤ │ │ │ │ │ │ ├─ 查询资源数量 │ │ │ │ │ │ ├─ 返回资源列表 │ │ │ │ │ │ └─ 构建资源结构 │ │ │ │ │ ├─ 返回资源信息 │ │ │ │ │ │ │ │ │ │ │ ├─ drmModeGetConnector() ──────────┤ │ │ │ │ │ │ ├─ 查询连接器状态 │ │ │ │ │ │ ├─ 获取支持模式 │ │ │ │ │ │ └─ 返回连接器信息 │ │ │ │ │ ├─ 返回连接器信息 │ │ │ │ │ │ │ │ │ │ │ ├─ drmModeGetEncoder() ────────────┤ │ │ │ │ │ │ ├─ 查询编码器信息 │ │ │ │ │ │ └─ 返回编码器信息 │ │ │ │ │ ├─ 返回编码器信息 │ │ │ │ │ │ │ │ │ │ │ ├─ drmModeGetCrtc() ───────────────┤ │ │ │ │ │ │ ├─ 查询CRTC状态 │ │ │ │ │ │ └─ 返回CRTC信息 │ │ │ │ │ ├─ 返回CRTC信息 │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─ commit() │ │ │ │ │ │ │ │ │ │ │ ├─ getDeviceCompositionChanges() ──────────────┤ │ │ │ │ │ │ │ │ │ │ │ ├─ validateDisplay() ─┤ │ │ │ │ │ ├─ 重复上述资源查询 │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─ setClientTarget() ───┤ │ │ │ │ │ ├─ setClientTarget() ─┤ │ │ │ │ │ ├─ 分配GEM对象 │ │ │ │ │ │ ├─ drmIoctl(GEM_CREATE) ──────────┤ │ │ │ │ │ ├─ 创建GEM对象 │ │ │ │ │ ├─ 分配显存 │ │ │ │ │ └─ 返回GEM句柄 │ │ │ │ │ │ │ │ │ ├─ drmIoctl(GEM_MMAP) ────────────┤ │ │ │ │ │ ├─ 映射GEM对象 │ │ │ │ │ ├─ 设置页表 │ │ │ │ │ └─ 返回偏移量 │ │ │ │ │ │ │ │ │ ├─ mmap() ─────────┤ │ │ │ │ │ │ ├─ 映射到用户空间 │ │ │ │ │ └─ 返回用户地址 │ │ │ │ │ │ │ │ │ ├─ drmModeAddFB() ─────────────────┤ │ │ │ │ │ ├─ 创建帧缓冲区 │ │ │ │ │ ├─ 关联GEM对象 │ │ │ │ │ └─ 返回FB ID │ │ │ │ │ │ │ │ │ │ │ │ ├─ presentAndGetReleaseFences() ───────────────┤ │ │ │ │ │ │ │ │ │ │ │ ├─ presentDisplay() ─┤ │ │ │ │ │ │ │ │ │ │ │ ├─ drmModeSetCrtc() ───────────────┤ │ │ │ │ │ ├─ 配置CRTC参数 │ │ │ │ │ ├─ 关联帧缓冲区 │ │ │ │ │ ├─ 设置时序 │ │ │ │ │ └─ 启用输出 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─ drmModePageFlip() ────────────┤ │ │ │ │ │ ├─ 请求页面翻转 │ │ │ │ │ ├─ 等待VBlank │ │ │ │ │ ├─ 交换缓冲区 │ │ │ │ │ └─ 释放栅栏 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─ 清理资源 │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─ drmModeRmFB() ─────────────────┤ │ │ │ │ │ ├─ 删除帧缓冲区 │ │ │ │ │ ├─ 取消GEM关联 │ │ │ │ │ └─ 释放资源 │ │ │ │ │ │ │ │ │ ├─ munmap() ──────┤ │ │ │ │ │ │ ├─ 解除映射 │ │ │ │ │ └─ 释放页表 │ │ │ │ │ │ │ │ │ ├─ drmClose() ────┤ │ │ │ │ │ │ ├─ 关闭设备 │ │ │ │ │ └─ 释放资源

相关文章:

SurfaceFlinger 调用 libdrm 的详细代码流程分析

1. 整体架构图 ┌─────────────────────────────────────────────────────────────────┐ │ 应用层框架 │ │ ┌──────────────…...

安卓上架权限弹窗

https://ask.dcloud.net.cn/article/41194 直接这个网站看,但是要注意!!!!!真机运行的时候,改了manifest.json的配置要重新打基座...

【限时开放】ElevenLabs波斯文语音调试秘钥包(含Persian SSML扩展标签库、RTL音频波形对齐工具、实时音素诊断CLI):仅支持至2024年Q3 API v2退役前

更多请点击: https://intelliparadigm.com 第一章:ElevenLabs波斯文语音支持的演进与技术边界 ElevenLabs自2022年推出多语言TTS服务以来,波斯文(Farsi)长期处于实验性支持阶段。早期版本仅能通过自定义音色音素级微调…...

用于参数扫描的自定义工具

能够改变光学系统的参数是任何设置分析的关键部分,以便更好地了解系统在从制造错误到组件潜在错位的任何情况下的行为。设计一个在面对这些不可避免的偏离理想化预期设计时表现出鲁棒性的系统,与找到一个完全满足所有规范的初始设计一样重要,…...

【专利视点】某抗病毒药物领域明星企业上市进程知产问题分析

医药领域IPO,正在随着证券市场监管新形势而发生变化,并从CXO板块向更多细分赛道延伸。知识产权问题是影响企业IPO上市的重要因素之一。从上海证券交易所官网统计得知,截至2024年10月14日,有102家医药制造业企业终止科创板IPO申请&…...

通用异步导出服务设计:从业务功能到平台基础能力的抽象

在后台管理系统中,“导出 Excel”几乎是一个绕不开的功能。看似只是点击一个按钮、下载一个文件,背后却经常隐藏着性能、稳定性、安全性和用户体验问题。 当数据量较小时,同步导出通常可以满足需求。但随着业务数据规模增长,导出操…...

影刀RPA跨境店群运营架构:TikTok Shop矩阵多节点高并发调度与Python环境隔离实战

大家好,我是林焱。 太有意思了,刚刷朋友圈,看到一个在跨境圈子里被疯狂转发的消息。 有几个当年和我一样,在职业技术学院念工程出身的 00 后学弟,最近跑回母校干了件特别硬核的事。 他们没有像传统的成功校友那样&a…...

维萨报告:AI 加速诈骗成消费者新危害,企业需提速应对

AI 加速类 ClickFix 诈骗还记得 ClickFix 吗?这是近年来流行的一种社会工程技术,它通过利用心理弱点绕过传统的网络钓鱼防御。在 ClickFix 攻击中,受害者会被呈现一个看似容易解决的问题,从而诱使他们自己执行恶意操作。例如&…...

特朗普移动数据泄露:客户信息险曝光,T1 手机真实订单远低于网传

特朗普移动数据泄露:客户信息岌岌可危就在 T1 手机似乎即将发布之时,特朗普移动(Trump Mobile)被指控不安全地存储客户数据,使得客户的地址和电话号码面临泄露风险。YouTuber Coffeezilla 最先在他的第二个频道 voidzi…...

影刀RPA跨境店群运营架构:Python协同Chromium底层调度与高并发容器化实战

定了。在跨境电商自动化的技术角斗场里,我们终于打破了“商业指纹浏览器单机RPA”的低效垄断,实现了一套足以支撑万级店铺矩阵的分布式微服务调度架构。 这几天,科技圈被“DeepSeek V4 首发华为昇腾芯片,国产 AI 开始打破英伟达 …...

小学期第一周

理论部分:学会了低通滤波器原理:只允许低于截止频率的信号通过,高于截止频率的信号被大幅衰减方波变成正弦波的原理:方波是基波无数奇次谐波的叠加,低通滤波器只留基波、滤掉高频谐波,输出就接近正弦波二阶…...

突破内存瓶颈:HBM、CXL与GPU新部署策略

训练生成式AI模型本身已是一项成本高昂、能耗巨大的工作。随着超大规模数据中心和前沿研究机构竞相扩展边缘推理与智能体AI能力,GPU的部署正变得愈加复杂,尤其是在内存层面。在数据中心中,对先进内存配置的需求日益迫切。不断增多的AI处理器正…...

网页端嵌入 Agent 对接前端方案

本文将深入探讨「网页端嵌入AI」的核心概念与实战技巧,帮助你快速掌握关键要点。让我们开始吧! 网页端嵌入 Agent 对接前端方案 1. 引言 当前前端项目正从被动展示走向主动交互,AI Agent 嵌入网页端可自动化 UI 操作、优化布局并辅助编码。…...

【ElevenLabs潮州话语音实战指南】:20年语音AI专家亲授3大落地陷阱与5步合规部署法

更多请点击: https://kaifayun.com 第一章:ElevenLabs潮州话语音技术全景概览 ElevenLabs 作为全球领先的语音合成平台,长期聚焦于高保真、多语言、情感化TTS技术研发。尽管其官方公开支持的语言列表尚未正式纳入潮州话(Teochew&…...

AI安全——实战敏感词汇绕过手法

一、前言 在今年大概 6 月份的时候,煮波在一些公众号以及 src 平台上看到了一个船新漏洞——AI 漏洞,后面更是看到了应运而生的所谓《ai 魔咒》,随着人工智能的兴起,一些学校或者机构或者平台都部署了 AI,有些 AI 虽然…...

CANN 推理引擎深度解析:从模型加载到执行结果的全流程追踪

一、ACL 推理引擎架构 1.1 整体架构 ACL(Ascend Compute Language)是昇腾的推理运行时框架,负责模型加载和执行。其核心组件包括:模型加载器(Model Loader)、内存管理器(Memory Manager&#xf…...

基于“点击化学”的聚合物荧光标记定制合成

当化学成为“纽带”:基于点击化学的聚合物荧光标记定制合成关于我们的定制在生物医学成像与材料科学的前沿研究中,获得一种既能稳定发光、又能精准标记目标分子的探针,往往是实验成功的关键。我们专注于为客户提供基于点击化学的聚合物荧光标…...

蒙古语AI语音落地难?ElevenLabs最新v3.2模型支持率提升至98.7%,但90%开发者忽略这5个编码陷阱

更多请点击: https://intelliparadigm.com 第一章:蒙古语AI语音落地的现实困境与技术拐点 蒙古语作为中国少数民族语言中使用人口较多、语法高度黏着、音系复杂的阿尔泰语系代表,其AI语音技术长期受限于低资源特性——标准语音数据集不足50小…...

RISC-V指令类型及核心功能解析

RV32I指令集通过六种基本指令格式(R、I、S、B、U、J)实现其核心功能,其中U型指令主要用于长立即数加载,而R、I、S、B、J型指令则承担了计算、访存、控制流等关键操作。根据博客内容提供的指令映射表(表2.3)…...

合同系统功能详解:相对方管理

上一期,我们讲解了合同系统的业务功用。本期开始,我们将逐一对合同系统的核心功能进行拆解,结合实际业务场景展开详细讲解。今天,我们重点介绍合同系统中的相对方管理功能。 在实际业务落地过程中,不同企业的经营业态…...

注塑行业的数智化突围:告别“黑盒”生产,拥抱透明化管理新纪元

在从“经验驱动”向“数据驱动”的关键跃迁中,注塑成型作为典型的离散制造环节,其数字化转型的痛点尤为尖锐。盘古信息基于近二十年的行业深耕,依托其自主研发的IMS工软底座,为注塑行业带来了一套完整的数智化破局方案&#xff0c…...

共聚焦vs触针 :表面粗糙度测量原理及ISO25178兼容性分析

表面粗糙度测量是精密制造和质量控制的核心环节,直接影响产品耐磨性、摩擦性能及使用寿命。在工业和科研应用中,准确测量Ra参数不仅保证零件性能稳定,还满足ISO25178标准和ISO4287标准等国际标准要求。传统触针仪器虽然精度高,但操…...

【仅剩72小时】ElevenLabs希腊文语音v2.4.1热更新前瞻:首次支持Cypriot方言变体,附迁移兼容性速查表

更多请点击: https://codechina.net 第一章:ElevenLabs希腊文语音v2.4.1热更新核心概览 ElevenLabs v2.4.1 版本针对希腊文(Greek)语音合成能力进行了深度热更新,显著提升了音素对齐精度、语调自然度及方言兼容性。本…...

大模型不再“一本正经地胡说八道”!揭秘RAG如何让AI「有据可查」

RAG(Retrieval-Augmented Generation)是一种结合信息检索与文本生成的AI架构,通过让大语言模型在回答问题前先查找外部知识库,有效缓解幻觉问题,并确保答案基于最新、专有数据。RAG通过文档切块、向量嵌入、向量检索和…...

从模糊到微距级细节:Midjourney纹理生成的6层提示结构法(工业级纹理资产生产标准)

更多请点击: https://kaifayun.com 第一章:从模糊到微距级细节:Midjourney纹理生成的6层提示结构法(工业级纹理资产生产标准) 在游戏、影视与工业设计领域,高质量纹理资产需同时满足物理可信性、UV可平铺性…...

5月22日截止报名!重庆农商行2026求职报名+备考解读

本文涵盖:重庆农村商业银行2026招聘报名时间、重庆农商行笔试内容、重庆农商行面试真题、在线刷题等备考信息小职划重点!重庆农村商业银行2026招聘,报名截止时间为2026年5月22日17:00① 招聘流程:报名→在线测评→资格审查→测试→…...

利用python计算

#题1:11/21/31/4...1/100sum1 0for i in range(1, 101):sum1 1 / iprint("题1结果:", sum1)# 题2:计算1 - 1/2 1/3 - 1/4 ... 1/nn 100 sum2 0for i in range(1, n1):# 奇数项加,偶数项减if i % 2 1:sum2 1 / ielse:sum2…...

本地能跑线上崩?MonkeyCode统一云端环境解决团队开发噩梦

行内深耕多年,深知绝大多数程序员都被开发环境问题绊住前行脚步,几大行业通病几乎人人都遇见过。换新设备就得全盘重搭开发环境,新电脑到手没空敲代码,反倒整日忙着安装各类工具、调配环境变量、适配项目依赖,耗费大把…...

ViMax 为什么会冲上 GitHub Trending:AI 视频生成开始从“出片”转向“制片”

今天刷 GitHub Trending 时,ViMax 这项目很难不注意到。它挂着 674 stars today 的当日热度,标题写得也很直接:Agentic Video Generation,导演、编剧、制片、视频生成一体化。真正让我觉得它值得写,不只是因为它又是一…...

焦度计的柱镜值是怎么算出来的

项目一直卡在柱镜值的准确性和重复性这里,柱镜值究竟要怎么写代码才能算出来啊?...