[Spice-devel] [PATCH qxl-wddm-dod v2 11/25] Add arbitrary resolution and monitors_config Escape
Sameeh Jubran
sameeh at daynix.com
Mon Sep 5 08:34:08 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 | 177 +++++++++++++++++++++++++++++--------------
qxldod/QxlDod.h | 9 +++
qxldod/include/qxl_windows.h | 9 +++
3 files changed, 138 insertions(+), 57 deletions(-)
diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp
index 5eac0a5..07b6fed 100755
--- a/qxldod/QxlDod.cpp
+++ b/qxldod/QxlDod.cpp
@@ -471,19 +471,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;
}
@@ -610,7 +597,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);
@@ -931,7 +918,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;
@@ -1287,7 +1274,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));
@@ -3147,22 +3134,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);
@@ -3355,6 +3347,7 @@ NTSTATUS QxlDevice::QxlInit(DXGK_DISPLAY_INFORMATION* pDispInfo)
m_RamHdr->int_mask = WIN_QXL_INT_MASK;
CreateMemSlots();
InitDeviceMemoryResources();
+ InitMonitorConfig();
return Status;
}
@@ -3419,8 +3412,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;
@@ -3570,12 +3565,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));
@@ -4177,12 +4184,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];
@@ -4437,45 +4445,100 @@ NTSTATUS QxlDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pS
return STATUS_SUCCESS;
}
-NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap)
+NTSTATUS QxlDevice::UpdateChildStatus(BOOLEAN connect)
+{
+ 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;
+}
+
+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;
+ }
+ 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 ERROR_NOT_ENOUGH_MEMORY;
+ }
+ UpdateVideoModeInfo(m_CustomMode, xres, yres, bpp);
+ 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__));
- QXLEscapeSetCustomDisplay *custom_display;
- UINT xres;
- UINT yres;
- UINT bpp;
-
- 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));
- return ERROR_INVALID_DATA;
- }
-
- if (m_CustomMode == (m_ModeCount - 1))
- m_CustomMode = (USHORT)(m_ModeCount - 2);
- else
- m_CustomMode = (USHORT)(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;
- }
- UpdateVideoModeInfo(m_CustomMode, xres, yres, bpp);
- DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
- return STATUS_SUCCESS;
+
+ 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 ab44259..acac36e 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
@@ -512,6 +513,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);
@@ -539,6 +541,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;
@@ -583,6 +589,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..c4eb2b5 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 {
@@ -11,4 +12,12 @@ typedef struct QXLEscapeSetCustomDisplay {
uint32_t bpp;
} QXLEscapeSetCustomDisplay;
+typedef struct QXLEscape {
+ uint32_t ioctl;
+ union {
+ QXLEscapeSetCustomDisplay custom_display;
+ QXLHead monitor_config;
+ };
+} QXLEscape;
+
#endif /* _H_QXL_WINDOWS */
--
2.7.0.windows.1
More information about the Spice-devel
mailing list