Direct Rendering Manager ( DRM ) は、 Linux カーネルのサブシステムで、最新のビデオ カードのGPUとのインターフェースを担当します。DRM は、ユーザー スペースプログラムが GPU にコマンドやデータを送信し、ディスプレイのモード設定などの操作を実行するために使用できるAPIを公開します。DRM は、 X Server Direct Rendering Infrastructure [ 1 ]のカーネル スペースコンポーネントとして最初に開発されましたが、それ以降、 Waylandなどの他のグラフィック スタックの代替手段や、 SDL2やKodiなどのスタンドアロン アプリケーションやライブラリで使用されています。
ユーザー空間プログラムは、DRM APIを使用して、GPUにハードウェアアクセラレーションによる3Dレンダリングやビデオデコード、GPGPUコンピューティングを実行するように指示できます。
Linuxカーネルには、グラフィックアダプタのフレームバッファを管理するために使用されるfbdevというAPIが既に存在していましたが[ 2 ]、最新の3DアクセラレーションGPUベースのビデオハードウェアのニーズに対応することはできませんでした。これらのデバイスは通常、 GPUにコマンドをディスパッチするために独自のメモリにコマンドキューを設定および管理する必要があり、またそのメモリ内のバッファと空き領域の管理も必要とします。[ 3 ]当初、ユーザー空間プログラム( Xサーバーなど)がこれらのリソースを直接管理していましたが、通常はそれらにアクセスできるのは自分たちだけであるかのように動作していました。2つ以上のプログラムが同時に同じハードウェアを制御し、それぞれ独自の方法でリソースを設定しようとすると、ほとんどの場合、致命的な結果に終わりました。[ 3 ]
Direct Rendering Manager は、複数のプログラムがビデオ ハードウェア リソースを協調して使用できるようにするために作成されました。[ 4 ] DRM は GPU への排他的アクセス権を持ち、コマンド キュー、メモリ、およびその他のハードウェア リソースの初期化と維持を担当します。GPU を使用したいプログラムは DRM にリクエストを送信し、DRM は仲裁役として機能し、起こりうる競合を回避するよう注意を払います。
DRM の範囲は、フレームバッファの管理やモード設定、メモリ共有オブジェクト、メモリ同期など、以前はユーザー空間プログラムによって処理されていたより多くの機能をカバーするように、長年にわたって拡張されてきました。[ 5 ] [ 6 ]これらの拡張の一部には、グラフィックス実行マネージャ(GEM) やカーネルモード設定(KMS)などの特定の名前が付けられており、それらが提供する機能が具体的に言及される場合は、その用語が優先されます。しかし、これらは実際にはカーネル DRM サブシステム全体の一部です。
コンピュータに2つのGPU (ディスクリートGPUと統合GPU )を搭載する傾向により、 GPU切り替えなどの新たな問題が発生し、DRMレイヤーでも解決する必要がありました。Nvidia Optimusテクノロジーに対応するため、DRMにはPRIMEと呼ばれるGPUオフロード機能が搭載されました。[ 7 ]

Direct Rendering Manager はカーネル空間に存在するため、ユーザー空間プログラムはカーネルシステムコールを使用してそのサービスを要求する必要があります。ただし、DRM は独自のカスタマイズされたシステムコールを定義していません。代わりに、Unixの「すべてはファイルである」という原則に従って、階層内のデバイスファイルを使用してファイルシステム名前空間を介してGPUを公開します。DRM によって検出された各 GPU はDRM デバイスと呼ばれ、デバイスファイル( Xは連番) が作成されて、それとインターフェースします。[ 8 ] [ 9 ] GPU と通信したいユーザー空間プログラムは、このファイルを開き、 ioctlコールを使用して DRM と通信する必要があります。異なる ioctl は、DRM APIの異なる機能に対応しています。/dev/dev/dri/cardX
libdrmと呼ばれるライブラリは、ユーザー空間プログラムと DRM サブシステムとのインターフェースを容易にするために作成されました。このライブラリは、 DRM API のすべての ioctl に対してCで記述された関数、定数、構造体、およびその他のヘルパー要素を提供する単なるラッパーです。 [ 10 ] libdrm を使用すると、カーネルインターフェースをアプリケーションに直接公開することを避けるだけでなく、プログラム間でコードを再利用および共有するという一般的な利点も得られます。

DRM は、汎用的な「DRM コア」と、サポートされるハードウェアの種類ごとに固有の「DRM ドライバ」の 2 つの部分で構成されています。[ 11 ] DRM コアは、さまざまな DRM ドライバが登録できる基本的なフレームワークを提供し、共通のハードウェア非依存機能を持つ最小限の ioctl セットをユーザー空間に提供します。[ 8 ]一方、DRM ドライバは、サポートする GPU の種類に固有の、ハードウェア依存の API 部分を実装します。DRM コアでカバーされていない残りの ioctl の実装を提供する必要がありますが、API を拡張して、そのようなハードウェアでのみ利用可能な追加機能を持つ追加の ioctl を提供することもできます。[ 8 ]特定の DRM ドライバが拡張 API を提供する場合、ユーザー空間の libdrm も、追加の ioctl とインターフェースするためにユーザー空間が使用できる追加のライブラリ libdrm- driverによって拡張されます。
DRMコアは、ユーザー空間アプリケーション向けに複数のインターフェースをエクスポートします。これらのインターフェースは、通常、対応するラッパー関数を介して使用されることを想定しています。さらに、ドライバは、 ioctlおよびsysfslibdrmファイルを介して、ユーザー空間ドライバおよびデバイス対応アプリケーションが使用できるデバイス固有のインターフェースをエクスポートします。外部インターフェースには、メモリマッピング、コンテキスト管理、DMA操作、AGP管理、vblank制御、フェンス管理、メモリ管理、および出力管理が含まれます。
DRM API には、セキュリティ上の理由または並行処理の問題から、デバイスごとに単一のユーザー空間プロセスのみが使用できるように制限する必要のある操作 (ioctl) がいくつかあります。[ 8 ]この制限を実装するために、DRM は、そのような ioctl を、通常DRM-Masterと呼ばれる DRM デバイスの「マスター」とみなされるプロセスのみが呼び出せるように制限します。デバイス ノードを開いているすべてのプロセスのうち、ファイル ハンドルがマスターとしてマークされるのは 1 つだけで、具体的には SET_MASTER ioctl を最初に呼び出したプロセスです。DRM-Master でない状態でこれらの制限された ioctl のいずれかを使用しようとすると、エラーが返されます。プロセスは、DROP_MASTER ioctlを呼び出すことで、マスター ロールを放棄し、別のプロセスに取得させることもできます。/dev/dri/cardX
Xサーバー(またはその他のディスプレイサーバー)は、通常、起動時に対応するデバイスノードを開いたときに、管理するすべてのDRMデバイスでDRMマスターのステータスを取得し、終了または停止するまで、グラフィカルセッション全体にわたってこの権限を保持します。
残りのユーザー空間プロセスについては、DRMデバイス上で制限された操作を実行する権限を取得する別の方法として、DRM-Authがあります。これは基本的に、プロセスがそのような権限を取得するために DRM-Master の承認を得ていることを DRMデバイスに証明するための、DRMデバイスに対する認証方法です。手順は次のとおりです。[ 12 ] : 13
ビデオメモリの容量増加とOpenGLなどのグラフィックスAPIの複雑化に伴い、コンテキストスイッチごとにグラフィックスカードの状態を再初期化する戦略は、パフォーマンスの面でコストが高すぎました。また、最新のLinuxデスクトップでは、オフスクリーンバッファをコンポジティングマネージャと共有するための最適な方法が必要でした。これらの要件により、カーネル内でグラフィックスバッファを管理するための新しい方法が開発されました。グラフィックス実行マネージャ(GEM)は、これらの方法の1つとして登場しました。[ 6 ]
GEM は明示的なメモリ管理プリミティブを備えた API を提供します。[ 6 ] GEM を介して、ユーザー空間プログラムは GPU ビデオ メモリに存在するメモリ オブジェクトを作成、処理、および破棄できます。これらのオブジェクトは「GEM オブジェクト」と呼ばれ、[ 14 ]ユーザー空間プログラムの観点からは永続的であり、プログラムが GPU の制御を取り戻すたびに再ロードする必要はありません。ユーザー空間プログラムがビデオ メモリのチャンク (フレームバッファ、テクスチャ、または GPU が必要とするその他のデータを格納するため[ 15 ] ) を必要とする場合、GEM API を使用して DRM ドライバに割り当てを要求します。DRM ドライバは使用中のビデオ メモリを追跡し、空きメモリが利用可能であれば要求に応じることができ、割り当てられたメモリを以降の操作で参照するための「ハンドル」をユーザー空間に返します。[ 6 ] [ 14 ] GEM API は、バッファを生成し、不要になったときにバッファを解放する操作も提供します。解放されていない GEM ハンドルのメモリは、ユーザー空間プロセスが DRM デバイスファイル ディスクリプタを閉じるとき(意図的に閉じるか、終了するため) に回復されます。[ 16 ]
GEM では、同じ DRM デバイス (つまり同じ DRM ドライバ) を使用する2 つ以上のユーザー空間プロセスが GEM オブジェクトを共有することもできます。 [ 16 ] GEM ハンドルは、プロセスに固有のローカル 32 ビット整数ですが、他のプロセスでは繰り返し使用できるため、共有には適していません。必要なのはグローバル名前空間であり、GEM はGEM 名と呼ばれるグローバルハンドルを使用することでそれを提供します。GEM 名は、同じ DRM デバイス内で同じ DRM ドライバによって作成された 1 つの GEM オブジェクトを、一意の 32 ビット整数を使用して参照します。GEM は、 GEM ハンドルから GEM 名を取得する操作flinkを提供します。 [ 16 ] [ 12 ] : 16プロセスは、利用可能な任意のIPCメカニズムを使用して、この GEM 名 (32 ビット整数) を別のプロセスに渡すことができます。[ 12 ] : 15受信側のプロセスは、GEM 名を使用して、元の GEM オブジェクトを指すローカル GEM ハンドルを取得できます。
残念ながら、バッファを共有するために GEM 名を使用することは安全ではありません。[ 12 ] : 16 [ 17 ] [ 18 ]同じ DRM デバイスにアクセスする悪意のあるサードパーティ プロセスは、32 ビット整数をプローブするだけで、他の 2 つのプロセスによって共有されているバッファの GEM 名を推測しようとする可能性があります。[ 19 ] [ 18 ] GEM 名が見つかると、その内容にアクセスして変更することができ、バッファの情報の機密性と完全性が侵害されます。この欠点は、 DMA-BUFサポートが DRM に導入されたことで後に克服されました。DMA-BUF は、ユーザー空間でバッファをファイル ディスクリプタとして表現し、安全に共有することができます。
ビデオメモリ管理システムにとって、ビデオメモリ空間の管理以外に重要なタスクは、GPUとCPU間のメモリ同期の処理です。現在のメモリアーキテクチャは非常に複雑で、通常はシステムメモリ、場合によってはビデオメモリにもさまざまなレベルのキャッシュが含まれています。そのため、ビデオメモリマネージャは、CPUとGPU間で共有されるデータの一貫性を確保するために、キャッシュの一貫性も処理する必要があります。 [ 20 ]これは、多くの場合、ビデオメモリ管理の内部処理がGPUとメモリアーキテクチャのハードウェアの詳細に大きく依存し、ドライバ固有のものであることを意味します。[ 21 ]
GEM は当初、Intel のエンジニアが i915 ドライバ用のビデオ メモリマネージャを提供するために開発しました。[ 20 ] Intel GMA 9xxファミリーは、GPU と CPU が物理メモリを共有し、専用の VRAM がない Uniform Memory Architecture (UMA) を備えた統合型 GPUです。 [ 22 ] GEM はメモリ同期のための「メモリ ドメイン」を定義しており、これらのメモリ ドメインは GPU に依存しませんが、[ 6 ] UMA メモリ アーキテクチャを念頭に置いて特別に設計されているため、独立した VRAM を持つものなどの他のメモリ アーキテクチャにはあまり適していません。このため、他の DRM ドライバは、ユーザー スペース プログラムに GEM API を公開することにしましたが、内部的には、特定のハードウェアとメモリ アーキテクチャにより適した別のメモリマネージャを実装しました。[ 23 ]
GEM API は、実行フロー (コマンド バッファ) を制御するための ioctl も提供していますが、これらは Intel 固有のもので、Intel i915 以降の GPU で使用されます。[ 6 ]他の DRM ドライバは、メモリ管理固有の ioctl 以外の GEM API の部分を実装しようとはしていません。
トランスレーション テーブル マップ(TTM) は、GEM より前に開発された GPU 用の汎用メモリマネージャの名前です。[ 5 ] [ 14 ]これは、専用のビデオ RAM (通常はビデオ カードに搭載)や、グラフィックス アドレス リマッピング テーブル(GART)と呼ばれるI/O メモリ管理ユニットを介してアクセスできるシステム メモリなど、GPU がアクセスする可能性のあるさまざまな種類のメモリを管理するように特別に設計されました。[ 5 ]また、TTM は、CPU が直接アドレス指定できないビデオ RAM の部分も処理し、ユーザー スペース グラフィックス アプリケーションは通常大量のビデオ データを扱うことを考慮して、可能な限り最高のパフォーマンスで処理する必要があります。もう 1 つの重要な事項は、関係するさまざまなメモリとキャッシュ間の一貫性を維持することでした。
TTM の主な概念は「バッファ オブジェクト」、つまり、ある時点で GPU からアドレス指定可能でなければならないビデオ メモリの領域です。[ 5 ]ユーザー空間グラフィックス アプリケーションが特定のバッファ オブジェクトにアクセスしたい場合 (通常はコンテンツを書き込むため)、TTM はそれを CPU からアドレス指定可能なタイプのメモリに再配置する必要がある場合があります。GPU がバッファ オブジェクトにアクセスする必要があるが、それがまだ GPU のアドレス空間にない場合、さらに再配置(または GART マッピング操作)が発生する可能性があります。これらの再配置操作はそれぞれ、関連するデータとキャッシュ コヒーレンシの問題を処理する必要があります。[ 5 ]
TTM のもう 1 つの重要な概念はフェンスです。フェンスは基本的に、CPU と GPU 間の並行性を管理するメカニズムです。[ 24 ]フェンスは、バッファ オブジェクトが GPU で使用されなくなったときに追跡し、通常はそれにアクセスするユーザー スペース プロセスに通知します。[ 5 ]
TTM は、専用 VRAM の有無を問わず、あらゆる種類のメモリ アーキテクチャを適切に管理し、あらゆる種類のハードウェアで使用するメモリマネージャで考えられるすべての機能を提供しようとしたため、必要以上に大きな API を持つ過度に複雑なソリューションとなりました。[ 24 ] [ 14 ]一部の DRM 開発者は、特に API に関しては、特定のドライバにはうまく適合しないと考えました。よりシンプルなメモリマネージャとして GEM が登場すると、API は TTM のものよりも好まれました。しかし、一部のドライバ開発者は、TTM のアプローチは専用ビデオ メモリと IOMMU を備えたディスクリート ビデオ カードに適していると考え、内部では TTM を使用し、バッファ オブジェクトを GEM オブジェクトとして公開して GEM API をサポートすることにしました。[ 23 ]現在のドライバで、内部メモリマネージャとして TTM を使用し、GEM API を提供している例としては、AMD ビデオ カード用の radeon ドライバとNVIDIA ビデオ カード用のnouveauドライバがあります。
DMA Buffer Sharing API (DMA-BUF と略されることが多い) は、異なるタイプのデバイスドライバによって管理される可能性のある複数のデバイス間でDMAバッファを共有するための汎用メカニズムを提供するように設計されたLinux カーネルの内部 API です。 [ 25 ] [ 26 ]例えば、Video4Linuxデバイスとグラフィックスアダプタデバイスは、DMA-BUF を介してバッファを共有することで、前者が生成し後者が消費するビデオストリームのデータのゼロコピーを実現できます。任意の Linuxデバイスドライバは、エクスポーター、ユーザー (コンシューマー)、またはその両方としてこの API を実装できます。
この機能は、DRM で初めて利用され、ディスクリート GPU と統合 GPU の DRM ドライバ間で結果として得られるフレームバッファを共有するために DMA-BUF を使用するGPU オフロードのソリューションである PRIME を実装しました。 [ 27 ] : 13 DMA-BUF の重要な機能は、共有バッファがファイルディスクリプタとしてユーザー空間に提示されることです。[ 14 ] [ 12 ] : 17 PRIME の開発のために、DRM API に 2 つの新しい ioctl が追加されました。1 つはローカル GEM ハンドルを DMA-BUF ファイルディスクリプタに変換するもので、もう 1 つはその正反対の操作を行うものです。
これらの 2 つの新しい ioctl は、後に GEM バッファ共有の固有の安全性の低さを修正する方法として再利用されました。[ 12 ] : 17 GEM 名とは異なり、ファイルディスクリプタは推測できません (グローバル名前空間ではない)。Unix オペレーティングシステムは、SCM_RIGHTS セマンティクスを使用してUnix ドメインソケットを介してファイルディスクリプタを渡す安全な方法を提供します。 [ 14 ] [ 28 ] : 11 GEM オブジェクトを別のプロセスと共有したいプロセスは、ローカル GEM ハンドルを DMA-BUF ファイルディスクリプタに変換して受信者に渡すことができ、受信者は受信したファイルディスクリプタから独自の GEM ハンドルを取得できます。[ 12 ] : 16この方法は、DRI3がクライアントと X サーバー間でバッファを共有するために使用されており[ 29 ] 、 Waylandでも使用されています。

ビデオカードまたはグラフィックアダプタが正しく動作するためには、画面解像度、色深度、リフレッシュレートの組み合わせであるモードを、自身と接続されているディスプレイ画面でサポートされている値の範囲内に設定する必要があります。この操作はモード設定と呼ばれ、[ 30 ]通常はグラフィックハードウェアへの生アクセス、つまりビデオカードのディスプレイコントローラの特定のレジスタに書き込む機能が必要です。[ 31 ] [ 32 ]モード設定操作は、フレームバッファの使用を開始する前、およびアプリケーションまたはユーザーによってモードの変更が必要な場合に実行する必要があります。
初期の頃は、グラフィカル フレーム バッファを使用したいユーザー スペースプログラムがモード設定操作を提供する責任も負っていました。[ 3 ]そのため、ビデオ ハードウェアへの特権アクセスで実行する必要がありました。Unix タイプのオペレーティングシステムでは、X サーバーが最も顕著な例でした。そのモード設定の実装は、特定のタイプのビデオ カード用の DDX ドライバにありました。 [ 33 ]後にユーザー スペース モード設定または UMSと呼ばれるこのアプローチには、いくつかの問題があります。[ 34 ] [ 35 ]これは、オペレーティングシステムがプログラムとハードウェアの間で提供すべき分離を破り、安定性とセキュリティの両方の懸念を引き起こすだけでなく、2 つ以上のユーザー スペース プログラムが同時にモード設定を実行しようとすると、グラフィック ハードウェアが矛盾した状態になる可能性もあります。これらの競合を回避するために、実際には、X サーバーがモード設定操作を実行する唯一のユーザー スペース プログラムになりました。残りのユーザー空間プログラムは、適切なモードを設定し、モード設定を含むその他の操作を処理するために X サーバーに依存していました。当初、モード設定は X サーバーの起動プロセス中にのみ実行されていましたが、後に X サーバーは実行中にそれを行う機能を獲得しました。[ 37 ] XFree86-VidModeExtension 拡張機能は、XFree86 3.1.2 で導入され、任意の X クライアントがモデルライン(解像度) の変更を X サーバーに要求できるようにしました。 [ 38 ] [ 39 ] VidMode 拡張機能は、後に、より汎用的なXRandR拡張機能に置き換えられました。
しかし、 Linuxシステムでモード設定を行うコードはこれだけではありませんでした。システムの起動プロセス中に、Linux カーネルは仮想コンソールの最小限のテキスト モードを設定する必要があります ( VESA BIOS拡張機能で定義された標準モードに基づいています)。[ 40 ]また、Linux カーネルのフレームバッファ ドライバには、フレームバッファ デバイスを構成するためのモード設定コードが含まれていました。[ 2 ]モード設定の競合を回避するために、XFree86 サーバー(後にX.Org サーバー)は、ユーザーがグラフィカル環境からテキスト仮想コンソールに切り替えた場合、そのモード設定状態を保存し、ユーザーが X に戻ったときにそれを復元することで処理しました。[ 41 ]このプロセスは、切り替え時に煩わしいちらつきを引き起こし、また失敗すると、出力表示が破損したり使用できなくなったりすることもあります。[ 42 ]
ユーザー空間モード設定アプローチは、他にも問題を引き起こしました。[ 43 ] [ 42 ]
これらの問題に対処するため、モード設定コードはカーネル内の単一の場所、具体的には既存の DRM モジュールに移動されました。[ 36 ] [ 37 ] [ 44 ] [ 42 ] [ 43 ]これにより、X サーバーを含むすべてのプロセスがカーネルにモード設定操作を実行するように指示できるようになり、カーネルは同時操作によって矛盾した状態にならないようにします。これらのモード設定操作を実行するために DRM モジュールに追加された新しいカーネル API とコードは、カーネルモード設定(KMS) と呼ばれました。[ 30 ]
Kernel Mode-Setting にはいくつかの利点があります。最も直接的な利点は、カーネル (Linux コンソール、fbdev) とユーザー空間 (X Server DDX ドライバー) の両方から重複するモード設定コードが削除されることです。KMS により、独自のモード設定コードを実装する必要がなくなった代替グラフィックスシステムの作成も容易になります。[ 42 ] [ 43 ] KMS は、集中型のモード管理を提供することで、コンソールと X の間、および X の異なるインスタンス間 (高速なユーザー切り替え) の切り替え時のちらつきの問題を解決します。[ 41 ] [ 44 ]カーネルで使用できるため、ブートプロセスの開始時にも使用でき、これらの初期段階でのモード変更によるちらつきを回避できます。
KMS がカーネルの一部であるという事実は、割り込みなどカーネル空間でのみ利用可能なリソースを使用することを可能にします。[ 45 ]例えば、サスペンド/レジューム プロセスの後のモード回復は、カーネル自体によって管理されるため、非常に簡素化され、結果的にセキュリティが向上します (root 権限を必要とするユーザー空間ツールが不要になります)。カーネルはまた、新しいディスプレイ デバイスを簡単にホットプラグできるようにし、長年の問題を解決します。[ 45 ]モード設定は、フレーム バッファが基本的にメモリ バッファであるため、メモリ管理とも密接に関連しています。そのため、グラフィックス メモリマネージャとの緊密な統合が強く推奨されます。これが、カーネル モード設定コードが独立したサブシステムとしてではなく、DRM に組み込まれた主な理由です。[ 44 ]
DRM API の後方互換性を損なわないようにするため、カーネル モード設定は、特定の DRM ドライバの追加ドライバ機能として提供されています。 [ 46 ]どの DRM ドライバも、DRM コアに登録する際にDRIVER_MODESETフラグを提供することで、KMS API をサポートしていることを示すことができます。[ 8 ]カーネル モード設定を実装するドライバは、KMS のない従来のDRM ドライバと区別するために、KMS ドライバと呼ばれることがよくあります。
KMS は、3D アクセラレーションを持たない (またはハードウェア ベンダーがそれを公開または実装したくない) 特定のドライバが、DRM API の残りの部分なしで KMS API を実装するほど広く採用されており、ディスプレイ サーバー ( Waylandなど) が容易に動作できるようになっている。[ 47 ] [ 48 ]
KMS は、ディスプレイコントローラのディスプレイ出力パイプラインによく見られる一連の抽象的なハードウェアブロックとして出力デバイスをモデル化および管理します。これらのブロックは次のとおりです。[ 49 ]
近年、KMS API に関連するいくつかの通常の操作、特にモード設定とページフリップ操作にアトミック性を導入する取り組みが継続的に行われています。[ 33 ] [ 52 ]この拡張された KMS API は、アトミックディスプレイ(以前はアトミックモード設定およびアトミックまたは核ページフリップとして知られていました) と呼ばれています。
アトミックモード設定の目的は、矛盾したビデオ状態や無効なビデオ状態につながる可能性のある中間ステップを回避することで、複数の制約がある複雑な構成でモードが正しく変更されることを保証することです。[ 52 ]また、失敗したモード設定プロセスを元に戻す(「ロールバック」する)必要がある場合にも、危険なビデオ状態を回避します。[ 53 ] : 9アトミックモード設定では、モードテスト機能を提供することで、特定のモード構成が適切かどうかを事前に知ることができます。[ 52 ]アトミックモードがテストされ、その有効性が確認されると、単一の不可分な(アトミック)コミット操作で適用できます。テスト操作とコミット操作は、異なるフラグを持つ同じ新しいioctlによって提供されます。
一方、アトミックページフリップでは、同じ出力上の複数のプレーン(例えば、プライマリプレーン、カーソルプレーン、場合によってはオーバーレイやセカンダリプレーン)を、すべて同じVBLANK間隔内で同期して更新できるため、ティアリングのない適切な表示が保証されます。[ 53 ]: 9、14 [ 52 ]この要件は、電力消費を抑えるために複数のプレーン/オーバーレイを使用する傾向のあるモバイルおよび組み込みディスプレイコントローラに特に関連しています。
新しいアトミック API は、古い KMS API をベースに構築されています。同じモデルとオブジェクト (CRTC、エンコーダ、コネクタ、プレーンなど) を使用しますが、変更可能なオブジェクト プロパティの数が増加しています。[ 52 ]アトミック手順は、テストまたはコミットしたい状態を構築するために、関連するプロパティを変更することに基づいています。変更するプロパティは、モード設定 (主に CRTC、エンコーダ、コネクタのプロパティ) を行うか、ページ反転 (通常はプレーンのプロパティ) を行うかによって異なります。ioctl はどちらの場合も同じですが、違いはそれぞれに渡されるプロパティのリストです。[ 54 ]
オリジナルの DRM API では、DRM デバイスは特権操作 (モード設定、その他の表示制御) と非特権操作(レンダリング、 GPGPU計算) の両方に使用されます。 [ 9 ]セキュリティ上の理由から、関連する DRM デバイス ファイルを開くには、「root 権限と同等」の特別な権限が必要です。[ 55 ]これにより、一部の信頼できるユーザー空間プログラム (X サーバー、グラフィカル コンポジタなど) のみが、モード設定 API などの特権部分を含む DRM API に完全にアクセスできるアーキテクチャになります。レンダリングや GPGPU 計算を実行したい他のユーザー空間アプリケーションは、特別な認証インターフェイスを使用して、DRM デバイスの所有者 (「DRM マスター」) から許可される必要があります。[ 56 ]その後、認証されたアプリケーションは、特権操作なしで制限されたバージョンの DRM API を使用してレンダリングや計算を実行できます。この設計は厳しい制約を課します。他のユーザー空間プログラムがデバイスの使用を許可されるように、GPGPU 計算のようにグラフィックス表示を伴わない場合でも、DRM デバイスの DRM マスターとして機能するグラフィックス サーバー (X サーバー、Wayland コンポジタなど) が常に実行されている必要があります。[ 55 ] [ 56 ]/dev/dri/cardX
「レンダーノード」の概念は、DRM ユーザー空間 API を特権インターフェースと非特権インターフェースの 2 つのインターフェースに分割し、それぞれに個別のデバイス ファイル (または「ノード」) を使用することで、これらのシナリオを解決しようとします。[ 9 ]検出された GPU ごとに、対応する DRM ドライバ(レンダーノード機能をサポートしている場合)は、プライマリ ノードに加えて、レンダー ノードと呼ばれるデバイス ファイルを作成します。[ 56 ] [ 9 ]直接レンダリング モデルを使用するクライアントや、GPU の計算機能を活用したいアプリケーションは、既存のレンダー ノードを開き、それらのノードがサポートする DRM API の限定されたサブセットを使用して GPU 操作をディスパッチするだけで、追加の権限を必要とせずにこれを行うことができます (デバイス ファイルを開くためのファイルシステム権限がある場合)。ディスプレイ サーバー、コンポジタ、およびモードセット API またはその他の特権操作を必要とするその他のプログラムは、完全な DRM API へのアクセスを許可する標準のプライマリ ノードを開き、通常どおり使用する必要があります。レンダリングノードは、安全でない GEM グローバル名を使用したバッファ共有を防ぐために、GEM flink操作を明示的に禁止します。グラフィックスサーバーを含む他のクライアントとバッファを共有するには、PRIME (DMA-BUF)ファイルディスクリプタのみを使用できます。[ 9 ] [ 56 ]/dev/dri/renderDX/dev/dri/cardX

