使用者介面

DRM 核心嚮應用程式匯出幾個介面,通常旨在透過相應的 libdrm 包裝函式使用。此外,驅動程式匯出特定於裝置的介面,供使用者空間驅動程式和裝置感知應用程式透過 ioctl 和 sysfs 檔案使用。

外部介面包括:記憶體對映、上下文管理、DMA 操作、AGP 管理、垂直消隱控制、柵欄管理、記憶體管理和輸出管理。

在此處涵蓋通用 ioctl 和 sysfs 佈局。我們只需要高階資訊,因為手冊頁應涵蓋其餘部分。

libdrm 裝置查詢

當心惡龍!注意陷阱!

為了警告其他試圖弄清楚這裡發生了什麼的人,我將嘗試總結一下這個故事。首先,讓我們理清名稱,因為核心內部、libdrm 和 ioctl 的命名都不同

  • 由 drm_getunique 實現的 GET_UNIQUE ioctl 透過 drmGetBusid 函式包裝在 libdrm 中。

  • libdrm drmSetBusid 函式由 SET_UNIQUE ioctl 支援。所有這些程式碼都在核心中透過 drm_invalid_op() 廢棄。

  • 內部 set_busid 核心函式和驅動程式回撥僅由 SET_VERSION ioctl 使用,因為只有 drm 1.0(已廢棄)允許使用者空間透過上述 ioctl 設定 busid。

  • 涉及的其他 ioctl 和函式的命名一致。

對於任何想知道 drm 1.1 和 1.4 之間區別的人:正確處理 ppc 上 busid 中的 pci 域。正確執行此操作僅在 2010 年的 libdrm 中實現,因此還不能廢棄。沒有人知道 drm 1.2 和 1.3 有什麼特別之處。

現在講述 drm 中裝置查詢的實際恐怖故事。總的來說,有兩種不同的方法,一種是透過 busid,另一種是透過裝置驅動程式名稱。

透過 busid 開啟非常簡單

  1. 首先呼叫 SET_VERSION 以確保正確處理 pci 域。作為副作用,這會在主結構中填寫唯一名稱。

  2. 呼叫 GET_UNIQUE 以從主結構中讀取唯一名稱,由於步驟 1,該名稱與 busid 匹配。如果不匹配,請繼續嘗試下一個裝置節點。

透過名稱開啟略有不同

  1. 直接呼叫 VERSION 以獲取版本並與該 ioctl 返回的驅動程式名稱匹配。請注意,未呼叫 SET_VERSION,這意味著剛開啟的主節點的唯一名稱_未_填寫。儘管當前的 drm 裝置節點始終繫結到一個裝置,並且不能像 drm 1.0 那樣在執行時分配。

  2. 匹配驅動程式名稱。如果不匹配,請繼續下一個裝置節點。

  3. 呼叫 GET_UNIQUE,並檢查唯一名稱的長度是否為零(透過檢查字串中的第一個位元組是否為 0)。如果不是這種情況,libdrm 將跳過並繼續下一個裝置節點。可能這只是從 drm 1.0 時代複製貼上過來的,當時設定的唯一名稱意味著驅動程式已在使用中,但這只是猜測。

長話短說:為了保持按名稱開啟邏輯的工作,當尚未呼叫 SET_VERSION 時,GET_UNIQUE 必須_不_返回唯一字串,否則 libdrm 會中斷。即使該唯一字串永遠無法更改,並且對於實際開啟裝置完全無關緊要,因為執行時可分配裝置例項僅在 drm 1.0 中支援,而 drm 1.0 早已消亡。但是 drmOpenByName 中的 libdrm 程式碼以某種方式倖存下來,因此不能破壞它。

主節點、DRM Master 和身份驗證

struct drm_master 用於跟蹤具有開啟的主裝置節點的客戶端組。對於每個至少一次成功成為裝置主裝置的 struct drm_file(透過 SET_MASTER IOCTL 或在當前沒有其他主裝置時隱式透過開啟主裝置節點),都存在一個 struct drm_master。這在 drm_file.is_master 中註明。所有其他客戶端只有一個指向與其關聯的 drm_master 的指標。

此外,只有一個 drm_master 可以是 drm_device 的當前主裝置。可以透過 DROP_MASTER 和 SET_MASTER IOCTL 或隱式透過關閉/開啟主裝置節點來切換它。另請參見 drm_is_current_master()

客戶端可以使用 GETMAGIC 和 AUTHMAGIC IOCTL 對當前主裝置(如果它匹配它們自己的)進行身份驗證。與交換主裝置一起,這允許對整個相互信任的客戶端組進行受控訪問裝置。

bool drm_is_current_master(struct drm_file *fpriv)

檢查 priv 是否為當前主裝置

引數

struct drm_file *fpriv

DRM 檔案私有資料

描述

檢查 fpriv 是否為其裝置上的當前主裝置。這決定了是否允許客戶端執行 DRM_MASTER IOCTL。

大多數需要 DRM_MASTER 的現代 IOCTL 用於核心模式設定 - 當前主裝置被假定為擁有不可共享的顯示硬體。

struct drm_master *drm_master_get(struct drm_master *master)

引用主裝置指標

引數

struct drm_master *master

struct drm_master

描述

遞增 master 的引用計數並返回指向 master 的指標。

struct drm_master *drm_file_get_master(struct drm_file *file_priv)

引用 file_privdrm_file.master

引數

struct drm_file *file_priv

DRM 檔案私有資料

描述

遞增 file_privdrm_file.master 的引用計數並返回 drm_file.master。如果 file_priv 沒有 drm_file.master,則返回 NULL。

從此函式返回的主裝置指標應使用 drm_master_put() 取消引用。

void drm_master_put(struct drm_master **master)

取消引用並清除主裝置指標

引數

struct drm_master **master

指向 struct drm_master 指標的指標

描述

這會遞減 master 後面的 drm_master 並將其設定為 NULL。

struct drm_master

drm 主裝置結構

定義:

struct drm_master {
    struct kref refcount;
    struct drm_device *dev;
    char *unique;
    int unique_len;
    struct idr magic_map;
    void *driver_priv;
    struct drm_master *lessor;
    int lessee_id;
    struct list_head lessee_list;
    struct list_head lessees;
    struct idr leases;
    struct idr lessee_idr;
};

成員

refcount

此主裝置物件的引用計數。

dev

連結回 DRM 裝置

unique

唯一識別符號:例如 busid。受 drm_device.master_mutex 保護。

unique_len

唯一欄位的長度。受 drm_device.master_mutex 保護。

magic_map

已使用的身份驗證令牌的對映。受 drm_device.master_mutex 保護。

driver_priv

指向驅動程式私有資訊的指標。

lessor

租賃授予者,僅當此 struct drm_master 表示持有來自 lessor 的物件租賃的承租人時才設定。裝置的完整所有者將其設定為 NULL。

一旦在 drm_lease_create() 中設定了出租人,出租人就不會更改,每個承租人都會持有對其出租人的引用,並在 drm_lease_destroy() 中銷燬時釋放該引用。

另請參見 關於顯示資源租賃的部分

lessee_id

承租人的 ID。所有者(即 lessor 為 NULL)始終具有 ID 0。受 drm_device.mode_configdrm_mode_config.idr_mutex 保護。

lessee_list

lessor 的承租人的列表條目,他們在其中連結到 lessees。不適用於所有者。受 drm_device.mode_configdrm_mode_config.idr_mutex 保護。

lessees

從此租賃的 drm_masters 列表。受 drm_device.mode_configdrm_mode_config.idr_mutex 保護。

如果沒有授予租賃,或者所有承租人都已被銷燬,則此列表為空。由於出租人被其所有承租人引用,因此除非列表為空,否則無法銷燬此主裝置。

leases

租賃給此 drm_master 的物件。受 drm_device.mode_configdrm_mode_config.idr_mutex 保護。

物件在 drm_lease_create() 中一起租賃,並在撤銷租賃時一起刪除。

lessee_idr

此所有者下的所有承租人(僅在 lessor 為 NULL 時使用)。受 drm_device.mode_configdrm_mode_config.idr_mutex 保護。

描述

請注意,主裝置結構僅與舊版/主裝置節點相關,因此每個裝置只能有一個,而不是每個 drm_minor 有一個。

DRM 顯示資源租賃

DRM 租賃提供有關 DRM 主裝置是否可以控制 DRM 模式設定物件的資訊。這使得可以建立管理顯示資源子集的多個 DRM 主裝置。

裝置的原始 DRM 主裝置“擁有”可用的 drm 資源。它可以建立額外的 DRM 主裝置並“租賃”它控制的資源給新的 DRM 主裝置。這使新的 DRM 主裝置可以控制租賃的資源,直到所有者撤銷租賃或關閉新的 DRM 主裝置。一些有用的術語

  • “所有者”是一個 struct drm_master,它不從另一個 struct drm_master 租賃物件,因此“擁有”物件。所有者可以識別為 struct drm_master,對於該 drm_master.lessor 為 NULL。

  • “出租人”是一個 struct drm_master,它將物件租賃給一個或多個其他 struct drm_master。目前,不允許承租人建立子租賃,因此出租人與所有者相同。

  • “承租人”是一個 struct drm_master,它從其他 struct drm_master 租賃物件。每個承租人僅從 drm_master.lessor 中記錄的單個出租人租賃資源,並在 drm_master.leases 中儲存其租賃的物件集。

  • “租賃”是出租人和承租人之間的合同,用於標識承租人可以控制哪些資源。租賃的所有資源必須由出租人擁有或租賃給出租人,並且不允許出租人將同一物件租賃給多個承租人。

任何 struct drm_master “控制”的物件集僅限於其租賃的物件集(對於承租人)或所有物件(對於所有者)。

不受 struct drm_master 控制的物件無法透過各種狀態操作 ioctl 修改,並且報告給使用者空間的任何狀態都將被編輯,使其看起來空閒和/或無法使用。例如,聯結器始終報告“已斷開連線”,而編碼器報告沒有可能的 crtc 或克隆。

由於每個承租人都可以從單個出租人租賃物件,因此顯示資源租賃形成 struct drm_master 樹。由於當前不允許承租人建立子租賃,因此樹深度限制為 1。所有這些都在頂級裝置所有者透過 SETMASTER 或 DROPMASTER IOCTL 更改時同時啟用,因此 drm_device.master 指向租賃樹頂部的所有者(即 struct drm_master,對於該 drm_master.lessor 為 NULL)。可以透過所有者的 drm_master.lessee_idr 搜尋從所有者租賃物件的完整承租人列表。

開源使用者空間要求

對於新的 uAPI 需要什麼樣的使用者空間端,DRM 子系統比大多數其他核心子系統具有更嚴格的要求。本節介紹了這些要求的具體內容以及它們存在的原因。

簡短的總結是,新增任何 DRM uAPI 都需要相應的開源使用者空間補丁,並且這些補丁必須經過審查並準備好合併到合適的和規範的上游專案中。

GFX 裝置(顯示和渲染/GPU 側)是非常複雜的硬體,使用者空間和核心必須緊密協作。渲染和模式設定的介面必須非常廣泛和靈活,因此幾乎不可能為每種可能的極端情況精確定義它們。反過來,這使得實際上幾乎不可能區分使用者空間要求的行為(必須不更改以避免迴歸)和僅是當前實現偶然產物的行為。

如果沒有訪問所有使用者空間使用者的完整原始碼,這意味著不可能更改實現細節,因為使用者空間可能會在細節上依賴於當前實現的偶然行為。並且在沒有訪問原始碼的情況下除錯此類迴歸幾乎是不可能的。因此,這意味著

  • Linux 核心的“無迴歸”策略實際上僅適用於 DRM 子系統的開源使用者空間。如果使用者空間中的閉源 blob 驅動程式使用與開源驅動程式相同的 uAPI,DRM 開發人員完全可以接受,但它們必須以與開源驅動程式完全相同的方式執行此操作。創造性地(濫)用介面將導致破壞,並且在過去經常導致破壞。

  • 任何新的使用者空間介面都必須具有一個開源實現作為演示工具。

需要開源使用者空間的另一個原因是 uAPI 審查。由於 GFX 堆疊的核心和使用者空間部分必須緊密協作,因此程式碼審查只能透過檢視雙方來評估新介面是否實現了其目標。確保介面確實完全涵蓋了用例導致了一些額外的要求

  • 開源使用者空間必須不是玩具/測試應用程式,而是真實的東西。具體來說,它需要處理所有常見的錯誤和極端情況。這些通常是新的 uAPI 分崩離析的地方,因此對於評估擬議介面的適用性至關重要。

  • 使用者空間端必須經過充分審查和測試,以符合該使用者空間專案的標準。例如,mesa 這意味著 piglit 測試用例和郵件列表上的審查。這再次是為了確保新介面實際上完成了工作。使用者空間側審查員還應在核心 uAPI 補丁上提供 Acked-by,表明他們認為擬議的 uAPI 是合理的,並且經過充分記錄和驗證以供使用者空間使用。

  • 使用者空間補丁必須針對規範上游,而不是某些供應商分支。這是為了確保沒有人透過進行快速分支來作弊審查和測試要求。

  • 核心補丁只有在滿足上述所有要求後才能合併,但它_必須_在使用者空間補丁落地_之前_合併到 drm-next 或 drm-misc-next 中。uAPI 始終從核心流出,以另一種方式做事會冒著 uAPI 定義和標頭檔案分歧的風險。

這些都是相當嚴格的要求,但多年來,人們對匆忙新增的 uAPI 積累了共同的痛苦和經驗,並且幾乎總是很快就後悔了。GFX 裝置變化非常快,至少每隔幾年就需要進行正規化轉變和全新的 uAPI 介面集。連同 Linux 核心保證保持現有使用者空間執行 10 多年的保證,這對 DRM 子系統來說已經相當痛苦,同一事物存在多個不同的 uAPI。如果我們在每年的組合中再新增一些完整的錯誤,這將完全無法管理。

渲染節點

DRM 核心為使用者空間提供了多個字元裝置供使用。根據開啟的裝置,使用者空間可以執行不同的操作集(主要是 ioctl)。主節點始終建立並呼叫 card。此外,還會建立一個當前未使用的控制節點,稱為 controlD。主節點提供所有舊版操作,並且歷史上是使用者空間使用的唯一介面。透過 KMS,引入了控制節點。但是,計劃的 KMS 控制介面尚未編寫,因此控制節點至今仍未使用。

隨著螢幕外渲染器和 GPGPU 應用程式的使用增加,客戶端不再需要執行合成器或圖形伺服器來使用 GPU。但是 DRM API 要求非特權客戶端在獲得 GPU 訪問許可權之前向 DRM-Master 進行身份驗證。為了避免此步驟並授予客戶端 GPU 訪問許可權而無需進行身份驗證,引入了渲染節點。渲染節點僅服務於渲染客戶端,也就是說,無法在渲染節點上發出模式設定或特權 ioctl。僅允許非全域性渲染命令。如果驅動程式支援渲染節點,則必須透過 DRIVER_RENDER DRM 驅動程式功能來宣告它。如果不支援,則必須將主節點用於渲染客戶端以及舊版 drmAuth 身份驗證過程。

如果驅動程式聲明瞭渲染節點支援,則 DRM 核心將建立一個單獨的渲染節點,稱為 renderD。每個裝置將有一個渲染節點。除 PRIME 相關的 ioctl 外,此節點上將不允許任何 ioctl。特別是,將明確禁止 GEM_OPEN。有關可以在渲染節點上使用的獨立於驅動程式的 ioctl 的完整列表,請參見 drm_ioctl.c 中標記為 DRM_RENDER_ALLOW 的 ioctl。渲染節點旨在避免緩衝區洩漏,如果客戶端猜測舊版介面上的 flink 名稱或 mmap 偏移,則會發生緩衝區洩漏。除了此基本介面外,驅動程式還必須將其依賴於驅動程式的僅渲染 ioctl 標記為 DRM_RENDER_ALLOW,以便渲染客戶端可以使用它們。驅動程式作者必須小心不要允許渲染節點上的任何特權 ioctl。

透過渲染節點,使用者空間現在可以透過基本檔案系統訪問模式控制對渲染節點的訪問。不再需要執行在特權主節點/舊版節點上對客戶端進行身份驗證的圖形伺服器。相反,客戶端可以開啟渲染節點,並且立即獲得 GPU 訪問許可權。客戶端(或伺服器)之間的通訊透過 PRIME 完成。不支援從渲染節點到舊版節點的 FLINK。新客戶端不得使用不安全的 FLINK 介面。

除了刪除所有模式設定/全域性 ioctl 外,渲染節點還刪除了 DRM-Master 概念。沒有理由將渲染客戶端與 DRM-Master 關聯,因為它們獨立於任何圖形伺服器。此外,無論如何,它們都必須在沒有任何正在執行的主裝置的情況下工作。如果驅動程式支援渲染節點,則必須能夠在沒有主裝置物件的情況下執行。另一方面,如果驅動程式需要客戶端之間共享狀態,該狀態對使用者空間可見且可超出開啟檔案邊界訪問,則它們不支援渲染節點。

裝置熱插拔

注意

以下是計劃。實現尚未完成(2020 年 5 月)。

圖形裝置(顯示和/或渲染)可以透過 USB(例如,顯示介面卡或擴充套件塢)或 Thunderbolt(例如,eGPU)連線。終端使用者可以在使用此類裝置時熱插拔它們,並期望機器至少不會崩潰。熱插拔 DRM 裝置造成的任何損壞都需要儘可能地限制,並且必須給使用者空間處理它的機會(如果使用者空間想要這樣做)。理想情況下,拔掉 DRM 裝置仍然可以讓桌面繼續執行,但這需要在整個圖形堆疊中獲得明確的支援:從核心和使用者空間驅動程式,到顯示伺服器,再到視窗系統協議,以及應用程式和庫。

其他應該導致相同結果的情況包括:不可恢復的 GPU 崩潰、PCI 裝置從總線上消失,或者強制從物理裝置上解除繫結驅動程式。

換句話說,從使用者空間的角度來看,一切都需要或多或少地保持工作狀態,直到使用者空間停止使用消失的 DRM 裝置並完全關閉它。使用者空間將從裝置移除的 uevent、返回 ENODEV 的 ioctl(或返回驅動程式特定內容的驅動程式特定 ioctl)或返回 ENXIO 的 open() 中得知裝置消失。

只有在使用者空間關閉了所有相關的 DRM 裝置和 dmabuf 檔案描述符並移除了所有 mmaps 之後,DRM 驅動程式才能拆除其不再存在的裝置的例項。如果同一物理裝置以某種方式在中間恢復,它應該是一個新的 DRM 裝置。

與 PID 類似,字元裝置次裝置號不會立即回收。與之前分配的次裝置號相比,新的 DRM 裝置總是選擇下一個空閒的次裝置號,並在次裝置號耗盡時迴繞。

該目標至少對核心和驅動程式提出了以下要求。

KMS UAPI 的要求

  • KMS 聯結器必須將其狀態更改為已斷開連線。

  • 傳統模式設定和頁面翻轉,以及原子提交,無論是真實的還是 TEST_ONLY,以及任何其他 ioctl,要麼失敗並返回 ENODEV,要麼假裝成功。

  • 掛起的非阻塞 KMS 操作會傳遞使用者空間期望的 DRM 事件。這也適用於假裝成功的 ioctl。

  • 對底層裝置已消失的裝置節點執行 open() 將失敗並返回 ENXIO。

  • 嘗試在消失的 DRM 裝置上建立 DRM 租賃將失敗並返回 ENODEV。現有的 DRM 租賃仍然存在並按上述方式工作。

渲染和跨裝置 UAPI 的要求

  • 所有無法再執行的 GPU 作業都必須強制發出其 fence 訊號,以避免在使用者空間中造成掛起。相關的錯誤程式碼是 ENODEV。

  • 一些使用者空間 API 已經定義了裝置消失時應該發生的情況(OpenGL、GL ES:GL_KHR_robustnessVulkan:VK_ERROR_DEVICE_LOST;等等)。DRM 驅動程式可以自由地以他們認為最好的方式實現此行為,例如,在驅動程式特定的 ioctl 中返回失敗並在使用者空間驅動程式中處理這些失敗,或者依賴 uevent,等等。

  • 指向已消失記憶體的 dmabuf 要麼無法匯入並返回 ENODEV,要麼繼續成功匯入(如果它在消失之前會成功匯入)。另請參閱下面關於已匯入 dmabuf 的記憶體對映。

  • 嘗試將 dmabuf 匯入到消失的裝置將失敗並返回 ENODEV,或者如果它在沒有消失的情況下會成功匯入,則匯入將成功。

  • 對底層裝置已消失的裝置節點執行 open() 將失敗並返回 ENXIO。

記憶體對映的要求

記憶體對映有進一步的要求,這些要求適用於現有對映和裝置消失後建立的對映。如果底層記憶體消失,則建立或修改對映,以便讀取和寫入仍然可以成功完成,但結果是未定義的。這適用於使用者空間 mmap() 的記憶體和 dmabuf 指向的記憶體,dmabuf 可能對映到其他裝置(跨裝置 dmabuf 匯入)。

引發 SIGBUS 不是一個選項,因為使用者空間無法實際處理它。訊號處理程式是全域性的,這使得從 Mesa 生成的庫等庫中正確使用它們極其困難。訊號處理程式是不可組合的,你不能為來自不同供應商的 GPU1 和 GPU2 設定不同的處理程式,也不能為 mmapped 常規檔案設定第三個處理程式。執行緒也會給訊號處理帶來額外的麻煩。

裝置重置

GPU 堆疊非常複雜,並且容易出錯,從硬體錯誤、錯誤的應用程式到許多層之間的所有內容。某些錯誤需要重置裝置才能使裝置再次可用。本節描述了 DRM 和使用者模式驅動程式在裝置重置時的預期行為,以及如何傳播重置狀態。

如果不汙染核心,則無法停用裝置重置,這可能會透過收縮器/mmu_notifiers 掛起整個核心。使用者空間在裝置重置中的作用是將訊息傳播到應用程式,並應用任何特殊的策略來阻止有問題的應用程式(如果有)。推論是,除錯掛起的 GPU 上下文需要硬體支援,以便能夠在 GPU 上下文停止時搶佔它。

核心模式驅動程式

KMD 負責檢查裝置是否需要重置,並根據需要執行重置。通常,當作業執行卡住時,會檢測到掛起。

事實證明,將錯誤傳播到使用者空間非常棘手,因為它與通常的命令流方向相反。因此, vendor 獨立錯誤處理已新增到 &dma_fence 物件中,這樣驅動程式可以在發出 fence 訊號之前將錯誤程式碼新增到其 fence 中。有關如何執行此操作以及要使用的錯誤程式碼示例,請參閱函式 dma_fence_set_error()

DRM 排程程式還允許在重置後重新啟動硬體提交時,在所有掛起的 fence 上設定錯誤程式碼。錯誤程式碼還會從硬體 fence 轉發到排程程式 fence,以便將錯誤傳播到堆疊的更高層,最終到達使用者空間。

使用者空間可以透過通用 SYNC_IOC_FILE_INFO IOCTL 以及透過驅動程式特定的介面查詢 Fence 錯誤。

除了設定 fence 錯誤之外,驅動程式還應跟蹤每個上下文的重置,DRM 排程程式提供了 drm_sched_entity_error() 函式作為此用例的助手。重置後,KMD 應拒絕受影響上下文的新命令提交。

使用者模式驅動程式

提交命令後,UMD 應檢查提交是否被接受或拒絕。重置後,KMD 應拒絕提交,UMD 可以向 KMD 發出 ioctl 以檢查重置狀態,如果 UMD 需要,可以更頻繁地檢查此狀態。檢測到重置後,UMD 將使用適當的 API 錯誤程式碼將其報告給應用程式,如下面關於魯棒性的部分中所述。

魯棒性

在重置後嘗試保持圖形 API 上下文工作的唯一方法是,如果它符合它正在使用的圖形 API 的魯棒性方面。

圖形 API 為應用程式提供了處理裝置重置的方法。但是,不能保證應用程式會正確使用這些功能,並且不支援魯棒介面的使用者空間(例如非魯棒 OpenGL 上下文或沒有任何魯棒性支援的 API(如 libva))會將魯棒性處理完全留給使用者空間驅動程式。對於使用者空間驅動程式在這種情況下應該做什麼,沒有強烈的社群共識,因為所有合理的方法都有一些明顯的缺點。

OpenGL

使用 OpenGL 的應用程式應使用可用的魯棒介面,例如擴充套件 GL_ARB_robustness(或 OpenGL ES 的 GL_EXT_robustness)。此介面會告知是否發生了重置,如果是,則所有上下文狀態都被視為丟失,應用程式會透過建立新的上下文來繼續。對於不使用魯棒性的情況下該怎麼做,沒有共識。

Vulkan

使用 Vulkan 的應用程式應檢查提交的 VK_ERROR_DEVICE_LOST。此錯誤程式碼表示,除其他外,發生了裝置重置,並且需要重新建立上下文才能繼續。

報告重置原因

除了透過堆疊傳播重置以使應用程式可以恢復之外,對於驅動程式開發人員來說,更多地瞭解導致重置的原因確實非常有用。為此,驅動程式可以利用 devcoredump 來儲存有關重置的相關資訊,併發送恢復方法為 none 的裝置 wedged 事件(如“Device Wedging”一章中所述)來通知使用者空間,以便可以收集此資訊並將其新增到使用者錯誤報告中。

裝置 Wedging

驅動程式可以選擇使用裝置 wedged 事件(在 DRM 子系統中實現為 drm_dev_wedged_event()),該事件透過 uevent 通知使用者空間 DRM 裝置的“wedged”(掛起/不可用)狀態。這在裝置不再按預期執行並且從驅動程式上下文中無法恢復的情況下尤其有用。此實現的目的是為驅動程式提供一種通用方法,以在使用者空間干預的幫助下恢復裝置,而無需在驅動程式中採取任何激烈的措施(例如重置或重新列舉完整的匯流排,底層物理裝置位於其上)。

“wedged”裝置基本上是指驅動程式在耗盡所有可能的嘗試以從驅動程式上下文中恢復裝置後宣告已死的裝置。uevent 是傳送到使用者空間的通知,其中包含關於可能嘗試從使用者空間恢復裝置並使其恢復到可用狀態的提示。不同的驅動程式可能對“wedged”裝置有不同的想法,具體取決於底層物理裝置的硬體實現,因此事件是供應商不可知的。驅動程式可以自行決定何時需要裝置恢復,以及他們希望如何從可用的方法中恢復。

驅動程式先決條件

驅動程式在選擇恢復之前,需要透過注意先決條件來確保“wedged”裝置不會對整個系統造成損害。必要的措施必須包括停用 DMA 到系統記憶體以及與其他裝置的任何通訊通道。此外,驅動程式必須確保所有 dma_fences 都已發出訊號,並且核心核心可能依賴的任何裝置狀態都已清理乾淨。所有現有的 mmaps 都應該失效,並且頁面錯誤應該重定向到虛擬頁面。傳送事件後,裝置必須保持“wedged”狀態,直到執行恢復。應該拒絕新的裝置訪問(IOCTL),最好使用類似於裝置遇到的故障型別的錯誤程式碼。這將表明 wedging 的原因,如果需要,可以將其報告給應用程式。

恢復

當前的實現定義了三種恢復方法,驅動程式可以從中選擇任何一種、多種或不選擇。選擇的方法將按副作用從小到大的順序在 uevent 環境中以 WEDGED=<method1>[,..,<methodN>] 的形式傳送。如果驅動程式不確定恢復或方法未知(例如軟/硬系統重啟、韌體重新整理、物理裝置更換或任何其他無法立即嘗試的過程),則會發送 WEDGED=unknown

使用者空間消費者可以解析此事件並根據以下期望嘗試恢復。

恢復方法

消費者期望

none

可選的遙測收集

rebind

unbind + bind 驅動程式

bus-reset

unbind + 匯流排重置/重新列舉 + bind

unknown

消費者策略

唯一的例外是 WEDGED=none,它表示裝置在某個時候暫時“wedged”,但已使用裝置特定的方法(如重置)從驅動程式上下文中恢復。在這種情況下,不期望消費者進行顯式恢復,但它仍然可以採取額外的步驟,例如收集遙測資訊(devcoredump、syslog)。這很有用,因為第一次掛起通常是最關鍵的一次,它可能導致連續的掛起或完全 wedging。

消費者先決條件

消費者有責任確保在嘗試恢復之前,任何程序都沒有使用該裝置或其資源。由於 IOCTL 發生錯誤,因此應取消對映所有裝置記憶體並關閉檔案描述符,以防止洩漏或未定義的行為。這裡的想法是在事先清除裝置的所有使用者上下文,併為乾淨的恢復做好準備。

示例

Udev 規則

SUBSYSTEM=="drm", ENV{WEDGED}=="rebind", DEVPATH=="*/drm/card[0-9]",
RUN+="/path/to/rebind.sh $env{DEVPATH}"

恢復指令碼

#!/bin/sh

DEVPATH=$(readlink -f /sys/$1/device)
DEVICE=$(basename $DEVPATH)
DRIVER=$(readlink -f $DEVPATH/driver)

echo -n $DEVICE > $DRIVER/unbind
echo -n $DEVICE > $DRIVER/bind

自定義

雖然可以使用簡單的指令碼進行基本恢復,但消費者可以圍繞恢復定義自定義策略。例如,如果驅動程式支援多種恢復方法,則消費者可以根據重複違規或供應商特定的故障等情況選擇合適的方法。消費者還可以選擇使裝置可用於除錯或遙測收集,並根據調查結果做出恢復決定。當驅動程式不確定恢復或方法未知時,這尤其有用。

裝置節點上的 IOCTL 支援

首先,驅動程式私有 IOCTL 應該只需要支援渲染的驅動程式。核心模式設定已全部標準化,並透過屬性進行擴充套件。在一些現有驅動程式中存在一些例外情況,這些驅動程式定義了供顯示 DRM master 使用的 IOCTL,但它們都早於屬性。

現在,如果你有一個渲染驅動程式,你總是必須透過驅動程式私有屬性來支援它。需要幾個步驟才能連線所有內容。

首先,你需要在你驅動程式私有的 UAPI 標頭檔案 include/uapi/drm/my_driver_drm.h 中定義你的 IOCTL 的結構。

struct my_driver_operation {
        u32 some_thing;
        u32 another_thing;
};

請確保你遵循 Documentation/process/botching-up-ioctls.rst 中的所有最佳實踐。請注意,drm_ioctl() 會自動零擴充套件結構,因此請確保你可以在末尾新增更多內容,即不要在那裡放置可變大小的陣列。

然後,你需要使用 DRM_IO()、DRM_IOR()、DRM_IOW() 或 DRM_IOWR() 之一定義你的 IOCTL 編號。它必須以 DRM_IOCTL_ 字首開頭。

##define DRM_IOCTL_MY_DRIVER_OPERATION \
    DRM_IOW(DRM_COMMAND_BASE, struct my_driver_operation)

DRM 驅動程式私有 IOCTL 必須在 DRM_COMMAND_BASE 到 DRM_COMMAND_END 的範圍內。最後,你需要一個 struct drm_ioctl_desc 陣列來連線處理程式並設定訪問許可權。

static const struct drm_ioctl_desc my_driver_ioctls[] = {
    DRM_IOCTL_DEF_DRV(MY_DRIVER_OPERATION, my_driver_operation,
            DRM_AUTH|DRM_RENDER_ALLOW),
};

然後將此分配給你的驅動程式結構中的 drm_driver.ioctls 欄位。

有關驅動程式特定的 IOCTL 如何連線的詳細資訊,請參閱關於 檔案操作 的單獨章節。

測試和驗證

使用者空間 API 的測試要求

新的跨驅動程式使用者空間介面擴充套件,例如新的 IOCTL、新的 KMS 屬性、sysfs 中的新檔案或構成 API 更改的任何其他內容,如果可以使用 IGT 為目標硬體合理地進行此類測試,則應在 IGT 中針對該功能進行驅動程式不可知的測試。

使用 IGT 驗證更改

有一個測試集合旨在覆蓋 DRM 驅動程式的全部功能,並且可以用於檢查對 DRM 驅動程式或核心的更改是否會使現有功能退化。此測試套件稱為 IGT,其程式碼和構建及執行說明可以在 https://gitlab.freedesktop.org/drm/igt-gpu-tools/ 中找到。

使用 VKMS 測試 DRM API

VKMS 是一個僅軟體的 KMS 驅動程式模型,可用於測試和執行合成器。 VKMS 旨在實現虛擬顯示,而無需硬體顯示功能。這些特性使 VKMS 成為驗證 DRM 核心行為以及支援合成器開發人員的完美工具。 VKMS 使得可以在沒有顯示的虛擬機器中測試 DRM 功能,從而簡化了一些核心更改的驗證。

要使用 VKMS 驗證 DRM API 中的更改,請開始設定核心:確保啟用 VKMS 模組;使用啟用的 VKMS 編譯核心並將其安裝在目標機器中。 VKMS 可以在虛擬機器(QEMU、virtme 或類似)中執行。建議使用具有至少 1GB RAM 和四個核心的 KVM。

可以透過兩種方式在 VM 中執行 IGT 測試

  1. 在 VM 中使用 IGT

  2. 從主機使用 IGT 並將結果寫入共享目錄。

以下是使用帶有與主機共享目錄的 VM 來執行 igt-tests 的示例。此示例使用 virtme

$ virtme-run --rwdir /path/for/shared_dir --kdir=path/for/kernel/directory --mods=auto

在訪客機器中執行 igt-tests。此示例執行“kms_flip”測試

$ /path/for/igt-gpu-tools/scripts/run-tests.sh -p -s -t "kms_flip.*" -v

在此示例中,Piglit 用於代替構建 igt_runner(-p 選項)。它建立了測試結果的 HTML 摘要,並將其儲存在“igt-gpu-tools/results”資料夾中。它僅執行與 -t 選項匹配的 igt-tests。

顯示 CRC 支援

DRM 裝置驅動程式可以向用戶空間提供每個幀的 CRC 資訊,因為它到達給定的硬體元件(CRC 取樣“源”)。

使用者空間可以透過寫入 debugfs 中的 dri/0/crtc-N/crc/control 檔案來控制給定 CRTC 中 CRC 的生成,其中 N 是 CRTC 的索引。可接受的值是源名稱(驅動程式特定的)和“auto”關鍵字,這將使驅動程式為此 CRTC 選擇幀 CRC 的預設源。

一旦啟用了幀 CRC 生成,使用者空間就可以透過讀取 dri/0/crtc-N/crc/data 檔案來捕獲它們。該檔案中的每一行都包含第一個欄位中的幀編號,然後是一些包含 CRC 資料的無符號整數字段。欄位用單個空格分隔,CRC 欄位的數量是源特定的。

請注意,儘管在某些情況下,CRC 是以指定的方式並在使用者空間提供的幀內容上計算的 (eDP 1.3),但通常 CRC 計算是以未指定的方式並在已以未指定的方式處理過的幀內容上執行的,因此使用者空間無法依賴於為其提交的幀內容生成匹配的 CRC 值。在這種一般情況下,使用者空間最多可以做的是比較應該具有相同內容的幀的報告 CRC。

在驅動程式端,實現工作量是最小的,驅動程式只需要實現 drm_crtc_funcs.set_crc_sourcedrm_crtc_funcs.verify_crc_source。如果設定了這些 vfuncs,則會自動設定 debugfs 檔案。 CRC 樣本需要在驅動程式中透過呼叫 drm_crtc_add_crc_entry() 來捕獲。根據驅動程式和硬體要求,drm_crtc_funcs.set_crc_source 可能會導致提交(甚至是完整的模式設定)。

CRC 結果必須在非完整模式設定原子提交中可靠,因此如果透過 DRM_IOCTL_MODE_ATOMIC 的提交將停用或以其他方式干擾 CRC 生成,則驅動程式必須將該提交標記為完整模式設定(drm_atomic_crtc_needs_modeset() 應返回 true)。因此,為了確保一致的結果,通用使用者空間必須在傳統的 SETCRTC 或帶有 DRM_MODE_ATOMIC_ALLOW_MODESET 的原子提交後重新設定 CRC 生成。

int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame, uint32_t frame, uint32_t *crcs)

新增帶有幀 CRC 資訊的條目

引數

struct drm_crtc *crtc

幀所屬的 CRTC

bool has_frame

此條目是否具有幀編號

uint32_t frame

這些 CRC 相關的幀編號

uint32_t *crcs

CRC 值陣列,其長度與 #drm_crtc_crc.values_cnt 匹配

描述

對於每一幀,驅動程式輪詢 CRC 源以獲取新資料,並呼叫此函式將它們新增到使用者空間從中讀取的緩衝區。

Debugfs 支援

DRM_DEBUGFS_GPUVA_INFO

DRM_DEBUGFS_GPUVA_INFO (show, data)

drm_info_list 條目以轉儲 GPU VA 空間

引數

show

drm_info_list 的 show 回撥

data

驅動程式私有資料

描述

驅動程式應使用此宏來定義 drm_info_list 條目,以提供一個 debugfs 檔案來轉儲 GPU VA 空間區域和對映。

對於每個 DRM GPU VA 空間,驅動程式應從其 show 回撥中呼叫 drm_debugfs_gpuva_info()

struct drm_info_list

debugfs 資訊列表條目

定義:

struct drm_info_list {
    const char *name;
    int (*show)(struct seq_file*, void*);
    u32 driver_features;
    void *data;
};

成員

name

檔名

show

Show 回撥。 seq_file->private 將設定為 struct drm_info_node,對應於給定 struct drm_minor 上此資訊的例項。

driver_features

此條目所需的驅動程式功能

data

驅動程式私有資料,不應是裝置特定的。

描述

此結構表示要由 DRM 核心建立的 debugfs 檔案。

struct drm_info_node

每個次要節點的 debugfs 節點結構

定義:

struct drm_info_node {
    struct drm_minor *minor;
    const struct drm_info_list *info_ent;
};

成員

minor

此節點的 struct drm_minor

info_ent

此節點的模板。

描述

此結構表示 debugfs 檔案,作為 struct drm_info_liststruct drm_minor 上的例項化。

FIXME

不,我們為渲染和主節點複製 debugfs 條目並沒有太大的意義,但這就是它有機增長的方式。如果需要,應該使用相容性連結對其進行修復。

struct drm_debugfs_info

debugfs 資訊列表條目

定義:

struct drm_debugfs_info {
    const char *name;
    int (*show)(struct seq_file*, void*);
    u32 driver_features;
    void *data;
};

成員

name

檔名

show

Show 回撥。 seq_file->private 將設定為 struct drm_debugfs_entry,對應於給定 struct drm_device 上此資訊的例項。

driver_features

此條目所需的驅動程式功能。

data

驅動程式私有資料,不應是裝置特定的。

描述

此結構表示要由 DRM 核心建立的 debugfs 檔案。

struct drm_debugfs_entry

每個裝置節點的 debugfs 節點結構

定義:

struct drm_debugfs_entry {
    struct drm_device *dev;
    struct drm_debugfs_info file;
    struct list_head list;
};

成員

dev

此節點的 struct drm_device

file

此節點的模板。

list

所有裝置節點的連結串列。

描述

此結構表示 debugfs 檔案,作為 struct drm_debugfs_infostruct drm_device 上的例項化。

int drm_debugfs_gpuva_info(struct seq_file *m, struct drm_gpuvm *gpuvm)

轉儲給定的 DRM GPU VA 空間

引數

struct seq_file *m

指向要寫入的 seq_file 的指標

struct drm_gpuvm *gpuvm

表示 GPU VA 空間的 drm_gpuvm

描述

轉儲給定 DRM GPU VA 管理器的 GPU VA 對映。

對於每個 DRM GPU VA 空間,驅動程式應從其 drm_info_list 的 show 回撥中呼叫此函式。

返回

成功時為 0,如果未初始化 gpuvm 則為 -ENODEV

void drm_debugfs_create_files(const struct drm_info_list *files, int count, struct dentry *root, struct drm_minor *minor)

初始化 DRM 次要節點的給定 debugfs 檔案集

引數

const struct drm_info_list *files

要建立的檔案陣列

int count

給定的檔案數

struct dentry *root

DRI debugfs 目錄條目。

struct drm_minor *minor

裝置次要編號

描述

在給定的根目錄中建立由 struct drm_info_list 陣列表示的給定 debugfs 檔案集。這些檔案將在 drm_debugfs_dev_fini() 上自動刪除。

void drm_debugfs_add_file(struct drm_device *dev, const char *name, int (*show)(struct seq_file*, void*), void *data)

將給定的檔案新增到 DRM 裝置 debugfs 檔案列表

引數

struct drm_device *dev

ioctl 的 DRM 裝置

const char *name

debugfs 檔名

int (*show)(struct seq_file*, void*)

show 回撥

void *data

驅動程式私有資料,不應是裝置特定的

描述

將給定的檔案條目新增到 DRM 裝置 debugfs 檔案列表中,以便在 drm_debugfs_init 上建立。

void drm_debugfs_add_files(struct drm_device *dev, const struct drm_debugfs_info *files, int count)

將檔案陣列新增到 DRM 裝置 debugfs 檔案列表

引數

struct drm_device *dev

ioctl 的 DRM 裝置

const struct drm_debugfs_info *files

要建立的檔案陣列

int count

給定的檔案數

描述

將由 struct drm_debugfs_info 陣列表示的給定 debugfs 檔案集新增到 DRM 裝置 debugfs 檔案列表中。

Sysfs 支援

除了所有標準內容之外,DRM 為驅動程式提供的 sysfs 互動支援很少。想要公開其他 sysfs 屬性和屬性組的驅動程式可以將其附加到 drm_device.devdrm_connector.kdev

在呼叫 drm_dev_register()drm_connector_register()(對於熱插拔聯結器)時,會自動處理註冊。取消註冊也由 drm_dev_unregister()drm_connector_unregister() 自動處理。

void drm_sysfs_hotplug_event(struct drm_device *dev)

生成 DRM uevent

引數

struct drm_device *dev

DRM 裝置

描述

dev 指定的 DRM 裝置傳送 uevent。目前,我們僅在 uevent 環境中設定 HOTPLUG=1,但這可以擴充套件以處理其他型別的事件。

