MTK Linux DRM分析(七)- KMS drm_plane.c

一、簡介

在 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…