Linux DRMサブシステムには、デスクトップコンピュータ向けGPUの主要メーカー3社(AMD、NVIDIA、Intel)のハードウェアに加え、増加傾向にあるモバイルGPUおよびシステムオンチップ(SoC)インテグレーターのハードウェアをサポートする、フリーかつオープンソースのドライバが含まれています。各ドライバの品質は、メーカーの協力度合いやその他の要因によって大きく異なります。
また、歴史的な資料として、古い旧式ハードウェア向けのドライバもいくつかあり、次の表に詳細を記載しています。
Direct Rendering Manager はLinux カーネル内で開発されており、そのソースコードはLinux ソースコードのディレクトリにあります/drivers/gpu/drm。サブシステムのメンテナーは Dave Airlie で、他のメンテナーが特定のドライバを担当しています。[ 132 ] Linux カーネル開発では、通常どおり、DRM サブメンテナーと貢献者は、新機能とバグ修正を含むパッチをメインの DRM メンテナーに送信し、メインの DRM メンテナーはそれらを独自の Linuxリポジトリに統合します。DRM メンテナーは、新しい Linux バージョンがリリースされるたびに、メインライン化の準備ができたこれらのパッチすべてをLinus Torvaldsに提出します。カーネル全体のトップメンテナーである Torvalds は、パッチがカーネルに含めるのに適しているかどうかについて最終的な決定権を持っています。
歴史的な理由から、libdrmライブラリのソースコードはMesaプロジェクトの傘下で管理されています。[ 133 ]
1999年、Precision InsightはXFree86用のDRIを開発中に、 Mesaソースコードに含まれるLinuxカーネルパッチとして、3dfxビデオカード用のDRMの最初のバージョンを作成しました。[ 134 ]同年後半、DRMコードは、文字デバイス用のディレクトリの下、Linuxカーネル2.3.18のメインラインに取り込まれました。[ 135 ]その後数年間で、サポートされるビデオカードの数は増加しました。2001年1月にLinux 2.4.0がリリースされた時点で、3dfx Voodoo3カードに加えて、Creative Labs GMX 2000、Intel i810、Matrox G200/G400、ATI Rage 128がすでにサポートされていました。[ 136 ]このリストは2.4.xシリーズで拡大し、 ATI Radeonカード、一部のSiSビデオカード、Intel 830Mおよびそれ以降の統合GPU用のドライバが追加されました。/drivers/char/drm/
DRMをDRMコアとDRMドライバの2つのコンポーネントに分割する、いわゆるDRMコア/パーソナリティ分割は、2004年後半に行われ、[ 11 ] [ 137 ]カーネルバージョン2.6.11に統合されました。[ 138 ]この分割により、複数のデバイス用の複数のDRMドライバが同時に動作できるようになり、マルチGPUサポートへの道が開かれました。
カーネル内にすべてのビデオ モード設定コードを 1 か所にまとめるというアイデアは何年も前から認識されていましたが、[ 139 ] [ 140 ]グラフィック カードメーカーは、モード設定を行う唯一の方法は、各グラフィック カードのビデオ BIOSに含まれる、メーカー自身が提供したルーチンを使用することだと主張していました。このようなコードは x86リアル モードを使用して実行する必要があったため、保護モードで実行されているカーネルから呼び出すことができませんでした。[ 44 ] Luc Verhaegen 氏や他の開発者が、BIOS ベースではなくネイティブにモード設定を行う方法を見つけたことで状況は変わりました。[ 141 ] [ 44 ]通常のカーネル コードを使用して実行できることが示され、カーネル モード設定の基礎が築かれました。2007 年 5 月、Jesse Barnes ( Intel ) は、 drm-modesetting APIの最初の提案と、i915 DRM ドライバ内の Intel GPU 用の動作するネイティブ モード設定の実装を公開しました。[ 42 ] 2007 年 12 月、ジェローム・グリッセは ATI カード用のネイティブ モード設定コードを radeon DRM ドライバに追加し始めた。[ 142 ] [ 143 ] API とドライバの両方の作業は 2008 年中も継続されたが、フレームバッファを処理するためにカーネル空間にもメモリマネージャが必要になったため遅延した。[ 144 ]
2008 年 10 月、Linux カーネル 2.6.27 では、今後の重要な変更に先立ち、ソース コードの大幅再編成が行われました。DRM ソース コード ツリーは独自のソース ディレクトリに移動され/drivers/gpu/drm/、さまざまなドライバは独自のサブ ディレクトリに移動されました。ヘッダーも新しい/include/drmディレクトリに移動されました。[ 145 ]
ビデオメモリ管理の複雑化に伴い、この問題を解決するためのいくつかのアプローチが生まれました。最初の試みは、Thomas Hellstrom ( Tungsten Graphics ) が Emma Anholt (Intel) および Dave Airlie ( Red Hat )と共同で開発したTranslation Table Maps (TTM) メモリマネージャでした。[ 5 ] TTM は、2007 年 11 月のメインラインカーネル 2.6.25 への組み込みが提案され、[ 5 ] 2008 年 5 月にも再び提案されましたが、 Graphics Execution Manager (GEM)と呼ばれる新しいアプローチが採用されたため、見送られました。[ 24 ] GEM は、Intel の Keith Packard と Emma Anholt が、i915 ドライバのメモリ管理をよりシンプルにするためのソリューションとして最初に開発しました。[ 6 ] GEM は好評を博し、2008 年 12 月にリリースされた Linux カーネル バージョン 2.6.28 に統合されました。[ 146 ]一方、TTM は新しい Radeon KMS DRM ドライバの要件として、最終的に Linux 2.6.31 に統合されるまで 2009 年 9 月まで待たなければなりませんでした。[ 147 ]
バッファ オブジェクトを処理するためのメモリ管理が実装されたことで、DRM 開発者は、モード設定を行うための既に完成している API とコードをカーネルに追加できるようになりました。この拡張された API はカーネル モード設定(KMS)と呼ばれ、これを実装するドライバはKMS ドライバと呼ばれることがよくあります。2009 年 3 月、KMS は、 i915 ドライバの KMS サポートとともに、Linux カーネル バージョン 2.6.29 に統合されました。 [ 30 ] [ 148 ] [ 149 ] KMS API は、libdrm 2.4.3 以降、ユーザー スペース プログラムに公開されています。[ 150 ] Intel グラフィックス カード用のユーザー スペースX.Org DDXドライバも、新しい GEM および KMS API を最初に使用しました。[ 151 ] radeon DRM ドライバの KMS サポートは、2009 年 9 月の Linux 2.6.31 リリースに追加されました。[ 152 ] [ 153 ] [ 154 ]新しい radeon KMS ドライバは TTM メモリマネージャを使用しましたが、TTM の代わりに GEM 互換のインターフェイスと ioctl を公開しました。[ 23 ]
2006年以来、nouveauプロジェクトは公式Linuxカーネルとは別にNVIDIA GPU用のフリーソフトウェアDRMドライバを開発していた。2010年、nouveauのソースコードは実験的なドライバとしてLinux 2.6.33にマージされた。 [ 58 ] [ 59 ]マージ当時、ドライバはすでにKMSに変換されており、GEM APIの背後ではメモリマネージャとしてTTMを使用していた。[ 155 ]
GEM API を含む新しい KMS API は、DRMの開発における大きなマイルストーンでしたが、その後数年間で API が強化されるのを止めることはありませんでした。KMS は、Linux 2.6.33 [ 156 ] [ 157 ]で非同期VBLANK通知と連携したページ フリップのサポートを獲得しました。これは i915 ドライバのみで、radeon と nouveau は後に Linux 2.6.38 リリースで追加しました。[ 158 ]新しいページ フリップ インターフェイスは libdrm 2.4.17 に追加されました。[ 159 ] 2011 年初頭、Linux 2.6.39 リリース サイクル中に、いわゆるダム バッファ(フレーム バッファとして使用するのに適した単純なバッファを処理するハードウェアに依存しない非アクセラレーション方式)が KMS API に追加されました。[ 160 ] [ 161 ]目標は、ドライバ固有の ioctl によって提供される特別な高速化操作を使用する必要のないPlymouthなどのアプリケーションの複雑さを軽減することでした。 [ 162 ]この機能は、バージョン 2.4.25 以降、libdrm によって公開されました。[ 163 ]その年の後半には、プレーンと呼ばれる新しいメインタイプのオブジェクトも追加されました。プレーンは、スキャンアウト エンジンによってサポートされているハードウェア オーバーレイを表すために開発されました。[ 164 ] [ 165 ]プレーンのサポートは、Linux 3.3 [ 166 ]および libdrm 2.4.30に統合されました。 Linux 3.5 [ 167 ]および libdrm 2.4.36 [ 168 ]リリース中にAPI に追加されたもう 1 つの概念は、汎用オブジェクト プロパティで、任意の KMS オブジェクトに汎用値を追加する方法です。プロパティは、CRTCや飛行機などのオブジェクトに特別な動作や機能を設定する際に特に役立ちます。
DRM ドライバ間で GPU オフロードを提供する初期の概念実証は、2010 年に Dave Airlie によって開発されました。[ 7 ] [ 169 ] Airlie はNVIDIA Optimusテクノロジーを模倣しようとしていたため、それを「PRIME」と名付けることにしました。[ 7 ] Airlie は 2011 年後半に PRIME の作業を再開しましたが、Linux カーネル 3.3 で導入された新しいDMA-BUFバッファ共有メカニズムに基づいています。 [ 170 ]基本的な DMA-BUF PRIME インフラストラクチャは 2012 年 3 月に完成し[ 171 ]、Linux 3.4 リリース[ 172 ] [ 173 ] [ 174 ]および libdrm 2.4.34 [ 175 ]に統合されました。その後、Linux 3.5 リリース中に、Intel カード用の i915、AMD カード用の radeon、NVIDIA カード用の nouveau など、いくつかの DRM ドライバが PRIME サポートを実装しました。[ 176 ] [ 177 ]
近年、DRM API は新しい機能や改良された機能で段階的に拡張されてきました。2013 年、GSoCの一環として、David Herrmann はマルチレンダーノード機能を開発しました。[ 55 ]彼のコードは、実験的な機能として Linux カーネル バージョン 3.12 に追加され[ 178 ] [ 179 ] 、i915 [ 180 ] 、 radeon [ 181 ]、nouveau [ 182 ]ドライバーでサポートされ、Linux 3.17 以降はデフォルトで有効になっています。[ 77 ] 2014 年、Matt Roper (Intel) は、フレームバッファ(プライマリ プレーン)、オーバーレイ (セカンダリプレーン)、カーソル (カーソル プレーン) をすべて統一された API を持つ単一のタイプのオブジェクトとして扱うユニバーサル プレーン (または統合プレーン)の概念を開発しました。 [ 183 ] ユニバーサル プレーンのサポートにより、より少ない汎用的なioctlで一貫性のある DRM API が提供されます。[ 33 ] API の後方互換性を維持するために、この機能は DRM コアによって、DRM ドライバが提供できる追加機能として公開されています。ユニバーサルプレーンのサポートは、Linux 3.15 [ 184 ]および libdrm 2.4.55 [ 185 ]で初めて導入されました。Intel i915 [ 186 ]など、いくつかのドライバは既にこれを実装しています。
最新の DRM API の強化は、アトミック モード設定API であり、DRM デバイスでのモード設定とページ反転操作にアトミック性をもたらします。モード設定用のアトミック API のアイデアは、2012 年初頭に初めて提案されました。 [ 187 ] Ville Syrjälä (Intel) が、このようなアトミック API の設計と実装のタスクを引き継ぎました。[ 188 ]彼の作業に基づいて、Rob Clark ( Texas Instruments ) は、アトミック ページ反転を実装することを目指して同様のアプローチを取りました。[ 189 ]その後 2013 年に、提案された両方の機能が、両方のタスクに単一の ioctl を使用して単一の機能に統合されました。[ 190 ]要件であったため、この機能は、2014 年半ばにユニバーサル プレーンのサポートがマージされるまで待つ必要がありました。[ 186 ] 2014 年後半には、既存の KMS ドライバを新しいアトミック フレームワークに移行しやすくするために、 Daniel Vetter (Intel) や他の DRM 開発者[ 191 ] : 18によってアトミック コードが大幅に強化されました。 [ 192 ]この作業はすべて、最終的に Linux 3.19 [ 193 ]および Linux 4.0 [ 194 ] [ 195 ] [ 196 ]リリースに統合され、Linux 4.2 以降はデフォルトで有効になっています。[ 197 ] libdrm はバージョン 2.4.62 以降、新しいアトミック API を公開しています。[ 198 ]複数のドライバがすでに新しいアトミック API に変換されています。[ 199 ] 2018 年までに、この新しいアトミック モデルに基づく 10 個の新しい DRM ドライバが Linux カーネルに追加されました。[ 200 ]
Direct Rendering Manager カーネルサブシステムは、当初、 XFree86 4.0 ディスプレイサーバーの新しいDirect Rendering Infrastructureで使用するために開発され、後に後継のX.Org Serverに引き継がれました。そのため、DRM の主なユーザーは、Mesa 3DライブラリにあるハードウェアアクセラレーションされたOpenGL実装にリンクする DRI クライアントと X Server 自体でした。現在では、 Westonリファレンス コンポジタを含むいくつかのWayland コンポジタでも DRM が使用されています。kmsconは、DRM KMS 機能を使用してユーザー空間で実行される仮想コンソール実装です。[ 201 ]
2015年に、Nvidia GeForceの独自ドライバのバージョン358.09(ベータ版)は、と呼ばれる新しいカーネルブロブとして実装されたDRMモード設定インターフェイスのサポートを受けましたnvidia-modeset.ko。この新しいドライバコンポーネントは、カーネルモジュールと連携してnvidia.koGPUのディスプレイエンジン(つまりディスプレイコントローラ)をプログラムします。[ 202 ]
{{cite web}}: CS1メンテナンス: アーカイブサービスは非推奨になりました (リンク){{cite web}}: CS1メンテナンス: アーカイブサービスは非推奨になりました (リンク)GEMは基本的にグラフィックスバッファオブジェクト(テクスチャ、レンダーバッファ、シェーダー、またはGPUで使用されるその他のあらゆる種類の状態オブジェクトとデータを含むことができる)を扱います。
flinkには多くの問題があります。flink名はグローバルであるため、デバイスにアクセスできる人は誰でもflinkデータコンテンツにアクセスできます。
gem-flink は、アプリケーションやサーバーにプライベート名前空間を提供しません。代わりに、DRM ノードごとに 1 つのグローバル名前空間のみが提供されます。悪意のある認証済みアプリケーションは、gem バッファのブルートフォース「名前推測」によって他のクライアントを攻撃することができます。
多くの最新のハイエンドGPUには独自のメモリマネージャが付属しています。アクセス時に同期する必要のある複数の異なるキャッシュも含まれています。[...]。したがって、GPUのメモリ管理はドライバとハードウェアに大きく依存します。
グラフィックカードはさまざまな方法でプログラムされますが、初期化とモード設定のほとんどはメモリマップドIOを介して行われます。これは、CPUが標準メモリアドレス空間を介してアクセスできるレジスタのセットです。このアドレス空間のレジスタは、モード設定、出力制御、クロック構成など、グラフィックカードのさまざまな機能を扱う範囲に分割されています。
従来、Xサーバーは起動時に出力状態を保存し、テキストモードに切り替わったときにそれを復元する役割を担っていました。高速なユーザー切り替えはVTスイッチで行われ、最初のユーザーのXサーバーから切り替えると、テキストモードに切り替わるために1回点滅し、すぐに2番目のユーザーのセッションに切り替わるために再び点滅しました。
より微妙な制限としては、ドライバが割り込みを処理できなかったため、ホットプラグ モニターのサポートがなかったことが挙げられる。
DRM/KMS ドライバは、DMA なしでは完全に動作するようになりました。ああ、Rust で書かれていますが、ほとんどが安全でない生のブロックでいっぱいです。
素晴らしいのは、通常の DRM/KMS ドライバー (および @emersion@hackerspace.pl の助け) があるので、次のようなことができます... iPod Nano 5G で Wayland! Weston を実行します。
管理チップHi1710に統合されたオンボードディスプレイチップを使用し、SM750のIPコアを使用しています。
drm/panthor ドライバと各種修正を追加。
この問題に対する最善の解決策は、カーネルが各ビデオハードウェアに対して単一の包括的なデバイスドライバを提供することだと私は考えています。これは、fbdevやDRMのような競合するドライバを協調システムに統合する必要があることを意味します。また、カーネルベースのデバイスドライバがロードされている間は、ユーザー空間からハードウェアを操作できないようにする必要があることも意味します。
現在、アトミックモード設定をサポートするドライバが17個あり、DRMサブシステムに統合されています。