[Spice-devel] [PATCH win-vdagent] Provide support for Windows CCD API

Dmitry Fleytman dmitry at daynix.com
Wed Aug 3 13:01:44 UTC 2016


> On 3 Aug 2016, at 12:25 PM, Frediano Ziglio <fziglio at redhat.com> wrote:

Hi Frediano,

Thanks for review. See my comments inline.

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


Not sure what were Sandy’s considerations when she wrote this, as for me it looks too complicated as well.
We’re dropping this in favour of public ctor/dctor in class CCD.
>  
> > +    CCD();
> > +    ~CCD();
> > +
> > +    bool query_display_config();
> > +    bool set_display_config();
> > +    bool update_mode_position(LPCTSTR device_name, DEVMODE* dev_mode);
> > +    bool update_mode_size(LPCTSTR DeviceNmae, DEVMODE* dev_mode);
> > +    void update_detached_primary_state(LPCTSTR device_name,
> > DISPLAYCONFIG_PATH_INFO * path_info);
> > +    bool set_path_state(LPCTSTR device_name, MONITOR_STATE state);
> > +    bool is_attached(LPCTSTR device_name);
> > +    bool is_active_path(DISPLAYCONFIG_PATH_INFO * path);
> > +    LONG error() { return _error; }
> > +
> > +private:
> > +    bool load_api();
> > +    bool get_config_buffers();
> > +    void free_config_buffers();
> > +    bool verify_primary_position();
> > +    bool is_device_path(LPCTSTR device_name, DISPLAYCONFIG_PATH_INFO* path);
> > +    DISPLAYCONFIG_MODE_INFO* get_active_mode(LPCTSTR device_name, bool
> > return_on_error);
> > +    DISPLAYCONFIG_PATH_INFO* get_device_path(LPCTSTR device_name, bool
> > bActive);
> > +    bool get_device_name_config(DISPLAYCONFIG_PATH_INFO* path, LPCTSTR
> > dev_name);
> > +    void debug_print_config(const char* prefix = NULL);
> > +
> > +private:
> > +    //CCD API stuff
> > +    UINT32 _NumPathElements;
> > +    UINT32 _NumModeElements;
> > +    DISPLAYCONFIG_PATH_INFO* _pPathInfo;
> > +    DISPLAYCONFIG_MODE_INFO* _pModeInfo;
> > +
> > +    //CCD API function pointers
> > +    PDISPLAYCONFIG_GETDEVICEINFO _pfnGetDeviceInfo;
> > +    PGETDISPLAYCONFIG_BUFFERSIZES _pfnGetDisplayConfigBufferSizes;
> > +    PQUERYDISPLAYCONFIG _pfnQueryDisplayConfig;
> > +    PSETDISPLAYCONFIG _pfnSetDisplayConfig;
> > +
> > +    LONG  _error;
> > +    bool  _primary_detached;
> > +    PATH_STATE _path_state;
> > +    friend class WDDMInterface;
> 
> There should be no reason for friend.
> 
> > +};
> > +
> > +class DisplayMode;
> > +
> > +//Class provides interface to get/set display configurations
> > +class DisplayConfig {
> > +public:
> > +    static DisplayConfig* create_config();
> > +    DisplayConfig();;
> 
> typo (;;).
> 
> > +    virtual ~DisplayConfig() {};
> > +
> > +    virtual bool is_attached(DISPLAY_DEVICE* dev_info) = 0;
> > +    virtual bool custom_display_escape(LPCTSTR device, DEVMODE* mode) = 0;
> > +    virtual bool update_monitor_config(LPCTSTR device, DisplayMode* mode,
> > DEVMODE* dev_mode) = 0;
> > +    virtual bool set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode,
> > MONITOR_STATE state) = 0;
> > +    virtual LONG update_display_settings() = 0;
> > +    virtual bool update_dev_mode_position(LPCTSTR dev_name, DEVMODE*
> > dev_mode, LONG x, LONG y) = 0;
> > +    DRIVER_TYPE type() { return _driver_type; };
> 
> const and actually quite a bad design, I would remove this member
> entirely.

