<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 3 Aug 2016, at 12:25 PM, Frediano Ziglio <<a href="mailto:fziglio@redhat.com" class="">fziglio@redhat.com</a>> wrote:</div></blockquote><div><br class=""></div><div>Hi Frediano,</div><div><br class=""></div><div>Thanks for review. See my comments inline.</div><br class=""><blockquote type="cite" class=""><br class="Apple-interchange-newline"><div class=""><blockquote style="font-size: 12pt; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; border-left-width: 2px; border-left-style: solid; border-left-color: rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; text-decoration: none; font-family: Helvetica, Arial, sans-serif;" class=""><div dir="ltr" class=""><br class="Apple-interchange-newline">Thanks for the review, comments are inline.<br class=""><div class="gmail_extra"><br class=""><div class="gmail_quote">On Tue, Aug 2, 2016 at 4:31 PM, Frediano Ziglio<span class="Apple-converted-space"> </span><span dir="ltr" class=""><<a href="mailto:fziglio@redhat.com" target="_blank" class="">fziglio@redhat.com</a>></span><span class="Apple-converted-space"> </span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div class=""><div class="h5">><br class="">> The Connecting and Configuring Displays (CCD) Win32 APIs<br class="">> provide more control over the desktop display setup. The CCD APIs<br class="">> move away from using Windows Graphics Device Interface (GDI)<br class="">> concepts like view name and toward Windows Display Driver Model<br class="">> (WDDM) concepts like adapter, source, and target identifiers.<br class="">> More info on the CCD API can be found here:<br class="">><span class="Apple-converted-space"> </span><a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff539590(v=vs.85).aspx" rel="noreferrer" target="_blank" class="">https://msdn.microsoft.com/en-us/library/windows/hardware/ff539590(v=vs.85).aspx</a><br class="">><br class="">> This patch introduces partial functionality from the CCD API<br class="">> needed by vdagent. It is needed by vdagent in order to support<br class="">> multiple monitors and arbitrary resolution on Windows 10.<br class="">><br class="">> Tested with both Windows 10 and Windows 7.<br class="">><br class="">> Based on a patch by Sandy Stutsman <<a href="mailto:sstutsma@redhat.com" target="_blank" class="">sstutsma@redhat.com</a>><br class="">><br class="">> Signed-off-by: Dmitry Fleytman <<a href="mailto:dfleytma@redhat.com" target="_blank" class="">dfleytma@redhat.com</a>><br class="">> Signed-off-by: Sameeh Jubran <<a href="mailto:sameeh@daynix.com" target="_blank" class="">sameeh@daynix.com</a>><br class="">> ---<br class="">>  Makefile.am                       |    2 +<br class="">>  vdagent/desktop_layout.cpp        |  150 ++----<br class="">>  vdagent/desktop_layout.h          |    9 +-<br class="">>  vdagent/display_configuration.cpp | 1071<br class="">>  +++++++++++++++++++++++++++++++++++++<br class="">>  vdagent/display_configuration.h   |  191 +++++++<br class="">>  5 files changed, 1301 insertions(+), 122 deletions(-)<br class="">>  create mode 100755 vdagent/display_configuration.cpp<br class="">>  create mode 100755 vdagent/display_configuration.h<br class="">><br class="">> diff --git a/Makefile.am b/Makefile.am<br class="">> index c3fc6bf..84507e8 100644<br class="">> --- a/Makefile.am<br class="">> +++ b/Makefile.am<br class="">> @@ -31,6 +31,8 @@ vdagent_SOURCES =                   \<br class="">>       common/vdcommon.h               \<br class="">>       common/vdlog.cpp                \<br class="">>       common/vdlog.h                  \<br class="">> +     vdagent/display_configuration.cpp \<br class="">> +     vdagent/display_configuration.h \<br class="">>       vdagent/desktop_layout.cpp      \<br class="">>       vdagent/desktop_layout.h        \<br class="">>       vdagent/display_setting.cpp     \<br class="">> diff --git a/vdagent/desktop_layout.cpp b/vdagent/desktop_layout.cpp<br class="">> index a7666ca..e59a1a4 100644<br class="">> --- a/vdagent/desktop_layout.cpp<br class="">> +++ b/vdagent/desktop_layout.cpp<br class="">> @@ -18,6 +18,7 @@<br class="">>  #include <spice/qxl_windows.h><br class="">>  #include <spice/qxl_dev.h><br class="">>  #include "desktop_layout.h"<br class="">> +#include "display_configuration.h"<br class="">>  #include "vdlog.h"<br class="">><br class="">>  #ifdef __MINGW32__<br class="">> @@ -35,15 +36,19 @@ void DisplayMode::set_res(DWORD width, DWORD height,<br class="">> DWORD depth)<br class="">>  DesktopLayout::DesktopLayout()<br class="">>      : _total_width (0)<br class="">>      , _total_height (0)<br class="">> -    , _send_monitors_position(false)<br class="">> +    , _display_config (NULL)<br class="">>  {<br class="">>      MUTEX_INIT(_mutex);<br class="">> +    _display_config = DisplayConfig::create_config();<br class="">>      get_displays();<br class="">>  }<br class="">><br class="">>  DesktopLayout::~DesktopLayout()<br class="">>  {<br class="">>      clean_displays();<br class="">> +    if (_display_config) {<br class="">> +        delete _display_config;<br class="">> +    }<br class=""><br class=""></div></div>just delete _display_config, the if is redundant.<br class=""><div class=""><div class="h5"><br class="">>  }<br class="">><br class="">>  void DesktopLayout::get_displays()<br class="">> @@ -59,6 +64,7 @@ void DesktopLayout::get_displays()<br class="">>          unlock();<br class="">>          return;<br class="">>      }<br class="">> +    _display_config->update_config_path();<br class="">>      clean_displays();<br class="">>      ZeroMemory(&dev_info, sizeof(dev_info));<br class="">>      dev_info.cb = sizeof(dev_info);<br class="">> @@ -82,12 +88,13 @@ void DesktopLayout::get_displays()<br class="">>                  _displays[i] = NULL;<br class="">>              }<br class="">>          }<br class="">> -        attached = !!(dev_info.StateFlags &<br class="">> DISPLAY_DEVICE_ATTACHED_TO_DESKTOP);<br class="">> +        attached = _display_config->is_attached(&dev_info);<br class="">> +<br class="">>          EnumDisplaySettings(dev_info.DeviceName, ENUM_CURRENT_SETTINGS,<br class="">>          &mode);<br class="">>          _displays[display_id] = new DisplayMode(mode.dmPosition.x,<br class="">>          mode.dmPosition.y,<br class="">>                                                  mode.dmPelsWidth,<br class="">>                                                  mode.dmPelsHeight,<br class="">>                                                  mode.dmBitsPerPel,<br class="">>                                                  attached);<br class="">> -        update_monitor_config(dev_info.DeviceName, _displays[display_id]);<br class="">> +        _display_config->update_monitor_config(dev_info.DeviceName,<br class="">> _displays[display_id], &mode);<br class="">>      }<br class="">>      normalize_displays_pos();<br class="">>      unlock();<br class="">> @@ -121,6 +128,7 @@ void DesktopLayout::set_displays()<br class="">>          unlock();<br class="">>          return;<br class="">>      }<br class="">> +    _display_config->update_config_path();<br class="">>      ZeroMemory(&dev_info, sizeof(dev_info));<br class="">>      dev_info.cb = sizeof(dev_info);<br class="">>      ZeroMemory(&dev_mode, sizeof(dev_mode));<br class="">> @@ -146,28 +154,32 @@ void DesktopLayout::set_displays()<br class="">>              break;<br class="">>          }<br class="">>          DisplayMode * mode(_<a href="http://displays.at/" rel="noreferrer" target="_blank" class="">displays.at</a>(display_id));<br class="">> -        if (!init_dev_mode(dev_info.DeviceName, &dev_mode, mode, normal_x,<br class="">> normal_y, true)) {<br class="">> +        if (!init_dev_mode(dev_info.DeviceName, &dev_mode, mode)) {<br class="">>              vd_printf("No suitable mode found for display %S",<br class="">>              dev_info.DeviceName);<br class="">>              break;<br class="">>          }<br class="">>          vd_printf("Set display mode %lux%lu", dev_mode.dmPelsWidth,<br class="">>          dev_mode.dmPelsHeight);<br class="">> -        LONG ret = ChangeDisplaySettingsEx(dev_info.DeviceName, &dev_mode,<br class="">> NULL,<br class="">> -                                           CDS_UPDATEREGISTRY | CDS_NORESET,<br class="">> NULL);<br class="">> -        if (ret == DISP_CHANGE_SUCCESSFUL) {<br class="">> +        if (_display_config->update_dev_mode_position(dev_info.DeviceName,<br class="">> &dev_mode,<br class="">> +                                                     mode->_pos_x -<br class="">> normal_x,<br class="">> +                                                     mode->_pos_y -<br class="">> normal_y)) {<br class="">>              dev_sets++;<br class="">> -            update_monitor_config(dev_info.DeviceName, mode);<br class="">> +            _display_config->update_monitor_config(dev_info.DeviceName,<br class="">> mode, &dev_mode);<br class="">>          }<br class="">>          if (!is_qxl) {<br class="">>              display_id++;<br class="">>          }<br class="">>      }<br class="">>      if (dev_sets) {<br class="">> -        ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);<br class="">> +        _display_config->update_display_settings();<br class="">>          normalize_displays_pos();<br class="">>      }<br class="">>      unlock();<br class="">>  }<br class="">><br class="">> +void DesktopLayout::set_position_configurable(bool flag) {<br class="">> +    _display_config->set_monitors_config(flag);<br class="">> +}<br class="">> +<br class="">>  // Normalize all display positions to non-negative coordinates and update<br class="">>  total width and height of<br class="">>  // the virtual desktop. Caller is responsible to lock() & unlock().<br class="">>  void DesktopLayout::normalize_displays_pos()<br class="">> @@ -265,125 +277,29 @@ bool DesktopLayout::get_qxl_device_id(WCHAR*<br class="">> device_key, DWORD* device_id)<br class="">>      return key_found;<br class="">>  }<br class="">><br class="">> -bool DesktopLayout::init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode,<br class="">> DisplayMode* mode,<br class="">> -                                  LONG normal_x, LONG normal_y, bool<br class="">> set_pos)<br class="">> +bool DesktopLayout::init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode,<br class="">> DisplayMode* mode)<br class="">>  {<br class="">> -    DWORD closest_diff = -1;<br class="">> -    DWORD best = -1;<br class="">> -    QXLEscapeSetCustomDisplay custom;<br class="">> -    HDC hdc = NULL;<br class="">> -    LONG ret;<br class="">> -<br class="">>      ZeroMemory(dev_mode, sizeof(DEVMODE));<br class="">>      dev_mode->dmSize = sizeof(DEVMODE);<br class="">> -    if (!mode || !mode->_attached) {<br class="">> -        //Detach monitor<br class="">> -        dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;<br class="">> -        return true;<br class="">> -    }<br class="">> -<br class="">> -    hdc = CreateDC(dev_name, NULL, NULL, NULL);<br class="">> -    if (!hdc) {<br class="">> -        // for some reason, windows want those 3 flags to enable monitor<br class="">> -        dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;<br class="">> -        dev_mode->dmPelsWidth = mode->_width;<br class="">> -        dev_mode->dmPelsHeight = mode->_height;<br class="">> -        ret = ChangeDisplaySettingsEx(dev_name, dev_mode, NULL,<br class="">> CDS_UPDATEREGISTRY, NULL);<br class="">> -        if (ret == DISP_CHANGE_BADMODE) {<br class="">> -            // custom resolution might not be set yet, use known resolution<br class="">> -            // FIXME: this causes client temporary resize... a<br class="">> -            // solution would involve passing custom resolution before<br class="">> -            // driver initialization, perhaps through registry<br class="">> -            dev_mode->dmPelsWidth = 640;<br class="">> -            dev_mode->dmPelsHeight = 480;<br class="">> -            ret = ChangeDisplaySettingsEx(dev_name, dev_mode, NULL,<br class="">> CDS_UPDATEREGISTRY, NULL);<br class="">> -        }<br class="">> -<br class="">> -        vd_printf("attach %ld", ret);<br class="">> -        hdc = CreateDC(dev_name, NULL, NULL, NULL);<br class="">> -    }<br class="">><br class="">> -    if (!hdc) {<br class="">> -        vd_printf("failed to create DC");<br class="">> -        return false;<br class="">> -    } else {<br class="">> -        // Update custom resolution<br class="">> -        custom.xres = mode->_width;<br class="">> -        custom.yres = mode->_height;<br class="">> -        custom.bpp = mode->_depth;<br class="">> -<br class="">> -        int err = ExtEscape(hdc, QXL_ESCAPE_SET_CUSTOM_DISPLAY,<br class="">> -                            sizeof(QXLEscapeSetCustomDisplay),<br class="">> (LPCSTR)&custom, 0, NULL);<br class="">> -        if (err <= 0) {<br class="">> -            vd_printf("can't set custom display, perhaps an old driver");<br class="">> -        }<br class="">> -        DeleteDC(hdc);<br class="">> +    //Update monitor state<br class="">> +    MONITOR_STATE monitor_state = (!mode || !mode->_attached)?<br class="">> MONITOR_DETACHED : MONITOR_ATTACHED;<br class="">> +    _display_config->set_monitor_state(dev_name, dev_mode, monitor_state);<br class="">> +    if (monitor_state == MONITOR_DETACHED) {<br class="">> +        return true;<br class="">>      }<br class="">><br class="">> -    // force refresh mode table<br class="">> -    DEVMODE tempDevMode;<br class="">> -    ZeroMemory(&tempDevMode, sizeof (tempDevMode));<br class="">> -    tempDevMode.dmSize = sizeof(DEVMODE);<br class="">> -    EnumDisplaySettings(dev_name, 0xffffff, &tempDevMode);<br class="">> -<br class="">> -    //Find the closest size which will fit within the monitor<br class="">> -    for (DWORD i = 0; EnumDisplaySettings(dev_name, i, dev_mode); i++) {<br class="">> -        if (dev_mode->dmPelsWidth > mode->_width ||<br class="">> -            dev_mode->dmPelsHeight > mode->_height ||<br class="">> -            dev_mode->dmBitsPerPel != mode->_depth) {<br class="">> -            continue;<br class="">> -        }<br class="">> -        DWORD wdiff = mode->_width - dev_mode->dmPelsWidth;<br class="">> -        DWORD hdiff = mode->_height - dev_mode->dmPelsHeight;<br class="">> -        DWORD diff = wdiff * wdiff + hdiff * hdiff;<br class="">> -        if (diff < closest_diff) {<br class="">> -            closest_diff = diff;<br class="">> -            best = i;<br class="">> -        }<br class="">> -    }<br class="">> -    if (best == (DWORD)-1 || !EnumDisplaySettings(dev_name, best, dev_mode))<br class="">> {<br class="">> +    // Update custom resolution<br class="">> +    dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;<br class="">> +    dev_mode->dmPelsWidth = mode->_width;<br class="">> +    dev_mode->dmPelsHeight = mode->_height;<br class="">> +    dev_mode->dmBitsPerPel = mode->_depth;<br class="">> +    if (!_display_config->custom_display_escape(dev_name, dev_mode))<br class="">>          return false;<br class="">> -    }<br class="">> -    dev_mode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;<br class="">> -    if (set_pos) {<br class="">> -        //Convert the position so that the primary is always at (0,0)<br class="">> -        dev_mode->dmPosition.x = mode->_pos_x - normal_x;<br class="">> -        dev_mode->dmPosition.y = mode->_pos_y - normal_y;<br class="">> -        dev_mode->dmFields |= DM_POSITION;<br class="">> -    }<br class="">><br class="">>      // update current DisplayMode (so mouse scaling works properly)<br class="">>      mode->_width = dev_mode->dmPelsWidth;<br class="">>      mode->_height = dev_mode->dmPelsHeight;<br class="">> -<br class="">>      return true;<br class="">> -}<br class="">> -<br class="">> -bool DesktopLayout::update_monitor_config(LPCTSTR dev_name, DisplayMode*<br class="">> mode)<br class="">> -{<br class="">> -    QXLHead monitor_config;<br class="">> -<br class="">> -    if (!mode || !mode->get_attached())<br class="">> -        return false;<br class="">> -<br class="">> -    //Don't configure monitors unless the client supports it<br class="">> -    if(!_send_monitors_position) return FALSE;<br class="">> -<br class="">> -    HDC hdc = CreateDC(dev_name, NULL, NULL, NULL);<br class="">> -<br class="">> -    memset(&monitor_config, 0, sizeof(monitor_config));<br class="">> -    monitor_config.x = mode->_pos_x;<br class="">> -    monitor_config.y = mode->_pos_y;<br class="">> -    monitor_config.width = mode->_width;<br class="">> -    monitor_config.height = mode->_height;<br class="">> -<br class="">> -    int err = ExtEscape(hdc, QXL_ESCAPE_MONITOR_CONFIG,<br class="">> -        sizeof(QXLHead), (LPCSTR) &monitor_config, 0, NULL);<br class="">> -<br class="">> -    if (err < 0){<br class="">> -        vd_printf("can't update monitor config, may have an older driver");<br class="">> -    }<br class="">><br class="">> -    DeleteDC(hdc);<br class="">> -    return (err >= 0);<br class="">>  }<br class="">> diff --git a/vdagent/desktop_layout.h b/vdagent/desktop_layout.h<br class="">> index ece3946..fd6af76 100644<br class="">> --- a/vdagent/desktop_layout.h<br class="">> +++ b/vdagent/desktop_layout.h<br class="">> @@ -60,6 +60,7 @@ private:<br class="">>  };<br class="">><br class="">>  typedef std::vector<DisplayMode*> Displays;<br class="">> +class DisplayConfig;<br class="">><br class="">>  class DesktopLayout {<br class="">>  public:<br class="">> @@ -73,23 +74,21 @@ public:<br class="">>      size_t get_display_count() { return _displays.size();}<br class="">>      DWORD get_total_width() { return _total_width;}<br class="">>      DWORD get_total_height() { return _total_height;}<br class="">> -    void set_position_configurable(bool flag) { _send_monitors_position =<br class="">> flag; }<br class="">> +    void set_position_configurable(bool flag);<br class="">>  private:<br class="">>      void clean_displays();<br class="">>      void normalize_displays_pos();<br class="">>      DisplayMode * get_primary_display();<br class="">> -    bool update_monitor_config(LPCTSTR dev_name, DisplayMode* mode);<br class="">> +    bool init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode, DisplayMode*<br class="">> mode);<br class="">>      static bool consistent_displays();<br class="">>      static bool is_attached(LPCTSTR dev_name);<br class="">>      static bool get_qxl_device_id(WCHAR* device_key, DWORD* device_id);<br class="">> -    static bool init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode,<br class="">> DisplayMode* mode,<br class="">> -                              LONG normal_x, LONG normal_y, bool set_pos);<br class="">>  private:<br class="">>      mutex_t _mutex;<br class="">>      Displays _displays;<br class="">>      DWORD _total_width;<br class="">>      DWORD _total_height;<br class="">> -    bool _send_monitors_position;<br class="">> +    DisplayConfig* _display_config;<br class="">>  };<br class="">><br class="">>  #endif<br class="">> diff --git a/vdagent/display_configuration.cpp<br class="">> b/vdagent/display_configuration.cpp<br class="">> new file mode 100755<br class="">> index 0000000..563f619<br class="">> --- /dev/null<br class="">> +++ b/vdagent/display_configuration.cpp<br class="">> @@ -0,0 +1,1071 @@<br class="">> +/*<br class="">> +Copyright (C) 2015 Red Hat, Inc.<br class="">> +<br class="">> +This program is free software; you can redistribute it and/or<br class="">> +modify it under the terms of the GNU General Public License as<br class="">> +published by the Free Software Foundation; either version 2 of<br class="">> +the License, or (at your option) any later version.<br class="">> +<br class="">> +This program is distributed in the hope that it will be useful,<br class="">> +but WITHOUT ANY WARRANTY; without even the implied warranty of<br class="">> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br class="">> +GNU General Public License for more details.<br class="">> +<br class="">> +You should have received a copy of the GNU General Public License<br class="">> +along with this program.  If not, see <<a href="http://www.gnu.org/licenses/" rel="noreferrer" target="_blank" class="">http://www.gnu.org/licenses/</a>>.<br class="">> +*/<br class="">> +<br class="">> +#include "display_configuration.h"<br class="">> +#include <winternl.h><br class="">> +<br class="">> +//<br class="">> +// Definitions used by QueryDisplayConfig.<br class="">> +//<br class="">> +<br class="">> +#define QDC_ALL_PATHS                    0x00000001<br class="">> +<br class="">> +//<br class="">> +// Definitions used by SetDisplayConfig.<br class="">> +//<br class="">> +<br class="">> +#define SDC_USE_SUPPLIED_DISPLAY_CONFIG  0x00000020<br class="">> +#define SDC_APPLY                        0x00000080<br class="">> +#define SDC_FORCE_MODE_ENUMERATION       0x00001000<br class="">> +<br class="">> +#define DISPLAYCONFIG_PATH_ACTIVE               0x00000001<br class="">> +#define DISPLAYCONFIG_PATH_MODE_IDX_INVALID     0xffffffff<br class="">> +<br class="">> +enum DISPLAYCONFIG_DEVICE_INFO_TYPE {<br class="">> +    DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1<br class="">> +};<br class="">> +<br class="">> +enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY {};<br class="">> +<br class="">> +enum DISPLAYCONFIG_ROTATION {};<br class="">> +<br class="">> +enum DISPLAYCONFIG_SCANLINE_ORDERING {};<br class="">> +<br class="">> +enum DISPLAYCONFIG_SCALING {};<br class="">> +<br class="">> +enum DISPLAYCONFIG_PIXELFORMAT {};<br class="">> +<br class="">> +enum DISPLAYCONFIG_MODE_INFO_TYPE {};<br class="">> +<br class="">> +struct DISPLAYCONFIG_DEVICE_INFO_HEADER {<br class="">> +    DISPLAYCONFIG_DEVICE_INFO_TYPE  type;<br class="">> +    UINT32                          size;<br class="">> +    LUID                            adapterId;<br class="">> +    UINT32                          id;<br class="">> +};<br class="">> +<br class="">> +struct DISPLAYCONFIG_SOURCE_DEVICE_NAME {<br class="">> +    DISPLAYCONFIG_DEVICE_INFO_HEADER            header;<br class="">> +    WCHAR<br class="">> viewGdiDeviceName[CCHDEVICENAME];<br class="">> +};<br class="">> +<br class="">> +struct DISPLAYCONFIG_DESKTOP_IMAGE_INFO {<br class="">> +    POINTL PathSourceSize;<br class="">> +    RECTL DesktopImageRegion;<br class="">> +    RECTL DesktopImageClip;<br class="">> +};<br class="">> +<br class="">> +struct DISPLAYCONFIG_RATIONAL {<br class="">> +    UINT32    Numerator;<br class="">> +    UINT32    Denominator;<br class="">> +};<br class="">> +<br class="">> +struct DISPLAYCONFIG_2DREGION {<br class="">> +    UINT32 cx;<br class="">> +    UINT32 cy;<br class="">> +};<br class="">> +<br class="">> +struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO {<br class="">> +    UINT64                          pixelRate;<br class="">> +    DISPLAYCONFIG_RATIONAL          hSyncFreq;<br class="">> +    DISPLAYCONFIG_RATIONAL          vSyncFreq;<br class="">> +    DISPLAYCONFIG_2DREGION          activeSize;<br class="">> +    DISPLAYCONFIG_2DREGION          totalSize;<br class="">> +<br class="">> +    union {<br class="">> +        struct {<br class="">> +            UINT32 videoStandard : 16;<br class="">> +            UINT32 vSyncFreqDivider : 6;<br class="">> +            UINT32 reserved : 10;<br class="">> +        } AdditionalSignalInfo;<br class="">> +        UINT32 videoStandard;<br class="">> +    } DUMMYUNIONNAME;<br class="">> +    DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;<br class="">> +};<br class="">> +<br class="">> +struct DISPLAYCONFIG_TARGET_MODE {<br class="">> +    DISPLAYCONFIG_VIDEO_SIGNAL_INFO   targetVideoSignalInfo;<br class="">> +};<br class="">> +<br class="">> +struct DISPLAYCONFIG_SOURCE_MODE {<br class="">> +    UINT32                      width;<br class="">> +    UINT32                      height;<br class="">> +    DISPLAYCONFIG_PIXELFORMAT   pixelFormat;<br class="">> +    POINTL                      position;<br class="">> +};<br class="">> +<br class="">> +struct DISPLAYCONFIG_MODE_INFO {<br class="">> +    DISPLAYCONFIG_MODE_INFO_TYPE    infoType;<br class="">> +    UINT32                          id;<br class="">> +    LUID                            adapterId;<br class="">> +    union {<br class="">> +        DISPLAYCONFIG_TARGET_MODE   targetMode;<br class="">> +        DISPLAYCONFIG_SOURCE_MODE   sourceMode;<br class="">> +        DISPLAYCONFIG_DESKTOP_IMAGE_INFO    desktopImageInfo;<br class="">> +    } DUMMYUNIONNAME;<br class="">> +};<br class="">> +<br class="">> +struct DISPLAYCONFIG_PATH_SOURCE_INFO {<br class="">> +    LUID    adapterId;<br class="">> +    UINT32  id;<br class="">> +    union {<br class="">> +        UINT32 modeInfoIdx;<br class="">> +        struct {<br class="">> +            UINT32 cloneGroupId : 16;<br class="">> +            UINT32 sourceModeInfoIdx : 16;<br class="">> +        } DUMMYSTRUCTNAME;<br class="">> +    } DUMMYUNIONNAME;<br class="">> +<br class="">> +    UINT32  statusFlags;<br class="">> +};<br class="">> +<br class="">> +struct DISPLAYCONFIG_PATH_TARGET_INFO {<br class="">> +    LUID                                    adapterId;<br class="">> +    UINT32                                  id;<br class="">> +    union {<br class="">> +        UINT32                                  modeInfoIdx;<br class="">> +        struct {<br class="">> +            UINT32 desktopModeInfoIdx : 16;<br class="">> +            UINT32 targetModeInfoIdx : 16;<br class="">> +        } DUMMYSTRUCTNAME;<br class="">> +    } DUMMYUNIONNAME;<br class="">> +    DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY   outputTechnology;<br class="">> +    DISPLAYCONFIG_ROTATION                  rotation;<br class="">> +    DISPLAYCONFIG_SCALING                   scaling;<br class="">> +    DISPLAYCONFIG_RATIONAL                  refreshRate;<br class="">> +    DISPLAYCONFIG_SCANLINE_ORDERING         scanLineOrdering;<br class="">> +    BOOL                                    targetAvailable;<br class="">> +    UINT32                                  statusFlags;<br class="">> +};<br class="">> +<br class="">> +struct DISPLAYCONFIG_PATH_INFO {<br class="">> +    DISPLAYCONFIG_PATH_SOURCE_INFO  sourceInfo;<br class="">> +    DISPLAYCONFIG_PATH_TARGET_INFO  targetInfo;<br class="">> +    UINT32                          flags;<br class="">> +};<br class="">> +<br class="">> +<br class="">> +enum D3DKMT_ESCAPETYPE {<br class="">> +    D3DKMT_ESCAPE_DRIVERPRIVATE = 0<br class="">> +};<br class="">> +<br class="">> +struct D3DDDI_ESCAPEFLAGS {<br class="">> +    union {<br class="">> +        struct {<br class="">> +            UINT    Reserved : 31;<br class="">> +        };<br class="">> +        UINT        Value;<br class="">> +    };<br class="">> +};<br class="">> +<br class="">> +struct D3DKMT_ESCAPE {<br class="">> +    D3DKMT_HANDLE       hAdapter;<br class="">> +    D3DKMT_HANDLE       hDevice;<br class="">> +    D3DKMT_ESCAPETYPE   Type;<br class="">> +    D3DDDI_ESCAPEFLAGS  Flags;<br class="">> +    VOID*               pPrivateDriverData;<br class="">> +    UINT                PrivateDriverDataSize;<br class="">> +    D3DKMT_HANDLE       hContext;<br class="">> +};<br class="">> +<br class="">> +typedef UINT  D3DDDI_VIDEO_PRESENT_SOURCE_ID;<br class="">> +<br class="">> +struct D3DKMT_OPENADAPTERFROMHDC {<br class="">> +    HDC                             hDc;<br class="">> +    D3DKMT_HANDLE                   hAdapter;<br class="">> +    LUID                            AdapterLuid;<br class="">> +    D3DDDI_VIDEO_PRESENT_SOURCE_ID  VidPnSourceId;<br class="">> +};<br class="">> +<br class="">> +struct D3DKMT_CLOSEADAPTER {<br class="">> +    D3DKMT_HANDLE   hAdapter;<br class="">> +};<br class="">> +<br class="">> +struct D3DKMT_OPENADAPTERFROMDEVICENAME {<br class="">> +    PCWSTR                          pDeviceName;<br class="">> +    D3DKMT_HANDLE                   hAdapter;<br class="">> +    LUID                            AdapterLuid;<br class="">> +};<br class="">> +<br class="">> +struct D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME {<br class="">> +    WCHAR                           DeviceName[32];<br class="">> +    D3DKMT_HANDLE                   hAdapter;<br class="">> +    LUID                            AdapterLuid;<br class="">> +    D3DDDI_VIDEO_PRESENT_SOURCE_ID  VidPnSourceId;<br class="">> +};<br class="">> +<br class=""><br class=""></div></div>There are defined from Microsoft, better to move them in<br class="">a separate file. The license can changed easier.<br class=""></blockquote><div class="">Can you please further explain regarding the licensing? which license should be used?</div></div></div></div></blockquote><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">These defines came from Microsoft headers or from the web like<br class=""></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff548113(v=vs.85).aspx" class="">https://msdn.microsoft.com/en-us/library/windows/hardware/ff548113(v=vs.85).aspx</a></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">simply you can't copy from header (which have its license) and/or from web<span class="Apple-converted-space"> </span><br class=""></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">(see<span class="Apple-converted-space"> </span><a href="https://www.microsoft.com/en-us/legal/intellectualproperty/copyright/default.aspx" class="">https://www.microsoft.com/en-us/legal/intellectualproperty/copyright/default.aspx</a>)<br class=""></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Not sure about the license. Looks like Mingw headers have public domain licensing.<br class=""></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">For instance<span class="Apple-converted-space"> </span><a href="https://searchcode.com/codesearch/raw/11987244/" class="">https://searchcode.com/codesearch/raw/11987244/</a><span class="Apple-converted-space"> </span>have a Microsoft disclaimer.<br class=""></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Maybe I'm too overcautious<br class=""></div><blockquote style="font-size: 12pt; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; border-left-width: 2px; border-left-style: solid; border-left-color: rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; text-decoration: none; font-family: Helvetica, Arial, sans-serif;" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div class=""><div class="h5"><br class="">> +struct QXLMonitorEscape {<br class="">> +    QXLMonitorEscape(DEVMODE* dev_mode)<br class="">> +    {<br class="">> +        ZeroMemory(&_head, sizeof(_head));<br class="">> +        _head.x = dev_mode->dmPosition.x;<br class="">> +        _head.y = dev_mode->dmPosition.y;<br class="">> +        _head.width = dev_mode->dmPelsWidth;<br class="">> +        _head.height = dev_mode->dmPelsHeight;<br class="">> +    }<br class="">> +    QXLHead _head;<br class="">> +};<br class="">> +<br class="">> +struct QxlCustomEscapeObj : public QXLEscapeSetCustomDisplay {<br class="">> +    QxlCustomEscapeObj(uint32_t bitsPerPel, uint32_t width, uint32_t height)<br class="">> +    {<br class="">> +        xres = width;<br class="">> +        yres = height;<br class="">> +        bpp = bitsPerPel;<br class="">> +    }<br class="">> +    QxlCustomEscapeObj() {};<br class="">> +};<br class="">> +<br class="">> +struct WDDMCustomDisplayEscape {<br class="">> +    WDDMCustomDisplayEscape(DEVMODE* dev_mode)<br class="">> +    {<br class="">> +        _ioctl = QXL_ESCAPE_SET_CUSTOM_DISPLAY;<br class="">> +        _custom.bpp  = dev_mode->dmBitsPerPel;<br class="">> +        _custom.xres = dev_mode->dmPelsWidth;<br class="">> +        _custom.yres = dev_mode->dmPelsHeight;<br class="">> +    }<br class="">> +    int                         _ioctl;<br class="">> +    QXLEscapeSetCustomDisplay   _custom;<br class="">> +};<br class="">> +<br class="">> +struct WDDMMonitorConfigEscape {<br class="">> +    WDDMMonitorConfigEscape(DisplayMode* mode)<br class="">> +    {<br class="">> +        _ioctl = QXL_ESCAPE_MONITOR_CONFIG;<br class="">> +        _<a href="http://head.id/" rel="noreferrer" target="_blank" class="">head.id</a><span class="Apple-converted-space"> </span>= _head.surface_id = 0;<br class="">> +        _head.x = mode->get_pos_x();<br class="">> +        _head.y = mode->get_pos_y();<br class="">> +        _head.width = mode->get_width();<br class="">> +        _head.height = mode->get_height();<br class="">> +    }<br class="">> +    int         _ioctl;<br class="">> +    QXLHead     _head;<br class="">> +};<br class="">> +<br class="">> +DisplayConfig* DisplayConfig::create_config()<br class="">> +{<br class="">> +    DisplayConfig* new_interface;<br class="">> +    //Try to open a WDDM adapter.<br class="">> +    new_interface = new  WDDMInterface();<br class="">> +    if(new_interface->type() == WDDM) {<br class="">> +        return new_interface;<br class="">> +    }<br class="">> +    //If that failed so clean up and assume we have an XPDM driver<br class="">> +    delete new_interface;<br class="">> +<br class="">> +    new_interface = new XPDMInterface();<br class="">> +    return new_interface;<br class="">> +}<br class="">> +<br class="">> +DisplayConfig::DisplayConfig()<br class="">> +    : _driver_type(INVALID_DRIVER)<br class="">> +    , _send_monitors_config(false)<br class="">> +{}<br class="">> +<br class="">> +bool XPDMInterface::is_attached(DISPLAY_DEVICE* dev_info)<br class="">> +{<br class="">> +    return !!(dev_info->StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP);<br class="">> +}<br class="">> +<br class="">> +bool XPDMInterface::set_monitor_state(LPCTSTR device_name, DEVMODE*<br class="">> dev_mode, MONITOR_STATE state)<br class="">> +{<br class="">> +    dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;<br class="">> +    if (state == MONITOR_ATTACHED) {<br class="">> +        return true;<br class="">> +    }<br class="">> +<br class="">> +    LONG status = ChangeDisplaySettingsEx(device_name, dev_mode, NULL,<br class="">> CDS_UPDATEREGISTRY, NULL);<br class="">> +    return (status == DISP_CHANGE_SUCCESSFUL);<br class="">> +}<br class="">> +<br class="">> +LONG XPDMInterface::update_display_settings()<br class="">> +{<br class="">> +    return ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);<br class="">> +}<br class="">> +<br class="">> +bool XPDMInterface::update_dev_mode_position(LPCTSTR device_name,<br class="">> +                                             DEVMODE* dev_mode, LONG x, LONG<br class="">> y)<br class="">> +{<br class="">> +    //Convert the position so that the primary is always at (0,0)<br class="">> +    dev_mode->dmPosition.x = x;<br class="">> +    dev_mode->dmPosition.y = y;<br class="">> +    dev_mode->dmFields |= DM_POSITION;<br class="">> +    vd_printf("%s: setting %S at (%lu, %lu)", __FUNCTION__, device_name,<br class="">> dev_mode->dmPosition.x,<br class="">> +        dev_mode->dmPosition.y);<br class="">> +<br class="">> +    LONG status = ChangeDisplaySettingsEx(device_name, dev_mode, NULL,<br class="">> +                                          CDS_UPDATEREGISTRY | CDS_NORESET,<br class="">> NULL);<br class="">> +    return (status == DISP_CHANGE_SUCCESSFUL);<br class="">> +}<br class="">> +<br class="">> +bool XPDMInterface::custom_display_escape(LPCTSTR device_name, DEVMODE*<br class="">> dev_mode)<br class="">> +{<br class="">> +    LONG        ret;<br class="">> +    NTSTATUS    Status (ERROR_SUCCESS);<br class="">> +    HDC         hdc = CreateDC(device_name, NULL, NULL, NULL);<br class="">> +<br class="">> +    if (!hdc) {<br class="">> +        ret = ChangeDisplaySettingsEx(device_name, dev_mode, NULL,<br class="">> CDS_UPDATEREGISTRY, NULL);<br class="">> +        if (ret == DISP_CHANGE_BADMODE) {<br class="">> +            // custom resolution might not be set yet, use known resolution<br class="">> +            // FIXME: this causes client temporary resize... a<br class="">> +            // solution would involve passing custom resolution before<br class="">> +            // driver initialization, perhaps through registry<br class="">> +            dev_mode->dmPelsWidth = 640;<br class="">> +            dev_mode->dmPelsHeight = 480;<br class="">> +            ret = ChangeDisplaySettingsEx(device_name, dev_mode, NULL,<br class="">> CDS_UPDATEREGISTRY, NULL);<br class="">> +        }<br class="">> +<br class="">> +        vd_printf("attach %ld", ret);<br class="">> +        if (!(hdc = CreateDC(device_name, NULL, NULL, NULL))) {<br class="">> +            vd_printf("%s: failed to create DC", __FUNCTION__);<br class="">> +            return false;<br class="">> +        }<br class="">> +    }<br class="">> +<br class="">> +    QxlCustomEscapeObj custom_escape(dev_mode->dmBitsPerPel,<br class="">> +                                            dev_mode->dmPelsWidth,<br class="">> dev_mode->dmPelsHeight);<br class="">> +<br class="">> +    int err = ExtEscape(hdc, QXL_ESCAPE_SET_CUSTOM_DISPLAY,<br class="">> +              sizeof(QXLEscapeSetCustomDisplay), (LPCSTR) &custom_escape, 0,<br class="">> NULL);<br class="">> +    if (err <= 0) {<br class="">> +        vd_printf("%s: Can't set custom display, perhaps running with an<br class="">> older driver?",<br class="">> +            __FUNCTION__);<br class="">> +    }<br class="">> +<br class="">> +    if (!find_best_mode(device_name, dev_mode)) {<br class="">> +        Status = E_FAIL;<br class="">> +    }<br class="">> +<br class="">> +    DeleteDC(hdc);<br class="">> +    return NT_SUCCESS(Status);<br class="">> +}<br class="">> +<br class="">> +bool XPDMInterface::update_monitor_config(LPCTSTR device_name, DisplayMode*<br class="">> mode,<br class="">> +                                           DEVMODE* dev_mode)<br class="">> +{<br class="">> +    if (!mode || !mode->get_attached()) {<br class="">> +        return false;<br class="">> +    }<br class="">> +<br class="">> +    QXLMonitorEscape monitor_config(dev_mode);<br class="">> +    HDC hdc(CreateDC(device_name, NULL, NULL, NULL));<br class="">> +    int err(0);<br class="">> +<br class="">> +    if (!hdc || !_send_monitors_config) {<br class="">> +        return false;<br class="">> +    }<br class="">> +<br class="">> +    err = ExtEscape(hdc, QXL_ESCAPE_MONITOR_CONFIG, sizeof(QXLHead),<br class="">> +                    (LPCSTR) &monitor_config, 0, NULL);<br class="">> +    if (err < 0) {<br class="">> +        vd_printf("%s: %S can't update monitor config, may have old, old<br class="">> driver",<br class="">> +                 __FUNCTION__, device_name);<br class="">> +    }<br class="">> +    DeleteDC(hdc);<br class="">> +    return (err >= 0);<br class="">> +}<br class="">> +<br class="">> +bool XPDMInterface::find_best_mode(LPCTSTR Device, DEVMODE* dev_mode)<br class="">> +{<br class="">> +    DWORD closest_diff = -1;<br class="">> +    DWORD best = -1;<br class="">> +<br class="">> +    // force refresh mode table<br class="">> +    DEVMODE test_dev_mode;<br class="">> +    ZeroMemory(&test_dev_mode, sizeof(test_dev_mode));<br class="">> +    test_dev_mode.dmSize = sizeof(DEVMODE);<br class="">> +    EnumDisplaySettings(Device, 0xffffff, &test_dev_mode);<br class="">> +<br class="">> +    //Find the closest size which will fit within the monitor<br class="">> +    for (DWORD i = 0; EnumDisplaySettings(Device, i, &test_dev_mode); i++) {<br class="">> +        if (dev_mode->dmPelsWidth > test_dev_mode.dmPelsWidth ||<br class="">> +            dev_mode->dmPelsHeight > test_dev_mode.dmPelsHeight ||<br class="">> +            dev_mode->dmBitsPerPel != test_dev_mode.dmBitsPerPel) {<br class="">> +            continue;<br class="">> +        }<br class="">> +        DWORD wdiff = dev_mode->dmPelsWidth - test_dev_mode.dmPelsWidth;<br class="">> +        DWORD hdiff = dev_mode->dmPelsHeight - test_dev_mode.dmPelsHeight;<br class="">> +        DWORD diff = wdiff * wdiff + hdiff * hdiff;<br class="">> +        if (diff < closest_diff) {<br class="">> +            closest_diff = diff;<br class="">> +            best = i;<br class="">> +        }<br class="">> +    }<br class="">> +    vd_printf("%s: closest_diff at %lu best %lu", __FUNCTION__,<br class="">> closest_diff, best);<br class="">> +    if (best == (DWORD) -1 || !EnumDisplaySettings(Device, best, dev_mode))<br class="">> {<br class="">> +        return false;<br class="">> +    }<br class="">> +<br class="">> +    //Change to the best fit<br class="">> +    LONG status = ChangeDisplaySettingsEx(Device, dev_mode, NULL,<br class="">> +                                          CDS_UPDATEREGISTRY | CDS_NORESET,<br class="">> NULL);<br class="">> +    return NT_SUCCESS(status);<br class="">> +}<br class="">> +<br class="">> +WDDMInterface::WDDMInterface()<br class="">> +    : _pfnOpen_adapter_hdc(NULL)<br class="">> +    , _pfnClose_adapter(NULL)<br class="">> +    , _pfnEscape(NULL)<br class="">> +    , _pfnOpen_adapter_device_name(NULL)<br class="">> +    , _pfnOpen_adapter_gdi_name(NULL)<br class="">> +{<br class="">> +    _driver_type = INVALID_DRIVER;<br class="">> +<br class="">> +    //Did the CCD load?<br class="">> +    if (_ccd.error() == ERROR_NOT_SUPPORTED) {<br class="">> +        return;<br class="">> +    }<br class="">> +<br class="">> +    //Can we find the D3D calls we need?<br class="">> +    if (!init_d3d_api()) {<br class="">> +        return;<br class="">> +    }<br class="">> +<br class="">> +    //Initialize  CCD path stuff<br class="">> +    if (!_ccd.query_display_config()) {<br class="">> +        return;;<br class="">> +    }<br class="">> +    if (!_ccd.set_display_config()) {<br class="">> +        return;<br class="">> +    }<br class="">> +    _driver_type = WDDM;<br class="">> +}<br class="">> +<br class="">> +WDDMInterface::~WDDMInterface()<br class="">> +{<br class="">> +    if (_driver_type != WDDM) {<br class="">> +        vd_printf("%s called with invalid driver type of %d", __FUNCTION__,<br class="">> _driver_type);<br class="">> +        return;<br class="">> +    }<br class="">> +}<br class="">> +<br class="">> +bool WDDMInterface::is_attached(DISPLAY_DEVICE* dev_info)<br class="">> +{<br class="">> +    return _<a href="http://ccd.is" class="">ccd.is</a>_attached(dev_info->DeviceName);<br class="">> +}<br class="">> +<br class="">> +bool WDDMInterface::set_monitor_state(LPCTSTR device_name, DEVMODE*<br class="">> dev_mode, MONITOR_STATE state)<br class="">> +{<br class="">> +   return  _ccd.set_path_state(device_name, state);<br class="">> +}<br class="">> +<br class="">> +bool WDDMInterface::custom_display_escape(LPCTSTR device_name, DEVMODE*<br class="">> dev_mode)<br class="">> +{<br class="">> +    DISPLAYCONFIG_MODE_INFO* mode = _ccd.get_active_mode(device_name,<br class="">> false);<br class="">> +    if (!mode) {<br class="">> +        return false;<br class="">> +    }<br class="">> +<br class="">> +    //Don't bother if we are already set to the new resolution<br class="">> +    if (mode->sourceMode.width == dev_mode->dmPelsWidth &&<br class="">> +        mode->sourceMode.height == dev_mode->dmPelsHeight) {<br class="">> +        return true;<br class="">> +    }<br class="">> +<br class="">> +    vd_printf("%s: updating %S resolution\n", __FUNCTION__, device_name);<br class="">> +<br class="">> +    WDDMCustomDisplayEscape wddm_escape(dev_mode);<br class="">> +    if (escape(device_name, &wddm_escape, sizeof(wddm_escape))) {<br class="">> +        return _ccd.update_mode_size(device_name, dev_mode);<br class="">> +    }<br class="">> +<br class="">> +    vd_printf("%s: (%dx%d)", __FUNCTION__, mode->sourceMode.width,<br class="">> mode->sourceMode.height);<br class="">> +    return false;<br class="">> +}<br class="">> +<br class="">> +bool WDDMInterface::update_monitor_config(LPCTSTR device_name, DisplayMode*<br class="">> display_mode,<br class="">> +                                           DEVMODE* dev_mode)<br class="">> +{<br class="">> +    if (!display_mode || !display_mode->get_attached()) {<br class="">> +        return false;<br class="">> +    }<br class="">> +    DISPLAYCONFIG_MODE_INFO* mode = _ccd.get_active_mode(device_name,<br class="">> false);<br class="">> +    if (!mode || !_send_monitors_config)<br class="">> +        return false;<br class="">> +<br class="">> +    WDDMMonitorConfigEscape wddm_escape(display_mode);<br class="">> +    if (escape(device_name, &wddm_escape, sizeof(wddm_escape))) {<br class="">> +        //Update the path position<br class="">> +        return _ccd.update_mode_position(device_name, dev_mode);<br class="">> +    }<br class="">> +<br class="">> +    vd_printf("%s: %S failed", __FUNCTION__, device_name);<br class="">> +    return false;<br class="">> +<br class="">> +}<br class="">> +<br class="">> +LONG WDDMInterface::update_display_settings()<br class="">> +{<br class="">> +    //If we removed the primary monitor since the last call, we need to<br class="">> +    //reorder the other monitors, making the leftmost one the primary<br class="">> +    _ccd.verify_primary_position();<br class="">> +<br class="">> +    if (!_ccd.set_display_config()) {<br class="">> +        if (_ccd._error != ERROR_INVALID_PARAMETER) {<br class="">> +            vd_printf("%s: set_display_config failed", __FUNCTION__);<br class="">> +        } else {<br class="">> +            vd_printf("%s: Invalid parameter!", __FUNCTION__);<br class="">> +            _ccd.debug_print_config("After error");<br class="">> +        }<br class="">> +    }<br class="">> +    return _ccd.error();<br class="">> +}<br class="">> +<br class="">> +void WDDMInterface::update_config_path()<br class="">> +{<br class="">> +    _ccd.query_display_config();<br class="">> +}<br class="">> +<br class="">> +bool WDDMInterface::update_dev_mode_position(LPCTSTR device_name, DEVMODE*<br class="">> dev_mode,<br class="">> +                                             LONG x, LONG y)<br class="">> +{<br class="">> +    //Convert the position so that the primary is always at (0,0)<br class="">> +    dev_mode->dmPosition.x = x;<br class="">> +    dev_mode->dmPosition.y = y;<br class="">> +    _ccd.update_mode_position(device_name, dev_mode);<br class="">> +    return _ccd.update_mode_position(device_name, dev_mode);<br class="">> +}<br class="">> +<br class="">> +bool WDDMInterface::init_d3d_api()<br class="">> +{<br class="">> +    HMODULE hModule = LoadLibrary(L"gdi32.dll");<br class="">> +<br class="">> +    //Look for the gdi32 functions we need to perform driver escapes<br class="">> +    if (!hModule) {<br class="">> +        vd_printf("%s something wildly wrong as we can't open gdi32.dll",<br class="">> __FUNCTION__);<br class="">> +        _driver_type = INVALID_DRIVER;<br class="">> +        return false;<br class="">> +    }<br class="">> +<br class="">> +    do {<br class="">> +        _pfnClose_adapter = (PFND3DKMT_CLOSEADAPTER)<br class="">> +            GetProcAddress(hModule, "D3DKMTCloseAdapter");<br class="">> +        if (!_pfnClose_adapter) {<br class="">> +            break;<br class="">> +        }<br class="">> +<br class="">> +        _pfnEscape = (PFND3DKMT_ESCAPE) GetProcAddress(hModule,<br class="">> "D3DKMTEscape");<br class="">> +        if (!_pfnEscape) {<br class="">> +            break;<br class="">> +        }<br class="">> +<br class="">> +        _pfnOpen_adapter_hdc = (PFND3DKMT_OPENADAPTERFROMHDC)<br class="">> +            GetProcAddress(hModule, "D3DKMTOpenAdapterFromHdc");<br class="">> +        if (!_pfnOpen_adapter_hdc) {<br class="">> +            break;<br class="">> +        }<br class="">> +<br class="">> +        _pfnOpen_adapter_device_name = (PFND3DKMT_OPENADAPTERFROMDEVICENAME)<br class="">> +            GetProcAddress(hModule, "D3DKMTOpenAdapterFromDeviceName");<br class="">> +        if (!_pfnOpen_adapter_device_name) {<br class="">> +            break;<br class="">> +        }<br class="">> +<br class="">> +        _pfnOpen_adapter_gdi_name =<br class="">> (PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME)<br class="">> +            GetProcAddress(hModule, "D3DKMTOpenAdapterFromGdiDisplayName");<br class="">> +        if (!_pfnOpen_adapter_gdi_name) {<br class="">> +            break;<br class="">> +        }<br class="">> +<br class="">> +    }<br class="">> +    while(0);<br class="">> +<br class="">> +    FreeLibrary(hModule);<br class="">> +<br class="">> +    //Did we get them ?<br class="">> +    if (!_pfnClose_adapter || !_pfnOpen_adapter_hdc || !_pfnEscape)  {<br class="">> +        return false;<br class="">> +    }<br class="">> +    _driver_type = WDDM;<br class="">> +    return true;<br class="">> +}<br class="">> +<br class="">> +D3DKMT_HANDLE WDDMInterface::adapter_handle(LPCTSTR device_name)<br class="">> +{<br class="">> +    D3DKMT_HANDLE hAdapter(0);<br class="">> +<br class="">> +    //For some reason, unknown to me, this call will occasionally fail.<br class="">> +    if ((hAdapter = handle_from_DC(device_name))) {<br class="">> +        return hAdapter;<br class="">> +    }<br class="">> +        //So try other available methods.<br class="">> +    if (_pfnOpen_adapter_device_name && (hAdapter =<br class="">> handle_from_device_name(device_name))) {<br class="">> +        return hAdapter;<br class="">> +    }<br class="">> +    //One last chance to open this guy<br class="">> +    if (_pfnOpen_adapter_gdi_name) {<br class="">> +        hAdapter = handle_from_GDI_name(device_name);<br class="">> +    }<br class="">> +<br class="">> +    if (!hAdapter) {<br class="">> +        vd_printf("%s: failed to open adapter %S", __FUNCTION__,<br class="">> device_name);<br class="">> +    }<br class="">> +<br class="">> +    return hAdapter;<br class="">> +}<br class="">> +<br class="">> +D3DKMT_HANDLE WDDMInterface::handle_from_DC(LPCTSTR adapter_name)<br class="">> +{<br class="">> +    NTSTATUS status;<br class="">> +    D3DKMT_OPENADAPTERFROMHDC open_data;<br class="">> +    HDC hDc(CreateDC(adapter_name, NULL, NULL, NULL));<br class="">> +<br class="">> +    if (!hDc) {<br class="">> +        vd_printf("%s: %S CreateDC failed with %lu", __FUNCTION__,<br class="">> adapter_name, GetLastError());<br class="">> +        return 0;<br class="">> +    }<br class="">> +<br class="">> +    ZeroMemory(&open_data, sizeof(D3DKMT_OPENADAPTERFROMHDC));<br class="">> +    open_data.hDc = hDc;<br class="">> +<br class="">> +    if (!NT_SUCCESS(status = _pfnOpen_adapter_hdc(&open_data))) {<br class="">> +        vd_printf("%s: %S open adapter from hdc failed with %lu",<br class="">> __FUNCTION__, adapter_name,<br class="">> +            status);<br class="">> +        open_data.hAdapter = 0;<br class="">> +    }<br class="">> +<br class="">> +    DeleteDC(hDc);<br class="">> +    return open_data.hAdapter;<br class="">> +}<br class="">> +<br class="">> +D3DKMT_HANDLE WDDMInterface::handle_from_device_name(LPCTSTR adapter_name)<br class="">> +{<br class="">> +    D3DKMT_OPENADAPTERFROMDEVICENAME display_name_data;<br class="">> +    NTSTATUS  status;<br class="">> +<br class="">> +    ZeroMemory(&display_name_data, sizeof(display_name_data));<br class="">> +    display_name_data.pDeviceName = adapter_name;<br class="">> +<br class="">> +    if (NT_SUCCESS(status =<br class="">> _pfnOpen_adapter_device_name(&display_name_data))) {<br class="">> +        return display_name_data.hAdapter;<br class="">> +    }<br class="">> +<br class="">> +    vd_printf("%s %S failed with 0x%lx", __FUNCTION__, adapter_name,<br class="">> status);<br class="">> +    return 0;<br class="">> +}<br class="">> +<br class="">> +D3DKMT_HANDLE WDDMInterface::handle_from_GDI_name(LPCTSTR adapter_name)<br class="">> +{<br class="">> +    D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME gdi_display_name;<br class="">> +    NTSTATUS status;<br class="">> +<br class="">> +    ZeroMemory(&gdi_display_name, sizeof(gdi_display_name));<br class="">> +    memcpy((void *) gdi_display_name.DeviceName, adapter_name,<br class="">> sizeof(TCHAR)* CCHDEVICENAME);<br class="">> +<br class="">> +    if (NT_SUCCESS(status = _pfnOpen_adapter_gdi_name(&gdi_display_name))) {<br class="">> +        return  gdi_display_name.hAdapter;<br class="">> +    }<br class="">> +<br class="">> +    vd_printf("%s: %S aurrrgghh nothing works..error  is 0x%lx",<br class="">> __FUNCTION__, adapter_name,<br class="">> +            status);<br class="">> +    return 0;<br class="">> +}<br class="">> +<br class="">> +void WDDMInterface::close_adapter(D3DKMT_HANDLE handle)<br class="">> +{<br class="">> +    D3DKMT_CLOSEADAPTER closeData;<br class="">> +    if (handle) {<br class="">> +        closeData.hAdapter = handle;<br class="">> +        _pfnClose_adapter(&closeData);<br class="">> +    }<br class="">> +}<br class="">> +<br class="">> +bool WDDMInterface::escape(LPCTSTR device_name, void* data, UINT size_data)<br class="">> +{<br class="">> +    D3DKMT_ESCAPE   escapeData;<br class="">> +    NTSTATUS        status;<br class="">> +    D3DKMT_HANDLE   hAdapter(0);<br class="">> +<br class="">> +    if (!(hAdapter = adapter_handle(device_name)))<br class="">> +        return false;<br class="">> +<br class="">> +    escapeData.hAdapter = hAdapter;<br class="">> +    escapeData.hDevice = 0;<br class="">> +    escapeData.hContext = 0;<br class="">> +    escapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;<br class="">> +    escapeData.Flags.Value = 0;<br class="">> +    escapeData.pPrivateDriverData = data;<br class="">> +    escapeData.PrivateDriverDataSize = size_data;<br class="">> +<br class="">> +    status = _pfnEscape(&escapeData);<br class="">> +<br class="">> +    if (!NT_SUCCESS(status)) {<br class="">> +        vd_printf("%s: this should never happen. Status is 0x%lx",<br class="">> __FUNCTION__, status);<br class="">> +        _driver_type = INVALID_DRIVER;<br class="">> +    }<br class="">> +<br class="">> +    //Close the handle to this device<br class="">> +    close_adapter(hAdapter);<br class="">> +    return NT_SUCCESS(status);<br class="">> +}<br class="">> +<br class="">> +CCD::CCD()<br class="">> +    :_NumPathElements(0)<br class="">> +    ,_NumModeElements(0)<br class="">> +    ,_pPathInfo(NULL)<br class="">> +    ,_pModeInfo(NULL)<br class="">> +    ,_pfnGetDeviceInfo(NULL)<br class="">> +    ,_pfnGetDisplayConfigBufferSizes(NULL)<br class="">> +    ,_pfnQueryDisplayConfig(NULL)<br class="">> +    ,_pfnSetDisplayConfig(NULL)<br class="">> +    ,_error(0)<br class="">> +    ,_primary_detached(false)<br class="">> +    ,_path_state(PATH_UPDATED)<br class="">> +{<br class="">> +    if (load_api()) {<br class="">> +        get_config_buffers();<br class="">> +    }<br class="">> +}<br class="">> +<br class="">> +CCD::~CCD()<br class="">> +{<br class="">> +    free_config_buffers();<br class="">> +}<br class="">> +<br class="">> +bool CCD::query_display_config()<br class="">> +{<br class="">> +    LONG query_error(ERROR_SUCCESS);<br class="">> +<br class="">> +    //Until we get it or error != ERROR_INSUFFICIENT_BUFFER<br class="">> +    do {<br class="">> +        query_error = _pfnQueryDisplayConfig(QDC_ALL_PATHS,<br class="">> &_NumPathElements, _pPathInfo,<br class="">> +            &_NumModeElements, _pModeInfo, NULL);<br class="">> +<br class="">> +        // if ERROR_INSUFFICIENT_BUFFER need to retry QueryDisplayConfig<br class="">> +        // to get a new set of config buffers<br class="">> +        //(see<br class="">><span class="Apple-converted-space"> </span><a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff569215(v=vs.85).aspx" rel="noreferrer" target="_blank" class="">https://msdn.microsoft.com/en-us/library/windows/hardware/ff569215(v=vs.85).aspx</a><br class="">> )<br class="">> +        if (query_error) {<br class="">> +             if (query_error == ERROR_INSUFFICIENT_BUFFER) {<br class="">> +                free_config_buffers();<br class="">> +                if (!get_config_buffers())<br class="">> +                    return false;<br class="">> +            } else {<br class="">> +                _error = query_error;<br class="">> +                vd_printf("%s failed QueryDisplayConfig with 0x%lx",<br class="">> __FUNCTION__, _error);<br class="">> +                return false;<br class="">> +            }<br class="">> +        }<br class="">> +    } while(query_error);<br class="">> +    _path_state = PATH_CURRENT;<br class="">> +    return true;<br class="">> +}<br class="">> +<br class="">> +DISPLAYCONFIG_MODE_INFO* CCD::get_active_mode(LPCTSTR device_name, bool<br class="">> return_on_error)<br class="">> +{<br class="">> +    DISPLAYCONFIG_PATH_INFO* active_path;<br class="">> +<br class="">> +    active_path = get_device_path(device_name, true);<br class="">> +<br class="">> +    if (!active_path ) {<br class="">> +        vd_printf("%s:%S failed", __FUNCTION__, device_name);<br class="">> +        return NULL;<br class="">> +    }<br class="">> +    return &_pModeInfo[active_path->sourceInfo.modeInfoIdx];<br class="">> +}<br class="">> +<br class="">> +bool CCD::set_display_config() {<br class="">> +<br class="">> +    debug_print_config("Before SetDisplayConfig");<br class="">> +<br class="">> +    if (_path_state == PATH_CURRENT) {<br class="">> +        vd_printf("%s: path states says nothing changed", __FUNCTION__);<br class="">> +        return true;<br class="">> +    }<br class="">> +<br class="">> +    if (!(_error = _pfnSetDisplayConfig(_NumPathElements, _pPathInfo,<br class="">> +            _NumModeElements, _pModeInfo,<br class="">> +            SDC_APPLY | SDC_USE_SUPPLIED_DISPLAY_CONFIG |<br class="">> SDC_FORCE_MODE_ENUMERATION))) {<br class="">> +        return true;<br class="">> +    }<br class="">> +<br class="">> +    vd_printf("%s failed SetDisplayConfig with 0x%lx", __FUNCTION__,<br class="">> _error);<br class="">> +    debug_print_config("After failed SetDisplayConfig");<br class="">> +    return false;<br class="">> +}<br class="">> +<br class="">> +DISPLAYCONFIG_PATH_INFO* CCD::get_device_path(LPCTSTR device_name, bool<br class="">> bActive)<br class="">> +{<br class="">> +    //Search for device's active path<br class="">> +    for (UINT32 i = 0; i < _NumPathElements; i++) {<br class="">> +        DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];<br class="">> +<br class="">> +        //if bActive, return only paths that are currently active<br class="">> +        if (bActive && !is_active_path(path_info))<br class="">> +            continue;<br class="">> +        if (!is_device_path(device_name, path_info))<br class="">> +            continue;<br class="">> +        return path_info;<br class="">> +    }<br class="">> +    _error = ERROR_GEN_FAILURE;<br class="">> +    return NULL;<br class="">> +}<br class="">> +<br class="">> +void CCD::debug_print_config(const char* prefix)<br class="">> +{<br class="">> +    TCHAR dev_name[CCHDEVICENAME];<br class="">> +    for (UINT32 i = 0; i < _NumPathElements; i++) {<br class="">> +        DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];<br class="">> +        if (!(path_info->flags & DISPLAYCONFIG_PATH_ACTIVE))<br class="">> +            continue;<br class="">> +        get_device_name_config(path_info, dev_name);<br class="">> +<br class="">> +        if (path_info->sourceInfo.modeInfoIdx ==<br class="">> DISPLAYCONFIG_PATH_MODE_IDX_INVALID) {<br class="">> +            vd_printf("%s: %S  [%s] This path is active but has invalid mode<br class="">> set.", __FUNCTION__,<br class="">> +                dev_name, prefix);<br class="">> +            continue;<br class="">> +        }<br class="">> +        DISPLAYCONFIG_MODE_INFO* mode =<br class="">> &_pModeInfo[path_info->sourceInfo.modeInfoIdx];<br class="">> +        vd_printf("%s: %S [%s] (%ld,%ld) (%ux%u).", __FUNCTION__, dev_name,<br class="">> prefix,<br class="">> +            mode->sourceMode.position.x, mode->sourceMode.position.y,<br class="">> +            mode->sourceMode.width, mode->sourceMode.height);<br class="">> +    }<br class="">> +}<br class="">> +<br class="">> +bool CCD::load_api()<br class="">> +{<br class="">> +    HMODULE hModule = LoadLibrary(L"user32.dll");<br class="">> +    if(!hModule) {<br class="">> +        return false;<br class="">> +    }<br class="">> +<br class="">> +    bool bFound_all(false);<br class="">> +    do {<br class="">> +        if (!(_pfnGetDeviceInfo = (PDISPLAYCONFIG_GETDEVICEINFO)<br class="">> +            GetProcAddress(hModule, "DisplayConfigGetDeviceInfo"))) {<br class="">> +            break;<br class="">> +        }<br class="">> +<br class="">> +        if (!(_pfnGetDisplayConfigBufferSizes =<br class="">> (PGETDISPLAYCONFIG_BUFFERSIZES)<br class="">> +            GetProcAddress(hModule, "GetDisplayConfigBufferSizes"))) {<br class="">> +            break;<br class="">> +        }<br class="">> +<br class="">> +        if (!(_pfnQueryDisplayConfig = (PQUERYDISPLAYCONFIG)<br class="">> +            GetProcAddress(hModule, "QueryDisplayConfig"))) {<br class="">> +            break;<br class="">> +        }<br class="">> +<br class="">> +        if (!(_pfnSetDisplayConfig = (PSETDISPLAYCONFIG)<br class="">> +            GetProcAddress(hModule, "SetDisplayConfig"))) {<br class="">> +            break;<br class="">> +        }<br class="">> +        bFound_all = true;<br class="">> +    }<br class="">> +    while(0);<br class="">> +<br class="">> +    FreeLibrary(hModule);<br class="">> +    return bFound_all;<br class="">> +}<br class="">> +<br class="">> +bool CCD::get_config_buffers()<br class="">> +{<br class="">> +    //Get Config Buffer Sizes<br class="">> +    free_config_buffers();<br class="">> +    _error = _pfnGetDisplayConfigBufferSizes(QDC_ALL_PATHS,<br class="">> &_NumPathElements,<br class="">> +                                            &_NumModeElements);<br class="">> +    if (_error) {<br class="">> +        vd_printf("%s: GetDisplayConfigBufferSizes failed with 0x%lx",<br class="">> __FUNCTION__, _error);<br class="">> +        return false;<br class="">> +    }<br class="">> +<br class="">> +    //Allocate arrays<br class="">> +    _pPathInfo = ((DISPLAYCONFIG_PATH_INFO*)<br class="">> malloc(sizeof(DISPLAYCONFIG_PATH_INFO) * _NumPathElements));<br class="">> +    _pModeInfo = ((DISPLAYCONFIG_MODE_INFO*)<br class="">> malloc(sizeof(DISPLAYCONFIG_MODE_INFO) * _NumModeElements));<br class="">> +<br class="">> +    if (!_pPathInfo || !_pModeInfo) {<br class="">> +        vd_printf("%s OOM ", __FUNCTION__);<br class="">> +        return false;<br class="">> +    }<br class="">> +<br class="">> +    ///clear the above arrays<br class="">> +    ZeroMemory(_pPathInfo, sizeof(DISPLAYCONFIG_PATH_INFO) *<br class="">> _NumPathElements);<br class="">> +    ZeroMemory(_pModeInfo, sizeof(DISPLAYCONFIG_MODE_INFO) *<br class="">> _NumModeElements);<br class="">> +    return true;<br class="">> +}<br class="">> +<br class="">> +void CCD::free_config_buffers()<br class="">> +{<br class="">> +    if (_pModeInfo) {<br class="">> +        free(_pModeInfo);<br class="">> +        _pModeInfo = NULL;<br class="">> +    }<br class="">> +    if (_pPathInfo) {<br class="">> +        free(_pPathInfo);<br class="">> +        _pPathInfo = NULL;<br class="">> +    }<br class="">> +    _NumModeElements = _NumPathElements = 0;<br class="">> +}<br class="">> +<br class="">> +bool  CCD::get_device_name_config(DISPLAYCONFIG_PATH_INFO* path, LPCTSTR<br class="">> dev_name)<br class="">> +{<br class="">> +    DISPLAYCONFIG_SOURCE_DEVICE_NAME source_name;<br class="">> +    source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;<br class="">> +    source_name.header.size = sizeof(DISPLAYCONFIG_SOURCE_DEVICE_NAME);<br class="">> +    source_name.header.adapterId = path->sourceInfo.adapterId;<br class="">> +   <span class="Apple-converted-space"> </span><a href="http://source_name.header.id/" rel="noreferrer" target="_blank" class="">source_name.header.id</a><span class="Apple-converted-space"> </span>= path->sourceInfo.id;<br class="">> +<br class="">> +    _error = _pfnGetDeviceInfo(&source_name.header);<br class="">> +    if (_error) {<br class="">> +        vd_printf("%s DisplayConfigGetDeviceInfo failed with %lu",<br class="">> __FUNCTION__, _error);<br class="">> +        return false;<br class="">> +    }<br class="">> +    memcpy((void *)dev_name, source_name.viewGdiDeviceName, CCHDEVICENAME*<br class="">> sizeof(TCHAR));<br class="">> +    return true;<br class="">> +}<br class="">> +<br class="">> +bool CCD::is_device_path(LPCTSTR device_name, DISPLAYCONFIG_PATH_INFO* path)<br class="">> +{<br class="">> +    //Does this path belong to device_name?<br class="">> +    TCHAR dev_name[CCHDEVICENAME];<br class="">> +    if (!get_device_name_config(path, dev_name)) {<br class="">> +        return false;<br class="">> +    }<br class="">> +    if (_tcscmp(dev_name, device_name)) {<br class="">> +        return false;<br class="">> +    }<br class="">> +    return true;<br class="">> +}<br class="">> +<br class="">> +// If we have detached the primary monitor, then we need to reset the<br class="">> positions of the remaining<br class="">> +// monitors to insure that at least one is positioned at (0,0)<br class="">> +bool CCD::verify_primary_position()<br class="">> +{<br class="">> +    LONG leftmost_x(0);<br class="">> +    if (!_primary_detached) {<br class="">> +        return true;<br class="">> +    }<br class="">> +    _primary_detached = false;<br class="">> +<br class="">> +    for (UINT32 i = 0; i < _NumPathElements; i++) {<br class="">> +        DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];<br class="">> +        if (!(path_info->flags & DISPLAYCONFIG_PATH_ACTIVE))<br class="">> +            continue;<br class="">> +<br class="">> +        DISPLAYCONFIG_MODE_INFO* mode =<br class="">> &_pModeInfo[path_info->sourceInfo.modeInfoIdx];<br class="">> +        if (leftmost_x > mode->sourceMode.position.x) {<br class="">> +            leftmost_x = mode->sourceMode.position.x;<br class="">> +        }<br class="">> +    }<br class="">> +<br class="">> +    if (leftmost_x == 0) {<br class="">> +        return false;<br class="">> +    }<br class="">> +<br class="">> +    for (UINT32 i = 0; i < _NumPathElements; i++) {<br class="">> +        DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];<br class="">> +        if ((!(path_info->flags & DISPLAYCONFIG_PATH_ACTIVE)))<br class="">> +            continue;<br class="">> +        DISPLAYCONFIG_MODE_INFO* mode =<br class="">> &_pModeInfo[path_info->sourceInfo.modeInfoIdx];<br class="">> +        vd_printf("%s: setting mode x to %lu", __FUNCTION__,<br class="">> mode->sourceMode.position.x);<br class="">> +        mode->sourceMode.position.x -= leftmost_x;<br class="">> +    }<br class="">> +    _path_state = PATH_UPDATED;<br class="">> +    return true;<br class="">> +}<br class="">> +<br class="">> +bool CCD::update_mode_position(LPCTSTR device_name, DEVMODE* dev_mode)<br class="">> +{<br class="">> +    DISPLAYCONFIG_MODE_INFO* mode = get_active_mode(device_name, false);<br class="">> +    if (!mode)<br class="">> +        return false;<br class="">> +<br class="">> +    mode->sourceMode.position.x = dev_mode->dmPosition.x;<br class="">> +    mode->sourceMode.position.y = dev_mode->dmPosition.y;<br class="">> +    vd_printf("%s: %S updated path mode to (%lu, %lu) - (%u x%u)",<br class="">> __FUNCTION__,<br class="">> +        device_name,<br class="">> +        mode->sourceMode.position.x, mode->sourceMode.position.y,<br class="">> +        mode->sourceMode.width, mode->sourceMode.height);<br class="">> +    _path_state = PATH_UPDATED;<br class="">> +    return true;<br class="">> +<br class="">> +}<br class="">> +<br class="">> +bool CCD::update_mode_size(LPCTSTR device_name, DEVMODE* dev_mode)<br class="">> +{<br class="">> +    DISPLAYCONFIG_MODE_INFO* mode = get_active_mode(device_name, false);<br class="">> +    if (!mode) {<br class="">> +        return false;<br class="">> +    }<br class="">> +<br class="">> +    mode->sourceMode.width = dev_mode->dmPelsWidth;<br class="">> +    mode->sourceMode.height = dev_mode->dmPelsHeight;<br class="">> +    vd_printf("%s: %S updated path mode to (%lu, %lu - (%u x %u)",<br class="">> __FUNCTION__,<br class="">> +        device_name,<br class="">> +        mode->sourceMode.position.x, mode->sourceMode.position.y,<br class="">> +        mode->sourceMode.width, mode->sourceMode.height);<br class="">> +    _path_state = PATH_UPDATED;<br class="">> +    return true;<br class="">> +}<br class="">> +<br class="">> +void CCD::update_detached_primary_state(LPCTSTR device_name,<br class="">> DISPLAYCONFIG_PATH_INFO * path_info)<br class="">> +{<br class="">> +    DISPLAYCONFIG_MODE_INFO* mode(get_active_mode(device_name, false));<br class="">> +<br class="">> +    //will need to reset monitor positions if primary detached<br class="">> +    path_info->flags = path_info->flags & ~DISPLAYCONFIG_PATH_ACTIVE;<br class="">> +    if (!mode|| mode->sourceMode.position.x != 0 ||<br class="">> mode->sourceMode.position.y != 0) {<br class="">> +        return ;<br class="">> +    }<br class="">> +    _primary_detached = true;<br class="">> +}<br class="">> +<br class="">> +bool CCD::set_path_state(LPCTSTR device_name, MONITOR_STATE new_state)<br class="">> +{<br class="">> +    DISPLAYCONFIG_PATH_INFO* path(get_device_path(device_name, false));<br class="">> +    MONITOR_STATE current_path_state(MONITOR_DETACHED);<br class="">> +<br class="">> +    if (path && (path->flags & DISPLAYCONFIG_PATH_ACTIVE)) {<br class="">> +        current_path_state = MONITOR_ATTACHED;<br class="">> +    }<br class="">> +<br class="">> +    //If state didn't change, nothing to do<br class="">> +    if (current_path_state == new_state ) {<br class="">> +        return true;<br class="">> +    }<br class="">> +<br class="">> +    if (!path) {<br class="">> +        return false;<br class="">> +    }<br class="">> +<br class="">> +    _path_state = PATH_UPDATED;<br class="">> +    if (new_state == MONITOR_DETACHED) {<br class="">> +        update_detached_primary_state(device_name, path);<br class="">> +    } else {<br class="">> +        path->flags = path->flags | DISPLAYCONFIG_PATH_ACTIVE;<br class="">> +        set_display_config();<br class="">> +    }<br class="">> +    return true;<br class="">> +}<br class="">> +<br class="">> +bool CCD::is_attached(LPCTSTR device_name)<br class="">> +{<br class="">> +    DISPLAYCONFIG_PATH_INFO* path(get_device_path(device_name, false));<br class="">> +    if (!path) {<br class="">> +        return false;<br class="">> +    }<br class="">> +    return (path->flags & DISPLAYCONFIG_PATH_ACTIVE);<br class="">> +}<br class="">> +<br class="">> +bool CCD::is_active_path(DISPLAYCONFIG_PATH_INFO * path)<br class="">> +{<br class="">> +    if (!path || !(path->flags & DISPLAYCONFIG_PATH_ACTIVE) ||<br class="">> +        (path->sourceInfo.modeInfoIdx ==<br class="">> DISPLAYCONFIG_PATH_MODE_IDX_INVALID)) {<br class="">> +        return false;<br class="">> +    }<br class="">> +    return true;<br class="">> +}<br class="">> diff --git a/vdagent/display_configuration.h<br class="">> b/vdagent/display_configuration.h<br class="">> new file mode 100755<br class="">> index 0000000..870a28d<br class="">> --- /dev/null<br class="">> +++ b/vdagent/display_configuration.h<br class="">> @@ -0,0 +1,191 @@<br class="">> +/*<br class="">> +Copyright (C) 2015 Red Hat, Inc.<br class="">> +<br class="">> +This program is free software; you can redistribute it and/or<br class="">> +modify it under the terms of the GNU General Public License as<br class="">> +published by the Free Software Foundation; either version 2 of<br class="">> +the License, or (at your option) any later version.<br class="">> +<br class="">> +This program is distributed in the hope that it will be useful,<br class="">> +but WITHOUT ANY WARRANTY; without even the implied warranty of<br class="">> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br class="">> +GNU General Public License for more details.<br class="">> +<br class="">> +You should have received a copy of the GNU General Public License<br class="">> +along with this program.  If not, see <<a href="http://www.gnu.org/licenses/" rel="noreferrer" target="_blank" class="">http://www.gnu.org/licenses/</a>>.<br class="">> +*/<br class="">> +#ifndef _H_DISPLAY_CONFIGURATION<br class="">> +#define _H_DISPLAY_CONFIGURATION<br class="">> +<br class="">> +#include <spice/qxl_windows.h><br class="">> +#include <spice/qxl_dev.h><br class="">> +#include "desktop_layout.h"<br class="">> +#include "vdlog.h"<br class="">> +<br class="">> +enum DRIVER_TYPE {<br class="">> +    XPDM,<br class="">> +    WDDM,<br class="">> +    INVALID_DRIVER,<br class="">> +};<br class="">> +<br class="">> +enum MONITOR_STATE {<br class="">> +    MONITOR_DETACHED,<br class="">> +    MONITOR_ATTACHED,<br class="">> +};<br class="">> +<br class="">> +enum PATH_STATE {<br class="">> +    PATH_UPDATED,<br class="">> +    PATH_CURRENT,<br class="">> +};<br class="">> +<br class="">> +enum DISPLAYCONFIG_TOPOLOGY_ID {};<br class="">> +<br class="">> +struct DISPLAYCONFIG_DEVICE_INFO_HEADER;<br class="">> +struct DISPLAYCONFIG_MODE_INFO;<br class="">> +struct DISPLAYCONFIG_PATH_INFO;<br class="">> +<br class="">> +//Makes calls into the CCD API for getting/setting display settings on WDDM<br class="">> drivers<br class="">> +//Use is exclusive to wddm display config class<br class="">> +<br class="">> +typedef LONG(APIENTRY*<br class="">> PDISPLAYCONFIG_GETDEVICEINFO)(DISPLAYCONFIG_DEVICE_INFO_HEADER*);<br class="">> +typedef LONG(APIENTRY* PGETDISPLAYCONFIG_BUFFERSIZES)(UINT32, UINT32*,<br class="">> UINT32*);<br class="">> +typedef LONG(APIENTRY* PQUERYDISPLAYCONFIG)(UINT32, UINT32*,<br class="">> DISPLAYCONFIG_PATH_INFO*, UINT32*,<br class="">> +                                            DISPLAYCONFIG_MODE_INFO*,<br class="">> DISPLAYCONFIG_TOPOLOGY_ID*);<br class="">> +typedef LONG(APIENTRY* PSETDISPLAYCONFIG)(UINT32, DISPLAYCONFIG_PATH_INFO*,<br class="">> UINT32,<br class="">> +                                          DISPLAYCONFIG_MODE_INFO*, UINT32);<br class="">> +<br class="">> +class CCD {<br class="">> +protected:<br class=""><br class=""></div></div>This should be public, protected is used for inheritance.</blockquote><div class="">The class "WDDMInterface" has an instance of the "CCD" class, The constructor and destructor of the</div><div class="">"CCD" class are both protected, this enables the<b class=""><span class="Apple-converted-space"> </span>friend<span class="Apple-converted-space"> </span></b>class "WDDMInterface" to</div><div class="">create and destroy CCD objects.</div></div></div></div></blockquote><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">I know what friend does. Still I think this usage is wrong. I prefer the Javer's CDDLibrary style.<br class=""></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">There is no reason to bound CCD to WDDMInterface and there are other better way to do it like a nested<br class=""></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">private class instead.<br class=""></div></div></blockquote><div><br class=""></div><div><br class=""></div><div>Not sure what were Sandy’s considerations when she wrote this, as for me it looks too complicated as well.</div><div>We’re dropping this in favour of public ctor/dctor in class CCD.</div><blockquote type="cite" class=""><div class=""><blockquote style="font-size: 12pt; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; border-left-width: 2px; border-left-style: solid; border-left-color: rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; text-decoration: none; font-family: Helvetica, Arial, sans-serif;" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div class=""><div class="h5"><span style="color: rgb(34, 34, 34);" class=""> </span><br class=""></div></div></blockquote><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div class=""><div class="h5">> +    CCD();<br class="">> +    ~CCD();<br class="">> +<br class="">> +    bool query_display_config();<br class="">> +    bool set_display_config();<br class="">> +    bool update_mode_position(LPCTSTR device_name, DEVMODE* dev_mode);<br class="">> +    bool update_mode_size(LPCTSTR DeviceNmae, DEVMODE* dev_mode);<br class="">> +    void update_detached_primary_state(LPCTSTR device_name,<br class="">> DISPLAYCONFIG_PATH_INFO * path_info);<br class="">> +    bool set_path_state(LPCTSTR device_name, MONITOR_STATE state);<br class="">> +    bool is_attached(LPCTSTR device_name);<br class="">> +    bool is_active_path(DISPLAYCONFIG_PATH_INFO * path);<br class="">> +    LONG error() { return _error; }<br class="">> +<br class="">> +private:<br class="">> +    bool load_api();<br class="">> +    bool get_config_buffers();<br class="">> +    void free_config_buffers();<br class="">> +    bool verify_primary_position();<br class="">> +    bool is_device_path(LPCTSTR device_name, DISPLAYCONFIG_PATH_INFO* path);<br class="">> +    DISPLAYCONFIG_MODE_INFO* get_active_mode(LPCTSTR device_name, bool<br class="">> return_on_error);<br class="">> +    DISPLAYCONFIG_PATH_INFO* get_device_path(LPCTSTR device_name, bool<br class="">> bActive);<br class="">> +    bool get_device_name_config(DISPLAYCONFIG_PATH_INFO* path, LPCTSTR<br class="">> dev_name);<br class="">> +    void debug_print_config(const char* prefix = NULL);<br class="">> +<br class="">> +private:<br class="">> +    //CCD API stuff<br class="">> +    UINT32 _NumPathElements;<br class="">> +    UINT32 _NumModeElements;<br class="">> +    DISPLAYCONFIG_PATH_INFO* _pPathInfo;<br class="">> +    DISPLAYCONFIG_MODE_INFO* _pModeInfo;<br class="">> +<br class="">> +    //CCD API function pointers<br class="">> +    PDISPLAYCONFIG_GETDEVICEINFO _pfnGetDeviceInfo;<br class="">> +    PGETDISPLAYCONFIG_BUFFERSIZES _pfnGetDisplayConfigBufferSizes;<br class="">> +    PQUERYDISPLAYCONFIG _pfnQueryDisplayConfig;<br class="">> +    PSETDISPLAYCONFIG _pfnSetDisplayConfig;<br class="">> +<br class="">> +    LONG  _error;<br class="">> +    bool  _primary_detached;<br class="">> +    PATH_STATE _path_state;<br class="">> +    friend class WDDMInterface;<br class=""><br class=""></div></div>There should be no reason for friend.<br class=""><span class=""><br class="">> +};<br class="">> +<br class="">> +class DisplayMode;<br class="">> +<br class="">> +//Class provides interface to get/set display configurations<br class="">> +class DisplayConfig {<br class="">> +public:<br class="">> +    static DisplayConfig* create_config();<br class="">> +    DisplayConfig();;<br class=""><br class=""></span>typo (;;).<br class=""><span class=""><br class="">> +    virtual ~DisplayConfig() {};<br class="">> +<br class="">> +    virtual bool is_attached(DISPLAY_DEVICE* dev_info) = 0;<br class="">> +    virtual bool custom_display_escape(LPCTSTR device, DEVMODE* mode) = 0;<br class="">> +    virtual bool update_monitor_config(LPCTSTR device, DisplayMode* mode,<br class="">> DEVMODE* dev_mode) = 0;<br class="">> +    virtual bool set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode,<br class="">> MONITOR_STATE state) = 0;<br class="">> +    virtual LONG update_display_settings() = 0;<br class="">> +    virtual bool update_dev_mode_position(LPCTSTR dev_name, DEVMODE*<br class="">> dev_mode, LONG x, LONG y) = 0;<br class="">> +    DRIVER_TYPE type() { return _driver_type; };<br class=""><br class=""></span>const and actually quite a bad design, I would remove this member<br class="">entirely.<br class=""></blockquote></div></div></div></blockquote></div></blockquote><div><br class=""></div><div>Yes, the C++ way is to throw exception from ctor. This is what we will do.</div><div>Thanks.</div><blockquote type="cite" class=""><div class=""><blockquote style="font-size: 12pt; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; border-left-width: 2px; border-left-style: solid; border-left-color: rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; text-decoration: none; font-family: Helvetica, Arial, sans-serif;" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><span class=""><br class="">> +    void set_monitors_config(bool flag) { _send_monitors_config = flag; }<br class="">> +    virtual void update_config_path() {};<br class="">> +<br class="">> +protected:<br class="">> +    DRIVER_TYPE _driver_type;<br class=""><br class=""></span>also I would remove this field. Would be much better to have a<br class="">WDDMInterface::init that returns true/false.<br class="">Actually WDDMInterface is quite a bad name for an implementation.<br class=""><span class=""><br class="">> +    bool _send_monitors_config;<br class="">> +};<br class="">> +<br class="">> +//DisplayConfig implementation for guest with XPDM graphics drivers<br class="">> +class XPDMInterface : public DisplayConfig {<br class="">> +public:<br class="">> +    XPDMInterface() :DisplayConfig() { _driver_type = XPDM; };<br class="">> +    ~XPDMInterface() {}<br class="">> +    bool is_attached(DISPLAY_DEVICE* dev_info);;<br class=""><br class=""></span>typo (;;).<br class=""><div class=""><div class="h5"><br class="">> +    bool custom_display_escape(LPCTSTR device_name, DEVMODE* dev_mode);<br class="">> +    bool update_monitor_config(LPCTSTR device_name, DisplayMode* mode,<br class="">> DEVMODE* dev_mode);<br class="">> +    bool set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode,<br class="">> MONITOR_STATE state);<br class="">> +    LONG update_display_settings();<br class="">> +    bool update_dev_mode_position(LPCTSTR device_name, DEVMODE * dev_mode,<br class="">> LONG x, LONG y);<br class="">> +<br class="">> +private:<br class="">> +    bool find_best_mode(LPCTSTR Device, DEVMODE* dev_mode);<br class="">> +};<br class="">> +<br class="">> +//DisplayConfig implementation for guest with WDDM graphics drivers<br class="">> +typedef UINT D3DKMT_HANDLE;<br class="">> +<br class="">> +struct D3DKMT_ESCAPE;<br class="">> +struct D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME;<br class="">> +struct D3DKMT_OPENADAPTERFROMDEVICENAME;<br class="">> +struct D3DKMT_CLOSEADAPTER;<br class="">> +struct D3DKMT_OPENADAPTERFROMHDC;<br class="">> +<br class="">> +typedef NTSTATUS(APIENTRY* PFND3DKMT_ESCAPE)(CONST D3DKMT_ESCAPE*);<br class="">> +typedef NTSTATUS(APIENTRY*<br class="">> PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME)(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME*);<br class="">> +typedef NTSTATUS(APIENTRY*<br class="">> PFND3DKMT_OPENADAPTERFROMDEVICENAME)(D3DKMT_OPENADAPTERFROMDEVICENAME*);<br class="">> +typedef NTSTATUS(APIENTRY* PFND3DKMT_CLOSEADAPTER)(D3DKMT_CLOSEADAPTER*);<br class="">> +typedef NTSTATUS(APIENTRY*<br class="">> PFND3DKMT_OPENADAPTERFROMHDC)(D3DKMT_OPENADAPTERFROMHDC*);<br class="">> +<br class="">> +class WDDMInterface : public DisplayConfig {<br class="">> +public:<br class="">> +    WDDMInterface();<br class="">> +    ~WDDMInterface();<br class="">> +    bool is_attached(DISPLAY_DEVICE* dev_info);<br class="">> +    bool set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode,<br class="">> MONITOR_STATE state);<br class="">> +    LONG update_display_settings();<br class="">> +    bool custom_display_escape(LPCTSTR device_name, DEVMODE* dev_mode);<br class="">> +    bool update_monitor_config(LPCTSTR device_name, DisplayMode* mode,<br class="">> DEVMODE* dev_mode);<br class="">> +    bool update_dev_mode_position(LPCTSTR device_name, DEVMODE * dev_mode,<br class="">> LONG x, LONG y);<br class="">> +    void update_config_path();<br class="">> +<br class="">> +private:<br class="">> +    bool init_d3d_api();<br class="">> +    D3DKMT_HANDLE adapter_handle(LPCTSTR device_name);<br class="">> +    D3DKMT_HANDLE handle_from_DC(LPCTSTR adapter_name);<br class="">> +    D3DKMT_HANDLE handle_from_device_name(LPCTSTR adapter_name);<br class="">> +    D3DKMT_HANDLE handle_from_GDI_name(LPCTSTR adapter_name);<br class="">> +<br class="">> +    void close_adapter(D3DKMT_HANDLE handle);<br class="">> +    bool escape(LPCTSTR device_name, void* data, UINT sizeData);<br class="">> +<br class="">> +private:<br class="">> +    //GDI Function pointers<br class="">> +    PFND3DKMT_OPENADAPTERFROMHDC _pfnOpen_adapter_hdc;<br class="">> +    PFND3DKMT_CLOSEADAPTER  _pfnClose_adapter;<br class="">> +    PFND3DKMT_ESCAPE _pfnEscape;<br class="">> +    PFND3DKMT_OPENADAPTERFROMDEVICENAME _pfnOpen_adapter_device_name;<br class="">> +    PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME _pfnOpen_adapter_gdi_name;<br class="">> +<br class="">> +    //object handles the CCD API<br class="">> +    CCD _ccd;<br class="">> +};<br class="">> +<br class="">> +#endif<br class="">> \ No newline at end of file</div></div></blockquote></div></div></div></blockquote><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">As I said this patch is too big and should be split.<br class=""></div></div></blockquote><div><br class=""></div><div>We can move introduction of CCD and *Interface classes into separate file.</div><div>Is it or did you mean something else?</div><div><br class=""></div><div>Thanks,</div><div>Dmitry</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Frediano</div></div></blockquote></div><br class=""></body></html>