任何新的 uapi 都應該使用 drm_sysfs_connector_status_event() 來處理聯結器狀態更改的 uevent。

void drm_sysfs_connector_hotplug_event(struct drm_connector *connector)

為任何聯結器更改生成 DRM uevent

引數

struct drm_connector *connector

已更改的聯結器

描述

connector 指定的 DRM 聯結器傳送 uevent。這將傳送一個帶有屬性 HOTPLUG=1 和 CONNECTOR 的 uevent。

void drm_sysfs_connector_property_event(struct drm_connector *connector, struct drm_property *property)

為聯結器屬性更改生成 DRM uevent

引數

struct drm_connector *connector

屬性已更改的聯結器

struct drm_property *property

已更改的聯結器屬性。

描述

為指定的 DRM 聯結器和屬性發送 uevent。目前,我們設定 HOTPLUG=1 和聯結器 ID,以及與更改相關的附加屬性 ID。

int drm_class_device_register(struct device *dev)

在 DRM sysfs 類中註冊新裝置

引數

struct device *dev

要註冊的裝置

描述

在 DRM sysfs 類中註冊一個新的 struct device。本質上僅由 ttm 用於擁有其全域性設定的位置。驅動程式不應使用此功能。

void drm_class_device_unregister(struct device *dev)

從 DRM sysfs 類中登出裝置

引數

struct device *dev

要登出的裝置

描述

從 DRM sysfs 類中登出 struct device。本質上僅由 ttm 用於擁有其全域性設定的位置。驅動程式不應使用此功能。

VBlank 事件處理

DRM 核心公開兩個垂直消隱相關 ioctl

DRM_IOCTL_WAIT_VBLANK

這採用 struct drm_wait_vblank 結構作為其引數,它用於在發生指定的 vblank 事件時阻止或請求訊號。

DRM_IOCTL_MODESET_CTL

這僅用於使用者模式設定驅動程式,用於模式設定更改,以允許核心在模式設定後更新 vblank 中斷,因為在許多裝置上,垂直消隱計數器在模式設定期間的某個時間點重置為 0。現代驅動程式不應再呼叫此函式,因為使用核心模式設定,它是一個空操作。

使用者空間 API 結構

DRM 公開許多 UAPI 和結構定義,以具有與使用者的一致且標準化的介面。使用者空間可以參考這些結構定義和 UAPI 格式來與驅動程式進行通訊。

CRTC 索引

CRTC 既有物件 ID 也有索引,但它們不是同一件事。索引用於需要 CRTC 的密集打包識別符號的情況,例如 CRTC 的位掩碼。struct drm_mode_get_plane 的成員 possible_crtcs 就是一個例子。

DRM_IOCTL_MODE_GETRESOURCES 用 CRTC ID 陣列填充結構,CRTC 索引是其在此陣列中的位置。

DRM_CAP_DUMB_BUFFER

DRM_CAP_DUMB_BUFFER

描述

如果設定為 1,則驅動程式支援透過 DRM_IOCTL_MODE_CREATE_DUMB ioctl 建立啞緩衝區。

DRM_CAP_VBLANK_HIGH_CRTC

DRM_CAP_VBLANK_HIGH_CRTC

描述

如果設定為 1,則核心支援在 drm_wait_vblank_request.type 的高位中指定 CRTC 索引

從核心版本 2.6.39 開始,此功能始終設定為 1。

DRM_CAP_DUMB_PREFERRED_DEPTH

DRM_CAP_DUMB_PREFERRED_DEPTH

描述

啞緩衝區的首選位深度。

位深度是用於指示單個畫素顏色的位數,不包括任何填充。這與每個畫素的位數不同。例如,XRGB8888 的位深度為 24,但每個畫素有 32 位。

請注意,此首選項僅適用於啞緩衝區,與其他型別的緩衝區無關。

DRM_CAP_DUMB_PREFER_SHADOW

DRM_CAP_DUMB_PREFER_SHADOW

描述

如果設定為 1,則驅動程式首選使用者空間渲染到陰影緩衝區,而不是直接渲染到啞緩衝區。為了獲得最佳速度,使用者空間應執行流式有序記憶體副本到啞緩衝區中,並且永遠不要從中讀取。

請注意,此首選項僅適用於啞緩衝區,與其他型別的緩衝區無關。

DRM_CAP_PRIME

DRM_CAP_PRIME

描述

支援的 PRIME 共享功能的位欄位。請參閱 DRM_PRIME_CAP_IMPORTDRM_PRIME_CAP_EXPORT

從核心版本 6.6 開始,DRM_PRIME_CAP_IMPORTDRM_PRIME_CAP_EXPORT 始終會進行通告。

PRIME 緩衝區公開為 dma-buf 檔案描述符。請參閱 PRIME 緩衝區共享

DRM_PRIME_CAP_IMPORT

DRM_PRIME_CAP_IMPORT

描述

如果此位在 DRM_CAP_PRIME 中設定,則驅動程式支援透過 DRM_IOCTL_PRIME_FD_TO_HANDLE ioctl 匯入 PRIME 緩衝區。

從核心版本 6.6 開始,此位始終在 DRM_CAP_PRIME 中設定。

DRM_PRIME_CAP_EXPORT

DRM_PRIME_CAP_EXPORT

描述

如果此位在 DRM_CAP_PRIME 中設定,則驅動程式支援透過 DRM_IOCTL_PRIME_HANDLE_TO_FD ioctl 匯出 PRIME 緩衝區。

從核心版本 6.6 開始,此位始終在 DRM_CAP_PRIME 中設定。

DRM_CAP_TIMESTAMP_MONOTONIC

DRM_CAP_TIMESTAMP_MONOTONIC

描述

如果設定為 0,則核心將在 struct drm_event_vblank 中使用 CLOCK_REALTIME 報告時間戳。如果設定為 1,則核心將使用 CLOCK_MONOTONIC 報告時間戳。有關這些時鐘的定義,請參閱 clock_gettime(2)

從核心版本 2.6.39 開始,此功能的預設值為 1。從核心版本 4.15 開始,此功能始終設定為 1。

DRM_CAP_ASYNC_PAGE_FLIP

DRM_CAP_ASYNC_PAGE_FLIP

描述

如果設定為 1,驅動程式支援傳統頁面翻轉的 DRM_MODE_PAGE_FLIP_ASYNC

DRM_CAP_CURSOR_WIDTH

DRM_CAP_CURSOR_WIDTH

描述

CURSOR_WIDTHCURSOR_HEIGHT 功能返回硬體游標的有效寬度 x 高度組合。目的是硬體無關的使用者空間可以查詢要使用的游標平面大小。

請注意,跨驅動程式的約定僅僅是返回一個有效的大小;驅動程式可以自由地新增其他含義,例如,i915 返回最大平面大小。

DRM_CAP_CURSOR_HEIGHT

DRM_CAP_CURSOR_HEIGHT

描述

參見 DRM_CAP_CURSOR_WIDTH

DRM_CAP_ADDFB2_MODIFIERS

DRM_CAP_ADDFB2_MODIFIERS

描述

如果設定為 1,驅動程式支援在 DRM_IOCTL_MODE_ADDFB2 ioctl 中提供修飾符。

DRM_CAP_PAGE_FLIP_TARGET

DRM_CAP_PAGE_FLIP_TARGET

描述

如果設定為 1,驅動程式支援 drm_mode_crtc_page_flip_target.flagsDRM_MODE_PAGE_FLIP_TARGET_ABSOLUTEDRM_MODE_PAGE_FLIP_TARGET_RELATIVE 標誌,用於 DRM_IOCTL_MODE_PAGE_FLIP ioctl。

DRM_CAP_CRTC_IN_VBLANK_EVENT

DRM_CAP_CRTC_IN_VBLANK_EVENT

描述

如果設定為 1,核心支援在 drm_event_vblank.crtc_id 中報告 CRTC ID,用於 DRM_EVENT_VBLANKDRM_EVENT_FLIP_COMPLETE 事件。

從核心版本 4.12 開始,此功能始終設定為 1。

DRM_CAP_SYNCOBJ

DRM_CAP_SYNCOBJ

描述

如果設定為 1,驅動程式支援同步物件。參見 DRM 同步物件

DRM_CAP_SYNCOBJ_TIMELINE

DRM_CAP_SYNCOBJ_TIMELINE

描述

如果設定為 1,驅動程式支援同步物件上的時間線操作。參見 DRM 同步物件

DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP

DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP

描述

如果設定為 1,驅動程式支援原子提交的 DRM_MODE_PAGE_FLIP_ASYNC

DRM_CLIENT_CAP_STEREO_3D

DRM_CLIENT_CAP_STEREO_3D

描述

如果設定為 1,DRM 核心將透過在 struct drm_mode_modeinfo 的標誌中公佈支援的 3D 佈局來公開監視器的立體 3D 功能。參見 DRM_MODE_FLAG_3D_*

從核心版本 3.13 開始,所有驅動程式都始終支援此功能。

DRM_CLIENT_CAP_UNIVERSAL_PLANES

DRM_CLIENT_CAP_UNIVERSAL_PLANES

描述

如果設定為 1,DRM 核心會將所有平面(覆蓋、主平面和游標)公開給使用者空間。

此功能已在核心版本 3.15 中引入。從核心版本 3.17 開始,所有驅動程式都始終支援此功能。

DRM_CLIENT_CAP_ATOMIC

DRM_CLIENT_CAP_ATOMIC

描述

如果設定為 1,DRM 核心會將原子屬性公開給使用者空間。這隱式地啟用了 DRM_CLIENT_CAP_UNIVERSAL_PLANESDRM_CLIENT_CAP_ASPECT_RATIO

如果驅動程式不支援原子模式設定,啟用此功能將失敗並顯示 -EOPNOTSUPP。

此功能已在核心版本 4.0 中引入。從核心版本 4.2 開始,原子功能的驅動程式始終支援此功能。

DRM_CLIENT_CAP_ASPECT_RATIO

DRM_CLIENT_CAP_ASPECT_RATIO

描述

如果設定為 1,DRM 核心將在模式中提供縱橫比資訊。參見 DRM_MODE_FLAG_PIC_AR_*

從核心版本 4.18 開始,所有驅動程式都始終支援此功能。

DRM_CLIENT_CAP_WRITEBACK_CONNECTORS

DRM_CLIENT_CAP_WRITEBACK_CONNECTORS

描述

如果設定為 1,DRM 核心將公開特殊聯結器,用於將提交中設定的場景寫回記憶體。客戶端必須首先啟用 DRM_CLIENT_CAP_ATOMIC

從核心版本 4.19 開始,原子功能的驅動程式始終支援此功能。

DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT

DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT

描述

