Windows.Devices.Display.Core API は、Windows のディスプレイ アダプターとディスプレイ ターゲットを列挙、構成、および駆動するための他のすべてのパブリック API の下にある、サードパーティのコンポジターおよび内部 Windows コンポーネント用の低レベルのWindows ランタイム (WinRT) API です。 この考え方は、ディスプレイ コントローラーを GPU 上の 3D エンジンとメディア エンジンに似た別のエンジンとして扱うことです。 この API の役割は次のとおりです。
- 表示ハードウェアに関するクエリへの回答 (機能や表示モードなど)
- 現在の構成に関するクエリへの応答
- ディスプレイ ハードウェアのプロパティの設定 (表示モードなど)
- ディスプレイ ハードウェアの構成 (接続されたモニターの解像度、ネットワーク形式など)
- プライマリと呼ばれる特殊な GPU サーフェスの割り当てとスキャン
- Direct3D と Windows.Devices.Display.Core API の間の相互運用を許可する (サーフェス、フェンスの共有など)
Windows.Devices.Display.Core にはないものを呼び出す価値があります。
- これは、ゲームやアプリがウィンドウにコンテンツを表示するために使用する API ではありません。 アプリは引き続き DXGI、XAML、コンポジション API、GDI などを使用します。
- これは、コンテンツを全画面表示するためにゲームやアプリで使用される API ではありません。 アプリは引き続き DXGI を使用し、Win32 アプリは HWND を引き続き使用し、UWP アプリは常に CoreWindow にコンテンツを表示します。
この API は、特殊なハードウェアのみを駆動するコンポジター アプリ用です。
カスタム コンポジターを構築するためのシナリオ
Windows.Devices.Display.Core API は、次のシナリオで使用するのが適切です。
- ディスプレイ コントローラーを直接駆動し、Windows デスクトップとは別のタイミングとモード構成をきめ細かく制御できる独自のコンポジターを必要とする仮想および拡張現実ディスプレイ。
- 商用設定でディスプレイを専用に制御する必要がある特殊なディスプレイ ハードウェア シナリオ。 例えば、ハードウェアの反り、グレースケールディスプレイなどで、Windows デスクトップがこのようなディスプレイに正しくレンダリングできない場合などです。
- モニターが長時間にわたって Windows デスクトップ エクスペリエンスからの干渉なしにアプリに完全に専用される特殊な "アプライアンス" シナリオ (専用ビデオ モニターなど)。
API は、次の方法でこれを実現します。
- ワイヤフォーマット、HDRなどのフルディスプレイモード情報をきめ細かく制御します。
- フェンスを使用してプレゼンテーションを同期すると、コンポジターは、パフォーマンスのオーバーヘッドがほぼゼロのプロセスまたはサブコンポーネント間でプレゼンテーションを連結できます。
- 基になる Video Present Network (VidPN) に対してクエリを実行して構成する機能が向上し、システム コンポーネントと低レベルコンポジション コンポーネントの両方で、エラーが発生しやすく拡張可能な方法でより複雑な操作を実行できるようになります。
この API は、特殊なハードウェアを使用する 非常に具体的なサードパーティのユース ケースのセット に対してのみであることに注意してください。 その使用は、この API の機能を必要とすることを宣言するハードウェアに非常に制限されています。 そのため、ハードウェアの概念に関する一定の知識が開発者から期待されており、パートナーは Microsoft に直接連絡して問題を解決する必要があります。
ハードウェアとソフトウェアの要件
サードパーティのカスタムコンポジターは、ヘッドマウントディスプレイ(HMD)または「特殊化」ディスプレイとして事前に指定されたディスプレイのみを取得できます。 この指定は、次の 2 つの方法のいずれかで指定する必要があります。
- EDID 拡張機能 - HMD、X 線モニター、ビデオウォール、またはその他の特殊なシナリオとして永続的に使用するように設計されたカスタム ディスプレイ デバイスは、ヘッドマウントおよび特殊化されたディスプレイ用の Microsoft EDID 拡張機能を実装する必要があります。
- ユーザーのオーバーライド - 既製のモニターを使用するカスタム ハードウェア インストールの場合、Windows にはモニターを "特殊化" として指定するための UI トグルが用意されています。
ソフトウェアで EDID をオーバーライドすることで、ディスプレイを HMD または特殊なディスプレイとして指定することはできません 。
Note
特殊化されたディスプレイは Windows 10 バージョン 2004 以降でのみ使用でき、Windows 10 Enterprise、Windows 10 Pro for Workstations、または Windows 10 IoT Enterprise が必要です。
カスタム コンポジターを実装するためのロードマップ
カスタム コンポジターの実装は、いくつかの段階に分けることができます。
- 関連付けられている HMD または特殊なディスプレイを列挙して検出する
- 選択したディスプレイの所有権を取得する
- 選択したすべてのディスプレイのモードを構成する
- ディスプレイにフレームを表示するためのリソースを作成する
- コンテンツのレンダリングとフレーム プレゼンテーションのスケジュール設定
表示関連 API の比較
API | 目的と対象ユーザー |
---|---|
DisplayInformation | CoreWindow のレンダリングプロパティとレイアウトプロパティを取得するために使用します。 |
HdmiDisplayInformation | 制限付きモードのセットを列挙および設定するための Xbox 専用 API。 Xbox メディア アプリのシナリオに特化しています。 |
DisplayMonitor | 物理モニター デバイスのプロパティのクエリに使用されます。 OS によってモニターがどのように構成されているか、現在使用されているかに関するランタイム情報は公開しません。 |
EnumDisplayDevices、EnumDisplayMonitors、EnumDisplaySettingsEx | HMONITOR、GDI デバイス、および物理モニター マッピングのクエリを実行するためのレガシ Win32 API。 ここで返される情報は高度に仮想化され、アプリケーションの互換性のためにメイン含まれます。 |
Direct3D | GPU サーフェスにピクセル コンテンツをレンダリングし、GPU で計算を実行するために使用されます。 |
DXGI スワップ チェーン | ウィンドウ表示と罫線なしのウィンドウ全画面表示プレゼンテーションに使用されます。 アプリ スワップ チェーンのコンテンツは、システム コンポジター DWM を介してフローします。 |
DXGI 出力列挙 | HMONITOR の DXGI ラッパーを提供します。 |
QueryDisplayConfig、 SetDisplayConfig、 DisplayConfigGetDeviceInfo、 DisplayConfigSetDeviceInfo | 表示トポロジを構成するための Win32 API。 複数のモードを列挙するメカニズムはありませんが、現在の構成と設定に関する豊富な情報セットがあります。 ただし、モードのすべての新しいプロパティがこれらの API によって公開されるわけではありません。 |
Windows.Devices.Display.Core (このドキュメント) | ターゲットの列挙、モードの列挙、モードの構成、プレゼンテーション用の GPU サーフェスの割り当て、および表示するコンテンツの表示に使用されます。 |
表示構成の概要
物理ハードウェアの列挙
Windows.Devices.Display.Core API には、物理ハードウェア オブジェクトを表すさまざまなオブジェクトがあります。 DisplayAdapter は通常、PCI Express に接続された GPU や CPU 上の統合 GPU などの物理ハードウェア デバイスです (ただし、必ずしもではありません)。 DisplayTarget オブジェクトは、GPU から接続できる物理コネクタ (HDMI、VGA、DisplayPort など) を表します。 これには、内部モニター (ノート PC、タブレットなど) を搭載したデバイスの内部の非ユーザー表示接続が含まれる場合があります。 ソフトウェアで表される DisplayTarget オブジェクトの数が、ユーザーが一度に物理的に接続できる数よりも多い場合があります。 たとえば、DisplayPort 接続標準では、ダイズ チェーンが可能であるため、GPU ドライバーは通常、チェーンされたモニターを考慮するために物理ポートごとに複数の DisplayPort ターゲットを列挙します。
モードを設定するためのオブジェクト
DisplayTarget オブジェクトを列挙する場合、設定モードやクエリ モードなど、DisplayTarget オブジェクトへの接続は DisplayPath オブジェクトで表されます。 同じコンテンツを表示するパスのグループ (複製グループ) は DisplayView で表され、これらは DisplayState に集計されます。 従って、1 つの DisplayState オブジェクトは、複数のモニターのドライバーに送信できるモード状態の完全なセットを表すことができます。
モード構成と列挙のアトミック状態
Windows.Devices.Display.Core API は、コンポジターがさまざまなシステム表示状態へのアクセスをアトミックかつ明確に定義された制約動作で確実に取得できるように設計されています。 GPU は共有リソースであり、帯域幅と電力の制約が非常に厳しいため、これは重要です。 最新のシステムでは、デバイスはいつでも到着/出発でき、その他のものが使用可能な表示モード (ドッキング/ドッキング解除、スリープ状態、別のパスの別のコンポーネント変更モードなど) の一覧に影響を与える可能性があります。 そのため、コンポジターは、Windows.Devices.Display.Core API を使用し、状態を構成するために推奨される次のパターンを使用して、システム構成の変更に対する回復性を持たせることが重要です。
そのため、Windows.Devices.Display.Core API は、データベースと同様の単純なトランザクション読み取り/変更コミット モデルを提供します。 クライアントは、システム内のディスプレイ デバイスの DisplayState オブジェクトをアトミックに読み取ることができます。 すべてのオブジェクトは不変であるか、システムに状態を更新/コミットするための適切に定義された API を提供します。 変更は、DisplayState.TryApply が呼び出されるまで 行われず、システムに 変更が "コミット" されます。 DisplayState に対する変更のコミット/適用は、影響を受けずに失敗するか、完全な変更が適用された状態で成功します。
API のアトミック機能を利用するには:
- 再試行ループでモード構成ロジックを記述します 。
- 各ループ内で、モード構成の先頭に新しい DisplayState を作成します 。
- DisplayState.TryApply を呼び出すときに FailIfStateChanged フラグを使用して、システム状態が DisplayState の作成時と同じでなくなったことを検出します。 これにより、操作を再試行できます。 SystemStateChanged で操作が失敗した場合は、ループ全体を再試行してください。
- 状態を読み取ったり変更したりする他の API (DXGI、GDI など) と Windows.Devices.Display.Core API の使用は混在しないでください 。これは、同じ原子性の保証がない可能性があるためです。
#include <winrt\Windows.Devices.Display.Core.h>
using namespace winrt::Windows::Devices::Display::Core;
...
// Create a DisplayManager
DisplayManager manager = DisplayManager::Create(DisplayManagerOptions::EnforceSourceOwnership);
// Loop around trying to acquire a target and set a mode
bool shouldRetry;
do
{
shouldRetry = false;
// ... Find the target that you want to use
auto targets = manager.GetCurrentTargets();
DisplayTarget selectedTarget = ...;
auto stateCreationResult = manager.TryAcquireTargetsAndCreateEmptyState(
winrt::single_threaded_vector<DisplayTarget>({ selectedTarget }));
if (stateCreationResult.ErrorCode() != DisplayManagerResult::Success)
{
winrt::check_hresult(stateCreationResult.ExtendedErrorCode());
}
auto state = stateCreationResult.State();
DisplayPath newPath = state.ConnectTarget(selectedTarget);
// ... Configure the path
auto applyResult = state.TryApply(DisplayStateApplyOptions::FailIfStateChanged);
if (applyResult.Status() == DisplayStateOperationStatus::SystemStateChanged)
{
shouldRetry = true;
}
else if (applyResult.Status() != DisplayStateOperationStatus::Success)
{
winrt::check_hresult(applyResult.ExtendedErrorCode());
}
} while (shouldRetry);
次の API は、システムから状態をアトミックに読み取ります。
- DisplayManager
- DisplayState
- DisplayPath
- DisplayTarget
次の API は、状態をシステムにコミットします。
- DisplayManager
- TryAcquireTarget/ReleaseTarget (および
TryAcquireTargetsAnd*
メソッドを使用した ターゲットの取得) システムから DisplayTargets の所有権を取得します。
- TryAcquireTarget/ReleaseTarget (および
- DisplayState
- TryApply は、ディスプレイ ドライバーを介して、システム内のすべての所有ターゲットのモードを設定またはクリアすることで、現在のシステムの表示状態を更新します。
既知の制限事項
Windows.Devices.Display.Core API には、いくつかの既知の制限があります (Windows 10 バージョン 2004 以降)。
- 間接ディスプレイ ドライバー (Miracast、USB ディスプレイ アダプター、ソフトウェア ドライバーなど) は現在対処できません。 DisplayManager.CreateDisplayDevice は、間接ディスプレイ アダプターに合格すると失敗します。
サンプル コード
サンプル アプリケーションについては、Windows.Devices.Display.Core カスタム コンポジターのサンプルをご参照ください。