[Spice-devel] [PATCH v3 13/28] Add arbitrary resolution and monitors_config Escape

Sameeh Jubran sameeh at daynix.com
Wed Sep 7 13:10:31 UTC 2016


Based on a patch by Sandy Stutsman <sstutsma at redhat.com>

Reviewed-by: Frediano Ziglio <fziglio at redhat.com>

Signed-off-by: Sameeh Jubran <sameeh at daynix.com>
---
 qxldod/QxlDod.cpp            | 168 ++++++++++++++++++++++++++++++-------------
 qxldod/QxlDod.h              |   9 +++
 qxldod/include/qxl_windows.h |   1 +
 3 files changed, 128 insertions(+), 50 deletions(-)

diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp
index 2b8dee5..05c6eb9 100755
--- a/qxldod/QxlDod.cpp
+++ b/qxldod/QxlDod.cpp
@@ -49,7 +49,13 @@ BYTE PixelMask[BITS_PER_BYTE]  = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
 
 #pragma code_seg(pop)
 
-
+struct QXLEscape {
+    uint32_t ioctl;
+    union {
+        QXLEscapeSetCustomDisplay custom_display;
+        QXLHead monitor_config;
+    };
+};
 
 QxlDod::QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pPhysicalDeviceObject),
                                                             m_MonitorPowerState(PowerDeviceD0),
@@ -470,19 +476,6 @@ NTSTATUS QxlDod::Escape(_In_ CONST DXGKARG_ESCAPE* pEscape)
     DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s Flags = %d\n", __FUNCTION__, pEscape->Flags));
 
     Status = m_pHWDevice->Escape(pEscape);
-    if (Status == STATUS_SUCCESS)
-    {
-        DXGK_CHILD_STATUS ChildStatus;
-        ChildStatus.Type = StatusConnection;
-        ChildStatus.ChildUid = 0;
-        ChildStatus.HotPlug.Connected = FALSE;
-        Status = m_DxgkInterface.DxgkCbIndicateChildStatus(m_DxgkInterface.DeviceHandle, &ChildStatus);
-        if (Status == STATUS_SUCCESS)
-        {
-            ChildStatus.HotPlug.Connected = TRUE;
-            Status = m_DxgkInterface.DxgkCbIndicateChildStatus(m_DxgkInterface.DeviceHandle, &ChildStatus);
-        }
-    }
     DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s Status = %x\n", __FUNCTION__, Status));
     return Status;
 }
@@ -609,7 +602,7 @@ NTSTATUS QxlDod::QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY*
 NTSTATUS QxlDod::IsSupportedVidPn(_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn)
 {
     PAGED_CODE();
-    DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+    DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s %d\n", __FUNCTION__, m_pHWDevice->GetId()));
 
     QXL_ASSERT(pIsSupportedVidPn != NULL);
 
@@ -930,7 +923,7 @@ NTSTATUS QxlDod::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODAL
     PAGED_CODE();
 
     QXL_ASSERT(pEnumCofuncModality != NULL);
-    DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+    DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s device %d\n", __FUNCTION__, m_pHWDevice->GetId()));
 
     D3DKMDT_HVIDPNTOPOLOGY                   hVidPnTopology = 0;
     D3DKMDT_HVIDPNSOURCEMODESET              hVidPnSourceModeSet = 0;
@@ -1286,7 +1279,7 @@ NTSTATUS QxlDod::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODAL
 NTSTATUS QxlDod::SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility)
 {
     PAGED_CODE();
-    DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+    DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s %d\n", __FUNCTION__, m_pHWDevice->GetId()));
     QXL_ASSERT(pSetVidPnSourceVisibility != NULL);
     QXL_ASSERT((pSetVidPnSourceVisibility->VidPnSourceId < MAX_VIEWS) ||
                (pSetVidPnSourceVisibility->VidPnSourceId == D3DDDI_ID_ALL));
@@ -3144,22 +3137,27 @@ NTSTATUS QxlDevice::QueryCurrentMode(PVIDEO_MODE RequestedMode)
 
 NTSTATUS QxlDevice::SetCurrentMode(ULONG Mode)
 {
-    DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s Mode = %x\n", __FUNCTION__, Mode));
+    PAGED_CODE();
+    DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s - %d: Mode = %d\n", __FUNCTION__, m_Id, Mode));
     for (ULONG idx = 0; idx < GetModeCount(); idx++)
     {
         if (Mode == m_ModeNumbers[idx])
         {
             DestroyPrimarySurface();
             CreatePrimarySurface(&m_ModeInfo[idx]);
+            DbgPrint(TRACE_LEVEL_INFORMATION, ("%s device %d: setting current mode %d (%d x %d)\n",
+                __FUNCTION__, m_Id, Mode, m_ModeInfo[idx].VisScreenWidth,
+                m_ModeInfo[idx].VisScreenHeight));
             return STATUS_SUCCESS;
         }
     }
-    DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+    DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s failed\n", __FUNCTION__));
     return STATUS_UNSUCCESSFUL;
 }
 
 NTSTATUS QxlDevice::GetCurrentMode(ULONG* pMode)
 {
+    PAGED_CODE();
     NTSTATUS Status = STATUS_SUCCESS;
     DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__));
     UNREFERENCED_PARAMETER(pMode);
@@ -3352,6 +3350,7 @@ NTSTATUS QxlDevice::QxlInit(DXGK_DISPLAY_INFORMATION* pDispInfo)
     m_RamHdr->int_mask = WIN_QXL_INT_MASK;
     CreateMemSlots();
     InitDeviceMemoryResources();
+    InitMonitorConfig();
     return Status;
 }
 
@@ -3416,8 +3415,10 @@ void QxlDevice::DestroyMemSlots(void)
 
 void QxlDevice::CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo)
 {
+    PAGED_CODE();
     QXLSurfaceCreate *primary_surface_create;
-    DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+    DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s - %d: (%d x %d)\n", __FUNCTION__, m_Id,
+        pModeInfo->VisScreenWidth, pModeInfo->VisScreenHeight));
     primary_surface_create = &m_RamHdr->create_surface;
     primary_surface_create->format = pModeInfo->BitsPerPlane;
     primary_surface_create->width = pModeInfo->VisScreenWidth;
@@ -3567,12 +3568,24 @@ BOOL QxlDevice::CreateMemSlots(void)
 
 void QxlDevice::InitDeviceMemoryResources(void)
 {
+    PAGED_CODE();
     DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s num_pages = %d\n", __FUNCTION__, m_RomHdr->num_pages));
     InitMspace(MSPACE_TYPE_DEVRAM, (m_RamStart + m_RomHdr->surface0_area_size), (size_t)(m_RomHdr->num_pages * PAGE_SIZE));
     InitMspace(MSPACE_TYPE_VRAM, m_VRamStart, m_VRamSize);
     DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
 }
 
+void QxlDevice::InitMonitorConfig(void)
+{
+    PAGED_CODE();
+    size_t config_size = sizeof(QXLMonitorsConfig) + sizeof(QXLHead);
+    m_monitor_config = (QXLMonitorsConfig*) AllocMem(MSPACE_TYPE_DEVRAM, config_size, TRUE);
+    RtlZeroMemory(m_monitor_config, config_size);
+
+    m_monitor_config_pa = &m_RamHdr->monitors_config;
+    *m_monitor_config_pa = PA(m_monitor_config, m_MainMemSlot);
+}
+
 void QxlDevice::InitMspace(UINT32 mspace_type, UINT8 *start, size_t capacity)
 {
     DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s type = %d, start = %p, capacity = %d\n", __FUNCTION__, mspace_type, start, capacity));
@@ -4174,12 +4187,13 @@ VOID QxlDevice::BltBits (
     LONG width;
     LONG height;
 
-    DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+    DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s device %d\n", __FUNCTION__,m_Id));
     UNREFERENCED_PARAMETER(NumRects);
     UNREFERENCED_PARAMETER(pDst);
 
     if (!(drawable = Drawable(QXL_DRAW_COPY, pRects, NULL, 0))) {
         DbgPrint(TRACE_LEVEL_ERROR, ("Cannot get Drawable.\n"));
+        return;
     }
 
     CONST RECT* pRect = &pRects[0];
@@ -4434,45 +4448,99 @@ NTSTATUS QxlDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pS
     return STATUS_SUCCESS;
 }
 
-NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap)
+NTSTATUS QxlDevice::UpdateChildStatus(BOOLEAN connect)
 {
-    DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
-    QXLEscapeSetCustomDisplay *custom_display;
-    UINT xres;
-    UINT yres;
-    UINT bpp;
+    PAGED_CODE();
+    NTSTATUS           Status(STATUS_SUCCESS);
+    DXGK_CHILD_STATUS  ChildStatus;
+    PDXGKRNL_INTERFACE pDXGKInterface(m_pQxlDod->GetDxgkInterface());
+
+    ChildStatus.Type = StatusConnection;
+    ChildStatus.ChildUid = 0;
+    ChildStatus.HotPlug.Connected = connect;
+    Status = pDXGKInterface->DxgkCbIndicateChildStatus(pDXGKInterface->DeviceHandle, &ChildStatus);
+    return Status;
+}
 
-    if (pEscap->PrivateDriverDataSize != sizeof(QXLEscapeSetCustomDisplay)) {
-        DbgPrint(TRACE_LEVEL_ERROR, ("<--> %s Incorrect buffer size %d instead of %d\n", __FUNCTION__, pEscap->PrivateDriverDataSize, sizeof(QXLEscapeSetCustomDisplay)));
-        return STATUS_INVALID_BUFFER_SIZE;
-    }
-    custom_display = (QXLEscapeSetCustomDisplay*)pEscap->pPrivateDriverData;
-    xres = custom_display->xres & ~0x3;
-    yres = custom_display->yres & ~0x3;
-    bpp = custom_display->bpp;
-    if (bpp != QXL_BPP)
-    {
-        bpp = QXL_BPP;
-    }
-    if (xres < MIN_WIDTH_SIZE || yres < MIN_HEIGHT_SIZE)
-    {
-        DbgPrint(TRACE_LEVEL_ERROR, ("%s: xres = %d, yres = %d\n", __FUNCTION__, xres, yres));
+NTSTATUS QxlDevice::SetCustomDisplay(QXLEscapeSetCustomDisplay* custom_display)
+{
+    PAGED_CODE();
+    NTSTATUS status;
+    UINT xres = custom_display->xres;
+    UINT yres = custom_display->yres;
+    UINT bpp = QXL_BPP;
+    DbgPrint(TRACE_LEVEL_ERROR, ("%s - %d (%dx%d#%d)\n", __FUNCTION__, m_Id, xres, yres, bpp));
+    if (xres < MIN_WIDTH_SIZE || yres < MIN_HEIGHT_SIZE) {
+        DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: (%dx%d#%d) must be at least (%dxd)\n", __FUNCTION__,
+            xres, yres, bpp, MIN_WIDTH_SIZE, MIN_HEIGHT_SIZE));
         return ERROR_INVALID_DATA;
     }
-
-    if (m_CustomMode == (m_ModeCount - 1))
-        m_CustomMode = (USHORT)(m_ModeCount - 2);
-    else
-        m_CustomMode = (USHORT)(m_ModeCount - 1);
+    m_CustomMode =(USHORT) ((m_CustomMode == m_ModeCount-1)?  m_ModeCount - 2 : m_ModeCount - 1);
 
     if ((xres * yres * bpp / 8) > m_RomHdr->surface0_area_size) {
         DbgPrint(TRACE_LEVEL_ERROR, ("%s: Mode (%dx%d#%d) doesn't fit in memory (%d)\n",
                     __FUNCTION__, xres, yres, bpp, m_RomHdr->surface0_area_size));
-        return STATUS_INVALID_PARAMETER;
+        return ERROR_NOT_ENOUGH_MEMORY;
     }
     UpdateVideoModeInfo(m_CustomMode, xres, yres, bpp);
-    DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
-    return STATUS_SUCCESS;
+    status = UpdateChildStatus(TRUE);
+    return status;
+}
+
+void QxlDevice::SetMonitorConfig(QXLHead * monitor_config)
+{
+    PAGED_CODE();
+    m_monitor_config->count = 1;
+    m_monitor_config->max_allowed = 1;
+
+    memcpy(&m_monitor_config->heads[0], monitor_config, sizeof(QXLHead));
+    m_monitor_config->heads[0].id = 0;
+    m_monitor_config->heads[0].surface_id = 0;
+
+    DbgPrint(TRACE_LEVEL_VERBOSE, ("%s:%d configuring monitor at (%d, %d)  (%dx%d)\n", __FUNCTION__, m_Id,
+        m_monitor_config->heads[0].x, m_monitor_config->heads[0].y,
+        m_monitor_config->heads[0].width, m_monitor_config->heads[0].height));
+    AsyncIo(QXL_IO_MONITORS_CONFIG_ASYNC, 0);
+}
+
+NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscape)
+{
+    size_t          data_size(sizeof(uint32_t));
+    QXLEscape*     pQXLEscape((QXLEscape*) pEscape->pPrivateDriverData);
+    NTSTATUS        status(STATUS_SUCCESS);
+
+    DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+    switch (pQXLEscape->ioctl) {
+    case QXL_ESCAPE_SET_CUSTOM_DISPLAY: {
+        data_size += sizeof(QXLEscapeSetCustomDisplay);
+        if (pEscape->PrivateDriverDataSize != data_size) {
+            status = STATUS_INVALID_BUFFER_SIZE;
+            break;
+        }
+        status = SetCustomDisplay(&pQXLEscape->custom_display);
+        break;
+    }
+    case QXL_ESCAPE_MONITOR_CONFIG: {
+        data_size += sizeof(QXLHead);
+        if (pEscape->PrivateDriverDataSize != data_size) {
+            status = STATUS_INVALID_BUFFER_SIZE;
+            break;
+        }
+        SetMonitorConfig(&pQXLEscape->monitor_config);
+        status = STATUS_SUCCESS;
+        break;
+    }
+    default:
+        DbgPrint(TRACE_LEVEL_ERROR, ("%s: invalid Escape 0x%x\n", __FUNCTION__, pQXLEscape->ioctl));
+        status = STATUS_INVALID_PARAMETER;
+    }
+
+    if (status == STATUS_INVALID_BUFFER_SIZE) {
+        DbgPrint(TRACE_LEVEL_ERROR, ("%s invalid buffer size of %d, should be %d\n", __FUNCTION__,
+            pEscape->PrivateDriverDataSize, data_size));
+    }
+
+    return status;
 }
 
 VOID QxlDevice::WaitForCmdRing()
diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h
index 3cc9132..a1a4980 100755
--- a/qxldod/QxlDod.h
+++ b/qxldod/QxlDod.h
@@ -1,6 +1,7 @@
 #pragma once
 #include "baseobject.h"
 #include "qxl_dev.h"
+#include "qxl_windows.h"
 #include "mspace.h"
 
 #define MAX_CHILDREN               1
@@ -505,6 +506,7 @@ private:
     UINT64 VA(QXLPHYSICAL paddr, UINT8 slot_id);
     QXLPHYSICAL PA(PVOID virt, UINT8 slot_id);
     void InitDeviceMemoryResources(void);
+    void InitMonitorConfig();
     void InitMspace(UINT32 mspace_type, UINT8 *start, size_t capacity);
     void FlushReleaseRing();
     void FreeMem(UINT32 mspace_type, void *ptr);
@@ -532,6 +534,10 @@ private:
     void DpcCallback(PDPC_CB_CONTEXT);
     void AsyncIo(UCHAR  Port, UCHAR Value);
     void SyncIo(UCHAR  Port, UCHAR Value);
+    NTSTATUS UpdateChildStatus(BOOLEAN connect);
+    NTSTATUS SetCustomDisplay(QXLEscapeSetCustomDisplay* custom_display);
+    void SetMonitorConfig(QXLHead* monitor_config);
+
 private:
     PUCHAR m_IoBase;
     BOOLEAN m_IoMapped;
@@ -576,6 +582,9 @@ private:
 
     UINT64 m_FreeOutputs;
     UINT32 m_Pending;
+
+    QXLMonitorsConfig* m_monitor_config;
+    QXLPHYSICAL* m_monitor_config_pa;
 };
 
 class QxlDod {
diff --git a/qxldod/include/qxl_windows.h b/qxldod/include/qxl_windows.h
index 237ffd8..5af21a9 100755
--- a/qxldod/include/qxl_windows.h
+++ b/qxldod/include/qxl_windows.h
@@ -3,6 +3,7 @@
 
 enum {
     QXL_ESCAPE_SET_CUSTOM_DISPLAY = 0x10001,
+    QXL_ESCAPE_MONITOR_CONFIG
 };
 
 typedef struct QXLEscapeSetCustomDisplay {
-- 
2.7.0.windows.1



More information about the Spice-devel mailing list