我正在尝试创建支持全屏模式的 Direct3D 10/11 应用程序。为此,我必须向用户提供可用视频模式的列表。此外,最好选择当前桌面设置作为默认视频模式,以最大程度地减少视频模式更改。
在 Direct3D 9 中执行此操作非常简单。例如,这是我的模式列表,由 Direct3D 9 提供:
Current mode: 1920x1080x60Hz 32bit X8R8G8B8
Available modes:
Front buffer format 32bit X8R8G8B8: 35
1: 1920x1080x60Hz
2: 640x480x60Hz
3: 640x480x72Hz
4: 640x480x75Hz
5: 720x480x56Hz
6: 720x480x60Hz
7: 720x480x72Hz
8: 720x480x75Hz
9: 720x576x56Hz
10: 720x576x60Hz
11: 720x576x72Hz
12: 720x576x75Hz
13: 800x600x56Hz
14: 800x600x60Hz
15: 800x600x72Hz
16: 800x600x75Hz
17: 1024x768x60Hz
18: 1024x768x70Hz
19: 1024x768x75Hz
20: 1152x864x75Hz
21: 1280x720x60Hz
22: 1280x768x60Hz
23: 1280x800x60Hz
24: 1280x960x60Hz
25: 1280x1024x60Hz
26: 1280x1024x75Hz
27: 1360x768x60Hz
28: 1366x768x60Hz
29: 1600x900x59Hz
30: 1600x900x60Hz
31: 1600x1024x59Hz
32: 1600x1024x60Hz
33: 1680x1050x59Hz
34: 1680x1050x60Hz
35: 1440x900x60Hz
但是通过 DXGI 做同样简单的事情有点复杂。最让我困惑的是,IDXGIOutpit.GetDisplayModeList方法最多返回 3 个相同视频模式的副本。不同之处在于提供的缩放模式:
DXGI_MODE_SCALING_UNSPECIFIED = 0
DXGI_MODE_SCALING_CENTERED = 1
DXGI_MODE_SCALING_STRETCHED = 2
这里是:
List of modes for format 32bit R8G8B8A8 UNorm:
640x480x60Hz Progressive Unspecified
640x480x72Hz Progressive Unspecified
640x480x75Hz Progressive Unspecified
720x480x56Hz Progressive Unspecified
720x480x56Hz Progressive Centered
720x480x56Hz Progressive Stretched
720x480x60Hz Progressive Unspecified
720x480x60Hz Progressive Centered
720x480x60Hz Progressive Stretched
720x480x72Hz Progressive Unspecified
720x480x72Hz Progressive Centered
720x480x72Hz Progressive Stretched
720x480x75Hz Progressive Unspecified
720x480x75Hz Progressive Centered
720x480x75Hz Progressive Stretched
720x576x56Hz Progressive Unspecified
720x576x56Hz Progressive Centered
720x576x56Hz Progressive Stretched
720x576x60Hz Progressive Unspecified
720x576x60Hz Progressive Centered
720x576x60Hz Progressive Stretched
720x576x72Hz Progressive Unspecified
720x576x72Hz Progressive Centered
720x576x72Hz Progressive Stretched
720x576x75Hz Progressive Unspecified
720x576x75Hz Progressive Centered
720x576x75Hz Progressive Stretched
800x600x56Hz Progressive Unspecified
800x600x60Hz Progressive Unspecified
800x600x72Hz Progressive Unspecified
800x600x75Hz Progressive Unspecified
1024x768x60Hz Progressive Unspecified
1024x768x70Hz Progressive Unspecified
1024x768x75Hz Progressive Unspecified
1152x864x75Hz Progressive Unspecified
1280x720x60Hz Progressive Unspecified
1280x768x59Hz Progressive Unspecified
1280x768x59Hz Progressive Centered
1280x768x59Hz Progressive Stretched
1280x800x59Hz Progressive Unspecified
1280x960x60Hz Progressive Unspecified
1280x1024x60Hz Progressive Unspecified
1280x1024x75Hz Progressive Unspecified
1360x768x59Hz Progressive Unspecified
1360x768x59Hz Progressive Centered
1360x768x59Hz Progressive Stretched
1366x768x59Hz Progressive Unspecified
1366x768x59Hz Progressive Centered
1366x768x59Hz Progressive Stretched
1440x900x59Hz Progressive Unspecified
1600x900x59Hz Progressive Unspecified
1600x900x59Hz Progressive Centered
1600x900x59Hz Progressive Stretched
1600x1024x59Hz Progressive Unspecified
1600x1024x59Hz Progressive Centered
1600x1024x59Hz Progressive Stretched
1680x1050x59Hz Progressive Unspecified
1920x1080x60Hz Progressive Unspecified
首先我想,DXGI_MODE_SCALING_STRETCHED = 这个模式需要拉伸(后缓冲区小,然后前一个,分辨率可能不是物理的),DXGI_MODE_SCALING_CENTERED = 在这个模式下图像可能不会占据整个屏幕(后缓冲区小,然后前一个,但保留物理分辨率),DXGI_MODE_SCALING_UNSPECIFIED = "正常模式"(前后缓冲区大小匹配,但不保证物理分辨率)。即我应该只列出那些具有 Scaling = DXGI_MODE_SCALING_UNSPECIFIED 的模式。
但后来我试图确定当前模式。根据 MSDN,当使用IDXGIOutput.FindClosestMatchingMode方法时,如果您未指定其中一个参数,则此方法会倾向于当前桌面设置,优先考虑已设置的参数并使用某种优先级(ScanlineOrdering>Scaling>Format> Resolution>RefreshRate) 来选择其他的。所以我创建了设备(为了能够将格式指定为 DXGI_FORMAT_UNKNOWN)并将完全未确定的模式传递给此方法(包括 Scaling = DXGI_MODE_SCALING_UNSPECIFIED)。
结果如下:
Suggested mode: 32bit B8G8R8A8 UNorm 1600x1024x59Hz Progressive Stretched
Suggested mode 1.1: 32bit B8G8R8A8 UNorm 1600x1024x59Hz Progressive Stretched Mono
如您所见,它与当前的桌面模式(即 1920x1080x60Hz)不匹配。我尝试将当前桌面模式更改为不同的模式并发现,IDXGIOutput.FindClosestMatchingMode倾向于选择最接近的可用模式,其参数接近桌面参数,但使用 Scaling = DXGI_MODE_SCALING_STRETCHED,只需忽略 Scaling = DXGI_MODE_SCALING_UNSPECIFIED,由我。
Current mode: 32bit B8G8R8A8 UNorm 1024x768x75Hz Progressive Unspecified
Suggested mode: 32bit B8G8R8A8 UNorm 1280x768x59Hz Progressive Stretched
Suggested mode 1.1: 32bit B8G8R8A8 UNorm 1280x768x59Hz Progressive Stretched Mono
这使我得出了一个惊人的结论,至少对于IDXGIFactory.CreateSwapChain方法,DXGI_MODE_SCALING_UNSPECIFIED 被视为 Scaling 参数的无效值(否则为什么IDXGIOutput.FindClosestMatchingMode用于选择模式,在大多数情况下将提供给IDXGIFactory.CreateSwapChain,拒绝选择1920x1080x60Hz?)。
我猜IDXGIFactory.CreateSwapChain甚至在内部调用IDXGIOutput.FindClosestMatchingMode来确定使用哪种“物理”模式。但是……那是什么意思?我无法提供没有 Scaling = DXGI_MODE_SCALING_CENTERED 或 DXGI_MODE_SCALING_STRETCHED 给用户的模式,因为这种模式不是“物理”模式 - 即IDXGIFactory.CreateSwapChain无论如何都会选择其他模式?
但是为什么 DXGI_MODE_SCALING_UNSPECIFIED 在可用模式列表中返回呢?如果仅在调用IDXGIFactory.CreateSwapChain方法时使用缩放参数来指定我要居中图像还是缩放它,如果提供的模式不匹配任何“物理”模式并且在调用IDXGISwapChain.ResizeTarget时未使用,因为此方法需要“仅物理”模式,那么为什么缩放参数混合在一个列表中,由IDXGIOutpit.GetDisplayModeList返回?
我应该向用户展示哪些模式?只有那些,有缩放<> DXGI_MODE_SCALING_UNSPECIFIED?还是我应该做相反的事情?以及如何通过 DXGI 本身确定当前模式,而不是使用传统的 Win API?
谁能给我解释一下?因为在 MSDN 中没有任何澄清。