> > 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 | 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 { Acked-by: Frediano Ziglio <fziglio@xxxxxxxxxx> Frediano _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel