一、简介

在 Linux DRM(Direct Rendering Manager)子系统中,Plane(平面)代表了一个图像源,可以在扫描输出过程中与 CRTC 混合或叠加显示。每个 Plane 从 drm_framebuffer 中获取输入数据,并负责图像的裁剪、缩放、旋转等变换,最终显示在 CRTC 代表的显示区域上。

Plane 分为三种类型:

  • Primary Plane:主平面,通常用于显示主内容,每个 CRTC 必须有一个主平面。

  • Cursor Plane:光标平面,用于显示硬件光标。

  • Overlay Plane:覆盖平面,用于额外的叠加层(如视频播放)。

二、代码分析

1. drm_plane.c

这是 DRM 核心中 Plane 的主要实现文件,包含了 Plane 的创建、初始化、销毁、属性管理等核心功能。

主要函数及作用:
函数名作用
drm_universal_plane_init初始化一个通用 Plane 对象
__drm_universal_plane_init内部函数,实际执行 Plane 初始化
drmm_universal_plane_alloc分配并初始化一个受 DRM 管理的 Plane
drm_plane_cleanup清理 Plane 资源,不释放结构体本身
drm_plane_force_disable强制禁用 Plane(非原子模式)
drm_mode_setplane处理 DRM_IOCTL_MODE_SETPLANE ioctl
drm_mode_cursor_ioctl处理光标设置 ioctl
drm_mode_page_flip_ioctl处理页面翻转 ioctl
drm_plane_enable_fb_damage_clips启用 Framebuffer 损伤区域属性
drm_plane_create_scaling_filter_property创建缩放滤波器属性

2. drm_plane_helper.c

这个文件提供了一些过渡性的辅助函数,主要用于传统(非原子)模式下的 Plane 操作,帮助驱动逐步迁移到原子模式。

主要函数及作用:
函数名作用
drm_primary_helper_update用于主 Plane 的更新操作(传统模式)
drm_primary_helper_disable用于主 Plane 的禁用操作(传统模式)
drm_primary_helper_destroy用于主 Plane 的销毁操作
drm_plane_helper_check_update检查 Plane 更新参数是否有效
drm_universal_plane_init()-> __drm_universal_plane_init()-> drm_mode_object_add()-> create_in_format_blob()-> drm_object_attach_property() [多次]drm_mode_setplane()-> drm_plane_find()-> drm_framebuffer_lookup()-> setplane_internal()-> __setplane_internal() 或 __setplane_atomic()drm_mode_cursor_ioctl()-> drm_mode_cursor_common()-> drm_mode_cursor_universal()-> __setplane_internal() 或 __setplane_atomic()drm_mode_page_flip_ioctl()-> drm_crtc_find()-> drm_framebuffer_lookup()-> crtc->funcs->page_flip() 或 crtc->funcs->page_flip_target()drm_primary_helper_update()-> drm_plane_helper_check_update()-> crtc->funcs->set_config()drm_primary_helper_disable()-> 返回 -EINVAL(表示需驱动自己实现)drm_primary_helper_destroy()-> drm_plane_cleanup()-> kfree(plane)
  • drm_plane.c 是 Plane 的核心实现,包含生命周期管理、属性控制、IOCTL 处理等。

  • drm_plane_helper.c 提供传统模式下的辅助函数,主要用于过渡期。

  • 现代 DRM 驱动应优先使用原子模式,逐步弃用传统辅助函数。

  • Plane 的类型、格式、修饰符、损伤区域、缩放滤波等属性都由这些函数管理。

drm_plane_helper.c 和 drm_plane.c 代码分析

这两个文件是 Linux 内核 DRM (Direct Rendering Manager) 子系统中与平面 (Plane) 管理相关的核心组件。平面是 DRM KMS (Kernel Mode Setting) 框架中的关键抽象,用于表示图像源,可以在扫描输出过程中与 CRTC (Cathode Ray Tube Controller) 混合或叠加。它们与 GPU 的显示硬件密切相关,支持裁剪、缩放、旋转和 Z 位置等属性。

  • drm_plane_helper.c:这是一个辅助库文件,提供主平面 (Primary Plane) 的实现支持,以及从遗留接口向原子 (Atomic) 接口的过渡函数。文件强调驱动应逐步迁移到原子接口,而这些辅助函数是过渡性的。它处理主平面的更新、禁用和销毁,并与 CRTC 和连接器交互。版权从 2014 年 Intel 开始,主要用于简化驱动开发,但注释警告新驱动不应依赖这些过渡性辅助。
  • drm_plane.c:这是平面管理的核心文件,实现平面的初始化、属性管理、损伤跟踪 (Damage Tracking) 和用户空间接口 (如 ioctl)。它定义了平面的类型 (主平面、覆盖平面、游标平面),支持修改器 (Modifiers) 和原子模式设置。文件处理平面与帧缓冲区 (Framebuffer) 的关联、标准属性 (如 IN_FORMATS、type) 和遗留 ioctl(如光标和页面翻转)。版权从 2016 年 Intel 开始,强调驱动必须为所有平面设置修改器支持。