para 虛擬化硬體(例如 vmwgfx、qxl、virtio 和 virtualbox)的驅動程式對游標平面有額外的限制(因此使得這些驅動程式上的游標平面不是真正通用的),例如,它們需要游標平面的行為像滑鼠游標一樣,並且具有正確設定的熱點屬性。如果未設定此客戶端上限,DRM 核心將隱藏這些虛擬化驅動程式上的游標平面,因為未設定它意味著客戶端無法處理這些額外的限制。設定游標熱點並將游標平面視為滑鼠游標的客戶端應設定此屬性。客戶端必須首先啟用 DRM_CLIENT_CAP_ATOMIC

在未特殊處理游標平面的驅動程式(即非虛擬化驅動程式)上設定此屬性將返回 EOPNOTSUPP,使用者空間可以使用它來衡量其執行的硬體/驅動程式的要求。

從核心版本 6.6 開始,原子功能的虛擬化驅動程式始終支援此功能。

struct drm_syncobj_eventfd

定義:

struct drm_syncobj_eventfd {
    __u32 handle;
    __u32 flags;
    __u64 point;
    __s32 fd;
    __u32 pad;
};

成員

handle

syncobj 控制代碼。

flags

零表示等待點被髮出訊號,或者 DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE 表示等待可用於該點的柵欄。

point

syncobj 時間線點(對於二進位制 syncobjs 設定為零)。

fd

現有 eventfd 以將事件傳送到。

pad

必須為零。

描述

註冊一個 eventfd,使其被 syncobj 發出訊號。eventfd 計數器將遞增 1。

DRM_IOCTL_GEM_CLOSE

DRM_IOCTL_GEM_CLOSE

關閉 GEM 控制代碼。

描述

核心不會對 GEM 控制代碼進行引用計數。使用者空間負責管理其生命週期。例如,如果使用者空間在同一個 DRM 檔案描述符上兩次匯入同一個記憶體物件,則兩次匯入都返回同一個 GEM 控制代碼,使用者空間需要確保只執行一次 DRM_IOCTL_GEM_CLOSE。當分配一個記憶體物件,然後匯出並在同一個 DRM 檔案描述符上再次匯入時,也會發生相同的情況。DRM_IOCTL_MODE_GETFB2 IOCTL 是一個例外,即使在執行 IOCTL 之前已經存在另一個 GEM 控制代碼引用同一個記憶體物件,它也總是返回新的 GEM 控制代碼。

DRM_IOCTL_PRIME_HANDLE_TO_FD

DRM_IOCTL_PRIME_HANDLE_TO_FD

將 GEM 控制代碼轉換為 DMA-BUF FD。

描述

使用者空間使用要匯出的 GEM 控制代碼設定 drm_prime_handle.handledrm_prime_handle.flags,並在 drm_prime_handle.fd 中獲取 DMA-BUF 檔案描述符。

匯出可能由於任何驅動程式特定的原因而失敗,例如,不支援為此特定 GEM 控制代碼匯出(但可能支援其他 GEM 控制代碼)。

對 DMA-BUF 匯出的支援透過 DRM_PRIME_CAP_EXPORT 公佈。

DRM_IOCTL_PRIME_FD_TO_HANDLE

DRM_IOCTL_PRIME_FD_TO_HANDLE

將 DMA-BUF FD 轉換為 GEM 控制代碼。

描述

使用者空間使用要匯入的 DMA-BUF 檔案描述符設定 drm_prime_handle.fd,並在 drm_prime_handle.handle 中獲取 GEM 控制代碼。drm_prime_handle.flags 未使用。

如果現有的 GEM 控制代碼引用 DMA-BUF 後面的記憶體物件,則返回該 GEM 控制代碼。因此,需要處理任意 DMA-BUF 的使用者空間必須具有使用者空間查詢資料結構來手動引用計數重複的 GEM 控制代碼。有關更多資訊,請參見 DRM_IOCTL_GEM_CLOSE

匯入可能由於任何驅動程式特定的原因而失敗,例如,僅支援為在此 DRM 裝置上分配的 DMA-BUF 匯入。

對 DMA-BUF 匯入的支援透過 DRM_PRIME_CAP_IMPORT 公佈。

DRM_IOCTL_MODE_RMFB

DRM_IOCTL_MODE_RMFB

刪除幀緩衝。

描述

這將刪除先前透過 ADDFB/ADDFB2 新增的幀緩衝。IOCTL 引數是幀緩衝物件 ID。

警告:刪除當前在已啟用平面上使用的幀緩衝將停用該平面。連結到該平面的 CRTC 也可能被停用(取決於驅動程式功能)。

DRM_IOCTL_MODE_CREATE_DUMB

DRM_IOCTL_MODE_CREATE_DUMB

建立一個新的 dumb 緩衝區物件。

描述

KMS dumb 緩衝區提供了一種非常原始的方式來分配適合掃描輸出的緩衝區物件,並將其對映以進行軟體渲染。KMS dumb 緩衝區不適用於硬體加速渲染或影片解碼。KMS dumb 緩衝區不適合在從其分配的 KMS 裝置以外的任何其他裝置上顯示。另請參見 Dumb 緩衝區物件

IOCTL 引數是 struct drm_mode_create_dumb

使用者空間應透過此 IOCTL 建立 KMS dumb 緩衝區,然後透過 DRM_IOCTL_MODE_ADDFB 將其新增為 KMS 幀緩衝,並透過 DRM_IOCTL_MODE_MAP_DUMB 對映它。

DRM_CAP_DUMB_BUFFER 指示是否支援此 IOCTL。DRM_CAP_DUMB_PREFERRED_DEPTHDRM_CAP_DUMB_PREFER_SHADOW 指示驅動程式對 dumb 緩衝區的首選項。

DRM_IOCTL_MODE_GETFB2

DRM_IOCTL_MODE_GETFB2

獲取幀緩衝元資料。

描述

這會查詢有關幀緩衝的元資料。使用者空間將 drm_mode_fb_cmd2.fb_id 作為輸入填充,核心將結構的其餘部分作為輸出填充。

如果客戶端是 DRM 主裝置或具有 CAP_SYS_ADMINdrm_mode_fb_cmd2.handles 將填充 GEM 緩衝區控制代碼。始終返回新的 GEM 控制代碼,即使在 DRM 檔案描述符上已經存在另一個 GEM 控制代碼引用同一個記憶體物件。呼叫者負責刪除新控制代碼,例如,透過 DRM_IOCTL_GEM_CLOSE IOCTL。如果多個平面使用同一個記憶體物件,將為多個平面返回相同的新控制代碼。平面有效,直到一個平面具有零控制代碼為止——這可用於計算平面的數量。

否則,drm_mode_fb_cmd2.handles 將被置零,並且平面有效,直到一個平面具有零 drm_mode_fb_cmd2.pitches

如果幀緩衝具有格式修飾符,DRM_MODE_FB_MODIFIERS 將在 drm_mode_fb_cmd2.flags 中設定,drm_mode_fb_cmd2.modifier 將包含修飾符。否則,使用者空間必須忽略 drm_mode_fb_cmd2.modifier

要獲取每個平面的 DMA-BUF FD 而不洩漏 GEM 控制代碼,使用者空間可以透過 DRM_IOCTL_PRIME_HANDLE_TO_FD 匯出每個控制代碼,然後立即透過 DRM_IOCTL_GEM_CLOSE 關閉每個唯一控制代碼,確保不雙重關閉陣列中多次指定的控制代碼。

DRM_IOCTL_MODE_CLOSEFB

DRM_IOCTL_MODE_CLOSEFB

關閉幀緩衝。

描述

這將關閉先前透過 ADDFB/ADDFB2 新增的幀緩衝。IOCTL 引數是幀緩衝物件 ID。

此 IOCTL 類似於 DRM_IOCTL_MODE_RMFB,只是它不會停用平面和 CRTC。只要平面使用幀緩衝,它就會保持活動狀態。當平面不再使用幀緩衝時(因為幀緩衝被另一個幀緩衝替換,或者平面被停用),幀緩衝將被清理。

這對於實現兩個程序之間的無閃爍轉換很有用。

根據威脅模型,使用者空間可能希望確保幀緩衝不暴露任何敏感的使用者資訊:附加到平面的已關閉幀緩衝可以被下一個 DRM 主裝置讀回。

DRM_IOCTL_SET_CLIENT_NAME

DRM_IOCTL_SET_CLIENT_NAME

將名稱附加到 drm_file

描述

擁有名稱可以更容易地進行跟蹤和除錯。名稱的長度(不包括空終止符)必須 <= DRM_CLIENT_NAME_MAX_LEN。如果名稱包含空格或不可列印字元,呼叫將失敗。

struct drm_event

DRM 事件的標頭

定義:

struct drm_event {
    __u32 type;
    __u32 length;
};

成員

type

事件型別。

length

有效負載位元組總數(包括標頭)。

描述

此結構是在 DRM FD 上寫回給使用者空間的事件的標頭。在 DRM FD 上的讀取將始終僅返回完整事件:例如,如果讀取緩衝區的大小為 100 位元組,並且有兩個 64 位元組的事件掛起,則只會返回一個事件。

事件型別 0 - 0x7fffffff 是通用 DRM 事件,0x80000000 及以上是晶片組特定的。通用 DRM 事件包括 DRM_EVENT_VBLANKDRM_EVENT_FLIP_COMPLETEDRM_EVENT_CRTC_SEQUENCE

DRM_EVENT_VBLANK

DRM_EVENT_VBLANK

垂直消隱事件

描述

此事件是在設定了 _DRM_VBLANK_EVENT 標誌的情況下,響應 DRM_IOCTL_WAIT_VBLANK 傳送的。

事件有效負載是一個 struct drm_event_vblank。

DRM_EVENT_FLIP_COMPLETE

DRM_EVENT_FLIP_COMPLETE

頁面翻轉完成事件

描述

此事件是在設定了 DRM_MODE_PAGE_FLIP_EVENT 標誌的情況下,響應原子提交或傳統頁面翻轉發送的。

事件有效負載是一個 struct drm_event_vblank。

DRM_EVENT_CRTC_SEQUENCE

DRM_EVENT_CRTC_SEQUENCE

CRTC 序列事件

描述

此事件是在響應 DRM_IOCTL_CRTC_QUEUE_SEQUENCE 傳送的。

事件有效負載是一個 struct drm_event_crtc_sequence。

struct drm_mode_modeinfo

顯示模式資訊。

定義:

struct drm_mode_modeinfo {
    __u32 clock;
    __u16 hdisplay;
    __u16 hsync_start;
    __u16 hsync_end;
    __u16 htotal;
    __u16 hskew;
    __u16 vdisplay;
    __u16 vsync_start;
    __u16 vsync_end;
    __u16 vtotal;
    __u16 vscan;
    __u32 vrefresh;
    __u32 flags;
    __u32 type;
    char name[DRM_DISPLAY_MODE_LEN];
};

