Based on a patch by Sandy Stutsman <sstutsma@xxxxxxxxxx> Reviewed-by: Frediano Ziglio <fziglio@xxxxxxxxxx> Signed-off-by: Sameeh Jubran <sameeh@xxxxxxxxxx> --- 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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel