헤드 탑재 및 특수 모니터용 사용자 지정 작성기 앱 빌드
Windows.Devices.Display.Core API는 Windows에서 디스플레이 어댑터 및 디스플레이 대상을 열거, 구성 및 구동하기 위해 다른 모든 공용 API 아래에 있는 타사 작성자 및 내부 Windows 구성 요소에 대한 하위 수준 Windows 런타임(WinRT) API입니다. 이 아이디어는 디스플레이 컨트롤러를 GPU의 3D 엔진 및 미디어 엔진과 유사한 별도의 엔진으로 처리하는 것입니다. 이 API는 다음을 담당합니다.
- 디스플레이 하드웨어에 대한 쿼리 응답(예: 기능 및 가능한 디스플레이 모드)
- 현재 구성에 대한 쿼리 응답
- 디스플레이 하드웨어에서 속성 설정(예: 디스플레이 모드)
- 디스플레이 하드웨어 구성(연결된 모니터의 해상도, 와이어 형식 등)
- 주 복제본이라고 하는 특수 GPU 표면 할당 및 검사
- Direct3D와 Windows.Devices.Display.Core API 간의 interop 허용(예: 화면 공유, 펜스)
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 등 전체 디스플레이 모드 정보에 대한 세분화된 제어 제공
- 펜스를 사용하여 프레젠테이션을 동기화하면 작성자가 거의 성능 오버헤드가 거의 없는 프로세스 또는 하위 구성 요소 간에 프레젠테이션을 연결할 수 있습니다.
- 기본 VidPN(Video Present Network)을 쿼리하고 구성하는 기능을 개선하여 시스템 구성 요소와 낮은 수준의 컴퍼지션 구성 요소가 모두 오류가 발생하기 쉽고 확장 가능한 방식으로 더 복잡한 작업을 수행할 수 있도록 합니다.
이 API는 특수 하드웨어를 사용하는 매우 구체적인 타사 사용 사례 집합 에만 해당됩니다. 해당 사용은 이 API의 기능이 필요하다고 선언하는 하드웨어로 매우 제한됩니다. 따라서 개발자는 하드웨어 개념에 어느 정도 익숙해져야 하며 파트너는 문제를 해결하기 위해 Microsoft에 직접 문의해야 합니다.
하드웨어 및 소프트웨어 요구 사항
타사 사용자 지정 작성자는 헤드 탑재 디스플레이(HMD) 또는 "특수" 디스플레이로 미리 지정된 디스플레이만 획득할 수 있습니다. 이 지정은 다음 두 가지 방법 중 하나로 제공되어야 합니다.
- EDID 확장 - HMD, X선 모니터, 비디오 벽 또는 기타 특수 시나리오로 영구적으로 사용하도록 설계된 사용자 지정 디스플레이 디바이스는 헤드 탑재 및 특수 디스플레이용 Microsoft EDID 확장을 구현해야 합니다.
- 사용자 재정 의 - 기존 모니터를 사용하는 사용자 지정 하드웨어 설치의 경우 Windows는 모니터를 "특수화됨"으로 지정하기 위한 UI 토글을 제공합니다.
소프트웨어에서 EDID를 재정의하여 디스플레이를 HMD 또는 특수 디스플레이로 지정할 수 없습니다 .
참고 항목
특수 디스플레이는 Windows 10 버전 2004부터만 사용할 수 있으며 Windows 10 Enterprise, 워크스테이션용 Windows 10 Pro 또는 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 등)를 나타냅니다. 여기에는 내부 모니터(노트북, 태블릿 등)가 있는 디바이스에 대한 사용자가 볼 수 없는 내부 연결이 포함될 수 있습니다. 사용자가 한 번에 물리적으로 연결할 수 있는 것보다 소프트웨어에 표시되는 DisplayTarget 개체가 더 많을 수 있습니다. 예를 들어 DisplayPort 연결 표준에서는 데이지 체인을 허용하므로 GPU 드라이버는 일반적으로 연결된 모니터를 고려하기 위해 실제 포트당 여러 DisplayPort 대상을 열거합니다.
모드를 설정하기 위한 개체
DisplayTarget 개체, 설정 및 쿼리 모드 등을 열거하는 경우 DisplayTarget 개체에 대한 연결은 DisplayPath 개체로 표시됩니다. 동일한 콘텐츠(복제 그룹)를 표시하는 경로 그룹은 DisplayView로 표시되며 DisplayState로 집계됩니다. 따라서 하나의 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 사용자 지정 작성기 샘플을 참조하세요.