OpenGL和Windows 10每监视器感知DPI扩展

时间:2017-11-01 06:52:45

标签: opengl windows-10 dpi

当应用程序具有DPI监视器感知功能时,在OpenGL应用程序中处理DPI扩展的正确方法是什么。又名:

SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);

我在不同设备上发现了不同的行为 - 可能与驱动程序有关,但有些机器需要像这样设置视口:

glViewport(0, 0, prc->right, prc->bottom)

而其他人则需要这样的事情:

glViewport(0, 0, (int)(prc->right * 96 / dpi), (int)(prc->bottom * 96 / dpi));

(其中prc是客户端rect,dpi是窗口的当前DPI)。

我整理了一个显示问题的simple demo program。在更改系统缩放之后,但在退出/退回之前会出现问题。

问题包括:

  1. 以错误的比例渲染(不确定哪个驱动程序错误)
  2. 在更改缩放比例之后,在更改缩放比例之前,标题栏高度的差异看起来像是垂直移位。 (在macbook pro / bootcamp上)
  3. 我已经尝试拆除并在WM_DPICHANGED上重新创建wgl上下文但是没有用,也不确定还有什么可以尝试。

    更新:我已经更新了示例程序repo以包含我所看到的屏幕截图,并且我已将.exe包含在测试程序中。

    见这里:https://bitbucket.org/toptensoftware/minimalopengl/overview

    更新2 - 发现了一个可以像预期一样工作的GPU Radeon RX460。在repo中更新了屏幕截图以显示预期的内容。

    更新3 - 我现在相当有信心这是由NVidia和Intel驱动程序的问题造成的,并且已经记录了两者的错误。我猜WHQL合规性不包括OpenGL驱动程序。

    仍然......微软提供适当的文档或示例程序,了解OpenGL和每个监视器的DPI支持是如何工作的。

1 个答案:

答案 0 :(得分:1)

在gtx 1050上遇到同样的问题。我注意到这个问题只出现在SetThreadDpiAwarenessContext函数中。

来自msdn:

  

SetThreadDpiAwarenessContext函数。   将当前线程的DPI感知设置为提供的值。

这意味着如果驱动程序创建一个或多个额外的线程来呈现OpenGL,则每个线程将具有不同的dpi感知级别。

所以有三种解决方案:

  1. 在Windows 8.1中使用旧的SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE)函数,并在WM_NCCREATE消息中调用EnableNonClientDpiScaling(hWnd);
  2. 使用Creators Update中的新SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
  3. 在应用程序清单中设置dpi感知级别(将应用于整个应用程序)。
  4. 这两个功能都为整个过程设定了认知水平。