MTK Linux DRM分析(十九)- KMS drm_framebuffer.c

发布于:2025-08-29 ⋅ 阅读:(12) ⋅ 点赞:(0)

一、drm_framebuffer分析

代码主要作用分析

drm_framebuffer.c 是 Linux 内核 DRM(Direct Rendering Manager)子系统的一部分,主要负责管理帧缓冲区(Frame Buffer,简称 FB)。帧缓冲区是抽象的内存对象,用于存储像素数据,供显示控制器(CRTC)扫描输出到显示设备。它是 DRM 内核模式设置(KMS)功能的核心组件之一,允许用户空间通过特定的 ioctl 接口创建、配置和操作帧缓冲区。

主要功能:
  1. 帧缓冲区创建与管理
    • 提供接口(如 drm_mode_addfb 和 drm_mode_addfb2)以创建帧缓冲区,支持单平面和多平面格式(通过 drm_mode_fb_cmd2 结构)。
    • 验证帧缓冲区参数(如分辨率、像素格式、修饰符等),确保符合硬件和驱动的要求。
    • 通过引用计数管理帧缓冲区的生命周期(如 drm_framebuffer_get 和 drm_framebuffer_put)。
  2. 帧缓冲区操作
    • 支持查询帧缓冲区信息(drm_mode_getfb 和 drm_mode_getfb2)。
    • 支持移除帧缓冲区(drm_mode_rmfb),包括从活动使用中移除并释放资源。
    • 支持刷新帧缓冲区(drm_mode_dirtyfb),用于手动更新显示设备(如 USB 显示链接或 EDP 自刷新面板)。
  3. 与硬件的交互
    • 帧缓冲区依赖底层的内存管理器(如 GEM 或 TTM)来分配存储空间。
    • 支持像素格式转换、修饰符(modifier)处理(如 Samsung 特定 tiling 格式)以及多平面帧缓冲区。
  4. 调试与信息输出
    • 提供调试接口(drm_framebuffer_debugfs_init)用于在调试文件系统中输出帧缓冲区信息。
    • 通过 DRM_DEBUG_KMS 宏记录调试信息,便于开发者诊断问题。
  5. 原子模式设置支持
    • 支持原子模式设置(atomic modeset),通过 atomic_remove_fb 函数在移除帧缓冲区时更新相关 CRTC 和平面状态。
    • 提供传统(非原子)模式设置的兼容实现(legacy_remove_fb)。
关键数据结构:
  • struct drm_framebuffer:表示帧缓冲区对象,包含宽度、高度、像素格式、修饰符、引用计数等信息。
  • struct drm_mode_fb_cmd 和 struct drm_mode_fb_cmd2:用户空间传递的帧缓冲区创建参数。
  • struct drm_format_info:描述像素格式的元数据,如平面数量、子采样等。

主要函数分析

