On Mon, Jul 18, 2016 at 09:34:36AM +0300, Dmitry Fleytman wrote: > diff --git a/vdagent/display_configuration.h b/vdagent/display_configuration.h > new file mode 100644 > index 0000000..eeba1c2 > --- /dev/null > +++ b/vdagent/display_configuration.h > @@ -0,0 +1,192 @@ > +/* > +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/>. > +*/ > +#pragma once > +#include <sdkddkver.h> > +#include <windows.h> > +#include <d3dtypes.h> > +#include "vdlog.h" > + > +#ifdef __MINGW32__ > +#include "d3dkmt.h" > +#include "CCD.h" > +#endif > + > +//Check for a reasonable SDK > +#if (_WIN32_WINNT < _WIN32_WINNT_WINXP) > +#error required Windows WDK not found > +#endif > + > +//Windows 10 build only > +#if (_WIN32_WINNT == _WIN32_WINNT_WIN10) > +#include <d3dumddi.h> > +#include <km/D3dkmthk.h> > +#endif > + > +#include <spice/qxl_windows.h> > +#include <spice/qxl_dev.h> > +#include "desktop_layout.h" > +#include "vdlog.h" > + > +typedef enum { > + XPDM, > + WDDM, > + INVALID_DRIVER, > +}DRIVER_TYPE; > + > +typedef enum { > + MONITOR_DETACHED, > + MONITOR_ATTACHED, > +}MONITOR_STATE; > + > +typedef enum { > + PATH_UPDATED, > + PATH_CURRENT, > +}PATH_STATE; > + > +#if (_WIN32_WINNT == _WIN32_WINNT_WIN10) > +//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: > + 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; > +}; > +#endif > + > +class DisplayMode; > + > +//Class provides interface to get/set display configurations > +class DisplayConfig { > +public: > + static DisplayConfig* create_config(); > + DisplayConfig();; > + 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; }; > + void set_monitors_config(bool flag) { _send_monitors_config = flag; } > + virtual void update_config_path() {}; > + > +protected: > + DRIVER_TYPE _driver_type; > + 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);; > + 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); > +}; > +#if (_WIN32_WINNT == _WIN32_WINNT_WIN10) > +//DisplayConfig implementation for guest with WDDM graphics drivers > +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 > +typedef class DisplayConfig DISPLAY_CONFIG; My understanding from this file is that there is a generic DisplayConfig interface, a WDDMInterface implementation for Win10, and a XPDMInterface implementation which will probably correspond to !Win10 agent? It seems the XPDMInterface implementation is absent. However, if you introduce DisplayConfig+XPDMInterface in the existing code (ie switch the existing code to DisplayConfig _without any functional change_), and then introduce the Win10 code, this will make this whole commit look less like a huge codedump (and will make it easier to review). Christophe
Attachment:
signature.asc
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel