模式配置和枚举的原子状态
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
- GetCurrentTargets
- GetCurrentAdapters
- TryReadCurrentStateForAllTargets/TryAcquireTargetsAndReadCurrentState
- DisplayState
- IsStale
- TryFunctionalize
- DisplayPath
- FindAllModes
- DisplayTarget
- DisplayTarget.IsStale
以下 API 将状态提交回系统:
- DisplayManager
- TryAcquireTarget ReleaseTarget/ (并使用方法获取目标TryAcquireTargetsAnd*)从系统获取 DisplayTargets 的所有权。
- DisplayState
TryApply 通过显示驱动程序在系统中所有拥有的目标上设置或清除模式来更新当前系统显示状态。