成員

clock

畫素時鐘(以 kHz 為單位)

hdisplay

水平顯示大小

hsync_start

水平同步開始

hsync_end

水平同步結束

htotal

水平總大小

hskew

水平傾斜

vdisplay

垂直顯示大小

vsync_start

垂直同步開始

vsync_end

垂直同步結束

vtotal

垂直總大小

vscan

垂直掃描

vrefresh

近似垂直重新整理率(以 Hz 為單位)

flags

misc. 標誌的位掩碼,參見 DRM_MODE_FLAG_* 定義

type

型別標誌的位掩碼,參見 DRM_MODE_TYPE_* 定義

name

描述模式解析度的字串

描述

這是使用者空間 API 顯示模式資訊結構。對於核心版本,請參見 struct drm_display_mode

struct drm_mode_get_plane

獲取平面元資料。

定義:

struct drm_mode_get_plane {
    __u32 plane_id;
    __u32 crtc_id;
    __u32 fb_id;
    __u32 possible_crtcs;
    __u32 gamma_size;
    __u32 count_format_types;
    __u64 format_type_ptr;
};

成員

plane_id

應檢索其資訊的平面的物件 ID。由呼叫者設定。

crtc_id

當前 CRTC 的物件 ID。

fb_id

當前 fb 的物件 ID。

possible_crtcs

與該平面相容的 CRTC 的位掩碼。CRTC 是建立的,它們接收一個索引,該索引對應於它們在位掩碼中的位置。位 N 對應於 CRTC 索引 N。

gamma_size

從未使用過。

count_format_types

格式數。

format_type_ptr

指向平面支援的格式的 __u32 陣列的指標。這些格式不需要修飾符。

描述

使用者空間可以執行 GETPLANE ioctl 來檢索有關平面的資訊。

要檢索支援的格式數,請將 count_format_types 設定為零並呼叫 ioctl。count_format_types 將使用該值進行更新。

要檢索這些格式,請分配一個數組,其中包含儲存 count_format_types 格式所需的記憶體。將 format_type_ptr 指向此陣列,然後再次呼叫 ioctl(其中 count_format_types 仍設定為在第一次 ioctl 呼叫中返回的值)。

struct drm_mode_get_connector

獲取聯結器元資料。

定義:

struct drm_mode_get_connector {
    __u64 encoders_ptr;
    __u64 modes_ptr;
    __u64 props_ptr;
    __u64 prop_values_ptr;
    __u32 count_modes;
    __u32 count_props;
    __u32 count_encoders;
    __u32 encoder_id;
    __u32 connector_id;
    __u32 connector_type;
    __u32 connector_type_id;
    __u32 connection;
    __u32 mm_width;
    __u32 mm_height;
    __u32 subpixel;
    __u32 pad;
};

成員

encoders_ptr

指向 __u32 物件 ID 陣列的指標。

modes_ptr

指向 struct drm_mode_modeinfo 陣列的指標。

props_ptr

指向 __u32 屬性 ID 陣列的指標。

prop_values_ptr

指向 __u64 屬性值陣列的指標。

count_modes

模式數。

count_props

屬性數。

count_encoders

編碼器數。

encoder_id

當前編碼器的物件 ID。

connector_id

聯結器的物件 ID。

connector_type

聯結器的型別。

參見 DRM_MODE_CONNECTOR_* 定義。

connector_type_id

型別特定的聯結器編號。

這不是物件 ID。這是一個每個型別的聯結器編號。每個(型別,type_id)組合在 DRM 裝置的所有聯結器中都是唯一的。

(型別,type_id)組合不是一個穩定的識別符號:type_id 可能會根據驅動程式探測順序而更改。

connection

聯結器的狀態。

參見 enum drm_connector_status

mm_width

連線的接收器的寬度(以毫米為單位)。

mm_height

連線的接收器的高度(以毫米為單位)。

subpixel

連線的接收器的子畫素順序。

參見 enum subpixel_order。

pad

填充,必須為零。

描述

使用者空間可以執行 GETCONNECTOR ioctl 來檢索有關聯結器的資訊。使用者空間應透過至少執行兩次此 ioctl 來檢索編碼器、模式和屬性:第一次檢索元素數量,第二次檢索元素本身。

要檢索元素數量,請將 count_propscount_encoders 設定為零,將 count_modes 設定為 1,並將 modes_ptr 設定為臨時的 struct drm_mode_modeinfo 元素。

要檢索元素,請為 encoders_ptrmodes_ptrprops_ptrprop_values_ptr 分配陣列,然後將 count_modescount_propscount_encoders 設定為其容量。

僅執行兩次 ioctl 可能會出現競爭情況:元素數量可能已在兩個 ioctl 之間因熱插拔事件而更改。使用者空間應重試上次 ioctl,直到元素數量穩定為止。核心不會填充任何不具有預期長度的陣列。

強制探測聯結器

如果 count_modes 欄位設定為零,並且 DRM 客戶端是當前的 DRM 主裝置,則核心將對聯結器執行強制探測以重新整理聯結器狀態、模式和 EDID。強制探測可能很慢,可能會導致閃爍,並且 ioctl 將阻塞。

使用者空間需要強制探測聯結器,以確保它們的元資料在啟動時和接收到熱插拔事件後是最新的。使用者空間可能會在使用者明確請求時執行強制探測。在其他情況下,使用者空間不應執行強制探測。

struct drm_mode_property_enum

列舉/位域條目的描述。

定義:

struct drm_mode_property_enum {
    __u64 value;
    char name[DRM_PROP_NAME_LEN];
};

成員

value

此列舉條目的數值。

name

name

描述

有關詳細資訊,請參見 struct drm_property_enum

struct drm_mode_get_property

獲取屬性元資料。

定義:

struct drm_mode_get_property {
    __u64 values_ptr;
    __u64 enum_blob_ptr;
    __u32 prop_id;
    __u32 flags;
    char name[DRM_PROP_NAME_LEN];
    __u32 count_values;
    __u32 count_enum_blobs;
};

成員

values_ptr

指向 __u64 陣列的指標。

enum_blob_ptr

指向 struct drm_mode_property_enum 陣列的指標。

prop_id

應檢索的屬性的物件 ID。由呼叫者設定。

flags

DRM_MODE_PROP_* 位域。有關標誌的定義,請參見 drm_property.flags

name

符號屬性名稱。使用者空間應使用此欄位來識別屬性。

count_values

values_ptr 中的元素數。

count_enum_blobs

enum_blob_ptr 中的元素數。

描述

使用者空間可以執行 GETPROPERTY ioctl 來檢索有關屬性的資訊。同一個屬性可以附加到多個物件,請參見“模式設定基本物件抽象”。

values_ptr 欄位的含義根據屬性型別而變化。有關更多詳細資訊,請參見 drm_property.flags

僅當屬性的型別為 DRM_MODE_PROP_ENUMDRM_MODE_PROP_BITMASK 時,enum_blob_ptrcount_enum_blobs 欄位才有意義。為了向後相容,當屬性的型別為 DRM_MODE_PROP_BLOB 時,核心將始終將 count_enum_blobs 設定為零。如果屬性具有不同的型別,則使用者空間必須忽略這兩個欄位。

使用者空間應透過至少執行兩次此 ioctl 來檢索值和列舉:第一次檢索元素數量,第二次檢索元素本身。

要檢索元素數量,請將 count_valuescount_enum_blobs 設定為零,然後呼叫 ioctl。count_values 將使用元素數量進行更新。如果屬性的型別為 DRM_MODE_PROP_ENUMDRM_MODE_PROP_BITMASK,則 count_enum_blobs 也將更新。

要檢索元素本身,請為 values_ptr 分配一個數組,並將 count_values 設定為其容量。如果屬性的型別為 DRM_MODE_PROP_ENUMDRM_MODE_PROP_BITMASK,則為 enum_blob_ptr 分配一個數組,並將 count_enum_blobs 設定為其容量。再次呼叫 ioctl 將填充陣列。

struct drm_mode_fb_cmd2

幀緩衝元資料。

定義:

struct drm_mode_fb_cmd2 {
    __u32 fb_id;
    __u32 width;
    __u32 height;
    __u32 pixel_format;
    __u32 flags;
    __u32 handles[4];
    __u32 pitches[4];
    __u32 offsets[4];
    __u64 modifier[4];
};

成員

fb_id

幀緩衝的物件 ID。

width

幀緩衝的寬度。

height

幀緩衝的高度。

pixel_format

FourCC 格式程式碼,請參見 drm_fourcc.h 中的 DRM_FORMAT_* 常量。

flags

幀緩衝標誌(請參見 DRM_MODE_FB_INTERLACEDDRM_MODE_FB_MODIFIERS)。

handles

GEM 緩衝區控制代碼,每個平面一個。如果未使用該平面,則設定為 0。同一個控制代碼可以用於多個平面。

pitches

步幅(也稱為 stride),以位元組為單位,每個平面一個。

offsets

到緩衝區中的偏移量,以位元組為單位,每個平面一個。

modifier

格式修飾符,每個平面一個。請參見 drm_fourcc.h 中的 DRM_FORMAT_MOD_* 常量。所有平面必須使用相同的修飾符。除非在 flags 中設定了 DRM_MODE_FB_MODIFIERS,否則將被忽略。

描述

此結構儲存幀緩衝元資料。有兩種使用它的方法

  • 使用者空間可以填充此結構並執行 DRM_IOCTL_MODE_ADDFB2 ioctl 以註冊新的幀緩衝。新的幀緩衝物件 ID 將由核心在 fb_id 中設定。

  • 使用者空間可以設定 fb_id 並執行 DRM_IOCTL_MODE_GETFB2 ioctl 以獲取有關現有幀緩衝的元資料。

在平面格式的情況下,此結構最多允許 4 個緩衝區物件,每個平面都有偏移量和步幅。步幅和偏移量順序由 drm_fourcc.h 定義的格式 FourCC 指定,例如,NV12 被描述為

YUV 4:2:0 影像,具有一個 8 位 Y 樣本的平面,後跟一個包含 8 位 2x2 子取樣的色差樣本的交錯 U/V 平面。

因此,它將由 offsets[0] 處的 Y 平面和 offsets[1] 處的 UV 平面組成。

為了適應平鋪、壓縮等格式,可以指定修飾符。 更多資訊請參見“格式修飾符”部分。 請注意,即使看起來我們每個平面都有一個修飾符,但實際上並非如此。 每個平面的修飾符必須相同。 因此,多平面格式的不同資料佈局的所有組合都必須列舉為單獨的修飾符。

當未使用時,handlespitchesoffsetsmodifier 中的所有條目必須為零。 警告:對於 offsetsmodifier,零不能用於判斷條目是否被使用,因為它是一個有效值(零偏移很常見,零修飾符是 DRM_FORMAT_MOD_LINEAR)。