这些文件紧密协作:drm_plane_helper.c 依赖 drm_plane.c 中的平面结构和函数(如 drm_plane_cleanup),而 drm_plane.c 提供更底层的平面管理。它们与 GPU 相关,因为平面操作直接映射到 GPU 的硬件平面(如 Intel 的 Universal Planes 或 AMD 的 Overlay),涉及缓冲区格式、修改器和原子更新。

关键函数分析

以下列出两个文件中需要注意和熟悉的关键函数。这些函数是导出的(EXPORT_SYMBOL),常用于驱动实现钩子、初始化或用户空间交互。重点关注:

  • 初始化和清理函数:用于设置平面对象。
  • 更新和检查函数:处理平面状态变化,与原子模式设置相关。
  • 属性管理函数:暴露给用户空间的属性,如损伤剪辑或缩放过滤。
  • ioctl 和遗留支持:处理用户空间请求,如光标移动或页面翻转。
  • 辅助迭代器:用于损伤处理。

我使用表格分类,便于阅读。每个函数包括描述、为什么重要(注意点)和在哪个文件定义。

函数名文件描述为什么需要注意和熟悉
drm_plane_helper_check_updatedrm_plane_helper.c检查平面更新的有效性,包括源/目标矩形、旋转、缩放和可见性,使用 drm_atomic_helper_check_plane_state。这是更新平面前的关键验证函数,确保硬件约束(如缩放范围、位置)。在过渡性驱动中常用,错误可能导致显示异常。熟悉它能帮助调试原子状态检查。
drm_primary_helper_updatedrm_plane_helper.c更新主平面,包括设置模式、连接器和帧缓冲区。调用 CRTC 的 set_config 并处理可见性。主平面是 CRTC 启用必需的,此函数桥接遗留 set_config 接口。注意它不调用 drm_mode_set_config_internal,以避免额外引用计数。迁移到原子接口时需替换。
drm_primary_helper_disabledrm_plane_helper.c禁用主平面,返回 -EINVAL(因为主平面通常不可禁用)。简单但重要:防止用户空间禁用主平面,导致 CRTC 失效。熟悉以理解遗留接口的限制。
drm_primary_helper_destroydrm_plane_helper.c销毁主平面,调用 drm_plane_cleanup 并释放内存。CRTC 销毁时调用,确保平面正确清理。导出函数,驱动常用作销毁钩子。注意内存管理(kfree)。
drm_primary_helper_funcsdrm_plane_helper.c主平面的函数表,包括 update、disable 和 destroy 钩子。这是主平面的标准回调表。驱动通过此表注册钩子。熟悉以实现自定义主平面行为。
drm_universal_plane_initdrm_plane.c初始化通用平面对象,包括分配格式、修改器、属性附件(如 type、IN_FORMATS)。核心初始化函数,所有平面创建必须调用。注意修改器支持(必须设置,即使仅线性)和类型(Primary/Overlay/Cursor)。导出,驱动广泛使用;警告:使用 drmm_ 版本以支持管理资源。
__drm_universal_plane_initdrm_plane.cdrm_universal_plane_init 的内部变体,支持 va_list 命名。内部实现,处理平面名称格式化。熟悉以理解初始化细节,如格式计数限制(<=64)。
drm_plane_enable_fb_damage_clipsdrm_plane.c启用 FB_DAMAGE_CLIPS 属性,允许用户空间指定损伤矩形。损伤跟踪的关键函数,提高虚拟设备效率(如网络传输)。注意:必须显式启用,否则属性不可用。导出,用于优化驱动。
drm_plane_get_damage_clips_countdrm_plane.c返回 FB_DAMAGE_CLIPS 中的矩形数量。简单计数器,但重要于处理用户空间损伤提示。熟悉以迭代损伤区域,避免全平面更新。
drm_plane_get_damage_clipsdrm_plane.c返回 FB_DAMAGE_CLIPS 中的 &drm_mode_rect 数组。获取用户空间损伤矩形。注意坐标是非固定点的(不像 src),且驱动可读取更多区域。导出,与 drm_atomic_helper_damage_iter_* 协作使用。
drm_plane_create_scaling_filter_propertydrm_plane.c创建 SCALING_FILTER 属性,支持默认/最近邻过滤。暴露缩放过滤给用户空间。注意支持掩码(必须包括 DEFAULT)。导出,用于高级缩放硬件的驱动。
drm_mode_cursor_ioctldrm_plane.c处理遗留光标 ioctl,包括设置/移动光标。用户空间光标控制入口。处理遗留和原子模式,支持热区。注意与 drm_mode_cursor2_ioctl 的兼容。
drm_mode_cursor2_ioctldrm_plane.c扩展光标 ioctl,支持热区 (hot_x/hot_y)。与 drm_mode_cursor_ioctl 类似,但添加热区。熟悉以支持旧应用(如 X Server)。
drm_mode_page_flip_ioctldrm_plane.c处理页面翻转,包括目标 VBlank 和事件。核心翻转函数,确保缓冲区切换原子性。注意标志(如 ASYNC)和目标序列。导出,驱动必须实现 CRTC 的 page_flip 钩子。
drm_plane_cleanupdrm_plane.c (隐式引用)清理平面资源,包括列表移除和内存释放。销毁钩子的核心。注意在 drm_primary_helper_destroy 中调用。熟悉以避免内存泄漏。
注意事项和熟悉建议
  • 迁移到原子接口:两个文件强调从遗留(如 set_config)迁移到原子(如 atomic_check/atomic_update)。关键函数如 drm_primary_helper_update 是过渡性的,新驱动应避免。
  • 属性和修改器:IN_FORMATS 和 FB_DAMAGE_CLIPS 是标准属性。熟悉 create_in_format_blob(内部函数),它构建修改器 blob。修改器支持是强制性的,即使仅线性格式。
  • 原子状态:函数如 drm_plane_helper_check_update 与 drm_atomic_helper_* 协作。熟悉 drm_plane_state 和 drm_crtc_state,以处理缩放/旋转。
  • 遗留支持:ioctl 函数(如 drm_mode_cursor_ioctl)处理旧 uAPI。注意与原子模式的混合使用警告(e.g., 不要混用遗留 ioctl 和原子提交)。
  • 错误处理:许多函数返回 -EINVAL/-ENOMEM/-EOPNOTSUPP。注意 WARN_ON(如格式计数 >64)和 drm_modeset_lock 以确保线程安全。
  • GPU 联系:这些函数间接调用驱动的钩子(如 format_mod_supported),映射到 GPU 硬件平面。熟悉 drm_plane_funcs 和 drm_plane_helper_funcs 以自定义硬件行为。
  • 文档和注释:文件有详细 DOC 部分,解释平面类型、属性和损伤。阅读以理解用户空间交互。

在 Linux 内核的 DRM (Direct Rendering Manager) 子系统中,FB_DAMAGE_CLIPS 和 SCALING_FILTER 是与显示平面(Plane)相关的标准属性,定义在 drm_plane.c 中,用于用户空间(如 Wayland、X Server)配置 GPU 显示行为。这两个属性与 GPU 的硬件功能密切相关,分别用于优化显示更新和控制图像缩放质量。以下是对这两个属性的详细解释,包括其定义、用途、实现和使用场景。


1. FB_DAMAGE_CLIPS 属性

定义
  • 属性名称:FB_DAMAGE_CLIPS
  • 类型:Blob 属性,包含一组 drm_mode_rect 结构,表示帧缓冲区(Framebuffer)中的损伤区域(Damage Regions)。
  • 作用:允许用户空间指定帧缓冲区中自上次更新以来发生变化的区域(即“损伤”区域),以优化 GPU 的显示更新。
  • 相关代码
    • 定义在 include/drm/drm_plane.h 和 drm_plane.c 的 DOC: damage tracking 部分。
    • 关键函数:
      • drm_plane_enable_fb_damage_clips:启用该属性。
      • drm_plane_get_damage_clips_count:返回损伤矩形数量。
      • drm_plane_get_damage_clips:返回损伤矩形数组。
      • 辅助迭代器:drm_atomic_helper_damage_iter_init 和 drm_atomic_helper_damage_iter_next(在 drm_atomic_helper.c)。
理解
  • 什么是损伤(Damage)
    • 损伤是指帧缓冲区中自上次平面更新(或页面翻转,Page Flip)以来发生变化的区域。例如,在桌面环境中,只有窗口移动或内容更新的区域需要重新绘制。
    • FB_DAMAGE_CLIPS 是一个提示(Hint),用户空间(如 Wayland 合成器)通过提供损伤矩形告诉内核哪些区域需要更新,减少不必要的渲染或数据传输。
  • 数据结构
    • 属性值是一个 Blob,包含 drm_mode_rect 数组,每个矩形定义为:

      c

      struct drm_mode_rect {__s32 x1, y1; // 左上角坐标(包含)__s32 x2, y2; // 右下角坐标(不包含)};

    • 坐标基于帧缓冲区(非固定点格式,区别于 drm_plane_state.src 的 16.16 固定点格式),不能为负值。
    • 矩形可以重叠,但文档强烈建议避免重叠以提高效率。
  • 用途
    • 优化性能:对于虚拟化或远程显示设备(如 USB 显示器、网络传输),只更新损伤区域可显著减少数据传输量。例如,VirtIO-GPU 使用损伤跟踪优化帧更新。
    • GPU 渲染效率:GPU 可以仅处理损伤区域的像素,降低渲染负载,节省功耗。
    • 用户空间控制:Wayland 等合成器通过 FB_DAMAGE_CLIPS 提供精确的更新区域,确保高效的显示刷新。
  • 实现细节
    • 驱动通过 drm_plane_enable_fb_damage_clips 启用该属性:

      c

      void drm_plane_enable_fb_damage_clips(struct drm_plane *plane) {struct drm_device *dev = plane->dev;struct drm_mode_config *config = &dev->mode_config;drm_object_attach_property(&plane->base, config->prop_fb_damage_clips, 0);}

    • 用户空间通过 DRM_IOCTL_MODE_OBJ_SETPROPERTY 设置 FB_DAMAGE_CLIPS,传递 Blob ID。
    • 内核验证 Blob 数据并提供迭代器(如 drm_atomic_helper_damage_iter_next)让驱动访问损伤矩形,剪裁到 drm_plane_state.src。
    • 驱动可选择全平面更新(忽略损伤)或仅更新损伤区域,但必须保证用户空间渲染整个可见区域,否则可能导致显示错误。
  • 注意事项
    • 可选性:FB_DAMAGE_CLIPS 是可选属性,未启用时驱动执行全平面更新。
    • 正确性:用户空间必须提供准确的损伤区域,否则可能导致显示内容丢失(如未包含实际变化区域)。
    • 驱动自由度:驱动可以读取超过损伤区域的内容(为效率或硬件限制),但用户空间需渲染整个帧缓冲区以避免潜在错误。
    • 调试:drm_plane_get_damage_clips 包含警告,检查是否调用 drm_plane_enable_fb_damage_clips:
      if (!drm_mode_obj_find_prop_id(&state->plane->base, config->prop_fb_damage_clips->base.id))drm_warn_once(dev, "drm_plane_enable_fb_damage_clips() not called\n");

  • 使用场景
    • 虚拟显示设备(如 QEMU 的 VirtIO-GPU)通过损伤跟踪减少网络传输。
    • 高性能 GPU(如 Intel、AMD)在多平面合成中优化渲染。
    • 嵌入式设备(如 Rockchip)在低功耗场景下减少显示更新开销。

2. SCALING_FILTER 属性

定义
  • 属性名称:SCALING_FILTER
  • 类型:枚举属性,支持的过滤器类型包括 DRM_SCALING_FILTER_DEFAULT 和 DRM_SCALING_FILTER_NEAREST_NEIGHBOR。
  • 作用:允许用户空间指定平面缩放时使用的过滤算法,控制 GPU 硬件缩放的质量。
  • 相关代码
    • 定义在 drm_plane.c 的 drm_create_scaling_filter_prop 和 drm_plane_create_scaling_filter_property。
    • 关键函数:
      • drm_create_scaling_filter_prop:创建枚举属性。
      • drm_plane_create_scaling_filter_property:为平面附加属性。
理解
  • 什么是缩放过滤
    • 当平面的源矩形(src_w、src_h)与目标矩形(crtc_w、crtc_h)大小不同时,GPU 需要缩放图像。缩放过滤器决定如何插值像素,影响图像质量。
    • 支持的过滤器:
      • DRM_SCALING_FILTER_DEFAULT:驱动默认的缩放算法(通常是线性插值或硬件优化)。
      • DRM_SCALING_FILTER_NEAREST_NEIGHBOR:最近邻插值,适合像素化效果(如游戏)。
  • 数据结构
    • 属性是一个枚举类型,值从 drm_prop_enum_list 获取:
      static const struct drm_prop_enum_list props[] = {{ DRM_SCALING_FILTER_DEFAULT, "Default" },{ DRM_SCALING_FILTER_NEAREST_NEIGHBOR, "Nearest Neighbor" },};
    • 驱动通过 supported_filters 位掩码指定支持的过滤器,必须包括 DEFAULT。
  • 用途
    • 图像质量控制:用户空间(如 Wayland 合成器)可以选择适合场景的缩放算法。例如,视频播放可能选择平滑的线性插值,而像素艺术游戏可能选择最近邻以保留锐利边缘。
    • 硬件优化:某些 GPU(如 Intel Skylake+)支持硬件缩放过滤,SCALING_FILTER 允许驱动利用这些功能。
    • 用户体验:提供一致的缩放行为,适配不同显示分辨率或缩放比例。
  • 实现细节
    • 驱动通过 drm_plane_create_scaling_filter_property 启用属性:
      int drm_plane_create_scaling_filter_property(struct drm_plane *plane,unsigned int supported_filters) {struct drm_property *prop = drm_create_scaling_filter_prop(plane->dev, supported_filters);if (IS_ERR(prop))return PTR_ERR(prop);drm_object_attach_property(&plane->base, prop, DRM_SCALING_FILTER_DEFAULT);plane->scaling_filter_property = prop;return 0;}

    • 用户空间通过 DRM_IOCTL_MODE_OBJ_SETPROPERTY 设置过滤器值。
    • 驱动在 drm_plane_funcs->atomic_check 或 atomic_update 中处理过滤器,配置 GPU 硬件的缩放寄存器。
    • supported_filters 必须包含 DRM_SCALING_FILTER_DEFAULT,否则返回 -EINVAL:
      if (WARN_ON((supported_filters & ~valid_mode_mask) ||((supported_filters & BIT(DRM_SCALING_FILTER_DEFAULT)) == 0)))return ERR_PTR(-EINVAL);
  • 注意事项
    • 硬件依赖:不是所有 GPU 支持多种缩放过滤器。例如,嵌入式 GPU 可能仅支持默认过滤器。
    • 默认值:属性默认值为 DRM_SCALING_FILTER_DEFAULT,确保兼容性。
    • 驱动实现:驱动必须在 atomic_check 中验证过滤器是否与硬件兼容,否则返回 -EINVAL。
    • 调试:检查 supported_filters 位掩码,确保只包含有效值(当前仅支持 DEFAULT 和 NEAREST_NEIGHBOR)。
  • 使用场景
    • 高分辨率显示(如 4K 屏幕)缩放低分辨率内容时,选择高质量过滤器。
    • 游戏或像素艺术应用选择最近邻过滤器以保留清晰像素。
    • 嵌入式设备(如手机)在缩放 UI 时优化性能和质量。

比较与联系

属性FB_DAMAGE_CLIPSSCALING_FILTER
类型Blob(drm_mode_rect 数组)枚举(DEFAULT、NEAREST_NEIGHBOR)
用途优化更新区域,减少 GPU 渲染/传输控制缩放算法,优化图像质量
启用函数drm_plane_enable_fb_damage_clipsdrm_plane_create_scaling_filter_property
用户空间交互通过 DRM_IOCTL_MODE_OBJ_SETPROPERTY 设置 Blob ID通过 DRM_IOCTL_MODE_OBJ_SETPROPERTY 设置枚举值
硬件依赖依赖 GPU 的损伤处理能力(如 VirtIO-GPU)依赖 GPU 的缩放硬件(如 Intel、AMD)
性能影响减少渲染/传输量,适合虚拟显示影响缩放质量和性能,适合高分辨率显示
  • 联系
    • 两者都是平面属性,通过 drm_object_attach_property 附加到 drm_plane。
    • 都在原子模式设置中起作用,用户空间通过 DRM_IOCTL_MODE_ATOMIC 配置。
    • 都依赖 GPU 硬件支持,驱动通过 drm_plane_funcs 的钩子(如 atomic_check)验证。
  • 区别
    • FB_DAMAGE_CLIPS 聚焦于优化更新区域,适合网络/低功耗场景;SCALING_FILTER 聚焦于图像质量,适合动态缩放场景。
    • FB_DAMAGE_CLIPS 是 Blob,处理复杂区域;SCALING_FILTER 是简单枚举,选择预定义算法。

使用建议

  • 用户空间开发
    • 使用 libdrm 获取和设置这些属性。确保检查驱动是否支持(通过 DRM_CAP_ADDFB2_MODIFIERS 或属性存在性)。
    • 对于 FB_DAMAGE_CLIPS,合成器需精确计算损伤区域,避免遗漏导致显示错误。
    • 对于 SCALING_FILTER,根据应用需求(如视频 vs 游戏)选择合适的过滤器。
  • 驱动开发
    • 启用 FB_DAMAGE_CLIPS 时,使用 drm_atomic_helper_damage_iter_* 迭代损伤区域,映射到 GPU 硬件的更新逻辑。
    • 实现 SCALING_FILTER 时,在 atomic_check 中验证过滤器支持,配置硬件缩放寄存器。
    • 检查硬件手册(如 Intel 或 AMD 的显示引擎文档)以确认支持的损伤/缩放功能。
  • 调试
    • 使用 DRM_DEBUG_KMS 日志检查属性设置是否正确。
    • 验证 FB_DAMAGE_CLIPS 的矩形坐标是否有效(非负,x2/y2 独占)。
    • 确保 SCALING_FILTER 的 supported_filters 包含 DEFAULT。

总结

  • FB_DAMAGE_CLIPS:一个 Blob 属性,允许用户空间指定帧缓冲区的变化区域,优化 GPU 渲染和传输效率,特别适合虚拟化或低功耗场景。驱动可选择性更新区域,但用户空间需渲染完整帧缓冲区。
  • SCALING_FILTER:一个枚举属性,控制平面缩放的过滤算法,影响图像质量,适合高分辨率或特定视觉需求(如游戏)。驱动必须支持默认过滤器并验证硬件兼容性。

两者通过 drm_plane.c 的函数暴露给用户空间,与 GPU 的显示硬件(如缩放单元、DMA 引擎)直接交互。

三、Android应用层到DRM Plane的流程

1. Android 与 DRM 的交互位置

在 Android 上,SurfaceFlinger / HWC(Hardware Composer HAL) 并不会直接写寄存器去驱动显示,而是通过内核 DRM/KMS 驱动 提供的 ioctl 接口 来完成显存分配、模式设置、atomic 提交等操作。

这些 ioctl 入口大部分在 drivers/gpu/drm/drm_ioctl.cdrivers/gpu/drm/drm_mode_object.c 中实现,核心接口是 drm_mode_* 系列。


2. drm_ioctl.c 里和 Android 相关的 ioctl

关键 ioctl(用户态可调用,HWC/Gralloc 会用到的)包括:

  • 资源查询类

    • DRM_IOCTL_MODE_GETRESOURCES → 获取 CRTC / Connector / Encoder 列表

    • DRM_IOCTL_MODE_GETCRTC / DRM_IOCTL_MODE_GETCONNECTOR / DRM_IOCTL_MODE_GETENCODER → 查询硬件资源状态

  • 缓冲区管理类(Gralloc)

    • DRM_IOCTL_MODE_CREATE_DUMB → 创建 dumb buffer(简单 framebuffer,用于测试或 fallback)

    • DRM_IOCTL_PRIME_FD_TO_HANDLE / DRM_IOCTL_PRIME_HANDLE_TO_FD → buffer 共享(dma-buf 机制),Android Gralloc 常用

  • 显示模式 / 原子操作类(HWC)

    • DRM_IOCTL_MODE_SETCRTC → legacy 模式设置

    • DRM_IOCTL_MODE_PAGE_FLIP → 翻页显示(传统方式)

    • DRM_IOCTL_MODE_ATOMIC原子操作接口(HWC2 通常走这个)


3. Android HWC / Gralloc 与 DRM 的对应关系

  • Gralloc HAL

    • 负责分配显存 buffer,一般通过 GBM (Generic Buffer Manager) 或 Ion/DMABUF 分配,再通过 PRIME fd 传给 DRM

    • ioctl 重点是 CREATE_DUMB, PRIME_*

  • HWC HAL

    • 负责控制显示输出(overlay 组合、VSync、显示提交)

    • 早期 Android 使用 SETCRTC + PAGE_FLIP,现在多数厂商实现 HWC2 时会调用 DRM_IOCTL_MODE_ATOMIC 来提交 plane/crtc/connector 的设置


4. DRM 四大对象的 ioctl 操作对应关系

你提到的 CRTC / Connector / Encoder / Plane 这四类对象,在 DRM 内核里都继承自 drm_mode_object,最终都可以通过 drm_mode_* ioctl 系列操作:

  • CRTC(显示控制器) → DRM_IOCTL_MODE_GETCRTC, SETCRTC, ATOMIC

  • Connector(面板/接口,比如 HDMI, DSI) → DRM_IOCTL_MODE_GETCONNECTOR, ATOMIC

  • Encoder(桥接器,CRTC 到 Connector 的转换逻辑) → DRM_IOCTL_MODE_GETENCODER

  • Plane(图层,Primary/Overlay/Cursor) → DRM_IOCTL_MODE_GETPLANE, ATOMIC

最终 Android HWC 调用 atomic 提交时,是把一组 对象 + 属性值(crtc_id, connector_id, plane_id 以及对应的 fb_id, src/dst rect, mode_id 等)一次性传到内核 → drm_mode_atomic_ioctl() → 内核再调用具体厂商驱动的 atomic_check / atomic_commit 来落地。


✅ 总结:
是的,Android 操作 DRM 主要是通过 drm_ioctl.c 中的 drm_mode_* ioctl 来实现对 crtc / connector / encoder / plane 的操作。

  • Gralloc → 侧重 buffer 分配 + PRIME fd handle

  • HWC → 侧重 DRM_IOCTL_MODE_ATOMIC 原子提交

四、Android DRM历史

1. 背景:Android 显示栈

在 Android 中,显示子系统大概分三层:

  • Gralloc (Graphics Allocator HAL)
    用于分配 GPU/显示 buffer(显存或系统内存中的显存缓冲区),供 SurfaceFlinger、HWC 等使用。

  • HWC (Hardware Composer HAL)
    负责把多个 Layer 合成,最终交给显示控制器(Display Controller / DRM)显示。

  • SurfaceFlinger
    Android 的合成服务,决定哪些图层由 GPU 合成,哪些交给 HWC。

Android 8.0 开始强制 HWC2 接口,Android 10 开始引入 drm_hwcomposer,直接基于 DRM/KMS。


2. DRM Atomic 操作

Linux DRM/KMS 提供两种模式:

  1. Legacy API(早期接口,如 drmModeSetCrtc()

    • 不支持原子性,单独设置 plane/crtc/connector。

  2. Atomic APIDRM_IOCTL_MODE_ATOMIC

    • 支持一次性提交所有显示属性(plane、crtc、connector),保证硬件配置原子更新。

    • 适合 Android 这种多层 buffer 合成的场景。


3. Android HWC 是否使用 DRM Atomic?

是的,现代 Android 的 HWC 主要使用 Atomic API,理由是:

  • 一致性:合成时需要同时更新多个 plane,如果用 legacy API,可能出现 tearing(撕裂)或中间状态。

  • 性能优化:Atomic 支持 非阻塞提交 (async commit)fence (release/acquire fence),这正好对应 Android HWC/Gralloc 的同步机制。

  • 多显示器支持:Atomic 可以一次提交多个 CRTC 的配置,适合手机 + 外接显示。

具体实现:

  • Android AOSP 有一个 drm_hwcomposer 项目(android_hardware_libhardware/drm_hwcomposer)。

  • 它在底层调用 DRM Atomic API 来实现:

    drmModeAtomicReq *req = drmModeAtomicAlloc(); 
    drmModeAtomicAddProperty(req, plane_id, FB_ID, fb_id); 
    drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, data);
  • 这就把 HWC2 的 presentDisplay() 映射到 DRM atomic commit。


4. Gralloc 和 DRM 的关系

  • Gralloc 本身不直接使用 atomic,它主要负责 buffer 分配和 handle/fd 管理(通常基于 GBM 或 ION/DMABUF)。

  • 但是分配的 buffer 会传给 HWC,HWC 在调用 drmModeAtomicCommit 时使用这些 buffer。

  • 因此 Gralloc → HWC → DRM Atomic 形成完整链路。


5. 小结

  • HWC:是 Atomic 的直接用户,通过 drm_hwcomposer 使用 DRM Atomic API

  • Gralloc:不直接调用 DRM Atomic,只是提供 buffer(fd/dmabuf),最终由 HWC 交给 DRM。

  • Android 从 Android 10 开始全面切换到 Atomic 模式,之前部分平台可能混用 legacy API。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/93925.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/93925.shtml
英文地址,请注明出处:http://en.pswp.cn/web/93925.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenHarmony之 蓝牙子系统全栈剖析:从协议栈到芯片适配的端到端实践(大合集)

1. 系统架构概述 OpenHarmony蓝牙系统采用分层架构设计&#xff0c;基于HDF&#xff08;Hardware Driver Foundation&#xff09;驱动框架和系统能力管理&#xff08;System Ability&#xff09;机制实现。 1.1 架构层次 ┌─────────────────────────…

探索 Ultralytics YOLOv8标记图片

1、下载YOLOv8模型文件 下载地址&#xff1a;https://docs.ultralytics.com/zh/models/yolov8/#performance-metrics 2、编写python脚本 aaa.py import cv2 import numpy as np from ultralytics import YOLO import matplotlib.pyplot as pltdef plot_detection(image, box…

Matplotlib数据可视化实战:Matplotlib子图布局与管理入门

Matplotlib多子图布局实战 学习目标 通过本课程的学习&#xff0c;学员将掌握如何在Matplotlib中创建和管理多个子图&#xff0c;了解子图布局的基本原理和调整方法&#xff0c;能够有效地展示多个数据集&#xff0c;提升数据可视化的效果。 相关知识点 Matplotlib子图 学习内容…

【python实用小脚本-194】Python一键给PDF加水印:输入文字秒出防伪文件——再也不用开Photoshop

Python一键给PDF加水印&#xff1a;输入文字秒出防伪文件——再也不用开Photoshop PDF加水印, 本地脚本, 零会员费, 防伪标记, 瑞士军刀 故事开场&#xff1a;一把瑞士军刀救了投标的你 周五下午&#xff0c;你把 100 页标书 PDF 发给客户&#xff0c;却担心被同行盗用。 想加水…

开源 C++ QT Widget 开发(四)文件--二进制文件查看编辑

文章的目的为了记录使用C 进行QT Widget 开发学习的经历。临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 C QT Widget 开发&#xff08;一&#xff09;工程文件结构-CSDN博客 开源 C…

【密码学实战】X86、ARM、RISC-V 全量指令集与密码加速技术全景解析

前言 CPU 指令集是硬件与软件交互的核心桥梁&#xff0c;其设计直接决定计算系统的性能边界与应用场景。在数字化时代&#xff0c;信息安全依赖密码算法的高效实现&#xff0c;而指令集扩展则成为密码加速的 “隐形引擎”—— 从服务器端的高吞吐量加密&#xff0c;到移动端的…

2025-08-21 Python进阶2——数据结构

文章目录1 列表&#xff08;List&#xff09;1.1 列表常用方法1.2 列表的特殊用途1.2.1 实现堆栈&#xff08;后进先出&#xff09;1.2.2 实现队列&#xff08;先进先出&#xff09;1.3 列表推导式1.4 嵌套列表推导式2 del 语句3 元组&#xff08;Tuple&#xff09;4 集合&…

告别手工编写测试脚本!Claude+Playwright MCP快速生成自动化测试脚本

在进行自动化测试时&#xff0c;前端页面因为频繁迭代UI 结构常有变动&#xff0c;这往往使得自动化测试的脚本往往“写得快、废得也快”&#xff0c;维护成本极高。在大模型之前大家往往都会使用录制类工具&#xff0c;但录制类工具生成的代码灵活性较差、定位方式不太合理只能…

一款更适合 SpringBoot 的API文档新选择(Spring Boot 应用 API 文档)

SpringDoc&#xff1a;Spring Boot 应用 API 文档生成的现代化解决方案 概述 SpringDoc 是一个专为 Spring Boot 应用设计的开源库&#xff0c;能够自动生成符合 OpenAPI 3 规范的 API 文档。它通过扫描项目中的控制器、方法注解及相关配置&#xff0c;动态生成 JSON/YAML/HTML…

文献阅读 250821-When and where soil dryness matters to ecosystem photosynthesis

When and where soil dryness matters to ecosystem photosynthesis 来自 <When and where soil dryness matters to ecosystem photosynthesis | Nature Plants> ## Abstract: Background: Projected increases in the intensity and frequency of droughts in the twen…

React学习(九)

目录&#xff1a;1.react-进阶-antd-新增2.react-进阶-antd-删除选中1.react-进阶-antd-新增新增代码&#xff0c;跟需改的代码类似&#xff0c;直接copy修改组件代码进行修改userEffect可以先带着&#xff0c;没啥用A6组件用到的函数跟修改的也类似&#xff1a;这个useEffect函…

零基础从头教学Linux(Day 17)

三层交换机一、三层交换机的配置1.关于如何配置三层交换机&#xff0c;首先我们应该先创建VLANSwitch>en Switch#vlan database % Warning: It is recommended to configure VLAN from config mode,as VLAN database mode is being deprecated. Please consult userdocument…

任务十四 推荐页面接口开发

一、接口准备 在对接qq音乐接口之前,首先要将之前的项目,一定要记得备份一份; 备份完成之后,首先要在vscode终端安装axios,这个是请求后端的工具,和之前的ajax一样,都是请求后端的工具。只不过axios更专业化,跟强大 至于qq音乐接口怎么获取,一般有两个途径,第一个是…

医疗AI与医院数据仓库的智能化升级:异构采集、精准评估与高效交互的融合方向(下)

核心功能创新详解: 统一门户与角色化工作台: 统一入口: 用户通过单一URL登录,系统根据其角色和权限自动呈现专属工作台。 角色化工作台: 临床医生工作台: 首屏展示常用患者查询入口、快速统计(如“我的患者检验异常趋势”)、相关临床文献推荐、待处理任务(如报告审核)…

数据库面试常见问题

数据库 Delete Truncate Drop 区别 答:这三个操作都是针对数据库的表进行操作,都有删除表的功能,其中的区别在于: Delete:只将表中的数据进行删除,不删除定义不释放空间,是dml语句,需要提交事务,如果不想删除可以回滚。delete每次删除一行,并在事务日志中为所删除…

用nohup setsid绕过超时断连,稳定反弹Shell

在We渗透过程中&#xff0c;我们常常会利用目标系统的远程代码执行&#xff08;RCE&#xff09;漏洞进行反弹Shell。然而&#xff0c;由于Web服务器&#xff08;如PHP、Python后端&#xff09;的执行环境通常存在超时限制&#xff08;如max_execution_time或进程管理策略&#…

Java设计模式-模板方法模式

Java设计模式-模板方法模式 模式概述 模板方法模式简介 核心思想&#xff1a;定义一个操作中的算法骨架&#xff08;模板方法&#xff09;&#xff0c;将算法中某些步骤的具体实现延迟到子类中完成。子类可以在不改变算法整体结构的前提下&#xff0c;重定义这些步骤的行为&…

Centos7物理安装 Redis8.2.0

Centos7物理安装 Redis8.2.0一、准备依赖环境首先安装编译 Redis 所需的依赖&#xff1a;# CentOS/RHEL系统 yum install -y gcc gcc-c make wget 二、下载并编译 Redis 8.2.0# 1. 下载Redis 8.2.0源码包 wget https://download.redis.io/releases/redis-8.2.0.tar.gz# 2. 解压…

牛津大学xDeepMind 自然语言处理(3)

条件语言模型无条件语言模型 概率计算&#xff1a;通过链式法则分解为预测下一词概率&#xff08;将语言建模问题简化为建模给定前面词语历史的下一个词的概率&#xff09;基于循环神经网络的无条件语言模型&#xff1a;根据历史词语预测下一个词的概率条件语言模型 定义&#…

Vue2.x核心技术与实战(一)

目录 一、Vue2.x:快速上手+插值表达式+指令上 1.1 Vue快速上手 1.1.1 Vue概念 1.1.2 创建实例 1.1.3 插值表达式 { { }} 1.1.4 响应式特性 1.1.5 开发者工具 1.2 Vue指令 1.2.1 v-html 1.2.3 v-show / v-if v-show v-if 1.2.4 v-else / v-else-if 1.2.5 v-on v…