Yes, the C++ way is to throw exception from ctor. This is what we will do.
Thanks.
> 
> > +    void set_monitors_config(bool flag) { _send_monitors_config = flag; }
> > +    virtual void update_config_path() {};
> > +
> > +protected:
> > +    DRIVER_TYPE _driver_type;
> 
> also I would remove this field. Would be much better to have a
> WDDMInterface::init that returns true/false.
> Actually WDDMInterface is quite a bad name for an implementation.
> 
> > +    bool _send_monitors_config;
> > +};
> > +
> > +//DisplayConfig implementation for guest with XPDM graphics drivers
> > +class XPDMInterface : public DisplayConfig {
> > +public:
> > +    XPDMInterface() :DisplayConfig() { _driver_type = XPDM; };
> > +    ~XPDMInterface() {}
> > +    bool is_attached(DISPLAY_DEVICE* dev_info);;
> 
> typo (;;).
> 
> > +    bool custom_display_escape(LPCTSTR device_name, DEVMODE* dev_mode);
> > +    bool update_monitor_config(LPCTSTR device_name, DisplayMode* mode,
> > DEVMODE* dev_mode);
> > +    bool set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode,
> > MONITOR_STATE state);
> > +    LONG update_display_settings();
> > +    bool update_dev_mode_position(LPCTSTR device_name, DEVMODE * dev_mode,
> > LONG x, LONG y);
> > +
> > +private:
> > +    bool find_best_mode(LPCTSTR Device, DEVMODE* dev_mode);
> > +};
> > +
> > +//DisplayConfig implementation for guest with WDDM graphics drivers
> > +typedef UINT D3DKMT_HANDLE;
> > +
> > +struct D3DKMT_ESCAPE;
> > +struct D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME;
> > +struct D3DKMT_OPENADAPTERFROMDEVICENAME;
> > +struct D3DKMT_CLOSEADAPTER;
> > +struct D3DKMT_OPENADAPTERFROMHDC;
> > +
> > +typedef NTSTATUS(APIENTRY* PFND3DKMT_ESCAPE)(CONST D3DKMT_ESCAPE*);
> > +typedef NTSTATUS(APIENTRY*
> > PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME)(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME*);
> > +typedef NTSTATUS(APIENTRY*
> > PFND3DKMT_OPENADAPTERFROMDEVICENAME)(D3DKMT_OPENADAPTERFROMDEVICENAME*);
> > +typedef NTSTATUS(APIENTRY* PFND3DKMT_CLOSEADAPTER)(D3DKMT_CLOSEADAPTER*);
> > +typedef NTSTATUS(APIENTRY*
> > PFND3DKMT_OPENADAPTERFROMHDC)(D3DKMT_OPENADAPTERFROMHDC*);
> > +
> > +class WDDMInterface : public DisplayConfig {
> > +public:
> > +    WDDMInterface();
> > +    ~WDDMInterface();
> > +    bool is_attached(DISPLAY_DEVICE* dev_info);
> > +    bool set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode,
> > MONITOR_STATE state);
> > +    LONG update_display_settings();
> > +    bool custom_display_escape(LPCTSTR device_name, DEVMODE* dev_mode);
> > +    bool update_monitor_config(LPCTSTR device_name, DisplayMode* mode,
> > DEVMODE* dev_mode);
> > +    bool update_dev_mode_position(LPCTSTR device_name, DEVMODE * dev_mode,
> > LONG x, LONG y);
> > +    void update_config_path();
> > +
> > +private:
> > +    bool init_d3d_api();
> > +    D3DKMT_HANDLE adapter_handle(LPCTSTR device_name);
> > +    D3DKMT_HANDLE handle_from_DC(LPCTSTR adapter_name);
> > +    D3DKMT_HANDLE handle_from_device_name(LPCTSTR adapter_name);
> > +    D3DKMT_HANDLE handle_from_GDI_name(LPCTSTR adapter_name);
> > +
> > +    void close_adapter(D3DKMT_HANDLE handle);
> > +    bool escape(LPCTSTR device_name, void* data, UINT sizeData);
> > +
> > +private:
> > +    //GDI Function pointers
> > +    PFND3DKMT_OPENADAPTERFROMHDC _pfnOpen_adapter_hdc;
> > +    PFND3DKMT_CLOSEADAPTER  _pfnClose_adapter;
> > +    PFND3DKMT_ESCAPE _pfnEscape;
> > +    PFND3DKMT_OPENADAPTERFROMDEVICENAME _pfnOpen_adapter_device_name;
> > +    PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME _pfnOpen_adapter_gdi_name;
> > +
> > +    //object handles the CCD API
> > +    CCD _ccd;
> > +};
> > +
> > +#endif
> > \ No newline at end of file
> 
> As I said this patch is too big and should be split.

We can move introduction of CCD and *Interface classes into separate file.
Is it or did you mean something else?

Thanks,
Dmitry

> 
> Frediano

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/spice-devel/attachments/20160803/dbd0ed38/attachment-0001.html>


More information about the Spice-devel mailing list