struct drm_plane_size_hint

平面大小提示

定義:

struct drm_plane_size_hint {
    __u16 width;
    __u16 height;
};

成員

width

平面畫素寬度

height

平面畫素高度

描述

平面 SIZE_HINTS 屬性 blob 包含 struct drm_plane_size_hint 的陣列。

struct hdr_metadata_infoframe

HDR 元資料資訊幀資料。

定義:

struct hdr_metadata_infoframe {
    __u8 eotf;
    __u8 metadata_type;
    struct {
        __u16 x, y;
    } display_primaries[3];
    struct {
        __u16 x, y;
    } white_point;
    __u16 max_display_mastering_luminance;
    __u16 min_display_mastering_luminance;
    __u16 max_cll;
    __u16 max_fall;
};

成員

eotf

流中使用的光電轉換函式 (EOTF)。

metadata_type

Static_Metadata_Descriptor_ID。

display_primaries

資料的色度座標。 這些值編碼為無符號 16 位值,單位為 0.00002,其中 0x0000 表示零,0xC350 表示 1.0000。 display_primaries.x:色度座標的 X 座標。 display_primaries.y:色度座標的 Y 座標。

white_point

色彩空間資料的白點。 這些值編碼為無符號 16 位值,單位為 0.00002,其中 0x0000 表示零,0xC350 表示 1.0000。 white_point.x:色度座標白點的 X 座標。 white_point.y:色度座標白點的 Y 座標。

max_display_mastering_luminance

Max Mastering Display Luminance。 此值編碼為無符號 16 位值,單位為 1 cd/m2,其中 0x0001 表示 1 cd/m2,0xFFFF 表示 65535 cd/m2。

min_display_mastering_luminance

Min Mastering Display Luminance。 此值編碼為無符號 16 位值,單位為 0.0001 cd/m2,其中 0x0001 表示 0.0001 cd/m2,0xFFFF 表示 6.5535 cd/m2。

max_cll

Max Content Light Level。 此值編碼為無符號 16 位值,單位為 1 cd/m2,其中 0x0001 表示 1 cd/m2,0xFFFF 表示 65535 cd/m2。

max_fall

Max Frame Average Light Level。 此值編碼為無符號 16 位值,單位為 1 cd/m2,其中 0x0001 表示 1 cd/m2,0xFFFF 表示 65535 cd/m2。

描述

根據 CTA 861.G 規範的 HDR 元資料資訊幀。 這預計與規範完全匹配。

使用者空間應按照此結構中描述的格式傳遞元資料資訊。

struct hdr_output_metadata

HDR 輸出元資料

定義:

struct hdr_output_metadata {
    __u32 metadata_type;
    union {
        struct hdr_metadata_infoframe hdmi_metadata_type1;
    };
};

成員

metadata_type

Static_Metadata_Descriptor_ID。

{unnamed_union}

anonymous

hdmi_metadata_type1

HDR 元資料資訊幀。

描述

要從使用者空間傳遞的元資料資訊

DRM_MODE_PAGE_FLIP_EVENT

DRM_MODE_PAGE_FLIP_EVENT

描述

請求核心在頁面翻轉完成後發回一個帶有 DRM_EVENT_FLIP_COMPLETE 型別的 vblank 事件(請參閱 struct drm_event_vblank)。

DRM_MODE_PAGE_FLIP_ASYNC

DRM_MODE_PAGE_FLIP_ASYNC

描述

請求儘快執行頁面翻轉,即沒有因等待 vblank 而造成的延遲。 這可能會導致螢幕上出現撕裂現象。

與 atomic uAPI 一起使用時,如果硬體不支援為此更新執行非同步頁面翻轉,驅動程式將返回錯誤。 使用者空間應處理此問題,例如,透過回退到常規頁面翻轉。

注意,某些硬體可能需要在切換到非同步頁面翻轉之前執行最後一次同步頁面翻轉。 作為例外,即使第一次頁面翻轉不是非同步的,驅動程式也會返回成功。

DRM_MODE_PAGE_FLIP_FLAGS

DRM_MODE_PAGE_FLIP_FLAGS

描述

適用於 drm_mode_crtc_page_flip_target.flags 的標誌位掩碼。

struct drm_mode_create_dumb

建立用於掃描輸出的 KMS dumb 緩衝區。

定義:

struct drm_mode_create_dumb {
    __u32 height;
    __u32 width;
    __u32 bpp;
    __u32 flags;
    __u32 handle;
    __u32 pitch;
    __u64 size;
};

成員

height

緩衝區高度,以畫素為單位

width

緩衝區寬度,以畫素為單位

bpp

每個畫素的位數

flags

必須為零

handle

緩衝區物件控制代碼

pitch

兩個連續行之間的位元組數

size

整個緩衝區的大小,以位元組為單位

描述

使用者空間填充 heightwidthbppflags。 如果 IOCTL 成功,則核心填充 handlepitchsize

DRM_MODE_ATOMIC_TEST_ONLY

DRM_MODE_ATOMIC_TEST_ONLY

描述

不應用原子提交,而是檢查硬體是否支援此配置。

有關僅測試提交的更多詳細資訊,請參見 drm_mode_config_funcs.atomic_check

DRM_MODE_ATOMIC_NONBLOCK

DRM_MODE_ATOMIC_NONBLOCK

描述

應用原子提交時不阻塞。DRM_IOCTL_MODE_ATOMIC IOCTL 立即返回,而不是等待硬體應用更改。 請注意,驅動程式仍將檢查是否可以在返回之前應用更新。

DRM_MODE_ATOMIC_ALLOW_MODESET

DRM_MODE_ATOMIC_ALLOW_MODESET

描述

允許更新在應用時導致臨時或瞬時可見偽影。 應用更新也可能比頁面翻轉花費更多的時間。 所有視覺偽影將在更新完成時消失,並透過 vblank 事件的時間戳發出訊號(請參見 struct drm_event_vblank)。

當 KMS 更新可能導致可見偽影時,必須設定此標誌。 如果沒有此標誌,此類 KMS 更新將返回 EINVAL 錯誤。 什麼型別的更新可能導致可見偽影取決於驅動程式和硬體。 需要預先知道更新是否可能導致可見偽影的使用者空間可以使用 DRM_MODE_ATOMIC_TEST_ONLY 而不使用 DRM_MODE_ATOMIC_ALLOW_MODESET 來檢視它是否失敗。

就驅動程式所知,如果不設定此標誌,則保證不會出現視覺偽影。 某些接收器可能會顯示驅動程式無法控制的視覺偽影。

DRM_MODE_ATOMIC_FLAGS

DRM_MODE_ATOMIC_FLAGS

描述

DRM_IOCTL_MODE_ATOMIC IOCTL 在 drm_mode_atomic.flags 中接受的標誌位域。

struct drm_mode_create_blob

建立新的 blob 屬性

定義:

struct drm_mode_create_blob {
    __u64 data;
    __u32 length;
    __u32 blob_id;
};

成員

data

指向要複製的資料的指標。

length

要複製的資料的長度。

blob_id

返回:新的屬性 ID。

描述

建立一個新的“blob”資料屬性,從資料指標複製 length 位元組,並返回新的 blob ID。

struct drm_mode_destroy_blob

銷燬使用者 blob

定義:

struct drm_mode_destroy_blob {
    __u32 blob_id;
};

成員

blob_id

要銷燬的 blob_id

描述

銷燬使用者建立的 blob 屬性。

使用者空間可以儘快釋放 blob,因為它們不需要透過其 blob 物件 ID 來引用它們。 例如,如果您在原子提交中使用 MODE_ID blob,並且您不會進行另一個重用相同 ID 的提交,則可以在發出提交後立即銷燬 blob,而無需等待其完成。

struct drm_mode_create_lease

建立租約

定義:

struct drm_mode_create_lease {
    __u64 object_ids;
    __u32 object_count;
    __u32 flags;
    __u32 lessee_id;
    __u32 fd;
};

成員

object_ids

指向物件 ID 陣列的指標 (__u32)

object_count

物件 ID 的數量

flags

新 FD 的標誌 (O_CLOEXEC 等)

lessee_id

返回:承租人的唯一識別符號。

fd

返回:指向新 drm_master 檔案的檔案描述符

描述

租賃模式資源,建立另一個 drm_master。

如果啟用了 DRM_CLIENT_CAP_UNIVERSAL_PLANESobject_ids 陣列必須至少引用一個 CRTC、一個聯結器和一個平面。 或者,租賃可以完全為空。

struct drm_mode_list_lessees

列出租戶

定義:

struct drm_mode_list_lessees {
    __u32 count_lessees;
    __u32 pad;
    __u64 lessees_ptr;
};

成員

count_lessees

承租人數量。

在輸入時,提供陣列的長度。 在輸出時,提供總數。 不會寫回超過輸入數字的數字,因此可以使用兩個呼叫來獲取大小,然後獲取資料。

pad

填充。

lessees_ptr

指向承租人的指標。

指向承租人 ID 的 __u64 陣列的指標

描述

從 drm_master 列出較少的資源。

struct drm_mode_get_lease

獲取租賃

定義:

struct drm_mode_get_lease {
    __u32 count_objects;
    __u32 pad;
    __u64 objects_ptr;
};

成員

count_objects

租賃物件的數量。

在輸入時,提供陣列的長度。 在輸出時,提供總數。 不會寫回超過輸入數字的數字,因此可以使用兩個呼叫來獲取大小,然後獲取資料。

pad

填充。

objects_ptr

指向物件的指標。

指向物件 ID 的 __u32 陣列的指標。

描述

獲取租賃物件。

struct drm_mode_revoke_lease

撤銷租賃

定義:

struct drm_mode_revoke_lease {
    __u32 lessee_id;
};

成員

lessee_id

承租人的唯一 ID

struct drm_mode_rect

二維矩形。

定義:

struct drm_mode_rect {
    __s32 x1;
    __s32 y1;
    __s32 x2;
    __s32 y2;
};

成員

x1

水平起始座標(含)。

y1

垂直起始座標(含)。

x2

水平結束座標(不含)。

y2

垂直結束座標(不含)。

描述

drm 子系統使用 struct drm_rect 來管理矩形區域,從而將其匯出到使用者空間。

當前由 drm_mode_atomic blob 屬性 FB_DAMAGE_CLIPS 使用。

struct drm_mode_closefb

定義:

struct drm_mode_closefb {
    __u32 fb_id;
    __u32 pad;
};

成員

fb_id

幀緩衝區 ID。

pad

必須為零。

dma-buf 互操作性

請參見 交換畫素緩衝區,瞭解有關 dma-buf 如何在 DRM 中整合和公開的資訊。