[Spice-devel] [RFC PATCH vdagent 02/16] Provide support for Windows 10 CCD API

Christophe Fergeau cfergeau at redhat.com
Wed Jul 20 15:53:51 UTC 2016


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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/spice-devel/attachments/20160720/8f240c35/attachment.sig>


More information about the Spice-devel mailing list