以下是代码中的主要函数及其作用:

  1. drm_framebuffer_check_src_coords
    • 作用:检查源坐标(src_x, src_y, src_w, src_h)是否在帧缓冲区的边界内。
    • 参数
      • src_x, src_y:源区域的起点坐标(以 16.16 固定点格式)。
      • src_w, src_h:源区域的宽度和高度。
      • fb:帧缓冲区对象。
    • 返回值:0 表示有效,-ENOSPC 表示坐标超出边界。
    • 用途:确保源坐标合法,防止扫描输出超出帧缓冲区范围。
  2. drm_mode_addfb
    • 作用:通过旧版 ioctl(DRM_IOCTL_MODE_ADDFB)添加帧缓冲区,仅支持 RGB 格式。
    • 参数
      • dev:DRM 设备。
      • or:旧版帧缓冲区参数(drm_mode_fb_cmd)。
      • file_priv:DRM 文件句柄。
    • 实现:将旧版参数转换为新版格式(drm_mode_fb_cmd2),调用 drm_mode_addfb2。
    • 返回值:0 表示成功,负数表示错误码。
  3. drm_mode_addfb2
    • 作用:通过新版 ioctl(DRM_IOCTL_MODE_ADDFB2)添加帧缓冲区,支持多平面格式和 fourcc 像素格式。
    • 参数
      • dev:DRM 设备。
      • data:帧缓冲区参数(drm_mode_fb_cmd2)。
      • file_priv:DRM 文件句柄。
    • 实现:调用 drm_internal_framebuffer_create 创建帧缓冲区,并将其加入文件句柄的帧缓冲区列表。
    • 返回值:0 表示成功,负数表示错误码。
  4. framebuffer_check
    • 作用:验证帧缓冲区参数的合法性,包括像素格式、分辨率、修饰符、句柄等。
    • 参数
      • dev:DRM 设备。
      • r:帧缓冲区参数(drm_mode_fb_cmd2)。
    • 实现
      • 检查像素格式是否支持。
      • 验证分辨率是否有效。
      • 检查每个平面的句柄、pitch 和修饰符。
      • 针对特定修饰符(如 DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)进行额外验证。
    • 返回值:0 表示通过,负数表示错误码。
  5. drm_internal_framebuffer_create
    • 作用:核心函数,用于创建帧缓冲区对象。
    • 参数
      • dev:DRM 设备。
      • r:帧缓冲区参数(drm_mode_fb_cmd2)。
      • file_priv:DRM 文件句柄。
    • 实现
      • 验证参数(调用 framebuffer_check)。
      • 检查分辨率是否在设备配置的范围内。
      • 调用驱动提供的 fb_create 函数创建帧缓冲区。
    • 返回值:指向创建的帧缓冲区对象的指针,或错误指针。
  6. drm_mode_rmfb
    • 作用:移除指定的帧缓冲区,从活动使用中移除并释放资源。
    • 参数
      • dev:DRM 设备。
      • fb_id:帧缓冲区 ID。
      • file_priv:DRM 文件句柄。
    • 实现
      • 查找帧缓冲区并验证其归属。
      • 如果仍有引用,使用工作队列(drm_mode_rmfb_work_fn)异步移除。
      • 否则直接释放引用。
    • 返回值:0 表示成功,负数表示错误码。
  7. drm_mode_getfbdrm_mode_getfb2
    • 作用:查询帧缓冲区信息,分别支持旧版(单平面)和新版(多平面)ioctl。
    • 参数
      • dev:DRM 设备。
      • data:用户空间传递的查询结构。
      • file_priv:DRM 文件句柄。
    • 实现
      • 查找帧缓冲区。
      • 填充分辨率、像素格式、pitch 等信息。
      • 对于非主控进程,返回无效句柄(0)。
    • 返回值:0 表示成功,负数表示错误码。
  8. drm_mode_dirtyfb_ioctl
    • 作用:刷新帧缓冲区的受损区域(clip rectangles),用于手动更新显示。
    • 参数
      • dev:DRM 设备。
      • data:包含 clip 矩形列表的结构。
      • file_priv:DRM 文件句柄。
    • 实现
      • 验证 clip 矩形数量和格式。
      • 调用帧缓冲区的 dirty 回调函数进行刷新。
    • 返回值:0 表示成功,负数表示错误码。
  9. drm_framebuffer_init
    • 作用:初始化帧缓冲区对象,分配 ID 并加入设备的管理列表。
    • 参数
      • dev:DRM 设备。
      • fb:帧缓冲区对象。
      • funcs:帧缓冲区操作函数集。
    • 实现
      • 设置帧缓冲区的函数集和任务名称。
      • 将帧缓冲区加入设备的模式配置列表。
    • 返回值:0 表示成功,负数表示错误码。
  10. drm_framebuffer_remove
    • 作用:从所有 CRTC 和平面中移除帧缓冲区,并释放引用。
    • 参数
      • fb:帧缓冲区对象。
    • 实现
      • 如果设备支持原子模式设置,调用 atomic_remove_fb。
      • 否则调用 legacy_remove_fb。
      • 最后释放帧缓冲区的引用。
    • 用途:在帧缓冲区移除或驱动卸载时清理资源。
  11. drm_framebuffer_cleanup
    • 作用:从设备的管理列表中移除帧缓冲区。
    • 参数
      • fb:帧缓冲区对象。
    • 实现:从设备的帧缓冲区列表中移除并更新计数。
  12. drm_framebuffer_debugfs_init
    • 作用:初始化调试文件系统接口,输出所有帧缓冲区的信息。
    • 参数
      • minor:DRM 次设备。
    • 实现:注册调试文件,调用 drm_framebuffer_info 输出信息。
drm_mode_addfb_ioctl
   └── drm_mode_addfb
       └── drm_mode_addfb2
           └── drm_internal_framebuffer_create
               ├── framebuffer_check
               │   ├── fb_plane_width
               │   ├── fb_plane_height
               │   ├── drm_get_format_info
               │   └── __drm_format_info
               └── dev->mode_config.funcs->fb_create

drm_mode_addfb2_ioctl
   └── drm_mode_addfb2
       └── drm_internal_framebuffer_create
           ├── framebuffer_check
           │   ├── fb_plane_width
           │   ├── fb_plane_height
           │   ├── drm_get_format_info
           │   └── __drm_format_info
           └── dev->mode_config.funcs->fb_create

drm_mode_rmfb_ioctl
   └── drm_mode_rmfb
       ├── drm_framebuffer_lookup
       │   └── __drm_mode_object_find
       ├── drm_framebuffer_put
       └── drm_mode_rmfb_work_fn (异步)
           ├── drm_dbg_kms
           └── drm_framebuffer_remove
               ├── atomic_remove_fb (原子模式设置)
               │   ├── drm_modeset_lock_all_ctx
               │   ├── drm_atomic_get_plane_state
               │   ├── drm_atomic_add_affected_connectors
               │   ├── drm_atomic_set_mode_for_crtc
               │   ├── drm_atomic_set_fb_for_plane
               │   ├── drm_atomic_set_crtc_for_plane
               │   ├── drm_atomic_commit
               │   ├── trace_android_vh_atomic_remove_fb
               │   └── drm_modeset_backoff
               ├── legacy_remove_fb (传统模式设置)
               │   ├── drm_modeset_lock_all
               │   ├── drm_crtc_force_disable
               │   └── drm_plane_force_disable
               └── drm_framebuffer_put

drm_mode_getfb
   ├── drm_framebuffer_lookup
   │   └── __drm_mode_object_find
   ├── fb->funcs->create_handle
   └── drm_framebuffer_put

drm_mode_getfb2_ioctl
   ├── drm_framebuffer_lookup
   │   └── __drm_mode_object_find
   ├── drm_gem_handle_create
   ├── fb->funcs->create_handle
   ├── drm_gem_handle_delete
   └── drm_framebuffer_put

drm_mode_dirtyfb_ioctl
   ├── drm_framebuffer_lookup
   │   └── __drm_mode_object_find
   ├── copy_from_user
   ├── fb->funcs->dirty
   ├── kfree
   └── drm_framebuffer_put

drm_fb_release
   ├── drm_framebuffer_put
   └── drm_mode_rmfb_work_fn
       ├── drm_dbg_kms
       └── drm_framebuffer_remove
           ├── atomic_remove_fb
           │   ├── drm_modeset_lock_all_ctx
           │   ├── drm_atomic_get_plane_state
           │   ├── drm_atomic_add_affected_connectors
           │   ├── drm_atomic_set_mode_for_crtc
           │   ├── drm_atomic_set_fb_for_plane
           │   ├── drm_atomic_set_crtc_for_plane
           │   ├── drm_atomic_commit
           │   ├── trace_android_vh_atomic_remove_fb
           │   └── drm_modeset_backoff
           ├── legacy_remove_fb
           │   ├── drm_modeset_lock_all
           │   ├── drm_crtc_force_disable
           │   └── drm_plane_force_disable
           └── drm_framebuffer_put

drm_framebuffer_init
   ├── __drm_mode_object_add
   └── drm_mode_object_register

drm_framebuffer_free
   ├── drm_mode_object_unregister
   └── fb->funcs->destroy

drm_framebuffer_cleanup
   └── list_del

drm_framebuffer_lookup
   └── __drm_mode_object_find

drm_framebuffer_remove
   ├── atomic_remove_fb
   │   ├── drm_modeset_lock_all_ctx
   │   ├── drm_atomic_get_plane_state
   │   ├── drm_atomic_add_affected_connectors
   │   ├── drm_atomic_set_mode_for_crtc
   │   ├── drm_atomic_set_fb_for_plane
   │   ├── drm_atomic_set_crtc_for_plane
   │   ├── drm_atomic_commit
   │   ├── trace_android_vh_atomic_remove_fb
   │   └── drm_modeset_backoff
   ├── legacy_remove_fb
   │   ├── drm_modeset_lock_all
   │   ├── drm_crtc_force_disable
   │   └── drm_plane_force_disable
   └── drm_framebuffer_put

drm_framebuffer_debugfs_init
   └── drm_debugfs_create_files
       └── drm_framebuffer_info
           ├── drm_seq_file_printer
           ├── drm_for_each_fb
           └── drm_framebuffer_print_info
               ├── drm_printf_indent
               ├── drm_framebuffer_plane_width
               ├── drm_framebuffer_plane_height
               └── drm_gem_print_info

总结

drm_framebuffer.c 是 DRM 框架中用于管理帧缓冲区的核心模块,提供创建、移除、查询和刷新帧缓冲区的功能。它通过用户空间的 ioctl 接口与内核交互,支持原子和传统模式设置,并通过引用计数和锁机制确保线程安全。函数调用图展示了主要函数之间的依赖关系,核心逻辑围绕 drm_internal_framebuffer_create 和 drm_framebuffer_remove,并通过 framebuffer_check 确保参数合法性。调试功能和多平面支持进一步增强了其灵活性,适用于现代显示设备和驱动程序。


网站公告

今日签到

点亮在社区的每一天
去签到