From d9c6d518c6110e6aa0c65011d0e223f05d4bffea Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 9 Dec 2013 05:34:03 -0500 Subject: [PATCH 01/46] New qxl wddm repository. Initial commit --- README | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 README diff --git a/README b/README new file mode 100644 index 0000000..e69de29 From a3f72ee429bac7ff0c402d52cb39a0f9b80a61fc Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 9 Dec 2013 21:55:42 +1100 Subject: [PATCH 02/46] Basic VGA support --- qxldod Package/qxldod Package.vcxproj | 155 +++ qxldod Package/qxldod Package.vcxproj.filters | 9 + qxldod.sln | 47 + qxldod/BaseObject.cpp | 80 ++ qxldod/BaseObject.h | 70 ++ qxldod/QxlDod.cpp | 1074 +++++++++++++++++ qxldod/QxlDod.h | 236 ++++ qxldod/driver.cpp | 676 +++++++++++ qxldod/driver.h | 255 ++++ qxldod/qxldod.inf | Bin 0 -> 4142 bytes qxldod/qxldod.rc | Bin 0 -> 696 bytes qxldod/qxldod.vcxproj | 288 +++++ qxldod/qxldod.vcxproj.filters | 56 + qxldod/resource.h | 14 + 14 files changed, 2960 insertions(+) create mode 100755 qxldod Package/qxldod Package.vcxproj create mode 100755 qxldod Package/qxldod Package.vcxproj.filters create mode 100755 qxldod.sln create mode 100755 qxldod/BaseObject.cpp create mode 100755 qxldod/BaseObject.h create mode 100755 qxldod/QxlDod.cpp create mode 100755 qxldod/QxlDod.h create mode 100755 qxldod/driver.cpp create mode 100755 qxldod/driver.h create mode 100755 qxldod/qxldod.inf create mode 100755 qxldod/qxldod.rc create mode 100755 qxldod/qxldod.vcxproj create mode 100755 qxldod/qxldod.vcxproj.filters create mode 100755 qxldod/resource.h diff --git a/qxldod Package/qxldod Package.vcxproj b/qxldod Package/qxldod Package.vcxproj new file mode 100755 index 0000000..d783186 --- /dev/null +++ b/qxldod Package/qxldod Package.vcxproj @@ -0,0 +1,155 @@ + + + + + Win8 Debug + Win32 + + + Win8 Release + Win32 + + + Win7 Debug + Win32 + + + Win7 Release + Win32 + + + Vista Debug + Win32 + + + Vista Release + Win32 + + + Win8 Debug + x64 + + + Win8 Release + x64 + + + Win7 Debug + x64 + + + Win7 Release + x64 + + + Vista Debug + x64 + + + Vista Release + x64 + + + + {B8C04B51-4207-491D-A7DD-C54861E8B528} + {4605da2c-74a5-4865-98e1-152ef136825f} + v4.5 + 11.0 + Win8 Debug + Win32 + + + qxldod_Package + $(VCTargetsPath11) + + + WindowsKernelModeDriver8.0 + Utility + Package + true + + + + Windows8 + true + + + Windows8 + false + + + Windows7 + true + + + Windows7 + false + + + Vista + true + + + Vista + false + + + Windows8 + true + + + Windows8 + false + + + Windows7 + true + + + Windows7 + false + + + Vista + true + + + Vista + false + + + + + + + + + + + DbgengKernelDebugger + False + True + + + + False + False + True + + 133563 + $(OutDir)qxldod Package + + + + + + + + + {a6f48fc7-97e9-48ec-bcdf-1e4f9b43aadd} + + + + + + \ No newline at end of file diff --git a/qxldod Package/qxldod Package.vcxproj.filters b/qxldod Package/qxldod Package.vcxproj.filters new file mode 100755 index 0000000..73af436 --- /dev/null +++ b/qxldod Package/qxldod Package.vcxproj.filters @@ -0,0 +1,9 @@ + + + + + {8E41214B-6785-4CFE-B992-037D68949A14} + inf;inv;inx;mof;mc; + + + \ No newline at end of file diff --git a/qxldod.sln b/qxldod.sln new file mode 100755 index 0000000..2b74fb7 --- /dev/null +++ b/qxldod.sln @@ -0,0 +1,47 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qxldod", "qxldod\qxldod.vcxproj", "{A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qxldod Package", "qxldod Package\qxldod Package.vcxproj", "{B8C04B51-4207-491D-A7DD-C54861E8B528}" + ProjectSection(ProjectDependencies) = postProject + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD} = {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Win8 Debug|Win32 = Win8 Debug|Win32 + Win8 Debug|x64 = Win8 Debug|x64 + Win8 Release|Win32 = Win8 Release|Win32 + Win8 Release|x64 = Win8 Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|x64.Build.0 = Win8 Debug|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|Win32.Build.0 = Win8 Release|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|x64.Build.0 = Win8 Release|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|x64.Deploy.0 = Win8 Release|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|x64.Build.0 = Win8 Debug|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|Win32.Build.0 = Win8 Release|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|x64.Build.0 = Win8 Release|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|x64.Deploy.0 = Win8 Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/qxldod/BaseObject.cpp b/qxldod/BaseObject.cpp new file mode 100755 index 0000000..0405541 --- /dev/null +++ b/qxldod/BaseObject.cpp @@ -0,0 +1,80 @@ +#include "BaseObject.h" + +#pragma code_seg("PAGE") + +#define QXLTAG 'LXQd' + +// +// New and delete operators +// +_When_((PoolType & NonPagedPoolMustSucceed) != 0, + __drv_reportError("Must succeed pool allocations are forbidden. " + "Allocation failures cause a system crash")) +void* __cdecl operator new(size_t Size, POOL_TYPE PoolType) +{ + PAGED_CODE(); + + Size = (Size != 0) ? Size : 1; + + void* pObject = ExAllocatePoolWithTag(PoolType, Size, QXLTAG); + +#if DBG + if (pObject != NULL) + { + RtlFillMemory(pObject, Size, 0xCD); + } +#endif // DBG + + return pObject; +} + +_When_((PoolType & NonPagedPoolMustSucceed) != 0, + __drv_reportError("Must succeed pool allocations are forbidden. " + "Allocation failures cause a system crash")) +void* __cdecl operator new[](size_t Size, POOL_TYPE PoolType) +{ + PAGED_CODE(); + + Size = (Size != 0) ? Size : 1; + + void* pObject = ExAllocatePoolWithTag(PoolType, Size, QXLTAG); + +#if DBG + if (pObject != NULL) + { + RtlFillMemory(pObject, Size, 0xCD); + } +#endif // DBG + + return pObject; +} + +void __cdecl operator delete(void* pObject) +{ + PAGED_CODE(); + + if (pObject != NULL) + { + ExFreePool(pObject); + } +} + +void __cdecl operator delete[](void* pObject) +{ + PAGED_CODE(); + + if (pObject != NULL) + { + ExFreePool(pObject); + } +} + + +BaseObject::BaseObject(void) +{ +} + + +BaseObject::~BaseObject(void) +{ +} diff --git a/qxldod/BaseObject.h b/qxldod/BaseObject.h new file mode 100755 index 0000000..fc4ca59 --- /dev/null +++ b/qxldod/BaseObject.h @@ -0,0 +1,70 @@ +#pragma once +extern "C" +{ + #define __CPLUSPLUS + + // Standard C-runtime headers + #include + #include + #include + #include + #include + + #include + + // NTOS headers + #include + + #ifndef FAR + #define FAR + #endif + + // Windows headers + #include + #include + + // Windows GDI headers + #include + + // Windows DDI headers + #include + #include + + #include + #include + + #include + #include + + #include +}; + +// +// Memory handling +// + +// Defaulting the value of PoolType means that any call to new Foo() +// will raise a compiler error for being ambiguous. This is to help keep +// any calls to allocate memory from accidentally NOT going through +// these functions. +_When_((PoolType & NonPagedPoolMustSucceed) != 0, + __drv_reportError("Must succeed pool allocations are forbidden. " + "Allocation failures cause a system crash")) +void* __cdecl operator new(size_t Size, POOL_TYPE PoolType = PagedPool); +_When_((PoolType & NonPagedPoolMustSucceed) != 0, + __drv_reportError("Must succeed pool allocations are forbidden. " + "Allocation failures cause a system crash")) +void* __cdecl operator new[](size_t Size, POOL_TYPE PoolType = PagedPool); +void __cdecl operator delete(void* pObject); +void __cdecl operator delete[](void* pObject); + +// Pool allocation tag for the Sample Display Driver. All allocations use this tag. + + +class BaseObject +{ +public: + BaseObject(void); + ~BaseObject(void); +}; + diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp new file mode 100755 index 0000000..9717c7d --- /dev/null +++ b/qxldod/QxlDod.cpp @@ -0,0 +1,1074 @@ +#include "driver.h" +#include "qxldod.h" + +QxlDod::QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pPhysicalDeviceObject), + m_MonitorPowerState(PowerDeviceD0), + m_AdapterPowerState(PowerDeviceD0) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + *((UINT*)&m_Flags) = 0; + RtlZeroMemory(&m_DxgkInterface, sizeof(m_DxgkInterface)); + RtlZeroMemory(&m_DeviceInfo, sizeof(m_DeviceInfo)); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); +} + + +QxlDod::~QxlDod(void) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + +// CleanUp(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); +} + + +NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, + _In_ DXGKRNL_INTERFACE* pDxgkInterface, + _Out_ ULONG* pNumberOfViews, + _Out_ ULONG* pNumberOfChildren) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + QXL_ASSERT(pDxgkStartInfo != NULL); + QXL_ASSERT(pDxgkInterface != NULL); + QXL_ASSERT(pNumberOfViews != NULL); + QXL_ASSERT(pNumberOfChildren != NULL); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + + DXGK_DISPLAY_INFORMATION DisplayInfo; + RtlCopyMemory(&m_DxgkInterface, pDxgkInterface, sizeof(m_DxgkInterface)); + // Get device information from OS. + NTSTATUS Status = m_DxgkInterface.DxgkCbGetDeviceInformation(m_DxgkInterface.DeviceHandle, &m_DeviceInfo); + if (!NT_SUCCESS(Status)) + { + QXL_LOG_ASSERTION1("DxgkCbGetDeviceInformation failed with status 0x%X\n", + Status); + return Status; + } + + Status = RegisterHWInfo(); + if (!NT_SUCCESS(Status)) + { + QXL_LOG_ASSERTION1("RegisterHWInfo failed with status 0x%X\n", + Status); + return Status; + } + +// TODO: Uncomment the line below after updating the TODOs in the function CheckHardware +// Status = CheckHardware(); +// if (!NT_SUCCESS(Status)) +// { +// return Status; +// } + + + Status = VbeGetModeList(); + if (!NT_SUCCESS(Status)) + { + QXL_LOG_ASSERTION1("RegisterHWInfo failed with status 0x%X\n", + Status); + return Status; + } + + + // This sample driver only uses the frame buffer of the POST device. DxgkCbAcquirePostDisplayOwnership + // gives you the frame buffer address and ensures that no one else is drawing to it. Be sure to give it back! + Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &DisplayInfo); + if (!NT_SUCCESS(Status) || DisplayInfo.Width == 0) + { + // The most likely cause of failure is that the driver is simply not running on a POST device, or we are running + // after a pre-WDDM 1.2 driver. Since we can't draw anything, we should fail to start. + return STATUS_UNSUCCESSFUL; + } + *pNumberOfViews = MAX_VIEWS; + *pNumberOfChildren = MAX_CHILDREN; + m_Flags.DriverStarted = TRUE; + return STATUS_SUCCESS; +} + +NTSTATUS QxlDod::StopDevice(VOID) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + m_Flags.DriverStarted = FALSE; + return STATUS_SUCCESS; +} + +VOID QxlDod::CleanUp(VOID) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); +} + + +NTSTATUS QxlDod::DispatchIoRequest(_In_ ULONG VidPnSourceId, + _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket) +{ + PAGED_CODE(); + UNREFERENCED_PARAMETER(VidPnSourceId); + UNREFERENCED_PARAMETER(pVideoRequestPacket); + + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + +NTSTATUS QxlDod::SetPowerState(_In_ ULONG HardwareUid, + _In_ DEVICE_POWER_STATE DevicePowerState, + _In_ POWER_ACTION ActionType) +{ + NTSTATUS Status = STATUS_SUCCESS; + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + + if (HardwareUid == DISPLAY_ADAPTER_HW_ID) + { + + if (DevicePowerState == PowerDeviceD0) + { + + // When returning from D3 the device visibility defined to be off for all targets + if (m_AdapterPowerState == PowerDeviceD3) + { + DXGKARG_SETVIDPNSOURCEVISIBILITY Visibility; + Visibility.VidPnSourceId = D3DDDI_ID_ALL; + Visibility.Visible = FALSE; + SetVidPnSourceVisibility(&Visibility); + } + } + + + // Store new adapter power state + m_AdapterPowerState = DevicePowerState; + } + + if ((ActionType == PowerActionHibernate) && + (DevicePowerState > PowerDeviceD0)) + { + ActionType = PowerActionHibernate; + } + else if ((ActionType >= PowerActionShutdown) && + (ActionType < PowerActionWarmEject) && + (DevicePowerState > PowerDeviceD0)) + { + ActionType = PowerActionShutdown; + } + + Status = VbeSetPowerState(ActionType); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); + + return Status; +} + + +NTSTATUS QxlDod::QueryChildRelations(_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations, + _In_ ULONG ChildRelationsSize) +{ + PAGED_CODE(); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + QXL_ASSERT(pChildRelations != NULL); + + // The last DXGK_CHILD_DESCRIPTOR in the array of pChildRelations must remain zeroed out, so we subtract this from the count + ULONG ChildRelationsCount = (ChildRelationsSize / sizeof(DXGK_CHILD_DESCRIPTOR)) - 1; + QXL_ASSERT(ChildRelationsCount <= MAX_CHILDREN); + + for (UINT ChildIndex = 0; ChildIndex < ChildRelationsCount; ++ChildIndex) + { + pChildRelations[ChildIndex].ChildDeviceType = TypeVideoOutput; + pChildRelations[ChildIndex].ChildCapabilities.HpdAwareness = HpdAwarenessAlwaysConnected; + pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = D3DKMDT_VOT_INTERNAL; + pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_NONE; + pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.SupportsSdtvModes = FALSE; + // TODO: Replace 0 with the actual ACPI ID of the child device, if available + pChildRelations[ChildIndex].AcpiUid = 0; + pChildRelations[ChildIndex].ChildUid = ChildIndex; + } + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + +NTSTATUS QxlDod::QueryChildStatus(_Inout_ DXGK_CHILD_STATUS* pChildStatus, + _In_ BOOLEAN NonDestructiveOnly) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + UNREFERENCED_PARAMETER(NonDestructiveOnly); + QXL_ASSERT(pChildStatus != NULL); + QXL_ASSERT(pChildStatus->ChildUid < MAX_CHILDREN); + + switch (pChildStatus->Type) + { + case StatusConnection: + { + // HpdAwarenessInterruptible was reported since HpdAwarenessNone is deprecated. + // However, BDD has no knowledge of HotPlug events, so just always return connected. + pChildStatus->HotPlug.Connected = IsDriverActive(); + return STATUS_SUCCESS; + } + + case StatusRotation: + { + // D3DKMDT_MOA_NONE was reported, so this should never be called + DbgPrint(TRACE_LEVEL_ERROR, ("Child status being queried for StatusRotation even though D3DKMDT_MOA_NONE was reported")); + return STATUS_INVALID_PARAMETER; + } + + default: + { + DbgPrint(TRACE_LEVEL_WARNING, ("Unknown pChildStatus->Type (0x%I64x) requested.", pChildStatus->Type)); + return STATUS_NOT_SUPPORTED; + } + } +} + +// EDID retrieval +NTSTATUS QxlDod::QueryDeviceDescriptor(_In_ ULONG ChildUid, + _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + QXL_ASSERT(pDeviceDescriptor != NULL); + QXL_ASSERT(ChildUid < MAX_CHILDREN); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA; +} + +NTSTATUS QxlDod::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo) +{ + PAGED_CODE(); + + QXL_ASSERT(pQueryAdapterInfo != NULL); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + switch (pQueryAdapterInfo->Type) + { + case DXGKQAITYPE_DRIVERCAPS: + { + if (pQueryAdapterInfo->OutputDataSize < sizeof(DXGK_DRIVERCAPS)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pQueryAdapterInfo->OutputDataSize (0x%I64x) is smaller than sizeof(DXGK_DRIVERCAPS) (0x%I64x)", pQueryAdapterInfo->OutputDataSize, sizeof(DXGK_DRIVERCAPS))); + return STATUS_BUFFER_TOO_SMALL; + } + + DXGK_DRIVERCAPS* pDriverCaps = (DXGK_DRIVERCAPS*)pQueryAdapterInfo->pOutputData; + + RtlZeroMemory(pDriverCaps, sizeof(DXGK_DRIVERCAPS)); + + pDriverCaps->WDDMVersion = DXGKDDI_WDDMv1_2; + pDriverCaps->HighestAcceptableAddress.QuadPart = -1; + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s 1\n", __FUNCTION__)); + return STATUS_SUCCESS; + } + + default: + { + // BDD does not need to support any other adapter information types + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_NOT_SUPPORTED; + } + } +} + +NTSTATUS QxlDod::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + QXL_ASSERT(pSetPointerPosition != NULL); + QXL_ASSERT(pSetPointerPosition->VidPnSourceId < MAX_VIEWS); + + if (!(pSetPointerPosition->Flags.Visible)) + { + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s Cursor is not visible\n", __FUNCTION__)); + return STATUS_SUCCESS; + } + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s cursor position X = %d, Y = %d\n", __FUNCTION__, pSetPointerPosition->X, pSetPointerPosition->Y)); + return STATUS_UNSUCCESSFUL; +} + +// Basic Sample Display Driver does not support hardware cursors, and reports such +// in QueryAdapterInfo. Therefore this function should never be called. +NTSTATUS QxlDod::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) +{ + PAGED_CODE(); + QXL_ASSERT(pSetPointerShape != NULL); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s Height = %d, Width = %d, XHot= %d, YHot = %d\n", __FUNCTION__, pSetPointerShape->Height, pSetPointerShape->Width, pSetPointerShape->XHot, pSetPointerShape->YHot)); + + if (pSetPointerShape->Flags.Color) + { + } + else if (pSetPointerShape->Flags.Monochrome) + { + } + else + { + return STATUS_UNSUCCESSFUL; + } + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS QxlDod::Escape(_In_ CONST DXGKARG_ESCAPE* pEscape) +{ + PAGED_CODE(); + QXL_ASSERT(pEscape != NULL); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s Flags = %d\n", __FUNCTION__, pEscape->Flags)); + + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS QxlDod::PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly) +{ + PAGED_CODE(); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + QXL_ASSERT(pPresentDisplayOnly != NULL); + QXL_ASSERT(pPresentDisplayOnly->VidPnSourceId < MAX_VIEWS); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + +NTSTATUS QxlDod::QueryInterface(_In_ CONST PQUERY_INTERFACE pQueryInterface) +{ + PAGED_CODE(); + QXL_ASSERT(pQueryInterface != NULL); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s Version = %d\n", __FUNCTION__, pQueryInterface->Version)); + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS QxlDod::StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, + _Out_ DXGK_DISPLAY_INFORMATION* pDisplayInfo) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(pDisplayInfo); + QXL_ASSERT(TargetId < MAX_CHILDREN); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + return StopDevice(); +} + +NTSTATUS QxlDod::QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + QXL_ASSERT(pVidPnHWCaps != NULL); + QXL_ASSERT(pVidPnHWCaps->SourceId < MAX_VIEWS); + QXL_ASSERT(pVidPnHWCaps->TargetId < MAX_CHILDREN); + + pVidPnHWCaps->VidPnHWCaps.DriverRotation = 1; // BDD does rotation in software + pVidPnHWCaps->VidPnHWCaps.DriverScaling = 0; // BDD does not support scaling + pVidPnHWCaps->VidPnHWCaps.DriverCloning = 0; // BDD does not support clone + pVidPnHWCaps->VidPnHWCaps.DriverColorConvert = 1; // BDD does color conversions in software + pVidPnHWCaps->VidPnHWCaps.DriverLinkedAdapaterOutput = 0; // BDD does not support linked adapters + pVidPnHWCaps->VidPnHWCaps.DriverRemoteDisplay = 0; // BDD does not support remote displays + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + + +// TODO: Need to also check pinned modes and the path parameters, not just topology +NTSTATUS QxlDod::IsSupportedVidPn(_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + QXL_ASSERT(pIsSupportedVidPn != NULL); + + if (pIsSupportedVidPn->hDesiredVidPn == 0) + { + // A null desired VidPn is supported + pIsSupportedVidPn->IsVidPnSupported = TRUE; + return STATUS_SUCCESS; + } + + // Default to not supported, until shown it is supported + pIsSupportedVidPn->IsVidPnSupported = FALSE; + + CONST DXGK_VIDPN_INTERFACE* pVidPnInterface; + NTSTATUS Status = m_DxgkInterface.DxgkCbQueryVidPnInterface(pIsSupportedVidPn->hDesiredVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbQueryVidPnInterface failed with Status = 0x%X, hDesiredVidPn = 0x%I64x\n", Status, pIsSupportedVidPn->hDesiredVidPn)); + return Status; + } + + D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology; + CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface; + Status = pVidPnInterface->pfnGetTopology(pIsSupportedVidPn->hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnGetTopology failed with Status = 0x%X, hDesiredVidPn = 0x%I64x\n", Status, pIsSupportedVidPn->hDesiredVidPn)); + return Status; + } + + // For every source in this topology, make sure they don't have more paths than there are targets + for (D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId = 0; SourceId < MAX_VIEWS; ++SourceId) + { + SIZE_T NumPathsFromSource = 0; + Status = pVidPnTopologyInterface->pfnGetNumPathsFromSource(hVidPnTopology, SourceId, &NumPathsFromSource); + if (Status == STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY) + { + continue; + } + else if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnGetNumPathsFromSource failed with Status = 0x%X hVidPnTopology = 0x%I64x, SourceId = 0x%I64x", + Status, hVidPnTopology, SourceId)); + return Status; + } + else if (NumPathsFromSource > MAX_CHILDREN) + { + // This VidPn is not supported, which has already been set as the default + return STATUS_SUCCESS; + } + } + + // All sources succeeded so this VidPn is supported + pIsSupportedVidPn->IsVidPnSupported = TRUE; + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + +NTSTATUS QxlDod::RecommendFunctionalVidPn(_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); + + QXL_ASSERT(pRecommendFunctionalVidPn == NULL); + + return STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN; +} + +NTSTATUS QxlDod::RecommendVidPnTopology(_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); + + QXL_ASSERT(pRecommendVidPnTopology == NULL); + + return STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN; +} + +NTSTATUS QxlDod::RecommendMonitorModes(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_SUCCESS; + D3DKMDT_MONITOR_SOURCE_MODE* pMonitorSourceMode = NULL; + PVBE_MODEINFO pVbeModeInfo = NULL; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + Status = pRecommendMonitorModes->pMonitorSourceModeSetInterface->pfnCreateNewModeInfo(pRecommendMonitorModes->hMonitorSourceModeSet, &pMonitorSourceMode); + if (!NT_SUCCESS(Status)) + { + // If failed to create a new mode info, mode doesn't need to be released since it was never created + DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewModeInfo failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x", Status, pRecommendMonitorModes->hMonitorSourceModeSet)); + return Status; + } + + pVbeModeInfo = &m_ModeInfo[m_CurrentMode]; + pMonitorSourceMode->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER; + pMonitorSourceMode->VideoSignalInfo.TotalSize.cx = pVbeModeInfo->XResolution;//m_CurrentModes[CorrespondingSourceId].DispInfo.Width; + pMonitorSourceMode->VideoSignalInfo.TotalSize.cy = pVbeModeInfo->YResolution;//m_CurrentModes[CorrespondingSourceId].DispInfo.Height; + pMonitorSourceMode->VideoSignalInfo.ActiveSize = pMonitorSourceMode->VideoSignalInfo.TotalSize; + pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pMonitorSourceMode->VideoSignalInfo.HSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pMonitorSourceMode->VideoSignalInfo.HSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pMonitorSourceMode->VideoSignalInfo.PixelRate = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pMonitorSourceMode->VideoSignalInfo.ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE; + + // We set the preference to PREFERRED since this is the only supported mode + pMonitorSourceMode->Origin = D3DKMDT_MCO_DRIVER; + pMonitorSourceMode->Preference = D3DKMDT_MP_PREFERRED; + pMonitorSourceMode->ColorBasis = D3DKMDT_CB_SRGB; + pMonitorSourceMode->ColorCoeffDynamicRanges.FirstChannel = 8; + pMonitorSourceMode->ColorCoeffDynamicRanges.SecondChannel = 8; + pMonitorSourceMode->ColorCoeffDynamicRanges.ThirdChannel = 8; + pMonitorSourceMode->ColorCoeffDynamicRanges.FourthChannel = 8; + + Status = pRecommendMonitorModes->pMonitorSourceModeSetInterface->pfnAddMode(pRecommendMonitorModes->hMonitorSourceModeSet, pMonitorSourceMode); + if (!NT_SUCCESS(Status)) + { + if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x, pMonitorSourceMode = 0x%I64x", + Status, pRecommendMonitorModes->hMonitorSourceModeSet, pMonitorSourceMode)); + } + else + { + Status = STATUS_SUCCESS; + } + + // If adding the mode failed, release the mode, if this doesn't work there is nothing that can be done, some memory will get leaked + NTSTATUS TempStatus = pRecommendMonitorModes->pMonitorSourceModeSetInterface->pfnReleaseModeInfo(pRecommendMonitorModes->hMonitorSourceModeSet, pMonitorSourceMode); + UNREFERENCED_PARAMETER(TempStatus); + NT_ASSERT(NT_SUCCESS(TempStatus)); + return Status; + } + // If AddMode succeeded with something other than STATUS_SUCCESS treat it as such anyway when propagating up + return STATUS_SUCCESS; +} + +// Tell DMM about all the modes, etc. that are supported +NTSTATUS QxlDod::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality) +{ + PAGED_CODE(); + + QXL_ASSERT(pEnumCofuncModality != NULL); + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + + D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology = 0; + D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet = 0; + D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet = 0; + CONST DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL; + CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface = NULL; + CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface = NULL; + CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface = NULL; + CONST D3DKMDT_VIDPN_PRESENT_PATH* pVidPnPresentPath = NULL; + CONST D3DKMDT_VIDPN_PRESENT_PATH* pVidPnPresentPathTemp = NULL; // Used for AcquireNextPathInfo + CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnPinnedSourceModeInfo = NULL; + CONST D3DKMDT_VIDPN_TARGET_MODE* pVidPnPinnedTargetModeInfo = NULL; + + // Get the VidPn Interface so we can get the 'Source Mode Set', 'Target Mode Set' and 'VidPn Topology' interfaces + NTSTATUS Status = m_DxgkInterface.DxgkCbQueryVidPnInterface(pEnumCofuncModality->hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbQueryVidPnInterface failed with Status = 0x%X, hFunctionalVidPn = 0x%I64x", Status, pEnumCofuncModality->hConstrainingVidPn)); + return Status; + } + + // Get the VidPn Topology interface so we can enumerate all paths + Status = pVidPnInterface->pfnGetTopology(pEnumCofuncModality->hConstrainingVidPn, &hVidPnTopology, &pVidPnTopologyInterface); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnGetTopology failed with Status = 0x%X, hFunctionalVidPn = 0x%I64x", Status, pEnumCofuncModality->hConstrainingVidPn)); + return Status; + } + + // Get the first path before we start looping through them + Status = pVidPnTopologyInterface->pfnAcquireFirstPathInfo(hVidPnTopology, &pVidPnPresentPath); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAcquireFirstPathInfo failed with Status =0x%X, hVidPnTopology = 0x%I64x", Status, hVidPnTopology)); + return Status; + } + + // Loop through all available paths. + while (Status != STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET) + { + +//FIXME + + pVidPnPresentPathTemp = NULL; // Successfully released it + }// End: while loop for paths in topology + + // If quit the while loop normally, set the return value to success + if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET) + { + Status = STATUS_SUCCESS; + } + + // Release any resources hanging around because the loop was quit early. + // Since in normal execution everything should be released by this point, TempStatus is initialized to a bogus error to be used as an + // assertion that if anything had to be released now (TempStatus changing) Status isn't successful. + NTSTATUS TempStatus = STATUS_NOT_FOUND; + + if ((pVidPnSourceModeSetInterface != NULL) && + (pVidPnPinnedSourceModeInfo != NULL)) + { + TempStatus = pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hVidPnSourceModeSet, pVidPnPinnedSourceModeInfo); + QXL_ASSERT_CHK(NT_SUCCESS(TempStatus)); + } + + if ((pVidPnTargetModeSetInterface != NULL) && + (pVidPnPinnedTargetModeInfo != NULL)) + { + TempStatus = pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pVidPnPinnedTargetModeInfo); + QXL_ASSERT_CHK(NT_SUCCESS(TempStatus)); + } + + if (pVidPnPresentPath != NULL) + { + TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPath); + QXL_ASSERT_CHK(NT_SUCCESS(TempStatus)); + } + + if (pVidPnPresentPathTemp != NULL) + { + TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPathTemp); + QXL_ASSERT_CHK(NT_SUCCESS(TempStatus)); + } + + if (hVidPnSourceModeSet != 0) + { + TempStatus = pVidPnInterface->pfnReleaseSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnSourceModeSet); + QXL_ASSERT_CHK(NT_SUCCESS(TempStatus)); + } + + if (hVidPnTargetModeSet != 0) + { + TempStatus = pVidPnInterface->pfnReleaseTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnTargetModeSet); + QXL_ASSERT_CHK(NT_SUCCESS(TempStatus)); + } + + QXL_ASSERT_CHK(TempStatus == STATUS_NOT_FOUND || Status != STATUS_SUCCESS); + + DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + return Status; +} + +NTSTATUS QxlDod::SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + QXL_ASSERT(pSetVidPnSourceVisibility != NULL); + QXL_ASSERT((pSetVidPnSourceVisibility->VidPnSourceId < MAX_VIEWS) || + (pSetVidPnSourceVisibility->VidPnSourceId == D3DDDI_ID_ALL)); + + UINT StartVidPnSourceId = (pSetVidPnSourceVisibility->VidPnSourceId == D3DDDI_ID_ALL) ? 0 : pSetVidPnSourceVisibility->VidPnSourceId; + UINT MaxVidPnSourceId = (pSetVidPnSourceVisibility->VidPnSourceId == D3DDDI_ID_ALL) ? MAX_VIEWS : pSetVidPnSourceVisibility->VidPnSourceId + 1; + + for (UINT SourceId = StartVidPnSourceId; SourceId < MaxVidPnSourceId; ++SourceId) + { + if (pSetVidPnSourceVisibility->Visible) + { +// m_CurrentModes[SourceId].Flags.FullscreenPresent = TRUE; + } + else + { +// BlackOutScreen(SourceId); + } + + // Store current visibility so it can be dealt with during Present call +// m_CurrentModes[SourceId].Flags.SourceNotVisible = !(pSetVidPnSourceVisibility->Visible); + } + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + +// NOTE: The value of pCommitVidPn->MonitorConnectivityChecks is ignored, since BDD is unable to recognize whether a monitor is connected or not +// The value of pCommitVidPn->hPrimaryAllocation is also ignored, since BDD is a display only driver and does not deal with allocations +NTSTATUS QxlDod::CommitVidPn(_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + QXL_ASSERT(pCommitVidPn != NULL); + QXL_ASSERT(pCommitVidPn->AffectedVidPnSourceId < MAX_VIEWS); + + NTSTATUS Status = STATUS_SUCCESS; + + +//FIXME + + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return Status; +} + +NTSTATUS QxlDod::UpdateActiveVidPnPresentPath(_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + QXL_ASSERT(pUpdateActiveVidPnPresentPath != NULL); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + + + +// +// Non-Paged Code +// +#pragma code_seg(push) +#pragma code_seg() + +VOID QxlDod::DpcRoutine(VOID) +{ + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + m_DxgkInterface.DxgkCbNotifyDpc((HANDLE)m_DxgkInterface.DeviceHandle); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); +} + +BOOLEAN QxlDod::InterruptRoutine(_In_ ULONG MessageNumber) +{ + UNREFERENCED_PARAMETER(MessageNumber); + + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> 0 %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); + return TRUE; +} + +VOID QxlDod::ResetDevice(VOID) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); +} + +// Must be Non-Paged, as it sets up the display for a bugcheck +NTSTATUS QxlDod::SystemDisplayEnable(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, + _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags, + _Out_ UINT* pWidth, + _Out_ UINT* pHeight, + _Out_ D3DDDIFORMAT* pColorFormat) +{ + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(pColorFormat); + UNREFERENCED_PARAMETER(pWidth); + UNREFERENCED_PARAMETER(pHeight); + QXL_ASSERT((TargetId < MAX_CHILDREN) || (TargetId == D3DDDI_ID_UNINITIALIZED)); + + return STATUS_SUCCESS; +} + +// Must be Non-Paged, as it is called to display the bugcheck screen +VOID QxlDod::SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VOID* pSource, + _In_ UINT SourceWidth, + _In_ UINT SourceHeight, + _In_ UINT SourceStride, + _In_ INT PositionX, + _In_ INT PositionY) +{ + UNREFERENCED_PARAMETER(pSource); + UNREFERENCED_PARAMETER(SourceStride); + // Rect will be Offset by PositionX/Y in the src to reset it back to 0 + RECT Rect; + Rect.left = PositionX; + Rect.top = PositionY; + Rect.right = Rect.left + SourceWidth; + Rect.bottom = Rect.top + SourceHeight; + +} + +#pragma code_seg(pop) // End Non-Paged Code + + + +NTSTATUS QxlDod::WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue) +{ + PAGED_CODE(); + + NTSTATUS Status; + ANSI_STRING AnsiStrValue; + UNICODE_STRING UnicodeStrValue; + UNICODE_STRING UnicodeStrValueName; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + // ZwSetValueKey wants the ValueName as a UNICODE_STRING + RtlInitUnicodeString(&UnicodeStrValueName, pszwValueName); + + // REG_SZ is for WCHARs, there is no equivalent for CHARs + // Use the ansi/unicode conversion functions to get from PSTR to PWSTR + RtlInitAnsiString(&AnsiStrValue, pszValue); + Status = RtlAnsiStringToUnicodeString(&UnicodeStrValue, &AnsiStrValue, TRUE); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("RtlAnsiStringToUnicodeString failed with Status: 0x%X\n", Status)); + return Status; + } + + // Write the value to the registry + Status = ZwSetValueKey(DevInstRegKeyHandle, + &UnicodeStrValueName, + 0, + REG_SZ, + UnicodeStrValue.Buffer, + UnicodeStrValue.MaximumLength); + + // Free the earlier allocated unicode string + RtlFreeUnicodeString(&UnicodeStrValue); + + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("ZwSetValueKey failed with Status: 0x%X\n", Status)); + } + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return Status; +} + +NTSTATUS QxlDod::RegisterHWInfo() +{ + PAGED_CODE(); + + NTSTATUS Status; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + // TODO: Replace these strings with proper information + PCSTR StrHWInfoChipType = "QEMU QXL"; + PCSTR StrHWInfoDacType = "QXL 1B36"; + PCSTR StrHWInfoAdapterString = "QXL"; + PCSTR StrHWInfoBiosString = "SEABIOS QXL"; + + HANDLE DevInstRegKeyHandle; + Status = IoOpenDeviceRegistryKey(m_pPhysicalDevice, PLUGPLAY_REGKEY_DRIVER, KEY_SET_VALUE, &DevInstRegKeyHandle); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("IoOpenDeviceRegistryKey failed for PDO: 0x%I64x, Status: 0x%I64x", m_pPhysicalDevice, Status)); + return Status; + } + + Status = WriteHWInfoStr(DevInstRegKeyHandle, L"HardwareInformation.ChipType", StrHWInfoChipType); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + Status = WriteHWInfoStr(DevInstRegKeyHandle, L"HardwareInformation.DacType", StrHWInfoDacType); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + Status = WriteHWInfoStr(DevInstRegKeyHandle, L"HardwareInformation.AdapterString", StrHWInfoAdapterString); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + Status = WriteHWInfoStr(DevInstRegKeyHandle, L"HardwareInformation.BiosString", StrHWInfoBiosString); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + // MemorySize is a ULONG, unlike the others which are all strings + UNICODE_STRING ValueNameMemorySize; + RtlInitUnicodeString(&ValueNameMemorySize, L"HardwareInformation.MemorySize"); + DWORD MemorySize = 0; // BDD has no access to video memory + Status = ZwSetValueKey(DevInstRegKeyHandle, + &ValueNameMemorySize, + 0, + REG_DWORD, + &MemorySize, + sizeof(MemorySize)); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("ZwSetValueKey for MemorySize failed with Status: 0x%X\n", Status)); + return Status; + } + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return Status; +} + +NTSTATUS QxlDod::VbeGetModeList() +{ + PAGED_CODE(); + USHORT m_Segment; + USHORT m_Offset; + USHORT ModeCount; + ULONG SuitableModeCount; + USHORT ModeTemp; + USHORT CurrentMode; + PVBE_MODEINFO VbeModeInfo; + VBE_INFO VbeInfo = {0}; + ULONG Length; + + NTSTATUS Status = STATUS_SUCCESS; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); +//Get VBE Mode List + Length = 0x400; + Status = x86BiosAllocateBuffer (&Length, &m_Segment, &m_Offset); + if (!NT_SUCCESS (Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosAllocateBuffer failed with Status: 0x%X\n", Status)); + return Status; + } + DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosAllocateBuffer 0x%x (%x.%x)\n", VbeInfo.VideoModePtr, m_Segment, m_Offset)); + + Status = x86BiosWriteMemory (m_Segment, m_Offset, "VBE2", 4); + + if (!NT_SUCCESS (Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosWriteMemory failed with Status: 0x%X\n", Status)); + return Status; + } + + X86BIOS_REGISTERS regs = {0}; + regs.SegEs = m_Segment; + regs.Edi = m_Offset; + regs.Eax = 0x4F00; + if (!x86BiosCall (0x10, ®s) /* || (regs.Eax & 0xFF00) != 0x4F00 */) + { + DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n")); + return STATUS_UNSUCCESSFUL; + } + + Status = x86BiosReadMemory (m_Segment, m_Offset, &VbeInfo, sizeof (VbeInfo)); + if (!NT_SUCCESS (Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosReadMemory failed with Status: 0x%X\n", Status)); + return Status; + } + + if (!RtlEqualMemory(VbeInfo.Signature, "VESA", 4)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("No VBE BIOS present\n")); + return STATUS_UNSUCCESSFUL; + } + + DbgPrint(TRACE_LEVEL_ERROR, ("VBE BIOS Present (%d.%d, %8ld Kb)\n", VbeInfo.Version / 0x100, VbeInfo.Version & 0xFF, VbeInfo.TotalMemory * 64)); + DbgPrint(TRACE_LEVEL_ERROR, ("Capabilities = 0x%x\n", VbeInfo.Capabilities)); + DbgPrint(TRACE_LEVEL_ERROR, ("VideoModePtr = 0x%x (0x%x.0x%x)\n", VbeInfo.VideoModePtr, HIWORD( VbeInfo.VideoModePtr), LOWORD( VbeInfo.VideoModePtr))); + + for (ModeCount = 0; ; ModeCount++) + { + /* Read the VBE mode number. */ + Status = x86BiosReadMemory ( + HIWORD(VbeInfo.VideoModePtr), + LOWORD(VbeInfo.VideoModePtr) + (ModeCount << 1), + &ModeTemp, + sizeof(ModeTemp)); + + if (!NT_SUCCESS (Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosReadMemory failed with Status: 0x%X\n", Status)); + break; + } + /* End of list? */ + if (ModeTemp == 0xFFFF || ModeTemp == 0) + { + break; + } + } + + DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount %d\n", ModeCount)); + + m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VBE_MODEINFO) * ModeCount]); + m_ModeNumbers = reinterpret_cast (new (PagedPool) BYTE [sizeof (USHORT) * ModeCount]); + m_CurrentMode = 0; + DbgPrint(TRACE_LEVEL_ERROR, ("m_ModeInfo = 0x%p, m_ModeNumbers = 0x%p\n", m_ModeInfo, m_ModeNumbers)); + for (CurrentMode = 0, SuitableModeCount = 0; + CurrentMode < ModeCount; + CurrentMode++) + { + Status = x86BiosReadMemory ( + HIWORD(VbeInfo.VideoModePtr), + LOWORD(VbeInfo.VideoModePtr) + (CurrentMode << 1), + &ModeTemp, + sizeof(ModeTemp)); + + if (!NT_SUCCESS (Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosReadMemory failed with Status: 0x%X\n", Status)); + break; + } + + DbgPrint(TRACE_LEVEL_ERROR, ("ModeTemp = 0x%X\n", ModeTemp)); + RtlZeroMemory(®s, sizeof(regs)); + regs.Eax = 0x4F01; + regs.Ecx = ModeTemp; + regs.Edi = m_Offset + sizeof (VbeInfo); + regs.SegEs = m_Segment; + if (!x86BiosCall (0x10, ®s)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n")); + return STATUS_UNSUCCESSFUL; + } + Status = x86BiosReadMemory ( + m_Segment, + m_Offset + sizeof (VbeInfo), + m_ModeInfo + SuitableModeCount, + sizeof(VBE_MODEINFO)); + + VbeModeInfo = m_ModeInfo + SuitableModeCount; + + if (VbeModeInfo->XResolution >= 1024 && + VbeModeInfo->YResolution >= 768 && + VbeModeInfo->BitsPerPixel == 32 && + VbeModeInfo->PhysBasePtr != 0) + { + m_ModeNumbers[SuitableModeCount] = ModeTemp; + if (VbeModeInfo->XResolution == 1024 && + VbeModeInfo->YResolution == 768) + { + m_CurrentMode = (USHORT)SuitableModeCount; + } + SuitableModeCount++; + } + } + + if (SuitableModeCount == 0) + { + DbgPrint(TRACE_LEVEL_ERROR, ("No video modes supported\n")); + Status = STATUS_UNSUCCESSFUL; + } + + m_ModeCount = SuitableModeCount; + DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount)); + + if (m_Segment != 0) + { + x86BiosFreeBuffer (m_Segment, m_Offset); + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return Status; +} + +NTSTATUS QxlDod::VbeQueryCurrentMode(PVIDEO_MODE RequestedMode) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + NTSTATUS Status = STATUS_SUCCESS; + PVBE_MODEINFO VBEMode = &m_ModeInfo[m_CurrentMode]; + + return Status; +} + +NTSTATUS QxlDod::VbeSetCurrentMode(PVIDEO_MODE RequestedMode) +{ + NTSTATUS Status = STATUS_SUCCESS; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + X86BIOS_REGISTERS regs = {0}; + regs.Eax = 0x4F02; + regs.Edx = m_ModeNumbers[RequestedMode->RequestedMode]; + if (!x86BiosCall (0x10, ®s)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n")); + return STATUS_UNSUCCESSFUL; + } + m_CurrentMode = (USHORT)RequestedMode->RequestedMode; + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return Status; +} + +NTSTATUS QxlDod::VbeSetPowerState(POWER_ACTION ActionType) +{ + NTSTATUS Status = STATUS_SUCCESS; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + X86BIOS_REGISTERS regs = {0}; + regs.Eax = 0x4F10; + regs.Ebx = 1; + switch (ActionType) + { + case PowerActionSleep: regs.Ebx |= 0x100; break; + case PowerActionHibernate: regs.Ebx |= 0x200; break; + case PowerActionShutdown: + case PowerActionShutdownReset: + case PowerActionShutdownOff: regs.Ebx |= 0x400; break; + } + if (!x86BiosCall (0x10, ®s)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n")); + return STATUS_UNSUCCESSFUL; + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return Status; +} diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h new file mode 100755 index 0000000..18ec7b1 --- /dev/null +++ b/qxldod/QxlDod.h @@ -0,0 +1,236 @@ +#pragma once +#include "baseobject.h" + +typedef struct _QXL_FLAGS +{ + UINT DriverStarted : 1; // ( 1) 1 after StartDevice and 0 after StopDevice + UINT Unused : 31; +} QXL_FLAGS; + +#define MAX_CHILDREN 1 +#define MAX_VIEWS 1 + +#pragma pack(push) +#pragma pack(1) + +typedef struct +{ + CHAR Signature[4]; + USHORT Version; + ULONG OemStringPtr; + LONG Capabilities; + ULONG VideoModePtr; + USHORT TotalMemory; + USHORT OemSoftwareRevision; + ULONG OemVendorNamePtr; + ULONG OemProductNamePtr; + ULONG OemProductRevPtr; + CHAR Reserved[222]; +// CHAR OemData[256]; +} VBE_INFO, *PVBE_INFO; + +typedef struct +{ +/* Mandatory information for all VBE revisions */ + USHORT ModeAttributes; + UCHAR WinAAttributes; + UCHAR WinBAttributes; + USHORT WinGranularity; + USHORT WinSize; + USHORT WinASegment; + USHORT WinBSegment; + ULONG WinFuncPtr; + USHORT BytesPerScanLine; +/* Mandatory information for VBE 1.2 and above */ + USHORT XResolution; + USHORT YResolution; + UCHAR XCharSize; + UCHAR YCharSize; + UCHAR NumberOfPlanes; + UCHAR BitsPerPixel; + UCHAR NumberOfBanks; + UCHAR MemoryModel; + UCHAR BankSize; + UCHAR NumberOfImagePages; + UCHAR Reserved1; +/* Direct Color fields (required for Direct/6 and YUV/7 memory models) */ + UCHAR RedMaskSize; + UCHAR RedFieldPosition; + UCHAR GreenMaskSize; + UCHAR GreenFieldPosition; + UCHAR BlueMaskSize; + UCHAR BlueFieldPosition; + UCHAR ReservedMaskSize; + UCHAR ReservedFieldPosition; + UCHAR DirectColorModeInfo; +/* Mandatory information for VBE 2.0 and above */ + ULONG PhysBasePtr; + ULONG Reserved2; + USHORT Reserved3; + /* Mandatory information for VBE 3.0 and above */ + USHORT LinBytesPerScanLine; + UCHAR BnkNumberOfImagePages; + UCHAR LinNumberOfImagePages; + UCHAR LinRedMaskSize; + UCHAR LinRedFieldPosition; + UCHAR LinGreenMaskSize; + UCHAR LinGreenFieldPosition; + UCHAR LinBlueMaskSize; + UCHAR LinBlueFieldPosition; + UCHAR LinReservedMaskSize; + UCHAR LinReservedFieldPosition; + ULONG MaxPixelClock; + CHAR Reserved4[189]; +} VBE_MODEINFO, *PVBE_MODEINFO; + +#pragma pack(pop) + +typedef struct _X86BIOS_REGISTERS // invented names +{ + ULONG Eax; + ULONG Ecx; + ULONG Edx; + ULONG Ebx; + ULONG Ebp; + ULONG Esi; + ULONG Edi; + USHORT SegDs; + USHORT SegEs; +} X86BIOS_REGISTERS, *PX86BIOS_REGISTERS; + +/* Undocumented imports from the HAL */ + +#ifdef __cplusplus +extern "C" { +#endif + +NTHALAPI BOOLEAN x86BiosCall (ULONG, PX86BIOS_REGISTERS); + +NTHALAPI NTSTATUS x86BiosAllocateBuffer (ULONG *, USHORT *, USHORT *); +NTHALAPI NTSTATUS x86BiosFreeBuffer (USHORT, USHORT); + +NTHALAPI NTSTATUS x86BiosReadMemory (USHORT, USHORT, PVOID, ULONG); +NTHALAPI NTSTATUS x86BiosWriteMemory (USHORT, USHORT, PVOID, ULONG); + +#ifdef __cplusplus +} +#endif + + +class QxlDod : + public BaseObject +{ +private: + DEVICE_OBJECT* m_pPhysicalDevice; + DXGKRNL_INTERFACE m_DxgkInterface; + DXGK_DEVICE_INFO m_DeviceInfo; + + DEVICE_POWER_STATE m_MonitorPowerState; + DEVICE_POWER_STATE m_AdapterPowerState; + QXL_FLAGS m_Flags; + PVBE_MODEINFO m_ModeInfo; + ULONG m_ModeCount; + PUSHORT m_ModeNumbers; + USHORT m_CurrentMode; +public: + QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject); + ~QxlDod(void); +#pragma code_seg(push) +#pragma code_seg() + BOOLEAN IsDriverActive() const + { + return m_Flags.DriverStarted; + } +#pragma code_seg(pop) + + NTSTATUS StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, + _In_ DXGKRNL_INTERFACE* pDxgkInterface, + _Out_ ULONG* pNumberOfViews, + _Out_ ULONG* pNumberOfChildren); + NTSTATUS StopDevice(VOID); + // Must be Non-Paged + VOID ResetDevice(VOID); + + NTSTATUS DispatchIoRequest(_In_ ULONG VidPnSourceId, + _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket); + NTSTATUS SetPowerState(_In_ ULONG HardwareUid, + _In_ DEVICE_POWER_STATE DevicePowerState, + _In_ POWER_ACTION ActionType); + // Report back child capabilities + NTSTATUS QueryChildRelations(_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations, + _In_ ULONG ChildRelationsSize); + + NTSTATUS QueryChildStatus(_Inout_ DXGK_CHILD_STATUS* pChildStatus, + _In_ BOOLEAN NonDestructiveOnly); + + // Return EDID if previously retrieved + NTSTATUS QueryDeviceDescriptor(_In_ ULONG ChildUid, + _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor); + + // Must be Non-Paged + // BDD doesn't have interrupts, so just returns false + BOOLEAN InterruptRoutine(_In_ ULONG MessageNumber); + + VOID DpcRoutine(VOID); + + // Return DriverCaps, doesn't support other queries though + NTSTATUS QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo); + + NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition); + + NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape); + + NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscape); + + NTSTATUS PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly); + + NTSTATUS QueryInterface(_In_ CONST PQUERY_INTERFACE QueryInterface); + + NTSTATUS IsSupportedVidPn(_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn); + + NTSTATUS RecommendFunctionalVidPn(_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn); + + NTSTATUS RecommendVidPnTopology(_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology); + + NTSTATUS RecommendMonitorModes(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes); + + NTSTATUS EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality); + + NTSTATUS SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility); + + NTSTATUS CommitVidPn(_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn); + + NTSTATUS UpdateActiveVidPnPresentPath(_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath); + + NTSTATUS QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps); + + // Part of PnPStop (PnP instance only), returns current mode information (which will be passed to fallback instance by dxgkrnl) + NTSTATUS StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, + _Out_ DXGK_DISPLAY_INFORMATION* pDisplayInfo); + + // Must be Non-Paged + // Call to initialize as part of bugcheck + NTSTATUS SystemDisplayEnable(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, + _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags, + _Out_ UINT* pWidth, + _Out_ UINT* pHeight, + _Out_ D3DDDIFORMAT* pColorFormat); + + // Must be Non-Paged + // Write out pixels as part of bugcheck + VOID SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VOID* pSource, + _In_ UINT SourceWidth, + _In_ UINT SourceHeight, + _In_ UINT SourceStride, + _In_ INT PositionX, + _In_ INT PositionY); +private: + VOID CleanUp(VOID); + NTSTATUS WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue); + NTSTATUS RegisterHWInfo(); + NTSTATUS VbeGetModeList(); + NTSTATUS VbeQueryCurrentMode(PVIDEO_MODE RequestedMode); + NTSTATUS VbeSetCurrentMode(PVIDEO_MODE RequestedMode); + NTSTATUS VbeSetPowerState(POWER_ACTION ActionType); +}; + diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp new file mode 100755 index 0000000..546fc88 --- /dev/null +++ b/qxldod/driver.cpp @@ -0,0 +1,676 @@ +#include "driver.h" +#include "QxlDod.h" + +#pragma code_seg(push) +#pragma code_seg("INIT") +// BEGIN: Init Code + +// +// Driver Entry point +// + +int nDebugLevel = TRACE_LEVEL_VERBOSE; + + +extern "C" +NTSTATUS +DriverEntry( + _In_ DRIVER_OBJECT* pDriverObject, + _In_ UNICODE_STRING* pRegistryPath) +{ + PAGED_CODE(); + + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> KMDOD build on on %s %s\n", __DATE__, __TIME__)); + +#ifdef DBG +// KdBreakPoint(); +#endif + // Initialize DDI function pointers and dxgkrnl + KMDDOD_INITIALIZATION_DATA InitialData = {0}; + + InitialData.Version = DXGKDDI_INTERFACE_VERSION_WIN8; + + InitialData.DxgkDdiAddDevice = DodAddDevice; + InitialData.DxgkDdiStartDevice = DodStartDevice; + InitialData.DxgkDdiStopDevice = DodStopDevice; + InitialData.DxgkDdiResetDevice = DodResetDevice; + InitialData.DxgkDdiRemoveDevice = DodRemoveDevice; + InitialData.DxgkDdiDispatchIoRequest = DodDispatchIoRequest; + InitialData.DxgkDdiInterruptRoutine = DodInterruptRoutine; + InitialData.DxgkDdiDpcRoutine = DodDpcRoutine; + InitialData.DxgkDdiQueryChildRelations = DodQueryChildRelations; + InitialData.DxgkDdiQueryChildStatus = DodQueryChildStatus; + InitialData.DxgkDdiQueryDeviceDescriptor = DodQueryDeviceDescriptor; + InitialData.DxgkDdiSetPowerState = DodSetPowerState; + InitialData.DxgkDdiUnload = DodUnload; + InitialData.DxgkDdiQueryInterface = DodQueryInterface; + InitialData.DxgkDdiQueryAdapterInfo = DodQueryAdapterInfo; + InitialData.DxgkDdiSetPointerPosition = DodSetPointerPosition; + InitialData.DxgkDdiSetPointerShape = DodSetPointerShape; + InitialData.DxgkDdiEscape = DodEscape; + InitialData.DxgkDdiIsSupportedVidPn = DodIsSupportedVidPn; + InitialData.DxgkDdiRecommendFunctionalVidPn = DodRecommendFunctionalVidPn; + InitialData.DxgkDdiEnumVidPnCofuncModality = DodEnumVidPnCofuncModality; + InitialData.DxgkDdiSetVidPnSourceVisibility = DodSetVidPnSourceVisibility; + InitialData.DxgkDdiCommitVidPn = DodCommitVidPn; + InitialData.DxgkDdiUpdateActiveVidPnPresentPath = DodUpdateActiveVidPnPresentPath; + InitialData.DxgkDdiRecommendMonitorModes = DodRecommendMonitorModes; + InitialData.DxgkDdiQueryVidPnHWCapability = DodQueryVidPnHWCapability; + InitialData.DxgkDdiPresentDisplayOnly = DodPresentDisplayOnly; + InitialData.DxgkDdiStopDeviceAndReleasePostDisplayOwnership = DodStopDeviceAndReleasePostDisplayOwnership; + InitialData.DxgkDdiSystemDisplayEnable = DodSystemDisplayEnable; + InitialData.DxgkDdiSystemDisplayWrite = DodSystemDisplayWrite; + + NTSTATUS Status = DxgkInitializeDisplayOnlyDriver(pDriverObject, pRegistryPath, &InitialData); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("DxgkInitializeDisplayOnlyDriver failed with Status: 0x%X\n", Status)); + } + + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); + return Status; +} +// END: Init Code +#pragma code_seg(pop) + +#pragma code_seg(push) +#pragma code_seg("PAGE") + +// +// PnP DDIs +// + +VOID +DodUnload(VOID) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--> %s\n", __FUNCTION__)); +} + +NTSTATUS +DodAddDevice( + _In_ DEVICE_OBJECT* pPhysicalDeviceObject, + _Outptr_ PVOID* ppDeviceContext) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + + if ((pPhysicalDeviceObject == NULL) || + (ppDeviceContext == NULL)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("One of pPhysicalDeviceObject (0x%I64x), ppDeviceContext (0x%I64x) is NULL", + pPhysicalDeviceObject, ppDeviceContext)); + return STATUS_INVALID_PARAMETER; + } + *ppDeviceContext = NULL; + + QxlDod* pQxl = new(NonPagedPoolNx) QxlDod(pPhysicalDeviceObject); + if (pQxl == NULL) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pQxl failed to be allocated")); + return STATUS_NO_MEMORY; + } + + *ppDeviceContext = pQxl; + + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + +NTSTATUS +DodRemoveDevice( + _In_ VOID* pDeviceContext) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + + if (pQxl) + { + delete pQxl; + pQxl = NULL; + } + + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + +NTSTATUS +DodStartDevice( + _In_ VOID* pDeviceContext, + _In_ DXGK_START_INFO* pDxgkStartInfo, + _In_ DXGKRNL_INTERFACE* pDxgkInterface, + _Out_ ULONG* pNumberOfViews, + _Out_ ULONG* pNumberOfChildren) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + return pQxl->StartDevice(pDxgkStartInfo, pDxgkInterface, pNumberOfViews, pNumberOfChildren); +} + +NTSTATUS +DodStopDevice( + _In_ VOID* pDeviceContext) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + return pQxl->StopDevice(); +} + + +NTSTATUS +DodDispatchIoRequest( + _In_ VOID* pDeviceContext, + _In_ ULONG VidPnSourceId, + _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return STATUS_UNSUCCESSFUL; + } + return pQxl->DispatchIoRequest(VidPnSourceId, pVideoRequestPacket); +} + +NTSTATUS +DodSetPowerState( + _In_ VOID* pDeviceContext, + _In_ ULONG HardwareUid, + _In_ DEVICE_POWER_STATE DevicePowerState, + _In_ POWER_ACTION ActionType) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + if (!pQxl->IsDriverActive()) + { + // If the driver isn't active, SetPowerState can still be called, however in QXL's case + // this shouldn't do anything, as it could for instance be called on QXL Fallback after + // Fallback has been stopped and QXL PnP is being started. Fallback doesn't have control + // of the hardware in this case. + return STATUS_SUCCESS; + } + return pQxl->SetPowerState(HardwareUid, DevicePowerState, ActionType); +} + +NTSTATUS +DodQueryChildRelations( + _In_ VOID* pDeviceContext, + _Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations, + _In_ ULONG ChildRelationsSize) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + return pQxl->QueryChildRelations(pChildRelations, ChildRelationsSize); +} + +NTSTATUS +DodQueryChildStatus( + _In_ VOID* pDeviceContext, + _Inout_ DXGK_CHILD_STATUS* pChildStatus, + _In_ BOOLEAN NonDestructiveOnly) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + return pQxl->QueryChildStatus(pChildStatus, NonDestructiveOnly); +} + +NTSTATUS +DodQueryDeviceDescriptor( + _In_ VOID* pDeviceContext, + _In_ ULONG ChildUid, + _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + if (!pQxl->IsDriverActive()) + { + // During stress testing of PnPStop, it is possible for QXL Fallback to get called to start then stop in quick succession. + // The first call queues a worker thread item indicating that it now has a child device, the second queues a worker thread + // item that it no longer has any child device. This function gets called based on the first worker thread item, but after + // the driver has been stopped. Therefore instead of asserting like other functions, we only warn. + DbgPrint(TRACE_LEVEL_WARNING, ("QXL (0x%I64x) is being called when not active!", pQxl)); + return STATUS_UNSUCCESSFUL; + } + return pQxl->QueryDeviceDescriptor(ChildUid, pDeviceDescriptor); +} + + +// +// WDDM Display Only Driver DDIs +// + +NTSTATUS +APIENTRY +DodQueryAdapterInfo( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + return pQxl->QueryAdapterInfo(pQueryAdapterInfo); +} + +NTSTATUS +APIENTRY +DodSetPointerPosition( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return STATUS_UNSUCCESSFUL; + } + return pQxl->SetPointerPosition(pSetPointerPosition); +} + +NTSTATUS +APIENTRY +DodSetPointerShape( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return STATUS_UNSUCCESSFUL; + } + return pQxl->SetPointerShape(pSetPointerShape); +} + +NTSTATUS +APIENTRY +DodEscape( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_ESCAPE* pEscape + ) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + return pQxl->Escape(pEscape); +} + +NTSTATUS +DodQueryInterface( + _In_ CONST PVOID pDeviceContext, + _In_ CONST PQUERY_INTERFACE QueryInterface + ) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + return pQxl->QueryInterface(QueryInterface); +} + +NTSTATUS +APIENTRY +DodPresentDisplayOnly( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); +// DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return STATUS_UNSUCCESSFUL; + } + return pQxl->PresentDisplayOnly(pPresentDisplayOnly); +} + +NTSTATUS +APIENTRY +DodStopDeviceAndReleasePostDisplayOwnership( + _In_ VOID* pDeviceContext, + _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, + _Out_ DXGK_DISPLAY_INFORMATION* DisplayInfo) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + return pQxl->StopDeviceAndReleasePostDisplayOwnership(TargetId, DisplayInfo); +} + +NTSTATUS +APIENTRY +DodIsSupportedVidPn( + _In_ CONST HANDLE hAdapter, + _Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + if (!pQxl->IsDriverActive()) + { + // This path might hit because win32k/dxgport doesn't check that an adapter is active when taking the adapter lock. + // The adapter lock is the main thing QXL Fallback relies on to not be called while it's inactive. It is still a rare + // timing issue around PnpStart/Stop and isn't expected to have any effect on the stability of the system. + DbgPrint(TRACE_LEVEL_WARNING, ("QXL (0x%I64x) is being called when not active!", pQxl)); + return STATUS_UNSUCCESSFUL; + } + return pQxl->IsSupportedVidPn(pIsSupportedVidPn); +} + +NTSTATUS +APIENTRY +DodRecommendFunctionalVidPn( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return STATUS_UNSUCCESSFUL; + } + return pQxl->RecommendFunctionalVidPn(pRecommendFunctionalVidPn); +} + +NTSTATUS +APIENTRY +DodRecommendVidPnTopology( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return STATUS_UNSUCCESSFUL; + } + return pQxl->RecommendVidPnTopology(pRecommendVidPnTopology); +} + +NTSTATUS +APIENTRY +DodRecommendMonitorModes( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return STATUS_UNSUCCESSFUL; + } + return pQxl->RecommendMonitorModes(pRecommendMonitorModes); +} + +NTSTATUS +APIENTRY +DodEnumVidPnCofuncModality( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return STATUS_UNSUCCESSFUL; + } + return pQxl->EnumVidPnCofuncModality(pEnumCofuncModality); +} + +NTSTATUS +APIENTRY +DodSetVidPnSourceVisibility( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return STATUS_UNSUCCESSFUL; + } + return pQxl->SetVidPnSourceVisibility(pSetVidPnSourceVisibility); +} + +NTSTATUS +APIENTRY +DodCommitVidPn( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return STATUS_UNSUCCESSFUL; + } + return pQxl->CommitVidPn(pCommitVidPn); +} + +NTSTATUS +APIENTRY +DodUpdateActiveVidPnPresentPath( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return STATUS_UNSUCCESSFUL; + } + return pQxl->UpdateActiveVidPnPresentPath(pUpdateActiveVidPnPresentPath); +} + +NTSTATUS +APIENTRY +DodQueryVidPnHWCapability( + _In_ CONST HANDLE hAdapter, + _Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps) +{ + PAGED_CODE(); + QXL_ASSERT_CHK(hAdapter != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(hAdapter); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return STATUS_UNSUCCESSFUL; + } + return pQxl->QueryVidPnHWCapability(pVidPnHWCaps); +} + +//END: Paged Code +#pragma code_seg(pop) + +#pragma code_seg(push) +#pragma code_seg() +// BEGIN: Non-Paged Code + +VOID +DodDpcRoutine( + _In_ VOID* pDeviceContext) +{ + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + if (!pQxl->IsDriverActive()) + { + QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + return; + } + pQxl->DpcRoutine(); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); +} + +BOOLEAN +DodInterruptRoutine( + _In_ VOID* pDeviceContext, + _In_ ULONG MessageNumber) +{ + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + return pQxl->InterruptRoutine(MessageNumber); +} + +VOID +DodResetDevice( + _In_ VOID* pDeviceContext) +{ + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + pQxl->ResetDevice(); +} + +NTSTATUS +APIENTRY +DodSystemDisplayEnable( + _In_ VOID* pDeviceContext, + _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, + _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags, + _Out_ UINT* Width, + _Out_ UINT* Height, + _Out_ D3DDDIFORMAT* ColorFormat) +{ + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + return pQxl->SystemDisplayEnable(TargetId, Flags, Width, Height, ColorFormat); +} + +VOID +APIENTRY +DodSystemDisplayWrite( + _In_ VOID* pDeviceContext, + _In_ VOID* Source, + _In_ UINT SourceWidth, + _In_ UINT SourceHeight, + _In_ UINT SourceStride, + _In_ UINT PositionX, + _In_ UINT PositionY) +{ + QXL_ASSERT_CHK(pDeviceContext != NULL); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + + QxlDod* pQxl = reinterpret_cast(pDeviceContext); + pQxl->SystemDisplayWrite(Source, SourceWidth, SourceHeight, SourceStride, PositionX, PositionY); +} + +#if defined(DBG) + +#define RHEL_DEBUG_PORT ((PUCHAR)0x3F8) +#define TEMP_BUFFER_SIZE 256 + +void DebugPrintFuncSerial(const char *format, ...) +{ + char buf[TEMP_BUFFER_SIZE]; + NTSTATUS status; + size_t len; + va_list list; + va_start(list, format); + status = RtlStringCbVPrintfA(buf, sizeof(buf), format, list); + if (status == STATUS_SUCCESS) + { + len = strlen(buf); + } + else + { + len = 2; + buf[0] = 'O'; + buf[1] = '\n'; + } + if (len) + { + WRITE_PORT_BUFFER_UCHAR(RHEL_DEBUG_PORT, (PUCHAR)buf, len); + WRITE_PORT_UCHAR(RHEL_DEBUG_PORT, '\r'); + } +} + +void DebugPrintFunc(const char *format, ...) +{ + va_list list; + va_start(list, format); + vDbgPrintEx(DPFLTR_DEFAULT_ID, 9 | DPFLTR_MASK, format, list); +} +#endif + +#pragma code_seg(pop) // End Non-Paged Code + diff --git a/qxldod/driver.h b/qxldod/driver.h new file mode 100755 index 0000000..72a8b46 --- /dev/null +++ b/qxldod/driver.h @@ -0,0 +1,255 @@ +#pragma once +#include "BaseObject.h" + + +extern "C" +DRIVER_INITIALIZE DriverEntry; + +// +// PnP DDIs +// + +VOID +DodUnload(VOID); + +// If uncommenting ENABLE_DXGK_SAL in the sources file, all the below function prototypes should be updated to use +// the function typedef's from the header files. Additionally, annotations on the function definitions can be removed +// as they are inherited from the prototype definition here. As an example the entire 4-line prototype for BddDdiAddDevice +// is replaced by the single commented line below: +// DXGKDDI_ADD_DEVICE BddDdiAddDevice; +NTSTATUS +DodAddDevice( + _In_ DEVICE_OBJECT* pPhysicalDeviceObject, + _Outptr_ PVOID* ppDeviceContext); + +NTSTATUS +DodRemoveDevice( + _In_ VOID* pDeviceContext); + +NTSTATUS +DodStartDevice( + _In_ VOID* pDeviceContext, + _In_ DXGK_START_INFO* pDxgkStartInfo, + _In_ DXGKRNL_INTERFACE* pDxgkInterface, + _Out_ ULONG* pNumberOfViews, + _Out_ ULONG* pNumberOfChildren); + +NTSTATUS +DodStopDevice( + _In_ VOID* pDeviceContext); + +VOID +DodResetDevice( + _In_ VOID* pDeviceContext); + + +NTSTATUS +DodDispatchIoRequest( + _In_ VOID* pDeviceContext, + _In_ ULONG VidPnSourceId, + _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket); + +NTSTATUS +DodSetPowerState( + _In_ VOID* pDeviceContext, + _In_ ULONG HardwareUid, + _In_ DEVICE_POWER_STATE DevicePowerState, + _In_ POWER_ACTION ActionType); + +NTSTATUS +DodQueryChildRelations( + _In_ VOID* pDeviceContext, + _Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations, + _In_ ULONG ChildRelationsSize); + +NTSTATUS +DodQueryChildStatus( + _In_ VOID* pDeviceContext, + _Inout_ DXGK_CHILD_STATUS* pChildStatus, + _In_ BOOLEAN NonDestructiveOnly); + +NTSTATUS +DodQueryDeviceDescriptor( + _In_ VOID* pDeviceContext, + _In_ ULONG ChildUid, + _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor); + +// Must be Non-Paged +BOOLEAN +DodInterruptRoutine( + _In_ VOID* pDeviceContext, + _In_ ULONG MessageNumber); + +VOID +DodDpcRoutine( + _In_ VOID* pDeviceContext); + +// +// WDDM Display Only Driver DDIs +// + +NTSTATUS +APIENTRY +DodQueryAdapterInfo( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo); + +NTSTATUS +APIENTRY +DodSetPointerPosition( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition); + +NTSTATUS +APIENTRY +DodSetPointerShape( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape); + +NTSTATUS +APIENTRY +DodEscape( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_ESCAPE* pEscape); + +NTSTATUS +DodQueryInterface( + _In_ CONST PVOID pDeviceContext, + _In_ CONST PQUERY_INTERFACE pQueryInterface); + +NTSTATUS +APIENTRY +DodPresentDisplayOnly( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly); + +NTSTATUS +APIENTRY +DodIsSupportedVidPn( + _In_ CONST HANDLE hAdapter, + _Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn); + +NTSTATUS +APIENTRY +DodRecommendFunctionalVidPn( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn); + +NTSTATUS +APIENTRY +DodRecommendVidPnTopology( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology); + +NTSTATUS +APIENTRY +DodRecommendMonitorModes( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes); + +NTSTATUS +APIENTRY +DodEnumVidPnCofuncModality( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality); + +NTSTATUS +APIENTRY +DodSetVidPnSourceVisibility( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility); + +NTSTATUS +APIENTRY +DodCommitVidPn( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn); + +NTSTATUS +APIENTRY +DodUpdateActiveVidPnPresentPath( + _In_ CONST HANDLE hAdapter, + _In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath); + +NTSTATUS +APIENTRY +DodQueryVidPnHWCapability( + _In_ CONST HANDLE hAdapter, + _Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps); + +NTSTATUS +APIENTRY +DodStopDeviceAndReleasePostDisplayOwnership( + _In_ VOID* pDeviceContext, + _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, + _Out_ DXGK_DISPLAY_INFORMATION* DisplayInfo); + +// Must be Non-Paged +NTSTATUS +APIENTRY +DodSystemDisplayEnable( + _In_ VOID* pDeviceContext, + _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, + _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags, + _Out_ UINT* Width, + _Out_ UINT* Height, + _Out_ D3DDDIFORMAT* ColorFormat); + +// Must be Non-Paged +VOID +APIENTRY +DodSystemDisplayWrite( + _In_ VOID* pDeviceContext, + _In_ VOID* Source, + _In_ UINT SourceWidth, + _In_ UINT SourceHeight, + _In_ UINT SourceStride, + _In_ UINT PositionX, + _In_ UINT PositionY); + + + +#if DBG + +extern int nDebugLevel; +void DebugPrintFuncSerial(const char *format, ...); + +void DebugPrintFunc(const char *format, ...); + +#define DbgPrint(level, line) \ + if (level > nDebugLevel) {} \ + else DebugPrintFuncSerial line +#else +#define DbgPrint(level, line) +#endif + +// else if (0) DebugPrintFuncSerial line \ + + +#ifndef TRACE_LEVEL_INFORMATION +#define TRACE_LEVEL_NONE 0 // Tracing is not on +#define TRACE_LEVEL_FATAL 1 // Abnormal exit or termination +#define TRACE_LEVEL_ERROR 2 // Severe errors that need logging +#define TRACE_LEVEL_WARNING 3 // Warnings such as allocation failure +#define TRACE_LEVEL_INFORMATION 4 // Includes non-error cases(e.g.,Entry-Exit) +#define TRACE_LEVEL_VERBOSE 5 // Detailed traces from intermediate steps +#define TRACE_LEVEL_RESERVED6 6 +#define TRACE_LEVEL_RESERVED7 7 +#define TRACE_LEVEL_RESERVED8 8 +#define TRACE_LEVEL_RESERVED9 9 +#endif // TRACE_LEVEL_INFORMATION + +#define QXL_LOG_ASSERTION0(Msg) NT_ASSERT(FALSE) +#define QXL_LOG_ASSERTION1(Msg,Param1) NT_ASSERT(FALSE) +#define QXL_LOG_ASSERTION2(Msg,Param1,Param2) NT_ASSERT(FALSE) +#define QXL_LOG_ASSERTION3(Msg,Param1,Param2,Param3) NT_ASSERT(FALSE) +#define QXL_LOG_ASSERTION4(Msg,Param1,Param2,Param3,Param4) NT_ASSERT(FALSE) +#define QXL_LOG_ASSERTION5(Msg,Param1,Param2,Param3,Param4,Param5) NT_ASSERT(FALSE) +#define QXL_ASSERT(exp) {if (!(exp)) {QXL_LOG_ASSERTION0(#exp);}} + + +#if DBG +#define QXL_ASSERT_CHK(exp) QXL_ASSERT(exp) +#else +#define QXL_ASSERT_CHK(exp) {} +#endif diff --git a/qxldod/qxldod.inf b/qxldod/qxldod.inf new file mode 100755 index 0000000000000000000000000000000000000000..28080d41826e7e53cb81e7d842bf63bb47a33e07 GIT binary patch literal 4142 zcmd^?T~8ZV5QgWrmHHo6R>?&RE|8>O$QOW3Y6UyQCXfay%fW`Cf=z4_l2-leZJ+my zm))~o)2dRhs@1M{&zX<+%)B$__|HGK>`SiC>{HvCKND-&*amiMS2nc7+Sa#g-o7tL zCCnxE(mo(p4;odww2_?`Jfq?40piZl@VE6SObqe$TNv!NYTWPnaDto`6Ky zglmB0)NUB<+ef~~$XtcDm-gEBgTw@x_d!3u!Zlk97&UfcM`3=7q%8atX1aV`@YM(J zE#Bp?#$B<`?U=a{-p6)_f5qpJ(Mr(U4QQr}*N90TpL}Jr&+L^ok*L{k_5@px?Q48| z$MajT4f)=*r@U=&o$L}`MD74q4( zJ${9u&U_jZU%A#L8((4NDbG#5+}xogBG!_~sW2xRB{iuKN-$$W)bPHOY) ztOgzl)c_Vei7Y95?m4Z|Pi&iLEAn?lWM)6JdR0W0TaAtx6GxID*=K&p?Uj{3dBpl>fiVZLylJOcZ?K{s+1d&0euQ>| z(OzJXc=U)YykfR%KXOY_To%8!S?^*5s)Y#se$f52HCQ#}?LAyo z-Fb)JgAG}K>msjys|wzu6UoOeBR6n64nmeaA`Jrp}`sA!hv)8dP!GUM7K=Cvm4JIlA#-LI=U6s(;)swRN*dfJ@!w1w|VaK zRp-4Ksd?LCvgn-TW(r3|TKEaDQX z4qc^#ttP#v9o`%FsPd8D37im0?euO>`@jmF=3TVkcrQ-l8Z#%}k(0pHKCzpHEGMi; zaXiD`I$|WsON`{93UgFHz>yBD)sBBe<@G}bwLkg} z{gx~a!>m_e`Evyu4e}_C9fw@j$&a5R(tN~N^S#57Je12=w}&sC?8LKuR(ugyI4;J59Zy@*HeDZ^S)7m zonm!=eqvvSs|~IZ*8eR&*)4YB9jf95{W9M>9hL7QWjcO3It-n+TyG;pzvye5v(+Kq z%60q%UDR3D-!qJlOMTUeeixSR5UmFB&E&IFT+!F^T`AKpU)i#KBh&M9c+q2C&-WVb zW&1g_fA3E=b+T1`X8y{fnfJGgMw5JKPmXjZ|7HDFRSLFeCo#|^A|t#Uv2;Z literal 0 HcmV?d00001 diff --git a/qxldod/qxldod.rc b/qxldod/qxldod.rc new file mode 100755 index 0000000000000000000000000000000000000000..ba45879d3826f3f9a4e42ef21fc91848ad3ee788 GIT binary patch literal 696 zcma))%TB^T6o$VwiSN*qeHW~a2{M&5DFtaMam4~8ng|uV^76_*GhhstY9`Y;oy>nZ zm+!A8k1Uz;#2Yj23Ap6L-OZ>Jy%6!h6&EzzKJ|XdEAPUtc|Lk=Ip>bga+kymnQ%iw zs<_~efzIHMRSHoEXM`?yKI)lsMqK}c-!r#|gSxwCmUU1iQ^VU$5mN8S?Q z3Vr)zV$2l}e`OYOtCi|zEEPjfk0YSdNC)-!Q(3Xlsx+a|Zo+&X ETWDiqhyVZp literal 0 HcmV?d00001 diff --git a/qxldod/qxldod.vcxproj b/qxldod/qxldod.vcxproj new file mode 100755 index 0000000..38cd91a --- /dev/null +++ b/qxldod/qxldod.vcxproj @@ -0,0 +1,288 @@ + + + + + Win8 Debug + Win32 + + + Win8 Release + Win32 + + + Win7 Debug + Win32 + + + Win7 Release + Win32 + + + Vista Debug + Win32 + + + Vista Release + Win32 + + + Win8 Debug + x64 + + + Win8 Release + x64 + + + Win7 Debug + x64 + + + Win7 Release + x64 + + + Vista Debug + x64 + + + Vista Release + x64 + + + + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD} + {dd38f7fc-d7bd-488b-9242-7d8754cde80d} + v4.5 + 11.0 + Win8 Debug + Win32 + + + qxldod + $(VCTargetsPath11) + + + WindowsKernelModeDriver8.0 + Driver + WDM + + + + Windows8 + true + + + Windows8 + false + + + Windows7 + true + + + Windows7 + false + + + Vista + true + + + Vista + false + + + Windows8 + true + + + Windows8 + false + + + Windows7 + true + + + Windows7 + false + + + Vista + true + + + Vista + false + + + + + + + + + + + DbgengKernelDebugger + + + + ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + Level3 + + + + + + ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + + + ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + + + ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + + + ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + + + ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + + + ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + + + ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + + + ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + + + ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + + + ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/qxldod/qxldod.vcxproj.filters b/qxldod/qxldod.vcxproj.filters new file mode 100755 index 0000000..db5df31 --- /dev/null +++ b/qxldod/qxldod.vcxproj.filters @@ -0,0 +1,56 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {8E41214B-6785-4CFE-B992-037D68949A14} + inf;inv;inx;mof;mc; + + + + + Driver Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/qxldod/resource.h b/qxldod/resource.h new file mode 100755 index 0000000..4c0462f --- /dev/null +++ b/qxldod/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by qxldod.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif From 51da605b0d54b6e7d3e11f59dfd02956dde8bfe0 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 30 Dec 2013 22:59:42 +1100 Subject: [PATCH 03/46] add build tools --- qxldod/buildAll.bat | 31 +++++++++++++++++++++++++++++++ qxldod/callVisualStudio.bat | 28 ++++++++++++++++++++++++++++ qxldod/checkWin8Tools.bat | 16 ++++++++++++++++ qxldod/clean.bat | 12 ++++++++++++ qxldod/getVisualStudioCmdLine.vbs | 28 ++++++++++++++++++++++++++++ 5 files changed, 115 insertions(+) create mode 100755 qxldod/buildAll.bat create mode 100755 qxldod/callVisualStudio.bat create mode 100755 qxldod/checkWin8Tools.bat create mode 100755 qxldod/clean.bat create mode 100755 qxldod/getVisualStudioCmdLine.vbs diff --git a/qxldod/buildAll.bat b/qxldod/buildAll.bat new file mode 100755 index 0000000..eed3b82 --- /dev/null +++ b/qxldod/buildAll.bat @@ -0,0 +1,31 @@ +@echo off + +call clean.bat + +rem WIN8_64 +setlocal +if exist Install\win8\amd64 rmdir Install\win8\amd64 /s /q +call callVisualStudio.bat 11 qxldod.vcxproj /Rebuild "Win8 Release|x64" /Out buildfre_win8_amd64.log +mkdir .\Install\Win8\x64 +del /Q .\Install\Win8\x64\* +copy /Y objfre_win8_amd64\amd64\qxldod.sys .\Install\Win8\x64 +copy /Y objfre_win8_amd64\amd64\qxldod.inf .\Install\Win8\x64 +copy /Y objfre_win8_amd64\amd64\qxldod.cat .\Install\Win8\x64 +copy /Y objfre_win8_amd64\amd64\qxldod.pdb .\Install\Win8\x64 +endlocal +if %ERRORLEVEL% NEQ 0 goto :eof + +rem WIN8_32 +setlocal +if exist Install\win8\x86 rmdir Install\win8\x86 /s /q +call callVisualStudio.bat 11 qxldod.vcxproj /Rebuild "Win8 Release|Win32" /Out buildfre_win8_x86.log +mkdir .\Install\Win8\x86 +del /Q .\Install\Win8\x86\* +copy /Y objfre_win8_x86\i386\qxldod.sys .\Install\Win8\x86 +copy /Y objfre_win8_x86\i386\qxldod.inf .\Install\Win8\x86 +copy /Y objfre_win8_x86\i386\qxldod.cat .\Install\Win8\x86 +copy /Y objfre_win8_x86\i386\qxldod.pdb .\Install\Win8\x86 +endlocal +if %ERRORLEVEL% NEQ 0 goto :eof + +:eof diff --git a/qxldod/callVisualStudio.bat b/qxldod/callVisualStudio.bat new file mode 100755 index 0000000..769752d --- /dev/null +++ b/qxldod/callVisualStudio.bat @@ -0,0 +1,28 @@ +@echo off + +call %~dp0\checkWin8Tools.bat + +for /f "tokens=*" %%a in ( +'cscript.exe /nologo "%~dp0\getVisualStudioCmdLine.vbs" %*' +) do ( +set vs_cmd=%%a +) + +IF NOT DEFINED vs_cmd ( +echo Visual Studio not found +EXIT /b 1 +) + +SET vs_cmd_no_quotes="%vs_cmd:"=%" +IF "vs_cmd_no_quotes" == "" ( +echo Visual Studio not found +EXIT /b 2 +) + +call %vs_cmd% +if %ERRORLEVEL% GEQ 1 ( +echo Build with Visual Studio FAILED +exit /b %ERRORLEVEL% +) + +exit /b 0 diff --git a/qxldod/checkWin8Tools.bat b/qxldod/checkWin8Tools.bat new file mode 100755 index 0000000..c95d30b --- /dev/null +++ b/qxldod/checkWin8Tools.bat @@ -0,0 +1,16 @@ +@echo off + +reg query "HKLM\Software\Microsoft\Windows Kits\WDK" /v WDKProductVersion >nul 2>nul +if %ERRORLEVEL% EQU 0 goto checkVS11 +reg query "HKLM\Software\Wow6432Node\Microsoft\Windows Kits\WDK" /v WDKProductVersion > nul 2>nul +if %ERRORLEVEL% EQU 0 goto checkVS11 +echo ERROR building Win8 drivers: Win8 WDK is not installed +exit /b 1 + +:checkVS11 +reg query HKLM\Software\Microsoft\VisualStudio\11.0 /v InstallDir > nul 2>nul +if %ERRORLEVEL% EQU 0 exit /b 0 +reg query HKLM\Software\Wow6432Node\Microsoft\VisualStudio\11.0 /v InstallDir > nul 2>nul +if %ERRORLEVEL% EQU 0 exit /b 0 +echo ERROR building Win8 drivers: VS11 is not installed +exit /b 2 \ No newline at end of file diff --git a/qxldod/clean.bat b/qxldod/clean.bat new file mode 100755 index 0000000..83da6de --- /dev/null +++ b/qxldod/clean.bat @@ -0,0 +1,12 @@ +@echo on + +rmdir /S /Q .\Install + +rmdir /S /Q objfre_win8_x86 +rmdir /S /Q objfre_win8_amd64 +rmdir /S /Q objchk_win8_x86 +rmdir /S /Q objchk_win8_amd64 + +del /F *.log *.wrn *.err + + diff --git a/qxldod/getVisualStudioCmdLine.vbs b/qxldod/getVisualStudioCmdLine.vbs new file mode 100755 index 0000000..07939d0 --- /dev/null +++ b/qxldod/getVisualStudioCmdLine.vbs @@ -0,0 +1,28 @@ +' $1 - Visual studio version to run (10 or 11) +' $2 ... Parameters to pass + +Dim strCmdLine, strTemp +Set WshShell = Wscript.CreateObject("Wscript.Shell") + +On Error Resume Next +strCmdLine = WshShell.RegRead("HKLM\SOFTWARE\Microsoft\VisualStudio\" + Wscript.Arguments(0) + ".0\InstallDir") +' In case of error assume WoW64 case +If Err <> 0 Then + On Error Goto 0 + strCmdLine = WshShell.RegRead("HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\" + Wscript.Arguments(0) + ".0\InstallDir") +End If + +On Error Goto 0 +strCmdLine = chr(34) + strCmdLine + "devenv.com" + chr(34) +For i = 0 to (Wscript.Arguments.Count - 1) + If i > 0 Then + strTemp = Wscript.Arguments(i) + If InStr(strTemp, " ") Or InStr(strTemp, "|") Then + strCmdLine = strCmdLine + " " + chr(34) + strTemp + chr(34) + Else + strCmdLine = strCmdLine + " " + strTemp + End If + End If +Next + +WScript.Echo strCmdLine + vbCrLf From ebf6eafdec3168764a39344577b6e2119512620e Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 30 Dec 2013 23:01:24 +1100 Subject: [PATCH 04/46] fix VS project file --- qxldod/qxldod.vcxproj | 191 ++++++++---------------------------------- 1 file changed, 35 insertions(+), 156 deletions(-) diff --git a/qxldod/qxldod.vcxproj b/qxldod/qxldod.vcxproj index 38cd91a..0bc2638 100755 --- a/qxldod/qxldod.vcxproj +++ b/qxldod/qxldod.vcxproj @@ -9,22 +9,6 @@ Win8 Release Win32 - - Win7 Debug - Win32 - - - Win7 Release - Win32 - - - Vista Debug - Win32 - - - Vista Release - Win32 - Win8 Debug x64 @@ -33,22 +17,6 @@ Win8 Release x64 - - Win7 Debug - x64 - - - Win7 Release - x64 - - - Vista Debug - x64 - - - Vista Release - x64 - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD} @@ -76,22 +44,6 @@ Windows8 false - - Windows7 - true - - - Windows7 - false - - - Vista - true - - - Vista - false - Windows8 true @@ -100,22 +52,6 @@ Windows8 false - - Windows7 - true - - - Windows7 - false - - - Vista - true - - - Vista - false - @@ -123,21 +59,29 @@ - + + objchk_win8_x86\i386\ + objchk_win8_x86\i386\ + qxldod + DbgengKernelDebugger - - - ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - + + objfre_win8_x86\i386\ + objfre_win8_x86\i386\ + qxldod + + + objfre_win8_amd64\amd64\ + objfre_win8_amd64\amd64\ + qxldod + + + objchk_win8_amd64\amd64\ + objchk_win8_amd64\amd64\ + qxldod + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib @@ -150,54 +94,13 @@ Level3 - - - - ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - - - ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - - - ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - + + Inf2Cat /driver:$(OutDir) /os:8_X86 + - ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - - - ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) @@ -205,43 +108,13 @@ %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + Inf2Cat /driver:$(OutDir) /os:8_X86 + - ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - - - ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - - - ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - - - - - ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) @@ -249,10 +122,13 @@ %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + Inf2Cat /driver:$(OutDir) /os:8_X64 + - ;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) @@ -260,6 +136,9 @@ %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + Inf2Cat /driver:$(OutDir) /os:8_X64 + From 52500420a892ac10f0f187fdf7c612df69cdee49 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 30 Dec 2013 23:01:57 +1100 Subject: [PATCH 05/46] fix inf file --- qxldod/qxldod.inf | Bin 4142 -> 4140 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/qxldod/qxldod.inf b/qxldod/qxldod.inf index 28080d41826e7e53cb81e7d842bf63bb47a33e07..af324eaab23226c8d7100ce947e568a478b878f6 100755 GIT binary patch delta 16 YcmZ3duts5n4fEtVOdOltm|yS!05gvTvj6}9 delta 20 acmZ3Zuufrv4KsTw{IVFn8T From 10be00160db5ec6205b00b46f45a8e36d00ff6ec Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 30 Dec 2013 23:02:44 +1100 Subject: [PATCH 06/46] add resolutions and PM support --- qxldod/QxlDod.cpp | 1907 +++++++++++++++++++++++++++++++++++++++++---- qxldod/QxlDod.h | 206 ++++- qxldod/driver.cpp | 66 +- 3 files changed, 1979 insertions(+), 200 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 9717c7d..5c7fd0a 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -1,6 +1,50 @@ #include "driver.h" #include "qxldod.h" +#pragma code_seg(push) +#pragma code_seg() +// BEGIN: Non-Paged Code + +// Bit is 1 from Idx to end of byte, with bit count starting at high order +BYTE lMaskTable[BITS_PER_BYTE] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; + +// Bit is 1 from Idx to start of byte, with bit count starting at high order +BYTE rMaskTable[BITS_PER_BYTE] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; + +// Bit of Idx is 1, with bit count starting at high order +BYTE PixelMask[BITS_PER_BYTE] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; + + +// For the following macros, pPixel must be a BYTE* pointing to the start of a 32 bit pixel +#define CONVERT_32BPP_TO_16BPP(pPixel) ((UPPER_5_BITS(pPixel[2]) << SHIFT_FOR_UPPER_5_IN_565) | \ + (UPPER_6_BITS(pPixel[1]) << SHIFT_FOR_MIDDLE_6_IN_565) | \ + (UPPER_5_BITS(pPixel[0]))) + +// 8bpp is done with 6 levels per color channel since this gives true grays, even if it leaves 40 empty palette entries +// The 6 levels per color is the reason for dividing below by 43 (43 * 6 == 258, closest multiple of 6 to 256) +// It is also the reason for multiplying the red channel by 36 (== 6*6) and the green channel by 6, as this is the +// equivalent to bit shifting in a 3:3:2 model. Changes to this must be reflected in vesasup.cxx with the Blues/Greens/Reds arrays +#define CONVERT_32BPP_TO_8BPP(pPixel) (((pPixel[2] / 43) * 36) + \ + ((pPixel[1] / 43) * 6) + \ + ((pPixel[0] / 43))) + +// 4bpp is done with strict grayscale since this has been found to be usable +// 30% of the red value, 59% of the green value, and 11% of the blue value is the standard way to convert true color to grayscale +#define CONVERT_32BPP_TO_4BPP(pPixel) ((BYTE)(((pPixel[2] * 30) + \ + (pPixel[1] * 59) + \ + (pPixel[0] * 11)) / (100 * 16))) + + +// For the following macro, Pixel must be a WORD representing a 16 bit pixel +#define CONVERT_16BPP_TO_32BPP(Pixel) (((ULONG)LOWER_5_BITS((Pixel) >> SHIFT_FOR_UPPER_5_IN_565) << SHIFT_UPPER_5_IN_565_BACK) | \ + ((ULONG)LOWER_6_BITS((Pixel) >> SHIFT_FOR_MIDDLE_6_IN_565) << SHIFT_MIDDLE_6_IN_565_BACK) | \ + ((ULONG)LOWER_5_BITS((Pixel)) << SHIFT_LOWER_5_IN_565_BACK)) + + +#pragma code_seg(pop) + + + QxlDod::QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pPhysicalDeviceObject), m_MonitorPowerState(PowerDeviceD0), m_AdapterPowerState(PowerDeviceD0) @@ -9,7 +53,8 @@ QxlDod::QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pP *((UINT*)&m_Flags) = 0; RtlZeroMemory(&m_DxgkInterface, sizeof(m_DxgkInterface)); RtlZeroMemory(&m_DeviceInfo, sizeof(m_DeviceInfo)); - + RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes)); + RtlZeroMemory(&m_PointerShape, sizeof(m_PointerShape)); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -19,7 +64,7 @@ QxlDod::~QxlDod(void) PAGED_CODE(); DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); -// CleanUp(); + CleanUp(); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -37,8 +82,9 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, QXL_ASSERT(pNumberOfChildren != NULL); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); - DXGK_DISPLAY_INFORMATION DisplayInfo; RtlCopyMemory(&m_DxgkInterface, pDxgkInterface, sizeof(m_DxgkInterface)); + RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes)); + m_CurrentModes[0].DispInfo.TargetId = D3DDDI_ID_UNINITIALIZED; // Get device information from OS. NTSTATUS Status = m_DxgkInterface.DxgkCbGetDeviceInformation(m_DxgkInterface.DeviceHandle, &m_DeviceInfo); if (!NT_SUCCESS(Status)) @@ -72,11 +118,10 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, return Status; } - // This sample driver only uses the frame buffer of the POST device. DxgkCbAcquirePostDisplayOwnership // gives you the frame buffer address and ensures that no one else is drawing to it. Be sure to give it back! - Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &DisplayInfo); - if (!NT_SUCCESS(Status) || DisplayInfo.Width == 0) + Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &(m_CurrentModes[0].DispInfo)); + if (!NT_SUCCESS(Status) || m_CurrentModes[0].DispInfo.Width == 0) { // The most likely cause of failure is that the driver is simply not running on a POST device, or we are running // after a pre-WDDM 1.2 driver. Since we can't draw anything, we should fail to start. @@ -85,16 +130,15 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, *pNumberOfViews = MAX_VIEWS; *pNumberOfChildren = MAX_CHILDREN; m_Flags.DriverStarted = TRUE; - return STATUS_SUCCESS; + return STATUS_SUCCESS; } NTSTATUS QxlDod::StopDevice(VOID) { PAGED_CODE(); DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); - - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); m_Flags.DriverStarted = FALSE; + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -102,7 +146,15 @@ VOID QxlDod::CleanUp(VOID) { PAGED_CODE(); DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + for (UINT Source = 0; Source < MAX_VIEWS; ++Source) + { + if (m_CurrentModes[Source].FrameBuffer.Ptr) + { + UnmapFrameBuffer(m_CurrentModes[Source].FrameBuffer.Ptr, m_CurrentModes[Source].DispInfo.Height * m_CurrentModes[Source].DispInfo.Pitch); + m_CurrentModes[Source].FrameBuffer.Ptr = NULL; + m_CurrentModes[Source].Flags.FrameBufferIsActive = FALSE; + } + } } @@ -117,17 +169,67 @@ NTSTATUS QxlDod::DispatchIoRequest(_In_ ULONG VidPnSourceId, return STATUS_SUCCESS; } +PCHAR +DbgDevicePowerString( + __in DEVICE_POWER_STATE Type + ) +{ + switch (Type) + { + case PowerDeviceUnspecified: + return "PowerDeviceUnspecified"; + case PowerDeviceD0: + return "PowerDeviceD0"; + case PowerDeviceD1: + return "PowerDeviceD1"; + case PowerDeviceD2: + return "PowerDeviceD2"; + case PowerDeviceD3: + return "PowerDeviceD3"; + case PowerDeviceMaximum: + return "PowerDeviceMaximum"; + default: + return "UnKnown Device Power State"; + } +} + +PCHAR +DbgPowerActionString( + __in POWER_ACTION Type + ) +{ + switch (Type) + { + case PowerActionNone: + return "PowerActionNone"; + case PowerActionReserved: + return "PowerActionReserved"; + case PowerActionSleep: + return "PowerActionSleep"; + case PowerActionHibernate: + return "PowerActionHibernate"; + case PowerActionShutdown: + return "PowerActionShutdown"; + case PowerActionShutdownReset: + return "PowerActionShutdownReset"; + case PowerActionShutdownOff: + return "PowerActionShutdownOff"; + case PowerActionWarmEject: + return "PowerActionWarmEject"; + default: + return "UnKnown Device Power State"; + } +} + NTSTATUS QxlDod::SetPowerState(_In_ ULONG HardwareUid, _In_ DEVICE_POWER_STATE DevicePowerState, _In_ POWER_ACTION ActionType) { - NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE(); - DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s HardwareUid = 0x%x ActionType = %s DevicePowerState = %s AdapterPowerState = %s\n", __FUNCTION__, HardwareUid, DbgPowerActionString(ActionType), DbgDevicePowerString(DevicePowerState), DbgDevicePowerString(m_AdapterPowerState))); if (HardwareUid == DISPLAY_ADAPTER_HW_ID) { - if (DevicePowerState == PowerDeviceD0) { @@ -141,30 +243,17 @@ NTSTATUS QxlDod::SetPowerState(_In_ ULONG HardwareUid, } } - // Store new adapter power state m_AdapterPowerState = DevicePowerState; - } - if ((ActionType == PowerActionHibernate) && - (DevicePowerState > PowerDeviceD0)) - { - ActionType = PowerActionHibernate; + // There is nothing to do to specifically power up/down the display adapter + return STATUS_SUCCESS; } - else if ((ActionType >= PowerActionShutdown) && - (ActionType < PowerActionWarmEject) && - (DevicePowerState > PowerDeviceD0)) - { - ActionType = PowerActionShutdown; - } - - Status = VbeSetPowerState(ActionType); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); - - return Status; + // TODO: This is where the specified monitor should be powered up/down + VbeSetPowerState(ActionType); + return STATUS_SUCCESS; } - NTSTATUS QxlDod::QueryChildRelations(_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations, _In_ ULONG ChildRelationsSize) { @@ -263,6 +352,12 @@ NTSTATUS QxlDod::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAda pDriverCaps->WDDMVersion = DXGKDDI_WDDMv1_2; pDriverCaps->HighestAcceptableAddress.QuadPart = -1; +/* + pDriverCaps->MaxPointerWidth = 64; + pDriverCaps->MaxPointerHeight = 64; + pDriverCaps->PointerCaps.Monochrome = 1; + pDriverCaps->PointerCaps.Color = 1; +*/ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s 1\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -289,7 +384,6 @@ NTSTATUS QxlDod::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetP DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s Cursor is not visible\n", __FUNCTION__)); return STATUS_SUCCESS; } - DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s cursor position X = %d, Y = %d\n", __FUNCTION__, pSetPointerPosition->X, pSetPointerPosition->Y)); return STATUS_UNSUCCESSFUL; } @@ -300,20 +394,9 @@ NTSTATUS QxlDod::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointer PAGED_CODE(); QXL_ASSERT(pSetPointerShape != NULL); - DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s Height = %d, Width = %d, XHot= %d, YHot = %d\n", __FUNCTION__, pSetPointerShape->Height, pSetPointerShape->Width, pSetPointerShape->XHot, pSetPointerShape->YHot)); - - if (pSetPointerShape->Flags.Color) - { - } - else if (pSetPointerShape->Flags.Monochrome) - { - } - else - { - return STATUS_UNSUCCESSFUL; - } - - return STATUS_NOT_IMPLEMENTED; + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s Height = %d, Width = %d, XHot= %d, YHot = %d SourceId = %d\n", + __FUNCTION__, pSetPointerShape->Height, pSetPointerShape->Width, pSetPointerShape->XHot, pSetPointerShape->YHot, pSetPointerShape->VidPnSourceId)); + return STATUS_NOT_SUPPORTED; } NTSTATUS QxlDod::Escape(_In_ CONST DXGKARG_ESCAPE* pEscape) @@ -330,13 +413,61 @@ NTSTATUS QxlDod::Escape(_In_ CONST DXGKARG_ESCAPE* pEscape) NTSTATUS QxlDod::PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly) { PAGED_CODE(); - + NTSTATUS Status = STATUS_SUCCESS; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); QXL_ASSERT(pPresentDisplayOnly != NULL); QXL_ASSERT(pPresentDisplayOnly->VidPnSourceId < MAX_VIEWS); + if (pPresentDisplayOnly->BytesPerPixel < 4) + { + // Only >=32bpp modes are reported, therefore this Present should never pass anything less than 4 bytes per pixel + DbgPrint(TRACE_LEVEL_ERROR, ("pPresentDisplayOnly->BytesPerPixel is 0x%d, which is lower than the allowed.\n", pPresentDisplayOnly->BytesPerPixel)); + return STATUS_INVALID_PARAMETER; + } + + // If it is in monitor off state or source is not supposed to be visible, don't present anything to the screen + if ((m_MonitorPowerState > PowerDeviceD0) || + (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Flags.SourceNotVisible)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; + } + + if (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Flags.FrameBufferIsActive) + { + + // If actual pixels are coming through, will need to completely zero out physical address next time in BlackOutScreen + m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].ZeroedOutStart.QuadPart = 0; + m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].ZeroedOutEnd.QuadPart = 0; + + + D3DKMDT_VIDPN_PRESENT_PATH_ROTATION RotationNeededByFb = pPresentDisplayOnly->Flags.Rotate ? + m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Rotation : + D3DKMDT_VPPR_IDENTITY; + BYTE* pDst = (BYTE*)m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].FrameBuffer.Ptr; + UINT DstBitPerPixel = BPPFromPixelFormat(m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].DispInfo.ColorFormat); + if (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Scaling == D3DKMDT_VPPS_CENTERED) + { + UINT CenterShift = (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].DispInfo.Height - + m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].SrcModeHeight)*m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].DispInfo.Pitch; + CenterShift += (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].DispInfo.Width - + m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].SrcModeWidth)*DstBitPerPixel/8; + pDst += (int)CenterShift/2; + } + Status = ExecutePresentDisplayOnly( + pDst, + DstBitPerPixel, + (BYTE*)pPresentDisplayOnly->pSource, + pPresentDisplayOnly->BytesPerPixel, + pPresentDisplayOnly->Pitch, + pPresentDisplayOnly->NumMoves, + pPresentDisplayOnly->pMoves, + pPresentDisplayOnly->NumDirtyRects, + pPresentDisplayOnly->pDirtyRect, + RotationNeededByFb); + } DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); - return STATUS_SUCCESS; + return Status; } NTSTATUS QxlDod::QueryInterface(_In_ CONST PQUERY_INTERFACE pQueryInterface) @@ -356,11 +487,73 @@ NTSTATUS QxlDod::StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRE UNREFERENCED_PARAMETER(pDisplayInfo); QXL_ASSERT(TargetId < MAX_CHILDREN); + D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId = FindSourceForTarget(TargetId, TRUE); + + // In case BDD is the next driver to run, the monitor should not be off, since + // this could cause the BIOS to hang when the EDID is retrieved on Start. + if (m_MonitorPowerState > PowerDeviceD0) + { + SetPowerState(TargetId, PowerDeviceD0, PowerActionNone); + } + + // The driver has to black out the display and ensure it is visible when releasing ownership + BlackOutScreen(SourceId); + + *pDisplayInfo = m_CurrentModes[SourceId].DispInfo; - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); return StopDevice(); } +VOID QxlDod::BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId) +{ + PAGED_CODE(); + + UINT ScreenHeight = m_CurrentModes[SourceId].DispInfo.Height; + UINT ScreenPitch = m_CurrentModes[SourceId].DispInfo.Pitch; + + PHYSICAL_ADDRESS NewPhysAddrStart = m_CurrentModes[SourceId].DispInfo.PhysicAddress; + PHYSICAL_ADDRESS NewPhysAddrEnd; + NewPhysAddrEnd.QuadPart = NewPhysAddrStart.QuadPart + (ScreenHeight * ScreenPitch); + + if (m_CurrentModes[SourceId].Flags.FrameBufferIsActive) + { + BYTE* MappedAddr = reinterpret_cast(m_CurrentModes[SourceId].FrameBuffer.Ptr); + + // Zero any memory at the start that hasn't been zeroed recently + if (NewPhysAddrStart.QuadPart < m_CurrentModes[SourceId].ZeroedOutStart.QuadPart) + { + if (NewPhysAddrEnd.QuadPart < m_CurrentModes[SourceId].ZeroedOutStart.QuadPart) + { + // No overlap + RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch); + } + else + { + RtlZeroMemory(MappedAddr, (UINT)(m_CurrentModes[SourceId].ZeroedOutStart.QuadPart - NewPhysAddrStart.QuadPart)); + } + } + + // Zero any memory at the end that hasn't been zeroed recently + if (NewPhysAddrEnd.QuadPart > m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart) + { + if (NewPhysAddrStart.QuadPart > m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart) + { + // No overlap + // NOTE: When actual pixels were the most recent thing drawn, ZeroedOutStart & ZeroedOutEnd will both be 0 + // and this is the path that will be used to black out the current screen. + RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch); + } + else + { + RtlZeroMemory(MappedAddr, (UINT)(NewPhysAddrEnd.QuadPart - m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart)); + } + } + } + + m_CurrentModes[SourceId].ZeroedOutStart.QuadPart = NewPhysAddrStart.QuadPart; + m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart = NewPhysAddrEnd.QuadPart; +} + NTSTATUS QxlDod::QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps) { PAGED_CODE(); @@ -466,25 +659,145 @@ NTSTATUS QxlDod::RecommendVidPnTopology(_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOG } NTSTATUS QxlDod::RecommendMonitorModes(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + return AddSingleMonitorMode(pRecommendMonitorModes); +} + + +NTSTATUS QxlDod::AddSingleSourceMode(_In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface, + D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet, + D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + UNREFERENCED_PARAMETER(SourceId); + + // There is only one source format supported by display-only drivers, but more can be added in a + // full WDDM driver if the hardware supports them + for (ULONG idx = 0; idx < m_ModeCount; ++idx) + { + // Create new mode info that will be populated + D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo = NULL; + NTSTATUS Status = pVidPnSourceModeSetInterface->pfnCreateNewModeInfo(hVidPnSourceModeSet, &pVidPnSourceModeInfo); + if (!NT_SUCCESS(Status)) + { + // If failed to create a new mode info, mode doesn't need to be released since it was never created + DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewModeInfo failed with Status = 0x%X, hVidPnSourceModeSet = 0x%I64x", Status, hVidPnSourceModeSet)); + return Status; + } + + // Populate mode info with values from current mode and hard-coded values + // Always report 32 bpp format, this will be color converted during the present if the mode is < 32bpp + pVidPnSourceModeInfo->Type = D3DKMDT_RMT_GRAPHICS; + pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx = m_ModeInfo[idx].XResolution; + pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy = m_ModeInfo[idx].YResolution; + pVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize; + pVidPnSourceModeInfo->Format.Graphics.Stride = m_ModeInfo[idx].BytesPerScanLine / m_ModeInfo[idx].XResolution; + pVidPnSourceModeInfo->Format.Graphics.PixelFormat = D3DDDIFMT_A8R8G8B8; + pVidPnSourceModeInfo->Format.Graphics.ColorBasis = D3DKMDT_CB_SCRGB; + pVidPnSourceModeInfo->Format.Graphics.PixelValueAccessMode = D3DKMDT_PVAM_DIRECT; + + // Add the mode to the source mode set + Status = pVidPnSourceModeSetInterface->pfnAddMode(hVidPnSourceModeSet, pVidPnSourceModeInfo); + if (!NT_SUCCESS(Status)) + { + // If adding the mode failed, release the mode, if this doesn't work there is nothing that can be done, some memory will get leaked + NTSTATUS TempStatus = pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hVidPnSourceModeSet, pVidPnSourceModeInfo); + UNREFERENCED_PARAMETER(TempStatus); + NT_ASSERT(NT_SUCCESS(TempStatus)); + + if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%X, hVidPnSourceModeSet = 0x%I64x, pVidPnSourceModeInfo = 0x%I64x", Status, hVidPnSourceModeSet, pVidPnSourceModeInfo)); + return Status; + } + } + } + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + +// Add the current mode information (acquired from the POST frame buffer) as the target mode. +NTSTATUS QxlDod::AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface, + D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet, + _In_opt_ CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnPinnedSourceModeInfo, + D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + UNREFERENCED_PARAMETER(pVidPnPinnedSourceModeInfo); + + D3DKMDT_VIDPN_TARGET_MODE* pVidPnTargetModeInfo = NULL; + NTSTATUS Status = STATUS_SUCCESS; + + for (UINT ModeIndex = 0; ModeIndex < m_ModeCount; ++ModeIndex) + { + pVidPnTargetModeInfo = NULL; + Status = pVidPnTargetModeSetInterface->pfnCreateNewModeInfo(hVidPnTargetModeSet, &pVidPnTargetModeInfo); + if (!NT_SUCCESS(Status)) + { + // If failed to create a new mode info, mode doesn't need to be released since it was never created + DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewModeInfo failed with Status = 0x%I64x, hVidPnTargetModeSet = 0x%I64x", Status, hVidPnTargetModeSet)); + return Status; + } + pVidPnTargetModeInfo->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER; + pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cx = m_ModeInfo[SourceId].XResolution; + pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cy = m_ModeInfo[SourceId].YResolution; + pVidPnTargetModeInfo->VideoSignalInfo.ActiveSize = pVidPnTargetModeInfo->VideoSignalInfo.TotalSize; + pVidPnTargetModeInfo->VideoSignalInfo.VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pVidPnTargetModeInfo->VideoSignalInfo.VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pVidPnTargetModeInfo->VideoSignalInfo.HSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pVidPnTargetModeInfo->VideoSignalInfo.HSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pVidPnTargetModeInfo->VideoSignalInfo.PixelRate = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pVidPnTargetModeInfo->VideoSignalInfo.ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE; + // We add this as PREFERRED since it is the only supported target + pVidPnTargetModeInfo->Preference = D3DKMDT_MP_NOTPREFERRED; // TODO: another logic for prefferred mode. Maybe the pinned source mode + + Status = pVidPnTargetModeSetInterface->pfnAddMode(hVidPnTargetModeSet, pVidPnTargetModeInfo); + if (!NT_SUCCESS(Status)) + { + if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%I64x, hVidPnTargetModeSet = 0x%I64x, pVidPnTargetModeInfo = 0x%I64x", Status, hVidPnTargetModeSet, pVidPnTargetModeInfo)); + } + + // If adding the mode failed, release the mode, if this doesn't work there is nothing that can be done, some memory will get leaked + Status = pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pVidPnTargetModeInfo); + NT_ASSERT(NT_SUCCESS(Status)); + } + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + + +NTSTATUS QxlDod::AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes) { PAGED_CODE(); NTSTATUS Status = STATUS_SUCCESS; D3DKMDT_MONITOR_SOURCE_MODE* pMonitorSourceMode = NULL; PVBE_MODEINFO pVbeModeInfo = NULL; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); Status = pRecommendMonitorModes->pMonitorSourceModeSetInterface->pfnCreateNewModeInfo(pRecommendMonitorModes->hMonitorSourceModeSet, &pMonitorSourceMode); if (!NT_SUCCESS(Status)) { // If failed to create a new mode info, mode doesn't need to be released since it was never created - DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewModeInfo failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x", Status, pRecommendMonitorModes->hMonitorSourceModeSet)); + DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewModeInfo failed with Status = 0x%X, hMonitorSourceModeSet = 0x%I64x", Status, pRecommendMonitorModes->hMonitorSourceModeSet)); return Status; } pVbeModeInfo = &m_ModeInfo[m_CurrentMode]; + + // Since we don't know the real monitor timing information, just use the current display mode (from the POST device) with unknown frequencies pMonitorSourceMode->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER; - pMonitorSourceMode->VideoSignalInfo.TotalSize.cx = pVbeModeInfo->XResolution;//m_CurrentModes[CorrespondingSourceId].DispInfo.Width; - pMonitorSourceMode->VideoSignalInfo.TotalSize.cy = pVbeModeInfo->YResolution;//m_CurrentModes[CorrespondingSourceId].DispInfo.Height; + pMonitorSourceMode->VideoSignalInfo.TotalSize.cx = pVbeModeInfo->XResolution; + pMonitorSourceMode->VideoSignalInfo.TotalSize.cy = pVbeModeInfo->YResolution; pMonitorSourceMode->VideoSignalInfo.ActiveSize = pMonitorSourceMode->VideoSignalInfo.TotalSize; pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED; pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED; @@ -507,7 +820,7 @@ NTSTATUS QxlDod::RecommendMonitorModes(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* { if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET) { - DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x, pMonitorSourceMode = 0x%I64x", + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%X, hMonitorSourceModeSet = 0x%I64x, pMonitorSourceMode = 0x%I64x", Status, pRecommendMonitorModes->hMonitorSourceModeSet, pMonitorSourceMode)); } else @@ -522,7 +835,62 @@ NTSTATUS QxlDod::RecommendMonitorModes(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* return Status; } // If AddMode succeeded with something other than STATUS_SUCCESS treat it as such anyway when propagating up - return STATUS_SUCCESS; + for (UINT Idx = 0; Idx < m_ModeCount; ++Idx) + { + // There is only one source format supported by display-only drivers, but more can be added in a + // full WDDM driver if the hardware supports them + + pVbeModeInfo = &m_ModeInfo[Idx]; + // TODO: add routine for filling Monitor modepMonitorSourceMode = NULL; + Status = pRecommendMonitorModes->pMonitorSourceModeSetInterface->pfnCreateNewModeInfo(pRecommendMonitorModes->hMonitorSourceModeSet, &pMonitorSourceMode); + if (!NT_SUCCESS(Status)) + { + // If failed to create a new mode info, mode doesn't need to be released since it was never created + DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewModeInfo failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x", Status, pRecommendMonitorModes->hMonitorSourceModeSet)); + return Status; + } + + + DbgPrint(TRACE_LEVEL_INFORMATION, ("%s: add pref mode, dimensions %ux%u, taken from DxgkCbAcquirePostDisplayOwnership at StartDevice\n", __FUNCTION__, + pVbeModeInfo->XResolution, pVbeModeInfo->YResolution)); + + // Since we don't know the real monitor timing information, just use the current display mode (from the POST device) with unknown frequencies + pMonitorSourceMode->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER; + pMonitorSourceMode->VideoSignalInfo.TotalSize.cx = pVbeModeInfo->XResolution; + pMonitorSourceMode->VideoSignalInfo.TotalSize.cy = pVbeModeInfo->YResolution; + pMonitorSourceMode->VideoSignalInfo.ActiveSize = pMonitorSourceMode->VideoSignalInfo.TotalSize; + pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pMonitorSourceMode->VideoSignalInfo.HSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pMonitorSourceMode->VideoSignalInfo.HSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pMonitorSourceMode->VideoSignalInfo.PixelRate = D3DKMDT_FREQUENCY_NOTSPECIFIED; + pMonitorSourceMode->VideoSignalInfo.ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE; //??? + + pMonitorSourceMode->Origin = D3DKMDT_MCO_DRIVER; // ???? + pMonitorSourceMode->Preference = D3DKMDT_MP_NOTPREFERRED; // TODO... + pMonitorSourceMode->ColorBasis = D3DKMDT_CB_SRGB; // ???? + pMonitorSourceMode->ColorCoeffDynamicRanges.FirstChannel = 8; + pMonitorSourceMode->ColorCoeffDynamicRanges.SecondChannel = 8; + pMonitorSourceMode->ColorCoeffDynamicRanges.ThirdChannel = 8; + pMonitorSourceMode->ColorCoeffDynamicRanges.FourthChannel = 8; + + Status = pRecommendMonitorModes->pMonitorSourceModeSetInterface->pfnAddMode(pRecommendMonitorModes->hMonitorSourceModeSet, pMonitorSourceMode); + if (!NT_SUCCESS(Status)) + { + if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x, pMonitorSourceMode = 0x%I64x", + Status, pRecommendMonitorModes->hMonitorSourceModeSet, pMonitorSourceMode)); + } + + // If adding the mode failed, release the mode, if this doesn't work there is nothing that can be done, some memory will get leaked + Status = pRecommendMonitorModes->pMonitorSourceModeSetInterface->pfnReleaseModeInfo(pRecommendMonitorModes->hMonitorSourceModeSet, pMonitorSourceMode); + NT_ASSERT(NT_SUCCESS(Status)); + } + } + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return Status; } // Tell DMM about all the modes, etc. that are supported @@ -531,7 +899,7 @@ NTSTATUS QxlDod::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODAL PAGED_CODE(); QXL_ASSERT(pEnumCofuncModality != NULL); - DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology = 0; D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet = 0; @@ -572,10 +940,261 @@ NTSTATUS QxlDod::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODAL // Loop through all available paths. while (Status != STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET) { + // Get the Source Mode Set interface so the pinned mode can be retrieved + Status = pVidPnInterface->pfnAcquireSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, + pVidPnPresentPath->VidPnSourceId, + &hVidPnSourceModeSet, + &pVidPnSourceModeSetInterface); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAcquireSourceModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%I64x, SourceId = 0x%I64x", + Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnSourceId)); + break; + } -//FIXME - - pVidPnPresentPathTemp = NULL; // Successfully released it + // Get the pinned mode, needed when VidPnSource isn't pivot, and when VidPnTarget isn't pivot + Status = pVidPnSourceModeSetInterface->pfnAcquirePinnedModeInfo(hVidPnSourceModeSet, &pVidPnPinnedSourceModeInfo); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAcquirePinnedModeInfo failed with Status = 0x%X, hVidPnSourceModeSet = 0x%I64x", Status, hVidPnSourceModeSet)); + break; + } + + // SOURCE MODES: If this source mode isn't the pivot point, do work on the source mode set + if (!((pEnumCofuncModality->EnumPivotType == D3DKMDT_EPT_VIDPNSOURCE) && + (pEnumCofuncModality->EnumPivot.VidPnSourceId == pVidPnPresentPath->VidPnSourceId))) + { + // If there's no pinned source add possible modes (otherwise they've already been added) + if (pVidPnPinnedSourceModeInfo == NULL) + { + // Release the acquired source mode set, since going to create a new one to put all modes in + Status = pVidPnInterface->pfnReleaseSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnSourceModeSet); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleaseSourceModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%I64x, hVidPnSourceModeSet = 0x%I64x", + Status, pEnumCofuncModality->hConstrainingVidPn, hVidPnSourceModeSet)); + break; + } + hVidPnSourceModeSet = 0; // Successfully released it + + // Create a new source mode set which will be added to the constraining VidPn with all the possible modes + Status = pVidPnInterface->pfnCreateNewSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, + pVidPnPresentPath->VidPnSourceId, + &hVidPnSourceModeSet, + &pVidPnSourceModeSetInterface); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewSourceModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%I64x, SourceId = 0x%I64x", + Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnSourceId)); + break; + } + + // Add the appropriate modes to the source mode set + { + Status = AddSingleSourceMode(pVidPnSourceModeSetInterface, hVidPnSourceModeSet, pVidPnPresentPath->VidPnSourceId); + } + + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("AddSingleSourceMode failed with Status = 0x%X, hFunctionalVidPn = 0x%I64x", Status, pEnumCofuncModality->hConstrainingVidPn)); + break; + } + + // Give DMM back the source modes just populated + Status = pVidPnInterface->pfnAssignSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnSourceId, hVidPnSourceModeSet); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAssignSourceModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%I64x, SourceId = 0x%I64x, hVidPnSourceModeSet = 0x%I64x", + Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnSourceId, hVidPnSourceModeSet)); + break; + } + hVidPnSourceModeSet = 0; // Successfully assigned it (equivalent to releasing it) + } + }// End: SOURCE MODES + + // TARGET MODES: If this target mode isn't the pivot point, do work on the target mode set + if (!((pEnumCofuncModality->EnumPivotType == D3DKMDT_EPT_VIDPNTARGET) && + (pEnumCofuncModality->EnumPivot.VidPnTargetId == pVidPnPresentPath->VidPnTargetId))) + { + // Get the Target Mode Set interface so modes can be added if necessary + Status = pVidPnInterface->pfnAcquireTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, + pVidPnPresentPath->VidPnTargetId, + &hVidPnTargetModeSet, + &pVidPnTargetModeSetInterface); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAcquireTargetModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%I64x, TargetId = 0x%I64x", + Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnTargetId)); + break; + } + + Status = pVidPnTargetModeSetInterface->pfnAcquirePinnedModeInfo(hVidPnTargetModeSet, &pVidPnPinnedTargetModeInfo); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAcquirePinnedModeInfo failed with Status = 0x%X, hVidPnTargetModeSet = 0x%I64x", Status, hVidPnTargetModeSet)); + break; + } + + // If there's no pinned target add possible modes (otherwise they've already been added) + if (pVidPnPinnedTargetModeInfo == NULL) + { + // Release the acquired target mode set, since going to create a new one to put all modes in + Status = pVidPnInterface->pfnReleaseTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnTargetModeSet); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleaseTargetModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%I64x, hVidPnTargetModeSet = 0x%I64x", + Status, pEnumCofuncModality->hConstrainingVidPn, hVidPnTargetModeSet)); + break; + } + hVidPnTargetModeSet = 0; // Successfully released it + + // Create a new target mode set which will be added to the constraining VidPn with all the possible modes + Status = pVidPnInterface->pfnCreateNewTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, + pVidPnPresentPath->VidPnTargetId, + &hVidPnTargetModeSet, + &pVidPnTargetModeSetInterface); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewTargetModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%I64x, TargetId = 0x%I64x", + Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnTargetId)); + break; + } + + Status = AddSingleTargetMode(pVidPnTargetModeSetInterface, hVidPnTargetModeSet, pVidPnPinnedSourceModeInfo, pVidPnPresentPath->VidPnSourceId); + + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("AddSingleTargetMode failed with Status = 0x%X, hFunctionalVidPn = 0x%I64x", Status, pEnumCofuncModality->hConstrainingVidPn)); + break; + } + + // Give DMM back the source modes just populated + Status = pVidPnInterface->pfnAssignTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnTargetId, hVidPnTargetModeSet); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAssignTargetModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%I64x, TargetId = 0x%I64x, hVidPnTargetModeSet = 0x%I64x", + Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnTargetId, hVidPnTargetModeSet)); + break; + } + hVidPnTargetModeSet = 0; // Successfully assigned it (equivalent to releasing it) + } + else + { + // Release the pinned target as there's no other work to do + Status = pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pVidPnPinnedTargetModeInfo); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleaseModeInfo failed with Status = 0x%X, hVidPnTargetModeSet = 0x%I64x, pVidPnPinnedTargetModeInfo = 0x%I64x", + Status, hVidPnTargetModeSet, pVidPnPinnedTargetModeInfo)); + break; + } + pVidPnPinnedTargetModeInfo = NULL; // Successfully released it + + // Release the acquired target mode set, since it is no longer needed + Status = pVidPnInterface->pfnReleaseTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnTargetModeSet); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleaseTargetModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%I64x, hVidPnTargetModeSet = 0x%I64x", + Status, pEnumCofuncModality->hConstrainingVidPn, hVidPnTargetModeSet)); + break; + } + hVidPnTargetModeSet = 0; // Successfully released it + } + }// End: TARGET MODES + + // Nothing else needs the pinned source mode so release it + if (pVidPnPinnedSourceModeInfo != NULL) + { + Status = pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hVidPnSourceModeSet, pVidPnPinnedSourceModeInfo); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleaseModeInfo failed with Status = 0x%X, hVidPnSourceModeSet = 0x%I64x, pVidPnPinnedSourceModeInfo = 0x%I64x", + Status, hVidPnSourceModeSet, pVidPnPinnedSourceModeInfo)); + break; + } + pVidPnPinnedSourceModeInfo = NULL; // Successfully released it + } + + // With the pinned source mode now released, if the source mode set hasn't been released, release that as well + if (hVidPnSourceModeSet != 0) + { + Status = pVidPnInterface->pfnReleaseSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnSourceModeSet); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleaseSourceModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%I64x, hVidPnSourceModeSet = 0x%I64x", + Status, pEnumCofuncModality->hConstrainingVidPn, hVidPnSourceModeSet)); + break; + } + hVidPnSourceModeSet = 0; // Successfully released it + } + + // If modifying support fields, need to modify a local version of a path structure since the retrieved one is const + D3DKMDT_VIDPN_PRESENT_PATH LocalVidPnPresentPath = *pVidPnPresentPath; + BOOLEAN SupportFieldsModified = FALSE; + + // SCALING: If this path's scaling isn't the pivot point, do work on the scaling support + if (!((pEnumCofuncModality->EnumPivotType == D3DKMDT_EPT_SCALING) && + (pEnumCofuncModality->EnumPivot.VidPnSourceId == pVidPnPresentPath->VidPnSourceId) && + (pEnumCofuncModality->EnumPivot.VidPnTargetId == pVidPnPresentPath->VidPnTargetId))) + { + // If the scaling is unpinned, then modify the scaling support field + if (pVidPnPresentPath->ContentTransformation.Scaling == D3DKMDT_VPPS_UNPINNED) + { + // Identity and centered scaling are supported, but not any stretch modes + RtlZeroMemory(&(LocalVidPnPresentPath.ContentTransformation.ScalingSupport), sizeof(D3DKMDT_VIDPN_PRESENT_PATH_SCALING_SUPPORT)); + LocalVidPnPresentPath.ContentTransformation.ScalingSupport.Identity = 1; + LocalVidPnPresentPath.ContentTransformation.ScalingSupport.Centered = 1; + SupportFieldsModified = TRUE; + } + } // End: SCALING + + // ROTATION: If this path's rotation isn't the pivot point, do work on the rotation support + if (!((pEnumCofuncModality->EnumPivotType != D3DKMDT_EPT_ROTATION) && + (pEnumCofuncModality->EnumPivot.VidPnSourceId == pVidPnPresentPath->VidPnSourceId) && + (pEnumCofuncModality->EnumPivot.VidPnTargetId == pVidPnPresentPath->VidPnTargetId))) + { + // If the rotation is unpinned, then modify the rotation support field + if (pVidPnPresentPath->ContentTransformation.Rotation == D3DKMDT_VPPR_UNPINNED) + { + LocalVidPnPresentPath.ContentTransformation.RotationSupport.Identity = 1; + // Sample supports only Rotate90 + LocalVidPnPresentPath.ContentTransformation.RotationSupport.Rotate90 = 1; + LocalVidPnPresentPath.ContentTransformation.RotationSupport.Rotate180 = 0; + LocalVidPnPresentPath.ContentTransformation.RotationSupport.Rotate270 = 0; + SupportFieldsModified = TRUE; + } + } // End: ROTATION + + if (SupportFieldsModified) + { + // The correct path will be found by this function and the appropriate fields updated + Status = pVidPnTopologyInterface->pfnUpdatePathSupportInfo(hVidPnTopology, &LocalVidPnPresentPath); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnUpdatePathSupportInfo failed with Status = 0x%X, hVidPnTopology = 0x%I64x", Status, hVidPnTopology)); + break; + } + } + + // Get the next path... + // (NOTE: This is the value of Status that will return STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET when it's time to quit the loop) + pVidPnPresentPathTemp = pVidPnPresentPath; + Status = pVidPnTopologyInterface->pfnAcquireNextPathInfo(hVidPnTopology, pVidPnPresentPathTemp, &pVidPnPresentPath); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAcquireNextPathInfo failed with Status = 0x%X, hVidPnTopology = 0x%I64x, pVidPnPresentPathTemp = 0x%I64x", Status, hVidPnTopology, pVidPnPresentPathTemp)); + break; + } + + // ...and release the last path + NTSTATUS TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPathTemp); + if (!NT_SUCCESS(TempStatus)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleasePathInfo failed with Status = 0x%X, hVidPnTopology = 0x%I64x, pVidPnPresentPathTemp = 0x%I64x", TempStatus, hVidPnTopology, pVidPnPresentPathTemp)); + Status = TempStatus; + break; + } + pVidPnPresentPathTemp = NULL; // Successfully released it }// End: while loop for paths in topology // If quit the while loop normally, set the return value to success @@ -629,14 +1248,14 @@ NTSTATUS QxlDod::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODAL QXL_ASSERT_CHK(TempStatus == STATUS_NOT_FOUND || Status != STATUS_SUCCESS); - DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return Status; } NTSTATUS QxlDod::SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility) { PAGED_CODE(); - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); +// DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); QXL_ASSERT(pSetVidPnSourceVisibility != NULL); QXL_ASSERT((pSetVidPnSourceVisibility->VidPnSourceId < MAX_VIEWS) || (pSetVidPnSourceVisibility->VidPnSourceId == D3DDDI_ID_ALL)); @@ -648,18 +1267,18 @@ NTSTATUS QxlDod::SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIB { if (pSetVidPnSourceVisibility->Visible) { -// m_CurrentModes[SourceId].Flags.FullscreenPresent = TRUE; + m_CurrentModes[SourceId].Flags.FullscreenPresent = TRUE; } else { -// BlackOutScreen(SourceId); + BlackOutScreen(SourceId); } // Store current visibility so it can be dealt with during Present call -// m_CurrentModes[SourceId].Flags.SourceNotVisible = !(pSetVidPnSourceVisibility->Visible); + m_CurrentModes[SourceId].Flags.SourceNotVisible = !(pSetVidPnSourceVisibility->Visible); } - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); +// DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -672,21 +1291,339 @@ NTSTATUS QxlDod::CommitVidPn(_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn) QXL_ASSERT(pCommitVidPn != NULL); QXL_ASSERT(pCommitVidPn->AffectedVidPnSourceId < MAX_VIEWS); - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status; + SIZE_T NumPaths = 0; + D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology = 0; + D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet = 0; + CONST DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL; + CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface = NULL; + CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface = NULL; + CONST D3DKMDT_VIDPN_PRESENT_PATH* pVidPnPresentPath = NULL; + CONST D3DKMDT_VIDPN_SOURCE_MODE* pPinnedVidPnSourceModeInfo = NULL; + // Check this CommitVidPn is for the mode change notification when monitor is in power off state. + if (pCommitVidPn->Flags.PathPoweredOff) + { + // Ignore the commitVidPn call for the mode change notification when monitor is in power off state. + Status = STATUS_SUCCESS; + goto CommitVidPnExit; + } -//FIXME + // Get the VidPn Interface so we can get the 'Source Mode Set' and 'VidPn Topology' interfaces + Status = m_DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPn->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbQueryVidPnInterface failed with Status = 0x%X, hFunctionalVidPn = 0x%I64x", Status, pCommitVidPn->hFunctionalVidPn)); + goto CommitVidPnExit; + } + // Get the VidPn Topology interface so can enumerate paths from source + Status = pVidPnInterface->pfnGetTopology(pCommitVidPn->hFunctionalVidPn, &hVidPnTopology, &pVidPnTopologyInterface); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnGetTopology failed with Status = 0x%X, hFunctionalVidPn = 0x%I64x", Status, pCommitVidPn->hFunctionalVidPn)); + goto CommitVidPnExit; + } + + // Find out the number of paths now, if it's 0 don't bother with source mode set and pinned mode, just clear current and then quit + Status = pVidPnTopologyInterface->pfnGetNumPaths(hVidPnTopology, &NumPaths); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnGetNumPaths failed with Status = 0x%X, hVidPnTopology = 0x%I64x", Status, hVidPnTopology)); + goto CommitVidPnExit; + } + + if (NumPaths != 0) + { + // Get the Source Mode Set interface so we can get the pinned mode + Status = pVidPnInterface->pfnAcquireSourceModeSet(pCommitVidPn->hFunctionalVidPn, + pCommitVidPn->AffectedVidPnSourceId, + &hVidPnSourceModeSet, + &pVidPnSourceModeSetInterface); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAcquireSourceModeSet failed with Status = 0x%X, hFunctionalVidPn = 0x%I64x, SourceId = 0x%I64x", Status, pCommitVidPn->hFunctionalVidPn, pCommitVidPn->AffectedVidPnSourceId)); + goto CommitVidPnExit; + } + + // Get the mode that is being pinned + Status = pVidPnSourceModeSetInterface->pfnAcquirePinnedModeInfo(hVidPnSourceModeSet, &pPinnedVidPnSourceModeInfo); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAcquirePinnedModeInfo failed with Status = 0x%X, hFunctionalVidPn = 0x%I64x", Status, pCommitVidPn->hFunctionalVidPn)); + goto CommitVidPnExit; + } + } + else + { + // This will cause the successful quit below + pPinnedVidPnSourceModeInfo = NULL; + } + + if (m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].FrameBuffer.Ptr && + !m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].Flags.DoNotMapOrUnmap) + { + Status = UnmapFrameBuffer(m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].FrameBuffer.Ptr, + m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].DispInfo.Pitch * m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].DispInfo.Height); + m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].FrameBuffer.Ptr = NULL; + m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].Flags.FrameBufferIsActive = FALSE; + + if (!NT_SUCCESS(Status)) + { + goto CommitVidPnExit; + } + } + + if (pPinnedVidPnSourceModeInfo == NULL) + { + // There is no mode to pin on this source, any old paths here have already been cleared + Status = STATUS_SUCCESS; + goto CommitVidPnExit; + } + + Status = IsVidPnSourceModeFieldsValid(pPinnedVidPnSourceModeInfo); + if (!NT_SUCCESS(Status)) + { + goto CommitVidPnExit; + } + + // Get the number of paths from this source so we can loop through all paths + SIZE_T NumPathsFromSource = 0; + Status = pVidPnTopologyInterface->pfnGetNumPathsFromSource(hVidPnTopology, pCommitVidPn->AffectedVidPnSourceId, &NumPathsFromSource); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnGetNumPathsFromSource failed with Status = 0x%X, hVidPnTopology = 0x%I64x", Status, hVidPnTopology)); + goto CommitVidPnExit; + } + + // Loop through all paths to set this mode + for (SIZE_T PathIndex = 0; PathIndex < NumPathsFromSource; ++PathIndex) + { + // Get the target id for this path + D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId = D3DDDI_ID_UNINITIALIZED; + Status = pVidPnTopologyInterface->pfnEnumPathTargetsFromSource(hVidPnTopology, pCommitVidPn->AffectedVidPnSourceId, PathIndex, &TargetId); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnEnumPathTargetsFromSource failed with Status = 0x%X, hVidPnTopology = 0x%I64x, SourceId = 0x%I64x, PathIndex = 0x%I64x", + Status, hVidPnTopology, pCommitVidPn->AffectedVidPnSourceId, PathIndex)); + goto CommitVidPnExit; + } + + // Get the actual path info + Status = pVidPnTopologyInterface->pfnAcquirePathInfo(hVidPnTopology, pCommitVidPn->AffectedVidPnSourceId, TargetId, &pVidPnPresentPath); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAcquirePathInfo failed with Status = 0x%X, hVidPnTopology = 0x%I64x, SourceId = 0x%I64x, TargetId = 0x%I64x", + Status, hVidPnTopology, pCommitVidPn->AffectedVidPnSourceId, TargetId)); + goto CommitVidPnExit; + } + + Status = IsVidPnPathFieldsValid(pVidPnPresentPath); + if (!NT_SUCCESS(Status)) + { + goto CommitVidPnExit; + } + + Status = SetSourceModeAndPath(pPinnedVidPnSourceModeInfo, pVidPnPresentPath); + if (!NT_SUCCESS(Status)) + { + goto CommitVidPnExit; + } + + Status = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPath); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleasePathInfo failed with Status = 0x%X, hVidPnTopoogy = 0x%I64x, pVidPnPresentPath = 0x%I64x", + Status, hVidPnTopology, pVidPnPresentPath)); + goto CommitVidPnExit; + } + pVidPnPresentPath = NULL; // Successfully released it + } + +CommitVidPnExit: + + NTSTATUS TempStatus; + UNREFERENCED_PARAMETER(TempStatus); + + if ((pVidPnSourceModeSetInterface != NULL) && + (hVidPnSourceModeSet != 0) && + (pPinnedVidPnSourceModeInfo != NULL)) + { + TempStatus = pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hVidPnSourceModeSet, pPinnedVidPnSourceModeInfo); + NT_ASSERT(NT_SUCCESS(TempStatus)); + } + + if ((pVidPnInterface != NULL) && + (pCommitVidPn->hFunctionalVidPn != 0) && + (hVidPnSourceModeSet != 0)) + { + TempStatus = pVidPnInterface->pfnReleaseSourceModeSet(pCommitVidPn->hFunctionalVidPn, hVidPnSourceModeSet); + NT_ASSERT(NT_SUCCESS(TempStatus)); + } + + if ((pVidPnTopologyInterface != NULL) && + (hVidPnTopology != 0) && + (pVidPnPresentPath != NULL)) + { + TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPath); + NT_ASSERT(NT_SUCCESS(TempStatus)); + } DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return Status; } +NTSTATUS QxlDod::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode, + CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + NTSTATUS Status = STATUS_SUCCESS; + + CURRENT_BDD_MODE* pCurrentBddMode = &m_CurrentModes[pPath->VidPnSourceId]; + + pCurrentBddMode->Scaling = pPath->ContentTransformation.Scaling; + pCurrentBddMode->SrcModeWidth = pSourceMode->Format.Graphics.VisibleRegionSize.cx; + pCurrentBddMode->SrcModeHeight = pSourceMode->Format.Graphics.VisibleRegionSize.cy; + pCurrentBddMode->Rotation = pPath->ContentTransformation.Rotation; + + pCurrentBddMode->DispInfo.Width = pSourceMode->Format.Graphics.PrimSurfSize.cx; + pCurrentBddMode->DispInfo.Height = pSourceMode->Format.Graphics.PrimSurfSize.cy; + pCurrentBddMode->DispInfo.Pitch = pSourceMode->Format.Graphics.PrimSurfSize.cx * BPPFromPixelFormat(pCurrentBddMode->DispInfo.ColorFormat) / BITS_PER_BYTE; + + + if (!pCurrentBddMode->Flags.DoNotMapOrUnmap) + { + // Map the new frame buffer + QXL_ASSERT(pCurrentBddMode->FrameBuffer.Ptr == NULL); + Status = MapFrameBuffer(pCurrentBddMode->DispInfo.PhysicAddress, + pCurrentBddMode->DispInfo.Pitch * pCurrentBddMode->DispInfo.Height, + &(pCurrentBddMode->FrameBuffer.Ptr)); + } + + if (NT_SUCCESS(Status)) + { + + pCurrentBddMode->Flags.FrameBufferIsActive = TRUE; + BlackOutScreen(pPath->VidPnSourceId); + + // Mark that the next present should be fullscreen so the screen doesn't go from black to actual pixels one dirty rect at a time. + pCurrentBddMode->Flags.FullscreenPresent = TRUE; + for (USHORT ModeIndex = 0; ModeIndex < m_ModeCount; ++ModeIndex) + { + if (pCurrentBddMode->DispInfo.Width == m_ModeInfo[ModeIndex].XResolution && + pCurrentBddMode->DispInfo.Height == m_ModeInfo[ModeIndex].YResolution ) + { + Status = VbeSetCurrentMode(m_ModeNumbers[ModeIndex]); + if (NT_SUCCESS(Status)) + { + m_CurrentMode = ModeIndex; + } + break; + } + } + } + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return Status; +} + +NTSTATUS QxlDod::IsVidPnPathFieldsValid(CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) const +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + if (pPath->VidPnSourceId >= MAX_VIEWS) + { + DbgPrint(TRACE_LEVEL_ERROR, ("VidPnSourceId is 0x%I64x is too high (MAX_VIEWS is 0x%I64x)", + pPath->VidPnSourceId, MAX_VIEWS)); + return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE; + } + else if (pPath->VidPnTargetId >= MAX_CHILDREN) + { + DbgPrint(TRACE_LEVEL_ERROR, ("VidPnTargetId is 0x%I64x is too high (MAX_CHILDREN is 0x%I64x)", + pPath->VidPnTargetId, MAX_CHILDREN)); + return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET; + } + else if (pPath->GammaRamp.Type != D3DDDI_GAMMARAMP_DEFAULT) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pPath contains a gamma ramp (0x%I64x)", pPath->GammaRamp.Type)); + return STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED; + } + else if ((pPath->ContentTransformation.Scaling != D3DKMDT_VPPS_IDENTITY) && + (pPath->ContentTransformation.Scaling != D3DKMDT_VPPS_CENTERED) && + (pPath->ContentTransformation.Scaling != D3DKMDT_VPPS_NOTSPECIFIED) && + (pPath->ContentTransformation.Scaling != D3DKMDT_VPPS_UNINITIALIZED)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pPath contains a non-identity scaling (0x%I64x)", pPath->ContentTransformation.Scaling)); + return STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED; + } + else if ((pPath->ContentTransformation.Rotation != D3DKMDT_VPPR_IDENTITY) && + (pPath->ContentTransformation.Rotation != D3DKMDT_VPPR_ROTATE90) && + (pPath->ContentTransformation.Rotation != D3DKMDT_VPPR_NOTSPECIFIED) && + (pPath->ContentTransformation.Rotation != D3DKMDT_VPPR_UNINITIALIZED)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pPath contains a not-supported rotation (0x%I64x)", pPath->ContentTransformation.Rotation)); + return STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED; + } + else if ((pPath->VidPnTargetColorBasis != D3DKMDT_CB_SCRGB) && + (pPath->VidPnTargetColorBasis != D3DKMDT_CB_UNINITIALIZED)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pPath has a non-linear RGB color basis (0x%I64x)", pPath->VidPnTargetColorBasis)); + return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE; + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + + +NTSTATUS QxlDod::IsVidPnSourceModeFieldsValid(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const +{ + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + if (pSourceMode->Type != D3DKMDT_RMT_GRAPHICS) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pSourceMode is a non-graphics mode (0x%I64x)", pSourceMode->Type)); + return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE; + } + else if ((pSourceMode->Format.Graphics.ColorBasis != D3DKMDT_CB_SCRGB) && + (pSourceMode->Format.Graphics.ColorBasis != D3DKMDT_CB_UNINITIALIZED)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pSourceMode has a non-linear RGB color basis (0x%I64x)", pSourceMode->Format.Graphics.ColorBasis)); + return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE; + } + else if (pSourceMode->Format.Graphics.PixelValueAccessMode != D3DKMDT_PVAM_DIRECT) + { + DbgPrint(TRACE_LEVEL_ERROR, ("pSourceMode has a palettized access mode (0x%I64x)", pSourceMode->Format.Graphics.PixelValueAccessMode)); + return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE; + } + else + { + if (pSourceMode->Format.Graphics.PixelFormat == D3DDDIFMT_A8R8G8B8) + { + return STATUS_SUCCESS; + } + } + DbgPrint(TRACE_LEVEL_ERROR, ("pSourceMode has an unknown pixel format (0x%I64x)", pSourceMode->Format.Graphics.PixelFormat)); + return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE; +} + NTSTATUS QxlDod::UpdateActiveVidPnPresentPath(_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath) { PAGED_CODE(); DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); QXL_ASSERT(pUpdateActiveVidPnPresentPath != NULL); + NTSTATUS Status = IsVidPnPathFieldsValid(&(pUpdateActiveVidPnPresentPath->VidPnPresentPathInfo)); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + // Mark the next present as fullscreen to make sure the full rotation comes through + m_CurrentModes[pUpdateActiveVidPnPresentPath->VidPnPresentPathInfo.VidPnSourceId].Flags.FullscreenPresent = TRUE; + + m_CurrentModes[pUpdateActiveVidPnPresentPath->VidPnPresentPathInfo.VidPnSourceId].Rotation = pUpdateActiveVidPnPresentPath->VidPnPresentPathInfo.ContentTransformation.Rotation; DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; @@ -729,11 +1666,51 @@ NTSTATUS QxlDod::SystemDisplayEnable(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID Target _Out_ D3DDDIFORMAT* pColorFormat) { UNREFERENCED_PARAMETER(Flags); - UNREFERENCED_PARAMETER(pColorFormat); - UNREFERENCED_PARAMETER(pWidth); - UNREFERENCED_PARAMETER(pHeight); + + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + m_SystemDisplaySourceId = D3DDDI_ID_UNINITIALIZED; + QXL_ASSERT((TargetId < MAX_CHILDREN) || (TargetId == D3DDDI_ID_UNINITIALIZED)); + // Find the frame buffer for displaying the bugcheck, if it was successfully mapped + if (TargetId == D3DDDI_ID_UNINITIALIZED) + { + for (UINT SourceIdx = 0; SourceIdx < MAX_VIEWS; ++SourceIdx) + { + if (m_CurrentModes[SourceIdx].FrameBuffer.Ptr != NULL) + { + m_SystemDisplaySourceId = SourceIdx; + break; + } + } + } + else + { + m_SystemDisplaySourceId = FindSourceForTarget(TargetId, FALSE); + } + + if (m_SystemDisplaySourceId == D3DDDI_ID_UNINITIALIZED) + { + { + return STATUS_UNSUCCESSFUL; + } + } + + if ((m_CurrentModes[m_SystemDisplaySourceId].Rotation == D3DKMDT_VPPR_ROTATE90) || + (m_CurrentModes[m_SystemDisplaySourceId].Rotation == D3DKMDT_VPPR_ROTATE270)) + { + *pHeight = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Width; + *pWidth = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Height; + } + else + { + *pWidth = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Width; + *pHeight = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Height; + } + + *pColorFormat = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.ColorFormat; + + return STATUS_SUCCESS; } @@ -754,12 +1731,38 @@ VOID QxlDod::SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VO Rect.right = Rect.left + SourceWidth; Rect.bottom = Rect.top + SourceHeight; + // Set up destination blt info + BLT_INFO DstBltInfo; + DstBltInfo.pBits = m_CurrentModes[m_SystemDisplaySourceId].FrameBuffer.Ptr; + DstBltInfo.Pitch = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Pitch; + DstBltInfo.BitsPerPel = BPPFromPixelFormat(m_CurrentModes[m_SystemDisplaySourceId].DispInfo.ColorFormat); + DstBltInfo.Offset.x = 0; + DstBltInfo.Offset.y = 0; + DstBltInfo.Rotation = m_CurrentModes[m_SystemDisplaySourceId].Rotation; + DstBltInfo.Width = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Width; + DstBltInfo.Height = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Height; + + // Set up source blt info + BLT_INFO SrcBltInfo; + SrcBltInfo.pBits = pSource; + SrcBltInfo.Pitch = SourceStride; + SrcBltInfo.BitsPerPel = 32; + + SrcBltInfo.Offset.x = -PositionX; + SrcBltInfo.Offset.y = -PositionY; + SrcBltInfo.Rotation = D3DKMDT_VPPR_IDENTITY; + SrcBltInfo.Width = SourceWidth; + SrcBltInfo.Height = SourceHeight; + + BltBits(&DstBltInfo, + &SrcBltInfo, + 1, // NumRects + &Rect); + } #pragma code_seg(pop) // End Non-Paged Code - - NTSTATUS QxlDod::WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue) { PAGED_CODE(); @@ -868,18 +1871,496 @@ NTSTATUS QxlDod::RegisterHWInfo() return Status; } + +NTSTATUS +QxlDod::ExecutePresentDisplayOnly( + _In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* Moves, + _In_ ULONG NumDirtyRects, + _In_ RECT* DirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation) +/*++ + + Routine Description: + + The method creates present worker thread and provides context + for it filled with present commands + + Arguments: + + DstAddr - address of destination surface + DstBitPerPixel - color depth of destination surface + SrcAddr - address of source surface + SrcBytesPerPixel - bytes per pixel of source surface + SrcPitch - source surface pitch (bytes in a row) + NumMoves - number of moves to be copied + Moves - moves' data + NumDirtyRects - number of rectangles to be copied + DirtyRect - rectangles' data + Rotation - roatation to be performed when executing copy + CallBack - callback for present worker thread to report execution status + + Return Value: + + Status + +--*/ +{ + + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + NTSTATUS Status = STATUS_SUCCESS; + + SIZE_T sizeMoves = NumMoves*sizeof(D3DKMT_MOVE_RECT); + SIZE_T sizeRects = NumDirtyRects*sizeof(RECT); + SIZE_T size = sizeof(DoPresentMemory) + sizeMoves + sizeRects; + + DoPresentMemory* ctx = reinterpret_cast + (new (NonPagedPoolNx) BYTE[size]); + + if (!ctx) + { + return STATUS_NO_MEMORY; + } + + RtlZeroMemory(ctx,size); + +// const CURRENT_BDD_MODE* pModeCur = GetCurrentMode(m_SourceId); + const CURRENT_BDD_MODE* pModeCur = &m_CurrentModes[0]; + ctx->DstAddr = DstAddr; + ctx->DstBitPerPixel = DstBitPerPixel; + ctx->DstStride = pModeCur->DispInfo.Pitch; //m_ModeInfo[m_CurrentMode].BytesPerScanLine;// + ctx->SrcWidth = pModeCur->SrcModeWidth;//m_ModeInfo[m_CurrentMode].XResolution;// + ctx->SrcHeight = pModeCur->SrcModeHeight;//m_ModeInfo[m_CurrentMode].YResolution;// + ctx->SrcAddr = NULL; + ctx->SrcPitch = SrcPitch; + ctx->Rotation = Rotation; + ctx->NumMoves = NumMoves; + ctx->Moves = Moves; + ctx->NumDirtyRects = NumDirtyRects; + ctx->DirtyRect = DirtyRect; +// ctx->SourceID = m_SourceId; +// ctx->hAdapter = m_DevExt; + ctx->Mdl = NULL; + ctx->DisplaySource = this; + + // Alternate between synch and asynch execution, for demonstrating + // that a real hardware implementation can do either + + { + // Map Source into kernel space, as Blt will be executed by system worker thread + UINT sizeToMap = SrcBytesPerPixel * ctx->SrcWidth * ctx->SrcHeight; + + PMDL mdl = IoAllocateMdl((PVOID)SrcAddr, sizeToMap, FALSE, FALSE, NULL); + if(!mdl) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + KPROCESSOR_MODE AccessMode = static_cast(( SrcAddr <= + (BYTE* const) MM_USER_PROBE_ADDRESS)?UserMode:KernelMode); + __try + { + // Probe and lock the pages of this buffer in physical memory. + // We need only IoReadAccess. + MmProbeAndLockPages(mdl, AccessMode, IoReadAccess); + } + #pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try/except is only able to protect against user-mode errors and these are the only errors we try to catch here"); + __except(EXCEPTION_EXECUTE_HANDLER) + { + Status = GetExceptionCode(); + IoFreeMdl(mdl); + return Status; + } + + // Map the physical pages described by the MDL into system space. + // Note: double mapping the buffer this way causes lot of system + // overhead for large size buffers. + ctx->SrcAddr = reinterpret_cast + (MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority )); + + if(!ctx->SrcAddr) { + Status = STATUS_INSUFFICIENT_RESOURCES; + MmUnlockPages(mdl); + IoFreeMdl(mdl); + return Status; + } + + // Save Mdl to unmap and unlock the pages in worker thread + ctx->Mdl = mdl; + } + + BYTE* rects = reinterpret_cast(ctx+1); + + // copy moves and update pointer + if (Moves) + { + memcpy(rects,Moves,sizeMoves); + ctx->Moves = reinterpret_cast(rects); + rects += sizeMoves; + } + + // copy dirty rects and update pointer + if (DirtyRect) + { + memcpy(rects,DirtyRect,sizeRects); + ctx->DirtyRect = reinterpret_cast(rects); + } + + +// HwExecutePresentDisplayOnly((PVOID)ctx); + + + // Set up destination blt info + BLT_INFO DstBltInfo; + DstBltInfo.pBits = ctx->DstAddr; + DstBltInfo.Pitch = ctx->DstStride; + DstBltInfo.BitsPerPel = ctx->DstBitPerPixel; + DstBltInfo.Offset.x = 0; + DstBltInfo.Offset.y = 0; + DstBltInfo.Rotation = ctx->Rotation; + DstBltInfo.Width = ctx->SrcWidth; + DstBltInfo.Height = ctx->SrcHeight; + + // Set up source blt info + BLT_INFO SrcBltInfo; + SrcBltInfo.pBits = ctx->SrcAddr; + SrcBltInfo.Pitch = ctx->SrcPitch; + SrcBltInfo.BitsPerPel = 32; + SrcBltInfo.Offset.x = 0; + SrcBltInfo.Offset.y = 0; + SrcBltInfo.Rotation = D3DKMDT_VPPR_IDENTITY; + if (ctx->Rotation == D3DKMDT_VPPR_ROTATE90 || + ctx->Rotation == D3DKMDT_VPPR_ROTATE270) + { + SrcBltInfo.Width = DstBltInfo.Height; + SrcBltInfo.Height = DstBltInfo.Width; + } + else + { + SrcBltInfo.Width = DstBltInfo.Width; + SrcBltInfo.Height = DstBltInfo.Height; + } + + + // Copy all the scroll rects from source image to video frame buffer. + for (UINT i = 0; i < ctx->NumMoves; i++) + { + BltBits(&DstBltInfo, + &SrcBltInfo, + 1, // NumRects + &ctx->Moves[i].DestRect); + } + + // Copy all the dirty rects from source image to video frame buffer. + for (UINT i = 0; i < ctx->NumDirtyRects; i++) + { + + BltBits(&DstBltInfo, + &SrcBltInfo, + 1, // NumRects + &ctx->DirtyRect[i]); + } + + // Unmap unmap and unlock the pages. + if (ctx->Mdl) + { + MmUnlockPages(ctx->Mdl); + IoFreeMdl(ctx->Mdl); + } + delete [] reinterpret_cast(ctx); + + return STATUS_SUCCESS; +} + + +VOID QxlDod::GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch) +{ + switch (pBltInfo->Rotation) + { + case D3DKMDT_VPPR_IDENTITY: + { + *pPixelPitch = (pBltInfo->BitsPerPel / BITS_PER_BYTE); + *pRowPitch = pBltInfo->Pitch; + return; + } + case D3DKMDT_VPPR_ROTATE90: + { + *pPixelPitch = -((LONG)pBltInfo->Pitch); + *pRowPitch = (pBltInfo->BitsPerPel / BITS_PER_BYTE); + return; + } + case D3DKMDT_VPPR_ROTATE180: + { + *pPixelPitch = -((LONG)pBltInfo->BitsPerPel / BITS_PER_BYTE); + *pRowPitch = -((LONG)pBltInfo->Pitch); + return; + } + case D3DKMDT_VPPR_ROTATE270: + { + *pPixelPitch = pBltInfo->Pitch; + *pRowPitch = -((LONG)pBltInfo->BitsPerPel / BITS_PER_BYTE); + return; + } + default: + { + QXL_LOG_ASSERTION1("Invalid rotation (0x%I64x) specified", pBltInfo->Rotation); + *pPixelPitch = 0; + *pRowPitch = 0; + return; + } + } +} + +BYTE* QxlDod::GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect) +{ + BYTE* pRet = NULL; + LONG OffLeft = pRect->left + pBltInfo->Offset.x; + LONG OffTop = pRect->top + pBltInfo->Offset.y; + LONG BytesPerPixel = (pBltInfo->BitsPerPel / BITS_PER_BYTE); + switch (pBltInfo->Rotation) + { + case D3DKMDT_VPPR_IDENTITY: + { + pRet = ((BYTE*)pBltInfo->pBits + + OffTop * pBltInfo->Pitch + + OffLeft * BytesPerPixel); + break; + } + case D3DKMDT_VPPR_ROTATE90: + { + pRet = ((BYTE*)pBltInfo->pBits + + (pBltInfo->Height - 1 - OffLeft) * pBltInfo->Pitch + + OffTop * BytesPerPixel); + break; + } + case D3DKMDT_VPPR_ROTATE180: + { + pRet = ((BYTE*)pBltInfo->pBits + + (pBltInfo->Height - 1 - OffTop) * pBltInfo->Pitch + + (pBltInfo->Width - 1 - OffLeft) * BytesPerPixel); + break; + } + case D3DKMDT_VPPR_ROTATE270: + { + pRet = ((BYTE*)pBltInfo->pBits + + OffLeft * pBltInfo->Pitch + + (pBltInfo->Width - 1 - OffTop) * BytesPerPixel); + break; + } + default: + { + QXL_LOG_ASSERTION1("Invalid rotation (0x%I64x) specified", pBltInfo->Rotation); + break; + } + } + + return pRet; +} + +/****************************Internal*Routine******************************\ + * CopyBitsGeneric + * + * + * Blt function which can handle a rotated dst/src, offset rects in dst/src + * and bpp combinations of: + * dst | src + * 32 | 32 // For identity rotation this is much faster in CopyBits32_32 + * 32 | 24 + * 32 | 16 + * 24 | 32 + * 16 | 32 + * 8 | 32 + * 24 | 24 // untested + * +\**************************************************************************/ + +VOID QxlDod::CopyBitsGeneric( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects) +{ + LONG DstPixelPitch = 0; + LONG DstRowPitch = 0; + LONG SrcPixelPitch = 0; + LONG SrcRowPitch = 0; + + DbgPrint(TRACE_LEVEL_VERBOSE , ("---> %s NumRects = %d Dst = %p Src = %p\n", __FUNCTION__, NumRects, pDst->pBits, pSrc->pBits)); + + GetPitches(pDst, &DstPixelPitch, &DstRowPitch); + GetPitches(pSrc, &SrcPixelPitch, &SrcRowPitch); + + for (UINT iRect = 0; iRect < NumRects; iRect++) + { + CONST RECT* pRect = &pRects[iRect]; + + NT_ASSERT(pRect->right >= pRect->left); + NT_ASSERT(pRect->bottom >= pRect->top); + + UINT NumPixels = pRect->right - pRect->left; + UINT NumRows = pRect->bottom - pRect->top; + + BYTE* pDstRow = GetRowStart(pDst, pRect); + CONST BYTE* pSrcRow = GetRowStart(pSrc, pRect); + + for (UINT y=0; y < NumRows; y++) + { + BYTE* pDstPixel = pDstRow; + CONST BYTE* pSrcPixel = pSrcRow; + + for (UINT x=0; x < NumPixels; x++) + { + if ((pDst->BitsPerPel == 24) || + (pSrc->BitsPerPel == 24)) + { + pDstPixel[0] = pSrcPixel[0]; + pDstPixel[1] = pSrcPixel[1]; + pDstPixel[2] = pSrcPixel[2]; + // pPixel[3] is the alpha channel and is ignored for whichever of Src/Dst is 32bpp + } + else if (pDst->BitsPerPel == 32) + { + if (pSrc->BitsPerPel == 32) + { + UINT32* pDstPixelAs32 = (UINT32*)pDstPixel; + UINT32* pSrcPixelAs32 = (UINT32*)pSrcPixel; + *pDstPixelAs32 = *pSrcPixelAs32; + } + else if (pSrc->BitsPerPel == 16) + { + UINT32* pDstPixelAs32 = (UINT32*)pDstPixel; + UINT16* pSrcPixelAs16 = (UINT16*)pSrcPixel; + + *pDstPixelAs32 = CONVERT_16BPP_TO_32BPP(*pSrcPixelAs16); + } + else + { + // Invalid pSrc->BitsPerPel on a pDst->BitsPerPel of 32 + NT_ASSERT(FALSE); + } + } + else if (pDst->BitsPerPel == 16) + { + NT_ASSERT(pSrc->BitsPerPel == 32); + + UINT16* pDstPixelAs16 = (UINT16*)pDstPixel; + *pDstPixelAs16 = CONVERT_32BPP_TO_16BPP(pSrcPixel); + } + else if (pDst->BitsPerPel == 8) + { + NT_ASSERT(pSrc->BitsPerPel == 32); + + *pDstPixel = CONVERT_32BPP_TO_8BPP(pSrcPixel); + } + else + { + // Invalid pDst->BitsPerPel + NT_ASSERT(FALSE); + } + pDstPixel += DstPixelPitch; + pSrcPixel += SrcPixelPitch; + } + + pDstRow += DstRowPitch; + pSrcRow += SrcRowPitch; + } + } +} + + +VOID QxlDod::CopyBits32_32( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects) +{ + NT_ASSERT((pDst->BitsPerPel == 32) && + (pSrc->BitsPerPel == 32)); + NT_ASSERT((pDst->Rotation == D3DKMDT_VPPR_IDENTITY) && + (pSrc->Rotation == D3DKMDT_VPPR_IDENTITY)); + + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + + for (UINT iRect = 0; iRect < NumRects; iRect++) + { + CONST RECT* pRect = &pRects[iRect]; + + NT_ASSERT(pRect->right >= pRect->left); + NT_ASSERT(pRect->bottom >= pRect->top); + + UINT NumPixels = pRect->right - pRect->left; + UINT NumRows = pRect->bottom - pRect->top; + UINT BytesToCopy = NumPixels * 4; + BYTE* pStartDst = ((BYTE*)pDst->pBits + + (pRect->top + pDst->Offset.y) * pDst->Pitch + + (pRect->left + pDst->Offset.x) * 4); + CONST BYTE* pStartSrc = ((BYTE*)pSrc->pBits + + (pRect->top + pSrc->Offset.y) * pSrc->Pitch + + (pRect->left + pSrc->Offset.x) * 4); + + for (UINT i = 0; i < NumRows; ++i) + { + RtlCopyMemory(pStartDst, pStartSrc, BytesToCopy); + pStartDst += pDst->Pitch; + pStartSrc += pSrc->Pitch; + } + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); +} + + +VOID QxlDod::BltBits ( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects) +{ + // pSrc->pBits might be coming from user-mode. User-mode addresses when accessed by kernel need to be protected by a __try/__except. + // This usage is redundant in the sample driver since it is already being used for MmProbeAndLockPages. However, it is very important + // to have this in place and to make sure developers don't miss it, it is in these two locations. + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + __try + { + if (pDst->BitsPerPel == 32 && + pSrc->BitsPerPel == 32 && + pDst->Rotation == D3DKMDT_VPPR_IDENTITY && + pSrc->Rotation == D3DKMDT_VPPR_IDENTITY) + { + // This is by far the most common copy function being called + CopyBits32_32(pDst, pSrc, NumRects, pRects); + } + else + { + CopyBitsGeneric(pDst, pSrc, NumRects, pRects); + } + } + #pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try/except is only able to protect against user-mode errors and these are the only errors we try to catch here"); + __except(EXCEPTION_EXECUTE_HANDLER) + { + DbgPrint(TRACE_LEVEL_ERROR, ("Either dst (0x%I64x) or src (0x%I64x) bits encountered exception during access.\n", pDst->pBits, pSrc->pBits)); + } +} + + NTSTATUS QxlDod::VbeGetModeList() { PAGED_CODE(); USHORT m_Segment; USHORT m_Offset; - USHORT ModeCount; - ULONG SuitableModeCount; - USHORT ModeTemp; - USHORT CurrentMode; - PVBE_MODEINFO VbeModeInfo; + USHORT ModeCount; + ULONG SuitableModeCount; + USHORT ModeTemp; + USHORT CurrentMode; + PVBE_MODEINFO VbeModeInfo; VBE_INFO VbeInfo = {0}; - ULONG Length; + ULONG Length; NTSTATUS Status = STATUS_SUCCESS; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); @@ -920,99 +2401,103 @@ NTSTATUS QxlDod::VbeGetModeList() if (!RtlEqualMemory(VbeInfo.Signature, "VESA", 4)) { - DbgPrint(TRACE_LEVEL_ERROR, ("No VBE BIOS present\n")); - return STATUS_UNSUCCESSFUL; - } + DbgPrint(TRACE_LEVEL_ERROR, ("No VBE BIOS present\n")); + return STATUS_UNSUCCESSFUL; + } DbgPrint(TRACE_LEVEL_ERROR, ("VBE BIOS Present (%d.%d, %8ld Kb)\n", VbeInfo.Version / 0x100, VbeInfo.Version & 0xFF, VbeInfo.TotalMemory * 64)); DbgPrint(TRACE_LEVEL_ERROR, ("Capabilities = 0x%x\n", VbeInfo.Capabilities)); DbgPrint(TRACE_LEVEL_ERROR, ("VideoModePtr = 0x%x (0x%x.0x%x)\n", VbeInfo.VideoModePtr, HIWORD( VbeInfo.VideoModePtr), LOWORD( VbeInfo.VideoModePtr))); - for (ModeCount = 0; ; ModeCount++) - { - /* Read the VBE mode number. */ - Status = x86BiosReadMemory ( - HIWORD(VbeInfo.VideoModePtr), - LOWORD(VbeInfo.VideoModePtr) + (ModeCount << 1), - &ModeTemp, - sizeof(ModeTemp)); - + for (ModeCount = 0; ; ModeCount++) + { + /* Read the VBE mode number. */ + Status = x86BiosReadMemory ( + HIWORD(VbeInfo.VideoModePtr), + LOWORD(VbeInfo.VideoModePtr) + (ModeCount << 1), + &ModeTemp, + sizeof(ModeTemp)); + if (!NT_SUCCESS (Status)) { DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosReadMemory failed with Status: 0x%X\n", Status)); break; } - /* End of list? */ - if (ModeTemp == 0xFFFF || ModeTemp == 0) - { - break; - } - } + /* End of list? */ + if (ModeTemp == 0xFFFF || ModeTemp == 0) + { + break; + } + } DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount %d\n", ModeCount)); - m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VBE_MODEINFO) * ModeCount]); + m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VBE_MODEINFO) * ModeCount]); m_ModeNumbers = reinterpret_cast (new (PagedPool) BYTE [sizeof (USHORT) * ModeCount]); m_CurrentMode = 0; DbgPrint(TRACE_LEVEL_ERROR, ("m_ModeInfo = 0x%p, m_ModeNumbers = 0x%p\n", m_ModeInfo, m_ModeNumbers)); - for (CurrentMode = 0, SuitableModeCount = 0; - CurrentMode < ModeCount; - CurrentMode++) - { - Status = x86BiosReadMemory ( - HIWORD(VbeInfo.VideoModePtr), - LOWORD(VbeInfo.VideoModePtr) + (CurrentMode << 1), - &ModeTemp, - sizeof(ModeTemp)); - + for (CurrentMode = 0, SuitableModeCount = 0; + CurrentMode < ModeCount; + CurrentMode++) + { + Status = x86BiosReadMemory ( + HIWORD(VbeInfo.VideoModePtr), + LOWORD(VbeInfo.VideoModePtr) + (CurrentMode << 1), + &ModeTemp, + sizeof(ModeTemp)); + if (!NT_SUCCESS (Status)) { DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosReadMemory failed with Status: 0x%X\n", Status)); break; } - + DbgPrint(TRACE_LEVEL_ERROR, ("ModeTemp = 0x%X\n", ModeTemp)); - RtlZeroMemory(®s, sizeof(regs)); - regs.Eax = 0x4F01; - regs.Ecx = ModeTemp; - regs.Edi = m_Offset + sizeof (VbeInfo); - regs.SegEs = m_Segment; + RtlZeroMemory(®s, sizeof(regs)); + regs.Eax = 0x4F01; + regs.Ecx = ModeTemp; + regs.Edi = m_Offset + sizeof (VbeInfo); + regs.SegEs = m_Segment; if (!x86BiosCall (0x10, ®s)) { DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n")); return STATUS_UNSUCCESSFUL; } - Status = x86BiosReadMemory ( - m_Segment, - m_Offset + sizeof (VbeInfo), - m_ModeInfo + SuitableModeCount, - sizeof(VBE_MODEINFO)); - - VbeModeInfo = m_ModeInfo + SuitableModeCount; - - if (VbeModeInfo->XResolution >= 1024 && - VbeModeInfo->YResolution >= 768 && - VbeModeInfo->BitsPerPixel == 32 && - VbeModeInfo->PhysBasePtr != 0) - { - m_ModeNumbers[SuitableModeCount] = ModeTemp; - if (VbeModeInfo->XResolution == 1024 && - VbeModeInfo->YResolution == 768) - { - m_CurrentMode = (USHORT)SuitableModeCount; - } - SuitableModeCount++; - } - } - - if (SuitableModeCount == 0) - { + Status = x86BiosReadMemory ( + m_Segment, + m_Offset + sizeof (VbeInfo), + m_ModeInfo + SuitableModeCount, + sizeof(VBE_MODEINFO)); + + VbeModeInfo = m_ModeInfo + SuitableModeCount; + + if (VbeModeInfo->XResolution >= 1024 && + VbeModeInfo->YResolution >= 768 && + VbeModeInfo->BitsPerPixel == 24 && + VbeModeInfo->PhysBasePtr != 0) + { + m_ModeNumbers[SuitableModeCount] = ModeTemp; + if (VbeModeInfo->XResolution == 1024 && + VbeModeInfo->YResolution == 768) + { + m_CurrentMode = (USHORT)SuitableModeCount; + } + SuitableModeCount++; + } + } + + if (SuitableModeCount == 0) + { DbgPrint(TRACE_LEVEL_ERROR, ("No video modes supported\n")); Status = STATUS_UNSUCCESSFUL; - } - - m_ModeCount = SuitableModeCount; + } + + m_ModeCount = SuitableModeCount; DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount)); + for (ULONG idx = 0; idx < m_ModeCount; idx++) + { + DbgPrint(TRACE_LEVEL_ERROR, ("type %x, XRes = %d, YRes = %d, BPP = %d\n", m_ModeNumbers[idx], m_ModeInfo[idx].XResolution, m_ModeInfo[idx].YResolution, m_ModeInfo[idx].BitsPerPixel)); + } if (m_Segment != 0) { @@ -1026,49 +2511,161 @@ NTSTATUS QxlDod::VbeQueryCurrentMode(PVIDEO_MODE RequestedMode) { DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); NTSTATUS Status = STATUS_SUCCESS; - PVBE_MODEINFO VBEMode = &m_ModeInfo[m_CurrentMode]; + UNREFERENCED_PARAMETER(RequestedMode); +// PVBE_MODEINFO VBEMode = &m_ModeInfo[m_CurrentMode]; return Status; } -NTSTATUS QxlDod::VbeSetCurrentMode(PVIDEO_MODE RequestedMode) +NTSTATUS QxlDod::VbeSetCurrentMode(ULONG Mode) { NTSTATUS Status = STATUS_SUCCESS; - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s Mode = %x\n", __FUNCTION__, Mode)); X86BIOS_REGISTERS regs = {0}; regs.Eax = 0x4F02; - regs.Edx = m_ModeNumbers[RequestedMode->RequestedMode]; + regs.Ebx = Mode | 0x000; if (!x86BiosCall (0x10, ®s)) { DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n")); return STATUS_UNSUCCESSFUL; } - m_CurrentMode = (USHORT)RequestedMode->RequestedMode; DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return Status; } +NTSTATUS QxlDod::VbeGetCurrentMode(ULONG* pMode) +{ + NTSTATUS Status = STATUS_SUCCESS; + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + X86BIOS_REGISTERS regs = {0}; + regs.Eax = 0x4F03; + if (!x86BiosCall (0x10, ®s)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n")); + return STATUS_UNSUCCESSFUL; + } + *pMode = regs.Ebx; + DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> EAX = %x, EBX = %x Mode = %x\n", regs.Eax, regs.Ebx, *pMode)); + return Status; +} + NTSTATUS QxlDod::VbeSetPowerState(POWER_ACTION ActionType) { - NTSTATUS Status = STATUS_SUCCESS; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); X86BIOS_REGISTERS regs = {0}; regs.Eax = 0x4F10; regs.Ebx = 1; - switch (ActionType) - { - case PowerActionSleep: regs.Ebx |= 0x100; break; - case PowerActionHibernate: regs.Ebx |= 0x200; break; - case PowerActionShutdown: - case PowerActionShutdownReset: - case PowerActionShutdownOff: regs.Ebx |= 0x400; break; - } + switch (ActionType) + { + case PowerActionNone: break; + case PowerActionSleep: regs.Ebx |= 0x100; break; + case PowerActionHibernate: regs.Ebx |= 0x200; break; + case PowerActionShutdown: + case PowerActionShutdownReset: + case PowerActionShutdownOff: regs.Ebx |= 0x400; break; + } if (!x86BiosCall (0x10, ®s)) { DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n")); return STATUS_UNSUCCESSFUL; } DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); - return Status; + return STATUS_SUCCESS; } + +// +// Non-Paged Code +// +#pragma code_seg(push) +#pragma code_seg() +D3DDDI_VIDEO_PRESENT_SOURCE_ID QxlDod::FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero) +{ + UNREFERENCED_PARAMETER(TargetId); + for (UINT SourceId = 0; SourceId < MAX_VIEWS; ++SourceId) + { + if (m_CurrentModes[SourceId].FrameBuffer.Ptr != NULL) + { + return SourceId; + } + } + + return DefaultToZero ? 0 : D3DDDI_ID_UNINITIALIZED; +} + +#pragma code_seg(pop) // End Non-Paged Code + +// +// Frame buffer map/unmap +// + +NTSTATUS +MapFrameBuffer( + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ ULONG Length, + _Outptr_result_bytebuffer_(Length) VOID** VirtualAddress) +{ + PAGED_CODE(); + + // + // Check for parameters + // + if ((PhysicalAddress.QuadPart == (ULONGLONG)0) || + (Length == 0) || + (VirtualAddress == NULL)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("One of PhysicalAddress.QuadPart (0x%I64x), Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0", + PhysicalAddress.QuadPart, Length, VirtualAddress)); + return STATUS_INVALID_PARAMETER; + } + + *VirtualAddress = MmMapIoSpace(PhysicalAddress, + Length, + MmWriteCombined); + if (*VirtualAddress == NULL) + { + // The underlying call to MmMapIoSpace failed. This may be because, MmWriteCombined + // isn't supported, so try again with MmNonCached + + *VirtualAddress = MmMapIoSpace(PhysicalAddress, + Length, + MmNonCached); + if (*VirtualAddress == NULL) + { + DbgPrint(TRACE_LEVEL_ERROR, ("MmMapIoSpace returned a NULL buffer when trying to allocate 0x%I64x bytes", Length)); + return STATUS_NO_MEMORY; + } + } + + return STATUS_SUCCESS; +} + +NTSTATUS +UnmapFrameBuffer( + _In_reads_bytes_(Length) VOID* VirtualAddress, + _In_ ULONG Length) +{ + PAGED_CODE(); + + + // + // Check for parameters + // + if ((VirtualAddress == NULL) && (Length == 0)) + { + // Allow this function to be called when there's no work to do, and treat as successful + return STATUS_SUCCESS; + } + else if ((VirtualAddress == NULL) || (Length == 0)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("Only one of Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0", + Length, VirtualAddress)); + return STATUS_INVALID_PARAMETER; + } + + MmUnmapIoSpace(VirtualAddress, + Length); + + return STATUS_SUCCESS; +} + diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 18ec7b1..048aec8 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -1,17 +1,32 @@ #pragma once #include "baseobject.h" +#define MAX_CHILDREN 1 +#define MAX_VIEWS 1 +#define BITS_PER_BYTE 8 + typedef struct _QXL_FLAGS { UINT DriverStarted : 1; // ( 1) 1 after StartDevice and 0 after StopDevice UINT Unused : 31; } QXL_FLAGS; -#define MAX_CHILDREN 1 -#define MAX_VIEWS 1 +// For the following macros, c must be a UCHAR. +#define UPPER_6_BITS(c) (((c) & rMaskTable[6 - 1]) >> 2) +#define UPPER_5_BITS(c) (((c) & rMaskTable[5 - 1]) >> 3) +#define LOWER_6_BITS(c) (((BYTE)(c)) & lMaskTable[BITS_PER_BYTE - 6]) +#define LOWER_5_BITS(c) (((BYTE)(c)) & lMaskTable[BITS_PER_BYTE - 5]) -#pragma pack(push) -#pragma pack(1) + +#define SHIFT_FOR_UPPER_5_IN_565 (6 + 5) +#define SHIFT_FOR_MIDDLE_6_IN_565 (5) +#define SHIFT_UPPER_5_IN_565_BACK ((BITS_PER_BYTE * 2) + (BITS_PER_BYTE - 5)) +#define SHIFT_MIDDLE_6_IN_565_BACK ((BITS_PER_BYTE * 1) + (BITS_PER_BYTE - 6)) +#define SHIFT_LOWER_5_IN_565_BACK ((BITS_PER_BYTE * 0) + (BITS_PER_BYTE - 5)) + + +#pragma pack(push) +#pragma pack(1) typedef struct { @@ -83,7 +98,7 @@ typedef struct CHAR Reserved4[189]; } VBE_MODEINFO, *PVBE_MODEINFO; -#pragma pack(pop) +#pragma pack(pop) typedef struct _X86BIOS_REGISTERS // invented names { @@ -116,6 +131,79 @@ NTHALAPI NTSTATUS x86BiosWriteMemory (USHORT, USHORT, PVOID, ULONG); } #endif +struct DoPresentMemory +{ + PVOID DstAddr; + UINT DstStride; + ULONG DstBitPerPixel; + UINT SrcWidth; + UINT SrcHeight; + BYTE* SrcAddr; + LONG SrcPitch; + ULONG NumMoves; // in: Number of screen to screen moves + D3DKMT_MOVE_RECT* Moves; // in: Point to the list of moves + ULONG NumDirtyRects; // in: Number of direct rects + RECT* DirtyRect; // in: Point to the list of dirty rects + D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation; + D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceID; + HANDLE hAdapter; + PMDL Mdl; + PVOID DisplaySource; +}; + +typedef struct _BLT_INFO +{ + PVOID pBits; + UINT Pitch; + UINT BitsPerPel; + POINT Offset; // To unrotated top-left of dirty rects + D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation; + UINT Width; // For the unrotated image + UINT Height; // For the unrotated image +} BLT_INFO; + +// Represents the current mode, may not always be set (i.e. frame buffer mapped) if representing the mode passed in on single mode setups. +typedef struct _CURRENT_BDD_MODE +{ + // The source mode currently set for HW Framebuffer + // For sample driver this info filled in StartDevice by the OS and never changed. + DXGK_DISPLAY_INFORMATION DispInfo; + + // The rotation of the current mode. Rotation is performed in software during Present call + D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation; + + D3DKMDT_VIDPN_PRESENT_PATH_SCALING Scaling; + // This mode might be different from one which are supported for HW frame buffer + // Scaling/displasment might be needed (if supported) + UINT SrcModeWidth; + UINT SrcModeHeight; + + // Various boolean flags the struct uses + struct _CURRENT_BDD_MODE_FLAGS + { + UINT SourceNotVisible : 1; // 0 if source is visible + UINT FullscreenPresent : 1; // 0 if should use dirty rects for present + UINT FrameBufferIsActive : 1; // 0 if not currently active (i.e. target not connected to source) + UINT DoNotMapOrUnmap : 1; // 1 if the FrameBuffer should not be (un)mapped during normal execution + UINT IsInternal : 1; // 1 if it was determined (i.e. through ACPI) that an internal panel is being driven + UINT Unused : 27; + } Flags; + + // The start and end of physical memory known to be all zeroes. Used to optimize the BlackOutScreen function to not write + // zeroes to memory already known to be zero. (Physical address is located in DispInfo) + PHYSICAL_ADDRESS ZeroedOutStart; + PHYSICAL_ADDRESS ZeroedOutEnd; + + // Linear frame buffer pointer + // A union with a ULONG64 is used here to ensure this struct looks the same on 32bit and 64bit builds + // since the size of a VOID* changes depending on the build. + union + { + VOID* Ptr; + ULONG64 Force8Bytes; + } FrameBuffer; +} CURRENT_BDD_MODE; + class QxlDod : public BaseObject @@ -128,10 +216,13 @@ private: DEVICE_POWER_STATE m_MonitorPowerState; DEVICE_POWER_STATE m_AdapterPowerState; QXL_FLAGS m_Flags; - PVBE_MODEINFO m_ModeInfo; + PVBE_MODEINFO m_ModeInfo; ULONG m_ModeCount; PUSHORT m_ModeNumbers; USHORT m_CurrentMode; + CURRENT_BDD_MODE m_CurrentModes[MAX_VIEWS]; + D3DDDI_VIDEO_PRESENT_SOURCE_ID m_SystemDisplaySourceId; + DXGKARG_SETPOINTERSHAPE m_PointerShape; public: QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject); ~QxlDod(void); @@ -219,18 +310,109 @@ public: // Must be Non-Paged // Write out pixels as part of bugcheck VOID SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VOID* pSource, - _In_ UINT SourceWidth, - _In_ UINT SourceHeight, - _In_ UINT SourceStride, - _In_ INT PositionX, - _In_ INT PositionY); + _In_ UINT SourceWidth, + _In_ UINT SourceHeight, + _In_ UINT SourceStride, + _In_ INT PositionX, + _In_ INT PositionY); private: VOID CleanUp(VOID); NTSTATUS WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue); + // Set the given source mode on the given path + NTSTATUS SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode, + CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath); + + // Add the current mode to the given monitor source mode set + NTSTATUS AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes); + + // Add the current mode to the given VidPn source mode set + NTSTATUS AddSingleSourceMode(_In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface, + D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet, + D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId); + + // Add the current mode (or the matching to pinned source mode) to the give VidPn target mode set + NTSTATUS AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface, + D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet, + _In_opt_ CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnPinnedSourceModeInfo, + D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId); + D3DDDI_VIDEO_PRESENT_SOURCE_ID FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero); + NTSTATUS IsVidPnSourceModeFieldsValid(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const; + NTSTATUS IsVidPnPathFieldsValid(CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) const; + + NTSTATUS RegisterHWInfo(); NTSTATUS VbeGetModeList(); + + NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* pMoves, + _In_ ULONG NumDirtyRects, + _In_ RECT* pDirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation); + BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect); + VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch); + VOID CopyBitsGeneric( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + + VOID CopyBits32_32( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + VOID BltBits ( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + VOID BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId); + NTSTATUS VbeQueryCurrentMode(PVIDEO_MODE RequestedMode); - NTSTATUS VbeSetCurrentMode(PVIDEO_MODE RequestedMode); + NTSTATUS VbeSetCurrentMode(ULONG Mode); + NTSTATUS VbeGetCurrentMode(ULONG* Mode); NTSTATUS VbeSetPowerState(POWER_ACTION ActionType); + UINT BPPFromPixelFormat(D3DDDIFORMAT Format) const + { + switch (Format) + { + case D3DDDIFMT_UNKNOWN: return 0; + case D3DDDIFMT_P8: return 8; + case D3DDDIFMT_R5G6B5: return 16; + case D3DDDIFMT_R8G8B8: return 24; + case D3DDDIFMT_X8R8G8B8: // fall through + case D3DDDIFMT_A8R8G8B8: return 32; + default: QXL_LOG_ASSERTION1("Unknown D3DDDIFORMAT 0x%I64x", Format); return 0; + } + } + + // Given bits per pixel, return the pixel format at the same bpp + D3DDDIFORMAT PixelFormatFromBPP(UINT BPP) const + { + switch (BPP) + { + case 8: return D3DDDIFMT_P8; + case 16: return D3DDDIFMT_R5G6B5; + case 24: return D3DDDIFMT_R8G8B8; + case 32: return D3DDDIFMT_X8R8G8B8; + default: QXL_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not supported.", BPP); return D3DDDIFMT_UNKNOWN; + } + } }; +NTSTATUS +MapFrameBuffer( + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ ULONG Length, + _Outptr_result_bytebuffer_(Length) VOID** VirtualAddress); + +NTSTATUS +UnmapFrameBuffer( + _In_reads_bytes_(Length) VOID* VirtualAddress, + _In_ ULONG Length); + diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp index 546fc88..bdf4c04 100755 --- a/qxldod/driver.cpp +++ b/qxldod/driver.cpp @@ -9,7 +9,7 @@ // Driver Entry point // -int nDebugLevel = TRACE_LEVEL_VERBOSE; +int nDebugLevel = TRACE_LEVEL_INFORMATION; extern "C" @@ -93,7 +93,7 @@ DodAddDevice( _Outptr_ PVOID* ppDeviceContext) { PAGED_CODE(); - DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); if ((pPhysicalDeviceObject == NULL) || (ppDeviceContext == NULL)) @@ -113,7 +113,7 @@ DodAddDevice( *ppDeviceContext = pQxl; - DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -122,7 +122,7 @@ DodRemoveDevice( _In_ VOID* pDeviceContext) { PAGED_CODE(); - DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); @@ -132,7 +132,7 @@ DodRemoveDevice( pQxl = NULL; } - DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -146,7 +146,7 @@ DodStartDevice( { PAGED_CODE(); QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); return pQxl->StartDevice(pDxgkStartInfo, pDxgkInterface, pNumberOfViews, pNumberOfChildren); @@ -158,7 +158,7 @@ DodStopDevice( { PAGED_CODE(); QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); return pQxl->StopDevice(); @@ -173,7 +173,7 @@ DodDispatchIoRequest( { PAGED_CODE(); QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); if (!pQxl->IsDriverActive()) @@ -193,7 +193,7 @@ DodSetPowerState( { PAGED_CODE(); QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); if (!pQxl->IsDriverActive()) @@ -215,7 +215,7 @@ DodQueryChildRelations( { PAGED_CODE(); QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); return pQxl->QueryChildRelations(pChildRelations, ChildRelationsSize); @@ -229,7 +229,7 @@ DodQueryChildStatus( { PAGED_CODE(); QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); return pQxl->QueryChildStatus(pChildStatus, NonDestructiveOnly); @@ -243,7 +243,7 @@ DodQueryDeviceDescriptor( { PAGED_CODE(); QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); if (!pQxl->IsDriverActive()) @@ -271,7 +271,7 @@ DodQueryAdapterInfo( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); return pQxl->QueryAdapterInfo(pQueryAdapterInfo); @@ -285,7 +285,7 @@ DodSetPointerPosition( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) @@ -304,7 +304,7 @@ DodSetPointerShape( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) @@ -324,7 +324,7 @@ DodEscape( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); return pQxl->Escape(pEscape); @@ -338,7 +338,7 @@ DodQueryInterface( { PAGED_CODE(); QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); return pQxl->QueryInterface(QueryInterface); @@ -352,7 +352,7 @@ DodPresentDisplayOnly( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); -// DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) @@ -372,7 +372,7 @@ DodStopDeviceAndReleasePostDisplayOwnership( { PAGED_CODE(); QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); return pQxl->StopDeviceAndReleasePostDisplayOwnership(TargetId, DisplayInfo); @@ -386,7 +386,7 @@ DodIsSupportedVidPn( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) @@ -408,7 +408,7 @@ DodRecommendFunctionalVidPn( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) @@ -427,7 +427,7 @@ DodRecommendVidPnTopology( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) @@ -446,7 +446,7 @@ DodRecommendMonitorModes( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) @@ -465,7 +465,7 @@ DodEnumVidPnCofuncModality( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) @@ -484,7 +484,7 @@ DodSetVidPnSourceVisibility( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) @@ -503,7 +503,7 @@ DodCommitVidPn( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) @@ -522,7 +522,7 @@ DodUpdateActiveVidPnPresentPath( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) @@ -541,7 +541,7 @@ DodQueryVidPnHWCapability( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) @@ -564,7 +564,7 @@ DodDpcRoutine( _In_ VOID* pDeviceContext) { QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); if (!pQxl->IsDriverActive()) @@ -573,7 +573,7 @@ DodDpcRoutine( return; } pQxl->DpcRoutine(); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } BOOLEAN @@ -582,7 +582,7 @@ DodInterruptRoutine( _In_ ULONG MessageNumber) { QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); return pQxl->InterruptRoutine(MessageNumber); @@ -593,7 +593,7 @@ DodResetDevice( _In_ VOID* pDeviceContext) { QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); pQxl->ResetDevice(); @@ -610,7 +610,7 @@ DodSystemDisplayEnable( _Out_ D3DDDIFORMAT* ColorFormat) { QXL_ASSERT_CHK(pDeviceContext != NULL); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(pDeviceContext); return pQxl->SystemDisplayEnable(TargetId, Flags, Width, Height, ColorFormat); From f15bf992ca7b097c77abb38c366f7207bf585fe3 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Thu, 2 Jan 2014 20:47:56 +1100 Subject: [PATCH 07/46] fix compilation warning --- qxldod/driver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp index bdf4c04..87ffbe6 100755 --- a/qxldod/driver.cpp +++ b/qxldod/driver.cpp @@ -659,7 +659,7 @@ void DebugPrintFuncSerial(const char *format, ...) } if (len) { - WRITE_PORT_BUFFER_UCHAR(RHEL_DEBUG_PORT, (PUCHAR)buf, len); + WRITE_PORT_BUFFER_UCHAR(RHEL_DEBUG_PORT, (PUCHAR)buf, (ULONG)len); WRITE_PORT_UCHAR(RHEL_DEBUG_PORT, '\r'); } } From 965ff992b6498d63e35ddccd2b9e22fbc03c0334 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Thu, 2 Jan 2014 20:58:18 +1100 Subject: [PATCH 08/46] fix bug in the modes initialization list --- qxldod/QxlDod.cpp | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 5c7fd0a..2f31a52 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -109,15 +109,6 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, // return Status; // } - - Status = VbeGetModeList(); - if (!NT_SUCCESS(Status)) - { - QXL_LOG_ASSERTION1("RegisterHWInfo failed with status 0x%X\n", - Status); - return Status; - } - // This sample driver only uses the frame buffer of the POST device. DxgkCbAcquirePostDisplayOwnership // gives you the frame buffer address and ensures that no one else is drawing to it. Be sure to give it back! Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &(m_CurrentModes[0].DispInfo)); @@ -127,8 +118,20 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, // after a pre-WDDM 1.2 driver. Since we can't draw anything, we should fail to start. return STATUS_UNSUCCESSFUL; } - *pNumberOfViews = MAX_VIEWS; - *pNumberOfChildren = MAX_CHILDREN; + + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s %dx%d ColorFormat = %d, \n", __FUNCTION__, + m_CurrentModes[0].DispInfo.Width, m_CurrentModes[0].DispInfo.Height, m_CurrentModes[0].DispInfo.ColorFormat)); + + Status = VbeGetModeList(); + if (!NT_SUCCESS(Status)) + { + QXL_LOG_ASSERTION1("RegisterHWInfo failed with status 0x%X\n", + Status); + return Status; + } + + *pNumberOfViews = MAX_VIEWS; + *pNumberOfChildren = MAX_CHILDREN; m_Flags.DriverStarted = TRUE; return STATUS_SUCCESS; } @@ -2471,9 +2474,13 @@ NTSTATUS QxlDod::VbeGetModeList() VbeModeInfo = m_ModeInfo + SuitableModeCount; - if (VbeModeInfo->XResolution >= 1024 && - VbeModeInfo->YResolution >= 768 && - VbeModeInfo->BitsPerPixel == 24 && + UINT Height = m_CurrentModes[0].DispInfo.Height; + UINT Width = m_CurrentModes[0].DispInfo.Width; + UINT BitsPerPixel = BPPFromPixelFormat(m_CurrentModes[0].DispInfo.ColorFormat); + + if (VbeModeInfo->XResolution >= Width && + VbeModeInfo->YResolution >= Height && + VbeModeInfo->BitsPerPixel == BitsPerPixel && VbeModeInfo->PhysBasePtr != 0) { m_ModeNumbers[SuitableModeCount] = ModeTemp; From 52603878f132f9fc1f2377a3edff3832e44ee18b Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Sun, 26 Jan 2014 22:28:01 +1100 Subject: [PATCH 09/46] add HW device interface --- qxldod/QxlDod.cpp | 314 +++++++++++++++++++++++++++------------------- qxldod/QxlDod.h | 118 +++++++++++------ qxldod/driver.cpp | 2 +- 3 files changed, 270 insertions(+), 164 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 5c7fd0a..117ec33 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -49,13 +49,14 @@ QxlDod::QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pP m_MonitorPowerState(PowerDeviceD0), m_AdapterPowerState(PowerDeviceD0) { - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); *((UINT*)&m_Flags) = 0; RtlZeroMemory(&m_DxgkInterface, sizeof(m_DxgkInterface)); RtlZeroMemory(&m_DeviceInfo, sizeof(m_DeviceInfo)); RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes)); RtlZeroMemory(&m_PointerShape, sizeof(m_PointerShape)); - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + m_pHWDevice = new(PagedPool) VgaDevice(this); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); } @@ -80,11 +81,11 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, QXL_ASSERT(pDxgkInterface != NULL); QXL_ASSERT(pNumberOfViews != NULL); QXL_ASSERT(pNumberOfChildren != NULL); - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); - +//CHECK ME!!!!!!!!!!!!! RtlCopyMemory(&m_DxgkInterface, pDxgkInterface, sizeof(m_DxgkInterface)); RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes)); - m_CurrentModes[0].DispInfo.TargetId = D3DDDI_ID_UNINITIALIZED; +//CHECK ME!!!!!!!!!!!!! + m_CurrentModes[0].DispInfo.TargetId = D3DDDI_ID_UNINITIALIZED; // Get device information from OS. NTSTATUS Status = m_DxgkInterface.DxgkCbGetDeviceInformation(m_DxgkInterface.DeviceHandle, &m_DeviceInfo); if (!NT_SUCCESS(Status)) @@ -109,15 +110,6 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, // return Status; // } - - Status = VbeGetModeList(); - if (!NT_SUCCESS(Status)) - { - QXL_LOG_ASSERTION1("RegisterHWInfo failed with status 0x%X\n", - Status); - return Status; - } - // This sample driver only uses the frame buffer of the POST device. DxgkCbAcquirePostDisplayOwnership // gives you the frame buffer address and ensures that no one else is drawing to it. Be sure to give it back! Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &(m_CurrentModes[0].DispInfo)); @@ -127,9 +119,19 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, // after a pre-WDDM 1.2 driver. Since we can't draw anything, we should fail to start. return STATUS_UNSUCCESSFUL; } + + Status = m_pHWDevice->GetModeList(&m_CurrentModes[0].DispInfo); + if (!NT_SUCCESS(Status)) + { + QXL_LOG_ASSERTION1("RegisterHWInfo failed with status 0x%X\n", + Status); + return Status; + } + *pNumberOfViews = MAX_VIEWS; *pNumberOfChildren = MAX_CHILDREN; m_Flags.DriverStarted = TRUE; + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -250,7 +252,7 @@ NTSTATUS QxlDod::SetPowerState(_In_ ULONG HardwareUid, return STATUS_SUCCESS; } // TODO: This is where the specified monitor should be powered up/down - VbeSetPowerState(ActionType); + m_pHWDevice->SetPowerState(ActionType); return STATUS_SUCCESS; } @@ -677,10 +679,11 @@ NTSTATUS QxlDod::AddSingleSourceMode(_In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFAC // There is only one source format supported by display-only drivers, but more can be added in a // full WDDM driver if the hardware supports them - for (ULONG idx = 0; idx < m_ModeCount; ++idx) + for (ULONG idx = 0; idx < m_pHWDevice->GetModeCount(); ++idx) { // Create new mode info that will be populated D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo = NULL; + PVBE_MODEINFO pModeInfo = m_pHWDevice->GetModeInfo(idx); NTSTATUS Status = pVidPnSourceModeSetInterface->pfnCreateNewModeInfo(hVidPnSourceModeSet, &pVidPnSourceModeInfo); if (!NT_SUCCESS(Status)) { @@ -692,10 +695,10 @@ NTSTATUS QxlDod::AddSingleSourceMode(_In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFAC // Populate mode info with values from current mode and hard-coded values // Always report 32 bpp format, this will be color converted during the present if the mode is < 32bpp pVidPnSourceModeInfo->Type = D3DKMDT_RMT_GRAPHICS; - pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx = m_ModeInfo[idx].XResolution; - pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy = m_ModeInfo[idx].YResolution; + pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx = pModeInfo->XResolution; + pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy = pModeInfo->YResolution; pVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize; - pVidPnSourceModeInfo->Format.Graphics.Stride = m_ModeInfo[idx].BytesPerScanLine / m_ModeInfo[idx].XResolution; + pVidPnSourceModeInfo->Format.Graphics.Stride = pModeInfo->BytesPerScanLine / pModeInfo->XResolution; pVidPnSourceModeInfo->Format.Graphics.PixelFormat = D3DDDIFMT_A8R8G8B8; pVidPnSourceModeInfo->Format.Graphics.ColorBasis = D3DKMDT_CB_SCRGB; pVidPnSourceModeInfo->Format.Graphics.PixelValueAccessMode = D3DKMDT_PVAM_DIRECT; @@ -733,9 +736,10 @@ NTSTATUS QxlDod::AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFAC D3DKMDT_VIDPN_TARGET_MODE* pVidPnTargetModeInfo = NULL; NTSTATUS Status = STATUS_SUCCESS; - - for (UINT ModeIndex = 0; ModeIndex < m_ModeCount; ++ModeIndex) +//FIXME !!!!!! + for (UINT ModeIndex = 0; ModeIndex < m_pHWDevice->GetModeCount(); ++ModeIndex) { + PVBE_MODEINFO pModeInfo = m_pHWDevice->GetModeInfo(SourceId); pVidPnTargetModeInfo = NULL; Status = pVidPnTargetModeSetInterface->pfnCreateNewModeInfo(hVidPnTargetModeSet, &pVidPnTargetModeInfo); if (!NT_SUCCESS(Status)) @@ -745,8 +749,8 @@ NTSTATUS QxlDod::AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFAC return Status; } pVidPnTargetModeInfo->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER; - pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cx = m_ModeInfo[SourceId].XResolution; - pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cy = m_ModeInfo[SourceId].YResolution; + pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cx = pModeInfo->XResolution; + pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cy = pModeInfo->YResolution; pVidPnTargetModeInfo->VideoSignalInfo.ActiveSize = pVidPnTargetModeInfo->VideoSignalInfo.TotalSize; pVidPnTargetModeInfo->VideoSignalInfo.VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED; pVidPnTargetModeInfo->VideoSignalInfo.VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED; @@ -792,7 +796,7 @@ NTSTATUS QxlDod::AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* return Status; } - pVbeModeInfo = &m_ModeInfo[m_CurrentMode]; + pVbeModeInfo = m_pHWDevice->GetModeInfo(m_pHWDevice->GetCurrentModeIndex());//&m_ModeInfo[m_CurrentMode]; // Since we don't know the real monitor timing information, just use the current display mode (from the POST device) with unknown frequencies pMonitorSourceMode->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER; @@ -835,12 +839,12 @@ NTSTATUS QxlDod::AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* return Status; } // If AddMode succeeded with something other than STATUS_SUCCESS treat it as such anyway when propagating up - for (UINT Idx = 0; Idx < m_ModeCount; ++Idx) + for (UINT Idx = 0; Idx < m_pHWDevice->GetModeCount(); ++Idx) { // There is only one source format supported by display-only drivers, but more can be added in a // full WDDM driver if the hardware supports them - pVbeModeInfo = &m_ModeInfo[Idx]; + pVbeModeInfo = m_pHWDevice->GetModeInfo(Idx); // TODO: add routine for filling Monitor modepMonitorSourceMode = NULL; Status = pRecommendMonitorModes->pMonitorSourceModeSetInterface->pfnCreateNewModeInfo(pRecommendMonitorModes->hMonitorSourceModeSet, &pMonitorSourceMode); if (!NT_SUCCESS(Status)) @@ -1510,15 +1514,16 @@ NTSTATUS QxlDod::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMo // Mark that the next present should be fullscreen so the screen doesn't go from black to actual pixels one dirty rect at a time. pCurrentBddMode->Flags.FullscreenPresent = TRUE; - for (USHORT ModeIndex = 0; ModeIndex < m_ModeCount; ++ModeIndex) + for (USHORT ModeIndex = 0; ModeIndex < m_pHWDevice->GetModeCount(); ++ModeIndex) { - if (pCurrentBddMode->DispInfo.Width == m_ModeInfo[ModeIndex].XResolution && - pCurrentBddMode->DispInfo.Height == m_ModeInfo[ModeIndex].YResolution ) + PVBE_MODEINFO pModeInfo = m_pHWDevice->GetModeInfo(m_pHWDevice->GetCurrentModeIndex()); + if (pCurrentBddMode->DispInfo.Width == pModeInfo->XResolution && + pCurrentBddMode->DispInfo.Height == pModeInfo->YResolution ) { - Status = VbeSetCurrentMode(m_ModeNumbers[ModeIndex]); + Status = m_pHWDevice->SetCurrentMode(m_pHWDevice->GetModeNumber(ModeIndex)); if (NT_SUCCESS(Status)) { - m_CurrentMode = ModeIndex; + m_pHWDevice->SetCurrentModeIndex(ModeIndex); } break; } @@ -2286,7 +2291,7 @@ VOID QxlDod::CopyBits32_32( NT_ASSERT((pDst->Rotation == D3DKMDT_VPPR_IDENTITY) && (pSrc->Rotation == D3DKMDT_VPPR_IDENTITY)); - DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); for (UINT iRect = 0; iRect < NumRects; iRect++) { @@ -2348,8 +2353,104 @@ VOID QxlDod::BltBits ( } } +// +// Non-Paged Code +// +#pragma code_seg(push) +#pragma code_seg() +D3DDDI_VIDEO_PRESENT_SOURCE_ID QxlDod::FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero) +{ + UNREFERENCED_PARAMETER(TargetId); + for (UINT SourceId = 0; SourceId < MAX_VIEWS; ++SourceId) + { + if (m_CurrentModes[SourceId].FrameBuffer.Ptr != NULL) + { + return SourceId; + } + } -NTSTATUS QxlDod::VbeGetModeList() + return DefaultToZero ? 0 : D3DDDI_ID_UNINITIALIZED; +} + +#pragma code_seg(pop) // End Non-Paged Code + +// +// Frame buffer map/unmap +// + +NTSTATUS +MapFrameBuffer( + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ ULONG Length, + _Outptr_result_bytebuffer_(Length) VOID** VirtualAddress) +{ + PAGED_CODE(); + + // + // Check for parameters + // + if ((PhysicalAddress.QuadPart == (ULONGLONG)0) || + (Length == 0) || + (VirtualAddress == NULL)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("One of PhysicalAddress.QuadPart (0x%I64x), Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0", + PhysicalAddress.QuadPart, Length, VirtualAddress)); + return STATUS_INVALID_PARAMETER; + } + + *VirtualAddress = MmMapIoSpace(PhysicalAddress, + Length, + MmWriteCombined); + if (*VirtualAddress == NULL) + { + // The underlying call to MmMapIoSpace failed. This may be because, MmWriteCombined + // isn't supported, so try again with MmNonCached + + *VirtualAddress = MmMapIoSpace(PhysicalAddress, + Length, + MmNonCached); + if (*VirtualAddress == NULL) + { + DbgPrint(TRACE_LEVEL_ERROR, ("MmMapIoSpace returned a NULL buffer when trying to allocate 0x%I64x bytes", Length)); + return STATUS_NO_MEMORY; + } + } + + return STATUS_SUCCESS; +} + +NTSTATUS +UnmapFrameBuffer( + _In_reads_bytes_(Length) VOID* VirtualAddress, + _In_ ULONG Length) +{ + PAGED_CODE(); + + + // + // Check for parameters + // + if ((VirtualAddress == NULL) && (Length == 0)) + { + // Allow this function to be called when there's no work to do, and treat as successful + return STATUS_SUCCESS; + } + else if ((VirtualAddress == NULL) || (Length == 0)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("Only one of Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0", + Length, VirtualAddress)); + return STATUS_INVALID_PARAMETER; + } + + MmUnmapIoSpace(VirtualAddress, + Length); + + return STATUS_SUCCESS; +} + +// HW specific code + +NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) { PAGED_CODE(); USHORT m_Segment; @@ -2470,10 +2571,13 @@ NTSTATUS QxlDod::VbeGetModeList() sizeof(VBE_MODEINFO)); VbeModeInfo = m_ModeInfo + SuitableModeCount; - - if (VbeModeInfo->XResolution >= 1024 && - VbeModeInfo->YResolution >= 768 && - VbeModeInfo->BitsPerPixel == 24 && + UINT Height = pDispInfo->Height; + UINT Width = pDispInfo->Width; + UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); + + if (VbeModeInfo->XResolution >= Width && + VbeModeInfo->YResolution >= Height && + VbeModeInfo->BitsPerPixel == BitsPerPixel && VbeModeInfo->PhysBasePtr != 0) { m_ModeNumbers[SuitableModeCount] = ModeTemp; @@ -2496,7 +2600,11 @@ NTSTATUS QxlDod::VbeGetModeList() DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount)); for (ULONG idx = 0; idx < m_ModeCount; idx++) { - DbgPrint(TRACE_LEVEL_ERROR, ("type %x, XRes = %d, YRes = %d, BPP = %d\n", m_ModeNumbers[idx], m_ModeInfo[idx].XResolution, m_ModeInfo[idx].YResolution, m_ModeInfo[idx].BitsPerPixel)); + DbgPrint(TRACE_LEVEL_ERROR, ("type %x, XRes = %d, YRes = %d, BPP = %d\n", + m_ModeNumbers[idx], + m_ModeInfo[idx].XResolution, + m_ModeInfo[idx].YResolution, + m_ModeInfo[idx].BitsPerPixel)); } if (m_Segment != 0) @@ -2507,7 +2615,7 @@ NTSTATUS QxlDod::VbeGetModeList() return Status; } -NTSTATUS QxlDod::VbeQueryCurrentMode(PVIDEO_MODE RequestedMode) +NTSTATUS VgaDevice::QueryCurrentMode(PVIDEO_MODE RequestedMode) { DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); NTSTATUS Status = STATUS_SUCCESS; @@ -2517,7 +2625,7 @@ NTSTATUS QxlDod::VbeQueryCurrentMode(PVIDEO_MODE RequestedMode) return Status; } -NTSTATUS QxlDod::VbeSetCurrentMode(ULONG Mode) +NTSTATUS VgaDevice::SetCurrentMode(ULONG Mode) { NTSTATUS Status = STATUS_SUCCESS; DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s Mode = %x\n", __FUNCTION__, Mode)); @@ -2533,7 +2641,7 @@ NTSTATUS QxlDod::VbeSetCurrentMode(ULONG Mode) return Status; } -NTSTATUS QxlDod::VbeGetCurrentMode(ULONG* pMode) +NTSTATUS VgaDevice::GetCurrentMode(ULONG* pMode) { NTSTATUS Status = STATUS_SUCCESS; DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); @@ -2549,7 +2657,7 @@ NTSTATUS QxlDod::VbeGetCurrentMode(ULONG* pMode) return Status; } -NTSTATUS QxlDod::VbeSetPowerState(POWER_ACTION ActionType) +NTSTATUS VgaDevice::SetPowerState(POWER_ACTION ActionType) { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); @@ -2574,98 +2682,52 @@ NTSTATUS QxlDod::VbeSetPowerState(POWER_ACTION ActionType) return STATUS_SUCCESS; } -// -// Non-Paged Code -// -#pragma code_seg(push) -#pragma code_seg() -D3DDDI_VIDEO_PRESENT_SOURCE_ID QxlDod::FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero) -{ - UNREFERENCED_PARAMETER(TargetId); - for (UINT SourceId = 0; SourceId < MAX_VIEWS; ++SourceId) - { - if (m_CurrentModes[SourceId].FrameBuffer.Ptr != NULL) - { - return SourceId; - } - } - return DefaultToZero ? 0 : D3DDDI_ID_UNINITIALIZED; -} - -#pragma code_seg(pop) // End Non-Paged Code - -// -// Frame buffer map/unmap -// - -NTSTATUS -MapFrameBuffer( - _In_ PHYSICAL_ADDRESS PhysicalAddress, - _In_ ULONG Length, - _Outptr_result_bytebuffer_(Length) VOID** VirtualAddress) +NTSTATUS QxlDevice::GetModeList() { PAGED_CODE(); - - // - // Check for parameters - // - if ((PhysicalAddress.QuadPart == (ULONGLONG)0) || - (Length == 0) || - (VirtualAddress == NULL)) + NTSTATUS Status = STATUS_SUCCESS; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + if (!NT_SUCCESS (Status)) { - DbgPrint(TRACE_LEVEL_ERROR, ("One of PhysicalAddress.QuadPart (0x%I64x), Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0", - PhysicalAddress.QuadPart, Length, VirtualAddress)); - return STATUS_INVALID_PARAMETER; + DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosWriteMemory failed with Status: 0x%X\n", Status)); + return Status; } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return Status; +} - *VirtualAddress = MmMapIoSpace(PhysicalAddress, - Length, - MmWriteCombined); - if (*VirtualAddress == NULL) - { - // The underlying call to MmMapIoSpace failed. This may be because, MmWriteCombined - // isn't supported, so try again with MmNonCached +NTSTATUS QxlDevice::QueryCurrentMode(PVIDEO_MODE RequestedMode) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + NTSTATUS Status = STATUS_SUCCESS; + UNREFERENCED_PARAMETER(RequestedMode); + return Status; +} - *VirtualAddress = MmMapIoSpace(PhysicalAddress, - Length, - MmNonCached); - if (*VirtualAddress == NULL) - { - DbgPrint(TRACE_LEVEL_ERROR, ("MmMapIoSpace returned a NULL buffer when trying to allocate 0x%I64x bytes", Length)); - return STATUS_NO_MEMORY; - } - } - - return STATUS_SUCCESS; -} - -NTSTATUS -UnmapFrameBuffer( - _In_reads_bytes_(Length) VOID* VirtualAddress, - _In_ ULONG Length) -{ - PAGED_CODE(); - - - // - // Check for parameters - // - if ((VirtualAddress == NULL) && (Length == 0)) - { - // Allow this function to be called when there's no work to do, and treat as successful - return STATUS_SUCCESS; - } - else if ((VirtualAddress == NULL) || (Length == 0)) - { - DbgPrint(TRACE_LEVEL_ERROR, ("Only one of Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0", - Length, VirtualAddress)); - return STATUS_INVALID_PARAMETER; - } - - MmUnmapIoSpace(VirtualAddress, - Length); +NTSTATUS QxlDevice::SetCurrentMode(ULONG Mode) +{ + NTSTATUS Status = STATUS_SUCCESS; + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s Mode = %x\n", __FUNCTION__, Mode)); + UNREFERENCED_PARAMETER(Mode); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return Status; +} +NTSTATUS QxlDevice::GetCurrentMode(ULONG* pMode) +{ + NTSTATUS Status = STATUS_SUCCESS; + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + UNREFERENCED_PARAMETER(pMode); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); + return Status; +} + +NTSTATUS QxlDevice::SetPowerState(POWER_ACTION ActionType) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + UNREFERENCED_PARAMETER(ActionType); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 048aec8..4536e18 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -24,7 +24,6 @@ typedef struct _QXL_FLAGS #define SHIFT_MIDDLE_6_IN_565_BACK ((BITS_PER_BYTE * 1) + (BITS_PER_BYTE - 6)) #define SHIFT_LOWER_5_IN_565_BACK ((BITS_PER_BYTE * 0) + (BITS_PER_BYTE - 5)) - #pragma pack(push) #pragma pack(1) @@ -204,6 +203,57 @@ typedef struct _CURRENT_BDD_MODE } FrameBuffer; } CURRENT_BDD_MODE; +class QxlDod; + +class HwDeviceIntrface : + public BaseObject +{ +public: +// HwDeviceIntrface(_In_ QxlDod* pQxlDod); +// virtual ~HwDeviceIntrface(void); + virtual NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; + virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0; + virtual NTSTATUS SetCurrentMode(ULONG Mode) = 0; + virtual NTSTATUS GetCurrentMode(ULONG* Mode) = 0; + virtual NTSTATUS SetPowerState(POWER_ACTION ActionType) = 0; + ULONG GetModeCount(void) {return m_ModeCount;} + PVBE_MODEINFO GetModeInfo(UINT idx) {return &m_ModeInfo[idx];} + USHORT GetModeNumber(USHORT idx) {return m_ModeNumbers[idx];} + USHORT GetCurrentModeIndex(void) {return m_CurrentMode;} + VOID SetCurrentModeIndex(USHORT idx) {m_CurrentMode = idx;} +protected: + QxlDod* m_pQxlDod; + PVBE_MODEINFO m_ModeInfo; + ULONG m_ModeCount; + PUSHORT m_ModeNumbers; + USHORT m_CurrentMode; +}; + +class VgaDevice : + public HwDeviceIntrface +{ +public: + VgaDevice(_In_ QxlDod* pQxlDod){m_pQxlDod = pQxlDod;} + virtual ~VgaDevice(void){;} + NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); + NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); + NTSTATUS SetCurrentMode(ULONG Mode); + NTSTATUS GetCurrentMode(ULONG* Mode); + NTSTATUS SetPowerState(POWER_ACTION ActionType); +}; + +class QxlDevice : + public HwDeviceIntrface +{ +public: + QxlDevice(_In_ QxlDod* pQxlDod){m_pQxlDod = pQxlDod;} + virtual ~QxlDevice(void){;} + NTSTATUS GetModeList(void); + NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); + NTSTATUS SetCurrentMode(ULONG Mode); + NTSTATUS GetCurrentMode(ULONG* Mode); + NTSTATUS SetPowerState(POWER_ACTION ActionType); +}; class QxlDod : public BaseObject @@ -216,13 +266,12 @@ private: DEVICE_POWER_STATE m_MonitorPowerState; DEVICE_POWER_STATE m_AdapterPowerState; QXL_FLAGS m_Flags; - PVBE_MODEINFO m_ModeInfo; - ULONG m_ModeCount; - PUSHORT m_ModeNumbers; - USHORT m_CurrentMode; + CURRENT_BDD_MODE m_CurrentModes[MAX_VIEWS]; + D3DDDI_VIDEO_PRESENT_SOURCE_ID m_SystemDisplaySourceId; DXGKARG_SETPOINTERSHAPE m_PointerShape; + HwDeviceIntrface* m_pHWDevice; public: QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject); ~QxlDod(void); @@ -341,7 +390,6 @@ private: NTSTATUS RegisterHWInfo(); - NTSTATUS VbeGetModeList(); NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, _In_ UINT DstBitPerPixel, @@ -372,37 +420,6 @@ private: UINT NumRects, _In_reads_(NumRects) CONST RECT *pRects); VOID BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId); - - NTSTATUS VbeQueryCurrentMode(PVIDEO_MODE RequestedMode); - NTSTATUS VbeSetCurrentMode(ULONG Mode); - NTSTATUS VbeGetCurrentMode(ULONG* Mode); - NTSTATUS VbeSetPowerState(POWER_ACTION ActionType); - UINT BPPFromPixelFormat(D3DDDIFORMAT Format) const - { - switch (Format) - { - case D3DDDIFMT_UNKNOWN: return 0; - case D3DDDIFMT_P8: return 8; - case D3DDDIFMT_R5G6B5: return 16; - case D3DDDIFMT_R8G8B8: return 24; - case D3DDDIFMT_X8R8G8B8: // fall through - case D3DDDIFMT_A8R8G8B8: return 32; - default: QXL_LOG_ASSERTION1("Unknown D3DDDIFORMAT 0x%I64x", Format); return 0; - } - } - - // Given bits per pixel, return the pixel format at the same bpp - D3DDDIFORMAT PixelFormatFromBPP(UINT BPP) const - { - switch (BPP) - { - case 8: return D3DDDIFMT_P8; - case 16: return D3DDDIFMT_R5G6B5; - case 24: return D3DDDIFMT_R8G8B8; - case 32: return D3DDDIFMT_X8R8G8B8; - default: QXL_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not supported.", BPP); return D3DDDIFMT_UNKNOWN; - } - } }; NTSTATUS @@ -416,3 +433,30 @@ UnmapFrameBuffer( _In_reads_bytes_(Length) VOID* VirtualAddress, _In_ ULONG Length); + +UINT BPPFromPixelFormat(D3DDDIFORMAT Format) +{ + switch (Format) + { + case D3DDDIFMT_UNKNOWN: return 0; + case D3DDDIFMT_P8: return 8; + case D3DDDIFMT_R5G6B5: return 16; + case D3DDDIFMT_R8G8B8: return 24; + case D3DDDIFMT_X8R8G8B8: // fall through + case D3DDDIFMT_A8R8G8B8: return 32; + default: QXL_LOG_ASSERTION1("Unknown D3DDDIFORMAT 0x%I64x", Format); return 0; + } +} + +// Given bits per pixel, return the pixel format at the same bpp +D3DDDIFORMAT PixelFormatFromBPP(UINT BPP) +{ + switch (BPP) + { + case 8: return D3DDDIFMT_P8; + case 16: return D3DDDIFMT_R5G6B5; + case 24: return D3DDDIFMT_R8G8B8; + case 32: return D3DDDIFMT_X8R8G8B8; + default: QXL_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not supported.", BPP); return D3DDDIFMT_UNKNOWN; + } +} diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp index bdf4c04..a92ab17 100755 --- a/qxldod/driver.cpp +++ b/qxldod/driver.cpp @@ -659,7 +659,7 @@ void DebugPrintFuncSerial(const char *format, ...) } if (len) { - WRITE_PORT_BUFFER_UCHAR(RHEL_DEBUG_PORT, (PUCHAR)buf, len); + WRITE_PORT_BUFFER_UCHAR(RHEL_DEBUG_PORT, (PUCHAR)buf, (ULONG)len); WRITE_PORT_UCHAR(RHEL_DEBUG_PORT, '\r'); } } From 08a8760977c5a9e25a21441bd35c05263838de8d Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Tue, 4 Feb 2014 22:50:47 +1100 Subject: [PATCH 10/46] more qxl bits --- qxldod/QxlDod.cpp | 362 +++++++++++++++++++++++++++++++++++------- qxldod/QxlDod.h | 65 ++++++-- qxldod/qxldod.vcxproj | 8 +- 3 files changed, 368 insertions(+), 67 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index c0eb839..a48023f 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -85,7 +85,7 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, RtlCopyMemory(&m_DxgkInterface, pDxgkInterface, sizeof(m_DxgkInterface)); RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes)); //CHECK ME!!!!!!!!!!!!! - m_CurrentModes[0].DispInfo.TargetId = D3DDDI_ID_UNINITIALIZED; + m_CurrentModes[0].DispInfo.TargetId = D3DDDI_ID_UNINITIALIZED; // Get device information from OS. NTSTATUS Status = m_DxgkInterface.DxgkCbGetDeviceInformation(m_DxgkInterface.DeviceHandle, &m_DeviceInfo); if (!NT_SUCCESS(Status)) @@ -120,7 +120,7 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, return STATUS_UNSUCCESSFUL; } - Status = m_pHWDevice->HWInit(m_DeviceInfo.TranslatedResourceList); + Status = m_pHWDevice->HWInit(m_DeviceInfo.TranslatedResourceList, &m_CurrentModes[0].DispInfo); if (!NT_SUCCESS(Status)) { QXL_LOG_ASSERTION1("HWInit failed with status 0x%X\n", @@ -128,14 +128,6 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, return Status; } - Status = m_pHWDevice->GetModeList(&m_CurrentModes[0].DispInfo); - if (!NT_SUCCESS(Status)) - { - QXL_LOG_ASSERTION1("GetModeList failed with status 0x%X\n", - Status); - return Status; - } - *pNumberOfViews = MAX_VIEWS; *pNumberOfChildren = MAX_CHILDREN; m_Flags.DriverStarted = TRUE; @@ -691,7 +683,7 @@ NTSTATUS QxlDod::AddSingleSourceMode(_In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFAC { // Create new mode info that will be populated D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo = NULL; - PVBE_MODEINFO pModeInfo = m_pHWDevice->GetModeInfo(idx); + PVIDEO_MODE_INFORMATION pModeInfo = m_pHWDevice->GetModeInfo(idx); NTSTATUS Status = pVidPnSourceModeSetInterface->pfnCreateNewModeInfo(hVidPnSourceModeSet, &pVidPnSourceModeInfo); if (!NT_SUCCESS(Status)) { @@ -703,10 +695,10 @@ NTSTATUS QxlDod::AddSingleSourceMode(_In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFAC // Populate mode info with values from current mode and hard-coded values // Always report 32 bpp format, this will be color converted during the present if the mode is < 32bpp pVidPnSourceModeInfo->Type = D3DKMDT_RMT_GRAPHICS; - pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx = pModeInfo->XResolution; - pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy = pModeInfo->YResolution; + pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx = pModeInfo->VisScreenWidth; + pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy = pModeInfo->VisScreenHeight; pVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize; - pVidPnSourceModeInfo->Format.Graphics.Stride = pModeInfo->BytesPerScanLine / pModeInfo->XResolution; + pVidPnSourceModeInfo->Format.Graphics.Stride = pModeInfo->ScreenStride; pVidPnSourceModeInfo->Format.Graphics.PixelFormat = D3DDDIFMT_A8R8G8B8; pVidPnSourceModeInfo->Format.Graphics.ColorBasis = D3DKMDT_CB_SCRGB; pVidPnSourceModeInfo->Format.Graphics.PixelValueAccessMode = D3DKMDT_PVAM_DIRECT; @@ -747,7 +739,7 @@ NTSTATUS QxlDod::AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFAC //FIXME !!!!!! for (UINT ModeIndex = 0; ModeIndex < m_pHWDevice->GetModeCount(); ++ModeIndex) { - PVBE_MODEINFO pModeInfo = m_pHWDevice->GetModeInfo(SourceId); + PVIDEO_MODE_INFORMATION pModeInfo = m_pHWDevice->GetModeInfo(SourceId); pVidPnTargetModeInfo = NULL; Status = pVidPnTargetModeSetInterface->pfnCreateNewModeInfo(hVidPnTargetModeSet, &pVidPnTargetModeInfo); if (!NT_SUCCESS(Status)) @@ -757,8 +749,8 @@ NTSTATUS QxlDod::AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFAC return Status; } pVidPnTargetModeInfo->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER; - pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cx = pModeInfo->XResolution; - pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cy = pModeInfo->YResolution; + pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cx = pModeInfo->VisScreenWidth; + pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cy = pModeInfo->VisScreenHeight; pVidPnTargetModeInfo->VideoSignalInfo.ActiveSize = pVidPnTargetModeInfo->VideoSignalInfo.TotalSize; pVidPnTargetModeInfo->VideoSignalInfo.VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED; pVidPnTargetModeInfo->VideoSignalInfo.VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED; @@ -792,7 +784,7 @@ NTSTATUS QxlDod::AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* PAGED_CODE(); NTSTATUS Status = STATUS_SUCCESS; D3DKMDT_MONITOR_SOURCE_MODE* pMonitorSourceMode = NULL; - PVBE_MODEINFO pVbeModeInfo = NULL; + PVIDEO_MODE_INFORMATION pVbeModeInfo = NULL; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); @@ -804,12 +796,12 @@ NTSTATUS QxlDod::AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* return Status; } - pVbeModeInfo = m_pHWDevice->GetModeInfo(m_pHWDevice->GetCurrentModeIndex());//&m_ModeInfo[m_CurrentMode]; + pVbeModeInfo = m_pHWDevice->GetModeInfo(m_pHWDevice->GetCurrentModeIndex()); // Since we don't know the real monitor timing information, just use the current display mode (from the POST device) with unknown frequencies pMonitorSourceMode->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER; - pMonitorSourceMode->VideoSignalInfo.TotalSize.cx = pVbeModeInfo->XResolution; - pMonitorSourceMode->VideoSignalInfo.TotalSize.cy = pVbeModeInfo->YResolution; + pMonitorSourceMode->VideoSignalInfo.TotalSize.cx = pVbeModeInfo->VisScreenWidth; + pMonitorSourceMode->VideoSignalInfo.TotalSize.cy = pVbeModeInfo->VisScreenHeight; pMonitorSourceMode->VideoSignalInfo.ActiveSize = pMonitorSourceMode->VideoSignalInfo.TotalSize; pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED; pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED; @@ -864,12 +856,12 @@ NTSTATUS QxlDod::AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* DbgPrint(TRACE_LEVEL_INFORMATION, ("%s: add pref mode, dimensions %ux%u, taken from DxgkCbAcquirePostDisplayOwnership at StartDevice\n", __FUNCTION__, - pVbeModeInfo->XResolution, pVbeModeInfo->YResolution)); + pVbeModeInfo->VisScreenWidth, pVbeModeInfo->VisScreenHeight)); // Since we don't know the real monitor timing information, just use the current display mode (from the POST device) with unknown frequencies pMonitorSourceMode->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER; - pMonitorSourceMode->VideoSignalInfo.TotalSize.cx = pVbeModeInfo->XResolution; - pMonitorSourceMode->VideoSignalInfo.TotalSize.cy = pVbeModeInfo->YResolution; + pMonitorSourceMode->VideoSignalInfo.TotalSize.cx = pVbeModeInfo->VisScreenWidth; + pMonitorSourceMode->VideoSignalInfo.TotalSize.cy = pVbeModeInfo->VisScreenHeight; pMonitorSourceMode->VideoSignalInfo.ActiveSize = pMonitorSourceMode->VideoSignalInfo.TotalSize; pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED; pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED; @@ -1524,9 +1516,9 @@ NTSTATUS QxlDod::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMo pCurrentBddMode->Flags.FullscreenPresent = TRUE; for (USHORT ModeIndex = 0; ModeIndex < m_pHWDevice->GetModeCount(); ++ModeIndex) { - PVBE_MODEINFO pModeInfo = m_pHWDevice->GetModeInfo(m_pHWDevice->GetCurrentModeIndex()); - if (pCurrentBddMode->DispInfo.Width == pModeInfo->XResolution && - pCurrentBddMode->DispInfo.Height == pModeInfo->YResolution ) + PVIDEO_MODE_INFORMATION pModeInfo = m_pHWDevice->GetModeInfo(m_pHWDevice->GetCurrentModeIndex()); + if (pCurrentBddMode->DispInfo.Width == pModeInfo->VisScreenWidth && + pCurrentBddMode->DispInfo.Height == pModeInfo->VisScreenHeight ) { Status = m_pHWDevice->SetCurrentMode(m_pHWDevice->GetModeNumber(ModeIndex)); if (NT_SUCCESS(Status)) @@ -1944,13 +1936,12 @@ QxlDod::ExecutePresentDisplayOnly( RtlZeroMemory(ctx,size); -// const CURRENT_BDD_MODE* pModeCur = GetCurrentMode(m_SourceId); const CURRENT_BDD_MODE* pModeCur = &m_CurrentModes[0]; ctx->DstAddr = DstAddr; ctx->DstBitPerPixel = DstBitPerPixel; - ctx->DstStride = pModeCur->DispInfo.Pitch; //m_ModeInfo[m_CurrentMode].BytesPerScanLine;// - ctx->SrcWidth = pModeCur->SrcModeWidth;//m_ModeInfo[m_CurrentMode].XResolution;// - ctx->SrcHeight = pModeCur->SrcModeHeight;//m_ModeInfo[m_CurrentMode].YResolution;// + ctx->DstStride = pModeCur->DispInfo.Pitch; + ctx->SrcWidth = pModeCur->SrcModeWidth; + ctx->SrcHeight = pModeCur->SrcModeHeight; ctx->SrcAddr = NULL; ctx->SrcPitch = SrcPitch; ctx->Rotation = Rotation; @@ -2477,6 +2468,43 @@ VgaDevice::~VgaDevice(void) m_ModeCount = 0; } +BOOL VgaDevice::SetVideoModeInfo(UINT Idx, PVBE_MODEINFO pModeInfo) +{ + PVIDEO_MODE_INFORMATION pMode = NULL; + PAGED_CODE(); + + pMode = &m_ModeInfo[Idx]; + pMode->Length = sizeof(VIDEO_MODE_INFORMATION); + pMode->ModeIndex = Idx;//m_ModeNumbers[Idx]; + pMode->VisScreenWidth = pModeInfo->XResolution; + pMode->VisScreenHeight = pModeInfo->YResolution; + pMode->ScreenStride = pModeInfo->LinBytesPerScanLine; + pMode->NumberOfPlanes = pModeInfo->NumberOfPlanes; + pMode->BitsPerPlane = pModeInfo->BitsPerPixel / pModeInfo->NumberOfPlanes; + pMode->Frequency = 60; + pMode->XMillimeter = pModeInfo->XResolution * 254 / 720; + pMode->YMillimeter = pModeInfo->YResolution * 254 / 720; + + if (pModeInfo->BitsPerPixel == 15 && pModeInfo->NumberOfPlanes == 1) + { + pMode->BitsPerPlane = 16; + } + + pMode->NumberRedBits = pModeInfo->LinRedMaskSize; + pMode->NumberGreenBits = pModeInfo->LinGreenMaskSize; + pMode->NumberBlueBits = pModeInfo->LinBlueMaskSize; + pMode->RedMask = ((1 << pModeInfo->LinRedMaskSize) - 1) << pModeInfo->LinRedFieldPosition; + pMode->GreenMask = ((1 << pModeInfo->LinGreenMaskSize) - 1) << pModeInfo->LinGreenFieldPosition; + pMode->BlueMask = ((1 << pModeInfo->LinBlueMaskSize) - 1) << pModeInfo->LinBlueFieldPosition; + + pMode->AttributeFlags = VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS | VIDEO_MODE_NO_OFF_SCREEN; + pMode->VideoMemoryBitmapWidth = pModeInfo->XResolution; + pMode->VideoMemoryBitmapHeight = pModeInfo->YResolution; + pMode->DriverSpecificAttributeFlags = 0; + + return TRUE; +} + NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) { PAGED_CODE(); @@ -2486,9 +2514,9 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) ULONG SuitableModeCount; USHORT ModeTemp; USHORT CurrentMode; - PVBE_MODEINFO VbeModeInfo; VBE_INFO VbeInfo = {0}; ULONG Length; + VBE_MODEINFO tmpModeInfo; NTSTATUS Status = STATUS_SUCCESS; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); @@ -2560,7 +2588,7 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount %d\n", ModeCount)); - m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VBE_MODEINFO) * ModeCount]); + m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VIDEO_MODE_INFORMATION) * ModeCount]); m_ModeNumbers = reinterpret_cast (new (PagedPool) BYTE [sizeof (USHORT) * ModeCount]); m_CurrentMode = 0; DbgPrint(TRACE_LEVEL_ERROR, ("m_ModeInfo = 0x%p, m_ModeNumbers = 0x%p\n", m_ModeInfo, m_ModeNumbers)); @@ -2594,22 +2622,22 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) Status = x86BiosReadMemory ( m_Segment, m_Offset + sizeof (VbeInfo), - m_ModeInfo + SuitableModeCount, + &tmpModeInfo, sizeof(VBE_MODEINFO)); - VbeModeInfo = m_ModeInfo + SuitableModeCount; UINT Height = pDispInfo->Height; UINT Width = pDispInfo->Width; UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); - if (VbeModeInfo->XResolution >= Width && - VbeModeInfo->YResolution >= Height && - VbeModeInfo->BitsPerPixel == BitsPerPixel && - VbeModeInfo->PhysBasePtr != 0) + if (tmpModeInfo.XResolution >= Width && + tmpModeInfo.YResolution >= Height && + tmpModeInfo.BitsPerPixel == BitsPerPixel && + tmpModeInfo.PhysBasePtr != 0) { m_ModeNumbers[SuitableModeCount] = ModeTemp; - if (VbeModeInfo->XResolution == 1024 && - VbeModeInfo->YResolution == 768) + SetVideoModeInfo(SuitableModeCount, &tmpModeInfo); + if (tmpModeInfo.XResolution == 1024 && + tmpModeInfo.YResolution == 768) { m_CurrentMode = (USHORT)SuitableModeCount; } @@ -2629,9 +2657,9 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) { DbgPrint(TRACE_LEVEL_ERROR, ("type %x, XRes = %d, YRes = %d, BPP = %d\n", m_ModeNumbers[idx], - m_ModeInfo[idx].XResolution, - m_ModeInfo[idx].YResolution, - m_ModeInfo[idx].BitsPerPixel)); + m_ModeInfo[idx].VisScreenWidth, + m_ModeInfo[idx].VisScreenHeight, + m_ModeInfo[idx].BitsPerPlane)); } if (m_Segment != 0) @@ -2684,11 +2712,18 @@ NTSTATUS VgaDevice::GetCurrentMode(ULONG* pMode) return Status; } -NTSTATUS VgaDevice::HWInit(PCM_RESOURCE_LIST pResList) +NTSTATUS VgaDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo) { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); UNREFERENCED_PARAMETER(pResList); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return GetModeList(pDispInfo); +} + +NTSTATUS VgaDevice::HWClose(void) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -2717,17 +2752,123 @@ NTSTATUS VgaDevice::SetPowerState(POWER_ACTION ActionType) return STATUS_SUCCESS; } +QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod) +{ + m_pQxlDod = pQxlDod; + m_ModeInfo = NULL; + m_ModeCount = 0; + m_ModeNumbers = NULL; + m_CurrentMode = 0; +} -NTSTATUS QxlDevice::GetModeList() +QxlDevice::~QxlDevice(void) +{ + delete [] reinterpret_cast(m_ModeInfo); + delete [] reinterpret_cast(m_ModeNumbers); + m_ModeInfo = NULL; + m_ModeNumbers = NULL; + m_CurrentMode = 0; + m_ModeCount = 0; +} + +BOOL QxlDevice::SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo) +{ + PVIDEO_MODE_INFORMATION pMode = NULL; + ULONG color_bits; + PAGED_CODE(); + + pMode = &m_ModeInfo[Idx]; + pMode->Length = sizeof(VIDEO_MODE_INFORMATION); + pMode->ModeIndex = Idx;//m_ModeNumbers[Idx]; + pMode->VisScreenWidth = pModeInfo->x_res; + pMode->VisScreenHeight = pModeInfo->y_res; + pMode->ScreenStride = pModeInfo->stride; + pMode->NumberOfPlanes = 1; + pMode->BitsPerPlane = pModeInfo->bits; + pMode->Frequency = 100; + pMode->XMillimeter = pModeInfo->x_mili; + pMode->YMillimeter = pModeInfo->y_mili; + color_bits = (pModeInfo->bits == 16) ? 5 : 8; + pMode->NumberRedBits = color_bits; + pMode->NumberGreenBits = color_bits; + pMode->NumberBlueBits = color_bits; + + pMode->BlueMask = (1 << color_bits) - 1; + pMode->GreenMask = pMode->BlueMask << color_bits; + pMode->RedMask = pMode->GreenMask << color_bits; + + pMode->AttributeFlags = VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS; + pMode->VideoMemoryBitmapWidth = pModeInfo->x_res; + pMode->VideoMemoryBitmapHeight = pModeInfo->y_res; + pMode->DriverSpecificAttributeFlags = pModeInfo->orientation; + return TRUE; +} + +NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) { PAGED_CODE(); NTSTATUS Status = STATUS_SUCCESS; + QXLModes *modes; + ULONG ModeCount; + ULONG SuitableModeCount; + USHORT CurrentMode; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - if (!NT_SUCCESS (Status)) - { - DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosWriteMemory failed with Status: 0x%X\n", Status)); - return Status; + + modes = (QXLModes *)((UCHAR*)m_RomHdr + m_RomHdr->modes_offset); + if (m_RomSize < m_RomHdr->modes_offset + sizeof(QXLModes) || + (ModeCount = modes->n_modes) == 0 || m_RomSize < + m_RomHdr->modes_offset + sizeof(QXLModes) + ModeCount * sizeof(QXLMode)) { + DbgPrint(TRACE_LEVEL_ERROR, ("%s: bad rom size\n", __FUNCTION__)); + return STATUS_UNSUCCESSFUL; } + + ModeCount += 2; + m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VIDEO_MODE_INFORMATION) * ModeCount]); + m_ModeNumbers = reinterpret_cast (new (PagedPool) BYTE [sizeof (USHORT) * ModeCount]); + m_CurrentMode = 0; + + for (CurrentMode = 0, SuitableModeCount = 0; + CurrentMode < ModeCount; + CurrentMode++) + { + + UINT Height = pDispInfo->Height; + UINT Width = pDispInfo->Width; + UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); + QXLMode* tmpModeInfo = &modes->modes[CurrentMode]; + + if (tmpModeInfo->x_res >= Width && + tmpModeInfo->y_res >= Height && + tmpModeInfo->bits == BitsPerPixel) + { + m_ModeNumbers[SuitableModeCount] = (USHORT)SuitableModeCount; + SetVideoModeInfo(SuitableModeCount, tmpModeInfo); + if (tmpModeInfo->x_res == 1024 && + tmpModeInfo->y_res == 768) + { + m_CurrentMode = (USHORT)SuitableModeCount; + } + SuitableModeCount++; + } + } + + if (SuitableModeCount == 0) + { + DbgPrint(TRACE_LEVEL_ERROR, ("No video modes supported\n")); + Status = STATUS_UNSUCCESSFUL; + } + + m_ModeCount = SuitableModeCount; + DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount)); + for (ULONG idx = 0; idx < m_ModeCount; idx++) + { + DbgPrint(TRACE_LEVEL_ERROR, ("type %x, XRes = %d, YRes = %d, BPP = %d\n", + m_ModeNumbers[idx], + m_ModeInfo[idx].VisScreenWidth, + m_ModeInfo[idx].VisScreenHeight, + m_ModeInfo[idx].BitsPerPlane)); + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return Status; } @@ -2766,9 +2907,10 @@ NTSTATUS QxlDevice::SetPowerState(POWER_ACTION ActionType) return STATUS_SUCCESS; } -NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList) +NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo) { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + NTSTATUS Status = STATUS_SUCCESS; PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod->GetDxgkInterrface(); UINT pci_range = QXL_RAM_RANGE_INDEX; for (ULONG i = 0; i < pResList->Count; ++i) @@ -2818,7 +2960,6 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList) m_IoBase, m_IoBase + m_IoSize)); - } break; case CmResourceTypeInterrupt: @@ -2886,13 +3027,32 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList) } if (m_IoBase == NULL || m_IoSize == 0 || m_RomHdr == NULL || m_RomSize == 0 || + m_RomHdr->magic != QXL_ROM_MAGIC || m_RamStart == NULL || m_RamSize == 0 || - m_VRamStart == NULL || m_VRamSize == 0) + m_VRamStart == NULL || m_VRamSize == 0 || + (m_RamHdr = (QXLRam *)(m_RamStart + m_RomHdr->ram_header_offset)) == NULL || + m_RamHdr->magic != QXL_RAM_MAGIC || !InitMemSlots()) { UnmapMemory(); + DestroyMemSlots(); return STATUS_UNSUCCESSFUL; } + m_LogBuf = m_RamHdr->log_buf; + m_LogPort = m_IoBase + QXL_IO_LOG; + + Status = GetModeList(pDispInfo); + if (!NT_SUCCESS(Status)) + { + QXL_LOG_ASSERTION1("GetModeList failed with status 0x%X\n", + Status); + return Status; + } + + CreateEvents(); + CreateRings(); + CreateMemSlots(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -2923,6 +3083,102 @@ void QxlDevice::UnmapMemory(void) m_VRamStart = NULL; } } + +BOOL QxlDevice::InitMemSlots(void) +{ + m_NumMemSlots = m_RomHdr->slots_end; + m_SlotGenBits = m_RomHdr->slot_gen_bits; + m_SlotIdBits = m_RomHdr->slot_id_bits; + m_VaSlotMask = (~(uint64_t)0) >> (m_SlotIdBits + m_SlotGenBits); + size_t size = m_NumMemSlots * sizeof(MemSlot); + m_MemSlots = reinterpret_cast + (new (PagedPool) BYTE[size]); + if (m_MemSlots) + { + RtlZeroMemory(m_MemSlots, size); + return TRUE; + } + return FALSE; +} + +void QxlDevice::DestroyMemSlots(void) +{ + delete [] reinterpret_cast(m_MemSlots); + m_MemSlots = NULL; +} + +void QxlDevice::SetupHWSlot(UINT8 Idx, MemSlot *pSlot) +{ + m_RamHdr->mem_slot.mem_start = pSlot->start_phys_addr; + m_RamHdr->mem_slot.mem_end = pSlot->end_phys_addr; + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_MEMSLOT_ADD), Idx); +} + +BOOL QxlDevice::CreateEvents() +{ + KeInitializeEvent(&m_DisplayEvent, + SynchronizationEvent, + FALSE); + KeInitializeEvent(&m_CursorEvent, + SynchronizationEvent, + FALSE); + KeInitializeEvent(&m_IoCmdEvent, + SynchronizationEvent, + FALSE); + return TRUE; +} + +BOOL QxlDevice::CreateRings() +{ + m_CommandRing = &(m_RamHdr->cmd_ring); + m_CursorRing = &(m_RamHdr->cursor_ring); + m_ReleaseRing = &(m_RamHdr->release_ring); + return TRUE; +} + +UINT8 QxlDevice::SetupMemSlot(UINT8 Idx, QXLPHYSICAL start, QXLPHYSICAL end) +{ + UINT64 high_bits; + MemSlot *pSlot; + UINT8 slot_index; + + slot_index = m_RomHdr->slots_start + Idx; + pSlot = &m_MemSlots[slot_index]; + pSlot->start_phys_addr = start; + pSlot->end_phys_addr = end; + + SetupHWSlot(Idx, pSlot); + + pSlot->generation = m_RomHdr->slot_generation; + high_bits = slot_index << m_SlotGenBits; + high_bits |= pSlot->generation; + high_bits <<= (64 - (m_SlotGenBits + m_SlotIdBits)); + pSlot->high_bits = high_bits; + return slot_index; +} + +BOOL QxlDevice::CreateMemSlots(void) +{ + m_MainMemSlot= SetupMemSlot(0, (QXLPHYSICAL)m_VRamStart, (QXLPHYSICAL)(m_VRamStart + m_RomHdr->ram_header_offset)); + m_SurfaceMemSlot = SetupMemSlot(1, (QXLPHYSICAL)m_RamStart, (QXLPHYSICAL)(m_RamStart + m_RamSize)); + return TRUE; +} + +void QxlDevice::ResetDevice(void) +{ + m_RamHdr->int_mask = ~0; + WRITE_PORT_UCHAR(m_IoBase + QXL_IO_MEMSLOT_ADD, 0); +} + +NTSTATUS QxlDevice::HWClose(void) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + UnmapMemory(); + DestroyMemSlots(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + UINT BPPFromPixelFormat(D3DDDIFORMAT Format) { switch (Format) diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 48aad47..36c8aa1 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -212,20 +212,22 @@ class HwDeviceIntrface : public: // HwDeviceIntrface(_In_ QxlDod* pQxlDod); // virtual ~HwDeviceIntrface(void); - virtual NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0; virtual NTSTATUS SetCurrentMode(ULONG Mode) = 0; virtual NTSTATUS GetCurrentMode(ULONG* Mode) = 0; virtual NTSTATUS SetPowerState(POWER_ACTION ActionType) = 0; - virtual NTSTATUS HWInit(PCM_RESOURCE_LIST pResList) = 0; + virtual NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; + virtual NTSTATUS HWClose(void) = 0; ULONG GetModeCount(void) {return m_ModeCount;} - PVBE_MODEINFO GetModeInfo(UINT idx) {return &m_ModeInfo[idx];} + PVIDEO_MODE_INFORMATION GetModeInfo(UINT idx) {return &m_ModeInfo[idx];} USHORT GetModeNumber(USHORT idx) {return m_ModeNumbers[idx];} USHORT GetCurrentModeIndex(void) {return m_CurrentMode;} VOID SetCurrentModeIndex(USHORT idx) {m_CurrentMode = idx;} +protected: + virtual NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; protected: QxlDod* m_pQxlDod; - PVBE_MODEINFO m_ModeInfo; + PVIDEO_MODE_INFORMATION m_ModeInfo; ULONG m_ModeCount; PUSHORT m_ModeNumbers; USHORT m_CurrentMode; @@ -237,28 +239,52 @@ class VgaDevice : public: VgaDevice(_In_ QxlDod* pQxlDod); virtual ~VgaDevice(void); - NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); NTSTATUS SetCurrentMode(ULONG Mode); NTSTATUS GetCurrentMode(ULONG* Mode); NTSTATUS SetPowerState(POWER_ACTION ActionType); - NTSTATUS HWInit(PCM_RESOURCE_LIST pResList); + NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); + NTSTATUS HWClose(void); +protected: + NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); +private: + BOOL SetVideoModeInfo(UINT Idx, PVBE_MODEINFO pModeInfo); }; +typedef struct _MemSlot { + UINT8 generation; + UINT64 start_phys_addr; + UINT64 end_phys_addr; + UINT64 start_virt_addr; + UINT64 end_virt_addr; + QXLPHYSICAL high_bits; +} MemSlot; + class QxlDevice : public HwDeviceIntrface { public: - QxlDevice(_In_ QxlDod* pQxlDod){m_pQxlDod = pQxlDod;} - virtual ~QxlDevice(void){;} - NTSTATUS GetModeList(void); + QxlDevice(_In_ QxlDod* pQxlDod); + virtual ~QxlDevice(void); NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); NTSTATUS SetCurrentMode(ULONG Mode); NTSTATUS GetCurrentMode(ULONG* Mode); NTSTATUS SetPowerState(POWER_ACTION ActionType); - NTSTATUS HWInit(PCM_RESOURCE_LIST pResList); + NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); + NTSTATUS HWClose(void); +protected: + NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); private: void UnmapMemory(void); + BOOL SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo); + BOOL InitMemSlots(void); + BOOL CreateMemSlots(void); + void DestroyMemSlots(void); + void ResetDevice(void); + void SetupHWSlot(UINT8 Idx, MemSlot *pSlot); + UINT8 SetupMemSlot(UINT8 Idx, QXLPHYSICAL start, QXLPHYSICAL end); + BOOL CreateEvents(); + BOOL CreateRings(); private: PUCHAR m_IoBase; BOOLEAN m_IoMapped; @@ -275,6 +301,25 @@ private: QXLRom *m_RomHdr; ULONG m_RomSize; + + MemSlot *m_MemSlots; + UINT8 m_NumMemSlots; + UINT8 m_MainMemSlot; + UINT8 m_SurfaceMemSlot; + UINT8 m_SlotIdBits; + UINT8 m_SlotGenBits; + QXLPHYSICAL m_VaSlotMask; + + QXLCommandRing *m_CommandRing; + QXLCursorRing *m_CursorRing; + QXLReleaseRing *m_ReleaseRing; + + KEVENT m_DisplayEvent; + KEVENT m_CursorEvent; + KEVENT m_IoCmdEvent; + + PUCHAR m_LogPort; + PUCHAR m_LogBuf; }; class QxlDod : diff --git a/qxldod/qxldod.vcxproj b/qxldod/qxldod.vcxproj index 0bc2638..12e6938 100755 --- a/qxldod/qxldod.vcxproj +++ b/qxldod/qxldod.vcxproj @@ -90,7 +90,7 @@ %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH);.\Include Level3 @@ -106,7 +106,7 @@ %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH);.\Include Inf2Cat /driver:$(OutDir) /os:8_X86 @@ -120,7 +120,7 @@ %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH);.\Include Inf2Cat /driver:$(OutDir) /os:8_X64 @@ -134,7 +134,7 @@ %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH);.\Include Inf2Cat /driver:$(OutDir) /os:8_X64 From 529445dbb99d4c5511644ecc257bfe786045ec78 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 10 Mar 2014 22:49:58 +1100 Subject: [PATCH 11/46] add dual interface to support QXL or VGA modes --- qxldod/QxlDod.cpp | 1204 ++++++++++++++++++++++++--------------------- qxldod/QxlDod.h | 116 +++-- 2 files changed, 728 insertions(+), 592 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index a48023f..3e29478 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -55,7 +55,7 @@ QxlDod::QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pP RtlZeroMemory(&m_DeviceInfo, sizeof(m_DeviceInfo)); RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes)); RtlZeroMemory(&m_PointerShape, sizeof(m_PointerShape)); - m_pHWDevice = new(PagedPool) VgaDevice(this); + m_pHWDevice = NULL; DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); } @@ -66,9 +66,46 @@ QxlDod::~QxlDod(void) DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); CleanUp(); delete m_pHWDevice; + m_pHWDevice = NULL; DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } +NTSTATUS QxlDod::CheckHardware() +{ + PAGED_CODE(); + + NTSTATUS Status; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + + // Get the Vendor & Device IDs on PCI system + PCI_COMMON_HEADER Header = {0}; + ULONG BytesRead; + + Status = m_DxgkInterface.DxgkCbReadDeviceSpace(m_DxgkInterface.DeviceHandle, + DXGK_WHICHSPACE_CONFIG, + &Header, + 0, + sizeof(Header), + &BytesRead); + + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbReadDeviceSpace failed with status 0x%X\n", Status)); + return Status; + } + + Status = STATUS_GRAPHICS_DRIVER_MISMATCH; + if (Header.VendorID == 0x1B36 && + Header.DeviceID == 0x0100 && + Header.RevisionID == 4) + { + Status = STATUS_SUCCESS; + } + + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s returned with status 0x%X\n", __FUNCTION__, Status)); + return Status; +} NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, _In_ DXGKRNL_INTERFACE* pDxgkInterface, @@ -103,13 +140,6 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, return Status; } -// TODO: Uncomment the line below after updating the TODOs in the function CheckHardware -// Status = CheckHardware(); -// if (!NT_SUCCESS(Status)) -// { -// return Status; -// } - // This sample driver only uses the frame buffer of the POST device. DxgkCbAcquirePostDisplayOwnership // gives you the frame buffer address and ensures that no one else is drawing to it. Be sure to give it back! Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &(m_CurrentModes[0].DispInfo)); @@ -117,14 +147,25 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, { // The most likely cause of failure is that the driver is simply not running on a POST device, or we are running // after a pre-WDDM 1.2 driver. Since we can't draw anything, we should fail to start. + DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbAcquirePostDisplayOwnership failed with status 0x%X Width = %d\n", + Status, m_CurrentModes[0].DispInfo.Width)); return STATUS_UNSUCCESSFUL; } + Status = CheckHardware(); + if (NT_SUCCESS(Status)) + { + m_pHWDevice = new(PagedPool) QxlDevice(this); + } + else + { + m_pHWDevice = new(PagedPool) VgaDevice(this); + } + Status = m_pHWDevice->HWInit(m_DeviceInfo.TranslatedResourceList, &m_CurrentModes[0].DispInfo); if (!NT_SUCCESS(Status)) { - QXL_LOG_ASSERTION1("HWInit failed with status 0x%X\n", - Status); + DbgPrint(TRACE_LEVEL_ERROR, ("HWInit failed with status 0x%X\n", Status)); return Status; } @@ -456,7 +497,7 @@ NTSTATUS QxlDod::PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPre m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].SrcModeWidth)*DstBitPerPixel/8; pDst += (int)CenterShift/2; } - Status = ExecutePresentDisplayOnly( + Status = m_pHWDevice->ExecutePresentDisplayOnly( pDst, DstBitPerPixel, (BYTE*)pPresentDisplayOnly->pSource, @@ -466,7 +507,8 @@ NTSTATUS QxlDod::PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPre pPresentDisplayOnly->pMoves, pPresentDisplayOnly->NumDirtyRects, pPresentDisplayOnly->pDirtyRect, - RotationNeededByFb); + RotationNeededByFb, + &m_CurrentModes[0]); } DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return Status; @@ -499,62 +541,13 @@ NTSTATUS QxlDod::StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRE } // The driver has to black out the display and ensure it is visible when releasing ownership - BlackOutScreen(SourceId); + m_pHWDevice->BlackOutScreen(&m_CurrentModes[SourceId]); *pDisplayInfo = m_CurrentModes[SourceId].DispInfo; return StopDevice(); } -VOID QxlDod::BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId) -{ - PAGED_CODE(); - - UINT ScreenHeight = m_CurrentModes[SourceId].DispInfo.Height; - UINT ScreenPitch = m_CurrentModes[SourceId].DispInfo.Pitch; - - PHYSICAL_ADDRESS NewPhysAddrStart = m_CurrentModes[SourceId].DispInfo.PhysicAddress; - PHYSICAL_ADDRESS NewPhysAddrEnd; - NewPhysAddrEnd.QuadPart = NewPhysAddrStart.QuadPart + (ScreenHeight * ScreenPitch); - - if (m_CurrentModes[SourceId].Flags.FrameBufferIsActive) - { - BYTE* MappedAddr = reinterpret_cast(m_CurrentModes[SourceId].FrameBuffer.Ptr); - - // Zero any memory at the start that hasn't been zeroed recently - if (NewPhysAddrStart.QuadPart < m_CurrentModes[SourceId].ZeroedOutStart.QuadPart) - { - if (NewPhysAddrEnd.QuadPart < m_CurrentModes[SourceId].ZeroedOutStart.QuadPart) - { - // No overlap - RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch); - } - else - { - RtlZeroMemory(MappedAddr, (UINT)(m_CurrentModes[SourceId].ZeroedOutStart.QuadPart - NewPhysAddrStart.QuadPart)); - } - } - - // Zero any memory at the end that hasn't been zeroed recently - if (NewPhysAddrEnd.QuadPart > m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart) - { - if (NewPhysAddrStart.QuadPart > m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart) - { - // No overlap - // NOTE: When actual pixels were the most recent thing drawn, ZeroedOutStart & ZeroedOutEnd will both be 0 - // and this is the path that will be used to black out the current screen. - RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch); - } - else - { - RtlZeroMemory(MappedAddr, (UINT)(NewPhysAddrEnd.QuadPart - m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart)); - } - } - } - - m_CurrentModes[SourceId].ZeroedOutStart.QuadPart = NewPhysAddrStart.QuadPart; - m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart = NewPhysAddrEnd.QuadPart; -} NTSTATUS QxlDod::QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps) { @@ -1275,7 +1268,7 @@ NTSTATUS QxlDod::SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIB } else { - BlackOutScreen(SourceId); + m_pHWDevice->BlackOutScreen(&m_CurrentModes[SourceId]); } // Store current visibility so it can be dealt with during Present call @@ -1481,7 +1474,7 @@ NTSTATUS QxlDod::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMo CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) { PAGED_CODE(); - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s SourceId = %d\n", __FUNCTION__, pPath->VidPnSourceId)); NTSTATUS Status = STATUS_SUCCESS; @@ -1510,13 +1503,15 @@ NTSTATUS QxlDod::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMo { pCurrentBddMode->Flags.FrameBufferIsActive = TRUE; - BlackOutScreen(pPath->VidPnSourceId); + m_pHWDevice->BlackOutScreen(&m_CurrentModes[pPath->VidPnSourceId]); // Mark that the next present should be fullscreen so the screen doesn't go from black to actual pixels one dirty rect at a time. pCurrentBddMode->Flags.FullscreenPresent = TRUE; for (USHORT ModeIndex = 0; ModeIndex < m_pHWDevice->GetModeCount(); ++ModeIndex) { - PVIDEO_MODE_INFORMATION pModeInfo = m_pHWDevice->GetModeInfo(m_pHWDevice->GetCurrentModeIndex()); + PVIDEO_MODE_INFORMATION pModeInfo = m_pHWDevice->GetModeInfo(ModeIndex); + DbgPrint(TRACE_LEVEL_INFORMATION, ("%d\t%d x %d\t%d x %d\n", ModeIndex, pCurrentBddMode->DispInfo.Width, pCurrentBddMode->DispInfo.Height, + pModeInfo->VisScreenWidth, pModeInfo->VisScreenHeight)); if (pCurrentBddMode->DispInfo.Width == pModeInfo->VisScreenWidth && pCurrentBddMode->DispInfo.Height == pModeInfo->VisScreenHeight ) { @@ -1530,7 +1525,7 @@ NTSTATUS QxlDod::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMo } } - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); return Status; } @@ -1877,481 +1872,6 @@ NTSTATUS QxlDod::RegisterHWInfo() } -NTSTATUS -QxlDod::ExecutePresentDisplayOnly( - _In_ BYTE* DstAddr, - _In_ UINT DstBitPerPixel, - _In_ BYTE* SrcAddr, - _In_ UINT SrcBytesPerPixel, - _In_ LONG SrcPitch, - _In_ ULONG NumMoves, - _In_ D3DKMT_MOVE_RECT* Moves, - _In_ ULONG NumDirtyRects, - _In_ RECT* DirtyRect, - _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation) -/*++ - - Routine Description: - - The method creates present worker thread and provides context - for it filled with present commands - - Arguments: - - DstAddr - address of destination surface - DstBitPerPixel - color depth of destination surface - SrcAddr - address of source surface - SrcBytesPerPixel - bytes per pixel of source surface - SrcPitch - source surface pitch (bytes in a row) - NumMoves - number of moves to be copied - Moves - moves' data - NumDirtyRects - number of rectangles to be copied - DirtyRect - rectangles' data - Rotation - roatation to be performed when executing copy - CallBack - callback for present worker thread to report execution status - - Return Value: - - Status - ---*/ -{ - - PAGED_CODE(); - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - - NTSTATUS Status = STATUS_SUCCESS; - - SIZE_T sizeMoves = NumMoves*sizeof(D3DKMT_MOVE_RECT); - SIZE_T sizeRects = NumDirtyRects*sizeof(RECT); - SIZE_T size = sizeof(DoPresentMemory) + sizeMoves + sizeRects; - - DoPresentMemory* ctx = reinterpret_cast - (new (NonPagedPoolNx) BYTE[size]); - - if (!ctx) - { - return STATUS_NO_MEMORY; - } - - RtlZeroMemory(ctx,size); - - const CURRENT_BDD_MODE* pModeCur = &m_CurrentModes[0]; - ctx->DstAddr = DstAddr; - ctx->DstBitPerPixel = DstBitPerPixel; - ctx->DstStride = pModeCur->DispInfo.Pitch; - ctx->SrcWidth = pModeCur->SrcModeWidth; - ctx->SrcHeight = pModeCur->SrcModeHeight; - ctx->SrcAddr = NULL; - ctx->SrcPitch = SrcPitch; - ctx->Rotation = Rotation; - ctx->NumMoves = NumMoves; - ctx->Moves = Moves; - ctx->NumDirtyRects = NumDirtyRects; - ctx->DirtyRect = DirtyRect; -// ctx->SourceID = m_SourceId; -// ctx->hAdapter = m_DevExt; - ctx->Mdl = NULL; - ctx->DisplaySource = this; - - // Alternate between synch and asynch execution, for demonstrating - // that a real hardware implementation can do either - - { - // Map Source into kernel space, as Blt will be executed by system worker thread - UINT sizeToMap = SrcBytesPerPixel * ctx->SrcWidth * ctx->SrcHeight; - - PMDL mdl = IoAllocateMdl((PVOID)SrcAddr, sizeToMap, FALSE, FALSE, NULL); - if(!mdl) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - KPROCESSOR_MODE AccessMode = static_cast(( SrcAddr <= - (BYTE* const) MM_USER_PROBE_ADDRESS)?UserMode:KernelMode); - __try - { - // Probe and lock the pages of this buffer in physical memory. - // We need only IoReadAccess. - MmProbeAndLockPages(mdl, AccessMode, IoReadAccess); - } - #pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try/except is only able to protect against user-mode errors and these are the only errors we try to catch here"); - __except(EXCEPTION_EXECUTE_HANDLER) - { - Status = GetExceptionCode(); - IoFreeMdl(mdl); - return Status; - } - - // Map the physical pages described by the MDL into system space. - // Note: double mapping the buffer this way causes lot of system - // overhead for large size buffers. - ctx->SrcAddr = reinterpret_cast - (MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority )); - - if(!ctx->SrcAddr) { - Status = STATUS_INSUFFICIENT_RESOURCES; - MmUnlockPages(mdl); - IoFreeMdl(mdl); - return Status; - } - - // Save Mdl to unmap and unlock the pages in worker thread - ctx->Mdl = mdl; - } - - BYTE* rects = reinterpret_cast(ctx+1); - - // copy moves and update pointer - if (Moves) - { - memcpy(rects,Moves,sizeMoves); - ctx->Moves = reinterpret_cast(rects); - rects += sizeMoves; - } - - // copy dirty rects and update pointer - if (DirtyRect) - { - memcpy(rects,DirtyRect,sizeRects); - ctx->DirtyRect = reinterpret_cast(rects); - } - - -// HwExecutePresentDisplayOnly((PVOID)ctx); - - - // Set up destination blt info - BLT_INFO DstBltInfo; - DstBltInfo.pBits = ctx->DstAddr; - DstBltInfo.Pitch = ctx->DstStride; - DstBltInfo.BitsPerPel = ctx->DstBitPerPixel; - DstBltInfo.Offset.x = 0; - DstBltInfo.Offset.y = 0; - DstBltInfo.Rotation = ctx->Rotation; - DstBltInfo.Width = ctx->SrcWidth; - DstBltInfo.Height = ctx->SrcHeight; - - // Set up source blt info - BLT_INFO SrcBltInfo; - SrcBltInfo.pBits = ctx->SrcAddr; - SrcBltInfo.Pitch = ctx->SrcPitch; - SrcBltInfo.BitsPerPel = 32; - SrcBltInfo.Offset.x = 0; - SrcBltInfo.Offset.y = 0; - SrcBltInfo.Rotation = D3DKMDT_VPPR_IDENTITY; - if (ctx->Rotation == D3DKMDT_VPPR_ROTATE90 || - ctx->Rotation == D3DKMDT_VPPR_ROTATE270) - { - SrcBltInfo.Width = DstBltInfo.Height; - SrcBltInfo.Height = DstBltInfo.Width; - } - else - { - SrcBltInfo.Width = DstBltInfo.Width; - SrcBltInfo.Height = DstBltInfo.Height; - } - - - // Copy all the scroll rects from source image to video frame buffer. - for (UINT i = 0; i < ctx->NumMoves; i++) - { - BltBits(&DstBltInfo, - &SrcBltInfo, - 1, // NumRects - &ctx->Moves[i].DestRect); - } - - // Copy all the dirty rects from source image to video frame buffer. - for (UINT i = 0; i < ctx->NumDirtyRects; i++) - { - - BltBits(&DstBltInfo, - &SrcBltInfo, - 1, // NumRects - &ctx->DirtyRect[i]); - } - - // Unmap unmap and unlock the pages. - if (ctx->Mdl) - { - MmUnlockPages(ctx->Mdl); - IoFreeMdl(ctx->Mdl); - } - delete [] reinterpret_cast(ctx); - - return STATUS_SUCCESS; -} - - -VOID QxlDod::GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch) -{ - switch (pBltInfo->Rotation) - { - case D3DKMDT_VPPR_IDENTITY: - { - *pPixelPitch = (pBltInfo->BitsPerPel / BITS_PER_BYTE); - *pRowPitch = pBltInfo->Pitch; - return; - } - case D3DKMDT_VPPR_ROTATE90: - { - *pPixelPitch = -((LONG)pBltInfo->Pitch); - *pRowPitch = (pBltInfo->BitsPerPel / BITS_PER_BYTE); - return; - } - case D3DKMDT_VPPR_ROTATE180: - { - *pPixelPitch = -((LONG)pBltInfo->BitsPerPel / BITS_PER_BYTE); - *pRowPitch = -((LONG)pBltInfo->Pitch); - return; - } - case D3DKMDT_VPPR_ROTATE270: - { - *pPixelPitch = pBltInfo->Pitch; - *pRowPitch = -((LONG)pBltInfo->BitsPerPel / BITS_PER_BYTE); - return; - } - default: - { - QXL_LOG_ASSERTION1("Invalid rotation (0x%I64x) specified", pBltInfo->Rotation); - *pPixelPitch = 0; - *pRowPitch = 0; - return; - } - } -} - -BYTE* QxlDod::GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect) -{ - BYTE* pRet = NULL; - LONG OffLeft = pRect->left + pBltInfo->Offset.x; - LONG OffTop = pRect->top + pBltInfo->Offset.y; - LONG BytesPerPixel = (pBltInfo->BitsPerPel / BITS_PER_BYTE); - switch (pBltInfo->Rotation) - { - case D3DKMDT_VPPR_IDENTITY: - { - pRet = ((BYTE*)pBltInfo->pBits + - OffTop * pBltInfo->Pitch + - OffLeft * BytesPerPixel); - break; - } - case D3DKMDT_VPPR_ROTATE90: - { - pRet = ((BYTE*)pBltInfo->pBits + - (pBltInfo->Height - 1 - OffLeft) * pBltInfo->Pitch + - OffTop * BytesPerPixel); - break; - } - case D3DKMDT_VPPR_ROTATE180: - { - pRet = ((BYTE*)pBltInfo->pBits + - (pBltInfo->Height - 1 - OffTop) * pBltInfo->Pitch + - (pBltInfo->Width - 1 - OffLeft) * BytesPerPixel); - break; - } - case D3DKMDT_VPPR_ROTATE270: - { - pRet = ((BYTE*)pBltInfo->pBits + - OffLeft * pBltInfo->Pitch + - (pBltInfo->Width - 1 - OffTop) * BytesPerPixel); - break; - } - default: - { - QXL_LOG_ASSERTION1("Invalid rotation (0x%I64x) specified", pBltInfo->Rotation); - break; - } - } - - return pRet; -} - -/****************************Internal*Routine******************************\ - * CopyBitsGeneric - * - * - * Blt function which can handle a rotated dst/src, offset rects in dst/src - * and bpp combinations of: - * dst | src - * 32 | 32 // For identity rotation this is much faster in CopyBits32_32 - * 32 | 24 - * 32 | 16 - * 24 | 32 - * 16 | 32 - * 8 | 32 - * 24 | 24 // untested - * -\**************************************************************************/ - -VOID QxlDod::CopyBitsGeneric( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects) -{ - LONG DstPixelPitch = 0; - LONG DstRowPitch = 0; - LONG SrcPixelPitch = 0; - LONG SrcRowPitch = 0; - - DbgPrint(TRACE_LEVEL_VERBOSE , ("---> %s NumRects = %d Dst = %p Src = %p\n", __FUNCTION__, NumRects, pDst->pBits, pSrc->pBits)); - - GetPitches(pDst, &DstPixelPitch, &DstRowPitch); - GetPitches(pSrc, &SrcPixelPitch, &SrcRowPitch); - - for (UINT iRect = 0; iRect < NumRects; iRect++) - { - CONST RECT* pRect = &pRects[iRect]; - - NT_ASSERT(pRect->right >= pRect->left); - NT_ASSERT(pRect->bottom >= pRect->top); - - UINT NumPixels = pRect->right - pRect->left; - UINT NumRows = pRect->bottom - pRect->top; - - BYTE* pDstRow = GetRowStart(pDst, pRect); - CONST BYTE* pSrcRow = GetRowStart(pSrc, pRect); - - for (UINT y=0; y < NumRows; y++) - { - BYTE* pDstPixel = pDstRow; - CONST BYTE* pSrcPixel = pSrcRow; - - for (UINT x=0; x < NumPixels; x++) - { - if ((pDst->BitsPerPel == 24) || - (pSrc->BitsPerPel == 24)) - { - pDstPixel[0] = pSrcPixel[0]; - pDstPixel[1] = pSrcPixel[1]; - pDstPixel[2] = pSrcPixel[2]; - // pPixel[3] is the alpha channel and is ignored for whichever of Src/Dst is 32bpp - } - else if (pDst->BitsPerPel == 32) - { - if (pSrc->BitsPerPel == 32) - { - UINT32* pDstPixelAs32 = (UINT32*)pDstPixel; - UINT32* pSrcPixelAs32 = (UINT32*)pSrcPixel; - *pDstPixelAs32 = *pSrcPixelAs32; - } - else if (pSrc->BitsPerPel == 16) - { - UINT32* pDstPixelAs32 = (UINT32*)pDstPixel; - UINT16* pSrcPixelAs16 = (UINT16*)pSrcPixel; - - *pDstPixelAs32 = CONVERT_16BPP_TO_32BPP(*pSrcPixelAs16); - } - else - { - // Invalid pSrc->BitsPerPel on a pDst->BitsPerPel of 32 - NT_ASSERT(FALSE); - } - } - else if (pDst->BitsPerPel == 16) - { - NT_ASSERT(pSrc->BitsPerPel == 32); - - UINT16* pDstPixelAs16 = (UINT16*)pDstPixel; - *pDstPixelAs16 = CONVERT_32BPP_TO_16BPP(pSrcPixel); - } - else if (pDst->BitsPerPel == 8) - { - NT_ASSERT(pSrc->BitsPerPel == 32); - - *pDstPixel = CONVERT_32BPP_TO_8BPP(pSrcPixel); - } - else - { - // Invalid pDst->BitsPerPel - NT_ASSERT(FALSE); - } - pDstPixel += DstPixelPitch; - pSrcPixel += SrcPixelPitch; - } - - pDstRow += DstRowPitch; - pSrcRow += SrcRowPitch; - } - } -} - - -VOID QxlDod::CopyBits32_32( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects) -{ - NT_ASSERT((pDst->BitsPerPel == 32) && - (pSrc->BitsPerPel == 32)); - NT_ASSERT((pDst->Rotation == D3DKMDT_VPPR_IDENTITY) && - (pSrc->Rotation == D3DKMDT_VPPR_IDENTITY)); - - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - - for (UINT iRect = 0; iRect < NumRects; iRect++) - { - CONST RECT* pRect = &pRects[iRect]; - - NT_ASSERT(pRect->right >= pRect->left); - NT_ASSERT(pRect->bottom >= pRect->top); - - UINT NumPixels = pRect->right - pRect->left; - UINT NumRows = pRect->bottom - pRect->top; - UINT BytesToCopy = NumPixels * 4; - BYTE* pStartDst = ((BYTE*)pDst->pBits + - (pRect->top + pDst->Offset.y) * pDst->Pitch + - (pRect->left + pDst->Offset.x) * 4); - CONST BYTE* pStartSrc = ((BYTE*)pSrc->pBits + - (pRect->top + pSrc->Offset.y) * pSrc->Pitch + - (pRect->left + pSrc->Offset.x) * 4); - - for (UINT i = 0; i < NumRows; ++i) - { - RtlCopyMemory(pStartDst, pStartSrc, BytesToCopy); - pStartDst += pDst->Pitch; - pStartSrc += pSrc->Pitch; - } - } - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); -} - - -VOID QxlDod::BltBits ( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects) -{ - // pSrc->pBits might be coming from user-mode. User-mode addresses when accessed by kernel need to be protected by a __try/__except. - // This usage is redundant in the sample driver since it is already being used for MmProbeAndLockPages. However, it is very important - // to have this in place and to make sure developers don't miss it, it is in these two locations. - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - __try - { - if (pDst->BitsPerPel == 32 && - pSrc->BitsPerPel == 32 && - pDst->Rotation == D3DKMDT_VPPR_IDENTITY && - pSrc->Rotation == D3DKMDT_VPPR_IDENTITY) - { - // This is by far the most common copy function being called - CopyBits32_32(pDst, pSrc, NumRects, pRects); - } - else - { - CopyBitsGeneric(pDst, pSrc, NumRects, pRects); - } - } - #pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try/except is only able to protect against user-mode errors and these are the only errors we try to catch here"); - __except(EXCEPTION_EXECUTE_HANDLER) - { - DbgPrint(TRACE_LEVEL_ERROR, ("Either dst (0x%I64x) or src (0x%I64x) bits encountered exception during access.\n", pDst->pBits, pSrc->pBits)); - } -} - // // Non-Paged Code // @@ -2447,8 +1967,279 @@ UnmapFrameBuffer( return STATUS_SUCCESS; } + + + // HW specific code +VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch) +{ + switch (pBltInfo->Rotation) + { + case D3DKMDT_VPPR_IDENTITY: + { + *pPixelPitch = (pBltInfo->BitsPerPel / BITS_PER_BYTE); + *pRowPitch = pBltInfo->Pitch; + return; + } + case D3DKMDT_VPPR_ROTATE90: + { + *pPixelPitch = -((LONG)pBltInfo->Pitch); + *pRowPitch = (pBltInfo->BitsPerPel / BITS_PER_BYTE); + return; + } + case D3DKMDT_VPPR_ROTATE180: + { + *pPixelPitch = -((LONG)pBltInfo->BitsPerPel / BITS_PER_BYTE); + *pRowPitch = -((LONG)pBltInfo->Pitch); + return; + } + case D3DKMDT_VPPR_ROTATE270: + { + *pPixelPitch = pBltInfo->Pitch; + *pRowPitch = -((LONG)pBltInfo->BitsPerPel / BITS_PER_BYTE); + return; + } + default: + { + QXL_LOG_ASSERTION1("Invalid rotation (0x%I64x) specified", pBltInfo->Rotation); + *pPixelPitch = 0; + *pRowPitch = 0; + return; + } + } +} + +BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect) +{ + BYTE* pRet = NULL; + LONG OffLeft = pRect->left + pBltInfo->Offset.x; + LONG OffTop = pRect->top + pBltInfo->Offset.y; + LONG BytesPerPixel = (pBltInfo->BitsPerPel / BITS_PER_BYTE); + switch (pBltInfo->Rotation) + { + case D3DKMDT_VPPR_IDENTITY: + { + pRet = ((BYTE*)pBltInfo->pBits + + OffTop * pBltInfo->Pitch + + OffLeft * BytesPerPixel); + break; + } + case D3DKMDT_VPPR_ROTATE90: + { + pRet = ((BYTE*)pBltInfo->pBits + + (pBltInfo->Height - 1 - OffLeft) * pBltInfo->Pitch + + OffTop * BytesPerPixel); + break; + } + case D3DKMDT_VPPR_ROTATE180: + { + pRet = ((BYTE*)pBltInfo->pBits + + (pBltInfo->Height - 1 - OffTop) * pBltInfo->Pitch + + (pBltInfo->Width - 1 - OffLeft) * BytesPerPixel); + break; + } + case D3DKMDT_VPPR_ROTATE270: + { + pRet = ((BYTE*)pBltInfo->pBits + + OffLeft * pBltInfo->Pitch + + (pBltInfo->Width - 1 - OffTop) * BytesPerPixel); + break; + } + default: + { + QXL_LOG_ASSERTION1("Invalid rotation (0x%I64x) specified", pBltInfo->Rotation); + break; + } + } + + return pRet; +} + +/****************************Internal*Routine******************************\ + * CopyBitsGeneric + * + * + * Blt function which can handle a rotated dst/src, offset rects in dst/src + * and bpp combinations of: + * dst | src + * 32 | 32 // For identity rotation this is much faster in CopyBits32_32 + * 32 | 24 + * 32 | 16 + * 24 | 32 + * 16 | 32 + * 8 | 32 + * 24 | 24 // untested + * +\**************************************************************************/ + +VOID CopyBitsGeneric( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects) +{ + LONG DstPixelPitch = 0; + LONG DstRowPitch = 0; + LONG SrcPixelPitch = 0; + LONG SrcRowPitch = 0; + + DbgPrint(TRACE_LEVEL_VERBOSE , ("---> %s NumRects = %d Dst = %p Src = %p\n", __FUNCTION__, NumRects, pDst->pBits, pSrc->pBits)); + + GetPitches(pDst, &DstPixelPitch, &DstRowPitch); + GetPitches(pSrc, &SrcPixelPitch, &SrcRowPitch); + + for (UINT iRect = 0; iRect < NumRects; iRect++) + { + CONST RECT* pRect = &pRects[iRect]; + + NT_ASSERT(pRect->right >= pRect->left); + NT_ASSERT(pRect->bottom >= pRect->top); + + UINT NumPixels = pRect->right - pRect->left; + UINT NumRows = pRect->bottom - pRect->top; + + BYTE* pDstRow = GetRowStart(pDst, pRect); + CONST BYTE* pSrcRow = GetRowStart(pSrc, pRect); + + for (UINT y=0; y < NumRows; y++) + { + BYTE* pDstPixel = pDstRow; + CONST BYTE* pSrcPixel = pSrcRow; + + for (UINT x=0; x < NumPixels; x++) + { + if ((pDst->BitsPerPel == 24) || + (pSrc->BitsPerPel == 24)) + { + pDstPixel[0] = pSrcPixel[0]; + pDstPixel[1] = pSrcPixel[1]; + pDstPixel[2] = pSrcPixel[2]; + // pPixel[3] is the alpha channel and is ignored for whichever of Src/Dst is 32bpp + } + else if (pDst->BitsPerPel == 32) + { + if (pSrc->BitsPerPel == 32) + { + UINT32* pDstPixelAs32 = (UINT32*)pDstPixel; + UINT32* pSrcPixelAs32 = (UINT32*)pSrcPixel; + *pDstPixelAs32 = *pSrcPixelAs32; + } + else if (pSrc->BitsPerPel == 16) + { + UINT32* pDstPixelAs32 = (UINT32*)pDstPixel; + UINT16* pSrcPixelAs16 = (UINT16*)pSrcPixel; + + *pDstPixelAs32 = CONVERT_16BPP_TO_32BPP(*pSrcPixelAs16); + } + else + { + // Invalid pSrc->BitsPerPel on a pDst->BitsPerPel of 32 + NT_ASSERT(FALSE); + } + } + else if (pDst->BitsPerPel == 16) + { + NT_ASSERT(pSrc->BitsPerPel == 32); + + UINT16* pDstPixelAs16 = (UINT16*)pDstPixel; + *pDstPixelAs16 = CONVERT_32BPP_TO_16BPP(pSrcPixel); + } + else if (pDst->BitsPerPel == 8) + { + NT_ASSERT(pSrc->BitsPerPel == 32); + + *pDstPixel = CONVERT_32BPP_TO_8BPP(pSrcPixel); + } + else + { + // Invalid pDst->BitsPerPel + NT_ASSERT(FALSE); + } + pDstPixel += DstPixelPitch; + pSrcPixel += SrcPixelPitch; + } + + pDstRow += DstRowPitch; + pSrcRow += SrcRowPitch; + } + } +} + + +VOID CopyBits32_32( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects) +{ + NT_ASSERT((pDst->BitsPerPel == 32) && + (pSrc->BitsPerPel == 32)); + NT_ASSERT((pDst->Rotation == D3DKMDT_VPPR_IDENTITY) && + (pSrc->Rotation == D3DKMDT_VPPR_IDENTITY)); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + for (UINT iRect = 0; iRect < NumRects; iRect++) + { + CONST RECT* pRect = &pRects[iRect]; + + NT_ASSERT(pRect->right >= pRect->left); + NT_ASSERT(pRect->bottom >= pRect->top); + + UINT NumPixels = pRect->right - pRect->left; + UINT NumRows = pRect->bottom - pRect->top; + UINT BytesToCopy = NumPixels * 4; + BYTE* pStartDst = ((BYTE*)pDst->pBits + + (pRect->top + pDst->Offset.y) * pDst->Pitch + + (pRect->left + pDst->Offset.x) * 4); + CONST BYTE* pStartSrc = ((BYTE*)pSrc->pBits + + (pRect->top + pSrc->Offset.y) * pSrc->Pitch + + (pRect->left + pSrc->Offset.x) * 4); + + for (UINT i = 0; i < NumRows; ++i) + { + RtlCopyMemory(pStartDst, pStartSrc, BytesToCopy); + pStartDst += pDst->Pitch; + pStartSrc += pSrc->Pitch; + } + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); +} + + +VOID BltBits ( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects) +{ + // pSrc->pBits might be coming from user-mode. User-mode addresses when accessed by kernel need to be protected by a __try/__except. + // This usage is redundant in the sample driver since it is already being used for MmProbeAndLockPages. However, it is very important + // to have this in place and to make sure developers don't miss it, it is in these two locations. + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + __try + { + if (pDst->BitsPerPel == 32 && + pSrc->BitsPerPel == 32 && + pDst->Rotation == D3DKMDT_VPPR_IDENTITY && + pSrc->Rotation == D3DKMDT_VPPR_IDENTITY) + { + // This is by far the most common copy function being called + CopyBits32_32(pDst, pSrc, NumRects, pRects); + } + else + { + CopyBitsGeneric(pDst, pSrc, NumRects, pRects); + } + } + #pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try/except is only able to protect against user-mode errors and these are the only errors we try to catch here"); + __except(EXCEPTION_EXECUTE_HANDLER) + { + DbgPrint(TRACE_LEVEL_ERROR, ("Either dst (0x%I64x) or src (0x%I64x) bits encountered exception during access.\n", pDst->pBits, pSrc->pBits)); + } +} + VgaDevice::VgaDevice(_In_ QxlDod* pQxlDod) { m_pQxlDod = pQxlDod; @@ -2692,7 +2483,7 @@ NTSTATUS VgaDevice::SetCurrentMode(ULONG Mode) DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n")); return STATUS_UNSUCCESSFUL; } - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); return Status; } @@ -2729,7 +2520,7 @@ NTSTATUS VgaDevice::HWClose(void) NTSTATUS VgaDevice::SetPowerState(POWER_ACTION ActionType) { - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); X86BIOS_REGISTERS regs = {0}; regs.Eax = 0x4F10; @@ -2748,10 +2539,268 @@ NTSTATUS VgaDevice::SetPowerState(POWER_ACTION ActionType) DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n")); return STATUS_UNSUCCESSFUL; } - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } + +NTSTATUS +VgaDevice::ExecutePresentDisplayOnly( + _In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* Moves, + _In_ ULONG NumDirtyRects, + _In_ RECT* DirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, + _In_ const CURRENT_BDD_MODE* pModeCur) +/*++ + + Routine Description: + + The method creates present worker thread and provides context + for it filled with present commands + + Arguments: + + DstAddr - address of destination surface + DstBitPerPixel - color depth of destination surface + SrcAddr - address of source surface + SrcBytesPerPixel - bytes per pixel of source surface + SrcPitch - source surface pitch (bytes in a row) + NumMoves - number of moves to be copied + Moves - moves' data + NumDirtyRects - number of rectangles to be copied + DirtyRect - rectangles' data + Rotation - roatation to be performed when executing copy + CallBack - callback for present worker thread to report execution status + + Return Value: + + Status + +--*/ +{ + + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + NTSTATUS Status = STATUS_SUCCESS; + + SIZE_T sizeMoves = NumMoves*sizeof(D3DKMT_MOVE_RECT); + SIZE_T sizeRects = NumDirtyRects*sizeof(RECT); + SIZE_T size = sizeof(DoPresentMemory) + sizeMoves + sizeRects; + + DoPresentMemory* ctx = reinterpret_cast + (new (NonPagedPoolNx) BYTE[size]); + + if (!ctx) + { + return STATUS_NO_MEMORY; + } + + RtlZeroMemory(ctx,size); + +// const CURRENT_BDD_MODE* pModeCur = &m_CurrentModes[0]; + ctx->DstAddr = DstAddr; + ctx->DstBitPerPixel = DstBitPerPixel; + ctx->DstStride = pModeCur->DispInfo.Pitch; + ctx->SrcWidth = pModeCur->SrcModeWidth; + ctx->SrcHeight = pModeCur->SrcModeHeight; + ctx->SrcAddr = NULL; + ctx->SrcPitch = SrcPitch; + ctx->Rotation = Rotation; + ctx->NumMoves = NumMoves; + ctx->Moves = Moves; + ctx->NumDirtyRects = NumDirtyRects; + ctx->DirtyRect = DirtyRect; +// ctx->SourceID = m_SourceId; +// ctx->hAdapter = m_DevExt; + ctx->Mdl = NULL; + ctx->DisplaySource = this; + + // Alternate between synch and asynch execution, for demonstrating + // that a real hardware implementation can do either + + { + // Map Source into kernel space, as Blt will be executed by system worker thread + UINT sizeToMap = SrcBytesPerPixel * ctx->SrcWidth * ctx->SrcHeight; + + PMDL mdl = IoAllocateMdl((PVOID)SrcAddr, sizeToMap, FALSE, FALSE, NULL); + if(!mdl) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + KPROCESSOR_MODE AccessMode = static_cast(( SrcAddr <= + (BYTE* const) MM_USER_PROBE_ADDRESS)?UserMode:KernelMode); + __try + { + // Probe and lock the pages of this buffer in physical memory. + // We need only IoReadAccess. + MmProbeAndLockPages(mdl, AccessMode, IoReadAccess); + } + #pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try/except is only able to protect against user-mode errors and these are the only errors we try to catch here"); + __except(EXCEPTION_EXECUTE_HANDLER) + { + Status = GetExceptionCode(); + IoFreeMdl(mdl); + return Status; + } + + // Map the physical pages described by the MDL into system space. + // Note: double mapping the buffer this way causes lot of system + // overhead for large size buffers. + ctx->SrcAddr = reinterpret_cast + (MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority )); + + if(!ctx->SrcAddr) { + Status = STATUS_INSUFFICIENT_RESOURCES; + MmUnlockPages(mdl); + IoFreeMdl(mdl); + return Status; + } + + // Save Mdl to unmap and unlock the pages in worker thread + ctx->Mdl = mdl; + } + + BYTE* rects = reinterpret_cast(ctx+1); + + // copy moves and update pointer + if (Moves) + { + memcpy(rects,Moves,sizeMoves); + ctx->Moves = reinterpret_cast(rects); + rects += sizeMoves; + } + + // copy dirty rects and update pointer + if (DirtyRect) + { + memcpy(rects,DirtyRect,sizeRects); + ctx->DirtyRect = reinterpret_cast(rects); + } + + +// HwExecutePresentDisplayOnly((PVOID)ctx); + + + // Set up destination blt info + BLT_INFO DstBltInfo; + DstBltInfo.pBits = ctx->DstAddr; + DstBltInfo.Pitch = ctx->DstStride; + DstBltInfo.BitsPerPel = ctx->DstBitPerPixel; + DstBltInfo.Offset.x = 0; + DstBltInfo.Offset.y = 0; + DstBltInfo.Rotation = ctx->Rotation; + DstBltInfo.Width = ctx->SrcWidth; + DstBltInfo.Height = ctx->SrcHeight; + + // Set up source blt info + BLT_INFO SrcBltInfo; + SrcBltInfo.pBits = ctx->SrcAddr; + SrcBltInfo.Pitch = ctx->SrcPitch; + SrcBltInfo.BitsPerPel = 32; + SrcBltInfo.Offset.x = 0; + SrcBltInfo.Offset.y = 0; + SrcBltInfo.Rotation = D3DKMDT_VPPR_IDENTITY; + if (ctx->Rotation == D3DKMDT_VPPR_ROTATE90 || + ctx->Rotation == D3DKMDT_VPPR_ROTATE270) + { + SrcBltInfo.Width = DstBltInfo.Height; + SrcBltInfo.Height = DstBltInfo.Width; + } + else + { + SrcBltInfo.Width = DstBltInfo.Width; + SrcBltInfo.Height = DstBltInfo.Height; + } + + + // Copy all the scroll rects from source image to video frame buffer. + for (UINT i = 0; i < ctx->NumMoves; i++) + { + BltBits(&DstBltInfo, + &SrcBltInfo, + 1, // NumRects + &ctx->Moves[i].DestRect); + } + + // Copy all the dirty rects from source image to video frame buffer. + for (UINT i = 0; i < ctx->NumDirtyRects; i++) + { + + BltBits(&DstBltInfo, + &SrcBltInfo, + 1, // NumRects + &ctx->DirtyRect[i]); + } + + // Unmap unmap and unlock the pages. + if (ctx->Mdl) + { + MmUnlockPages(ctx->Mdl); + IoFreeMdl(ctx->Mdl); + } + delete [] reinterpret_cast(ctx); + + return STATUS_SUCCESS; +} + +VOID VgaDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) +{ + PAGED_CODE(); + + UINT ScreenHeight = pCurrentBddMod->DispInfo.Height; + UINT ScreenPitch = pCurrentBddMod->DispInfo.Pitch; + + PHYSICAL_ADDRESS NewPhysAddrStart = pCurrentBddMod->DispInfo.PhysicAddress; + PHYSICAL_ADDRESS NewPhysAddrEnd; + NewPhysAddrEnd.QuadPart = NewPhysAddrStart.QuadPart + (ScreenHeight * ScreenPitch); + + if (pCurrentBddMod->Flags.FrameBufferIsActive) + { + BYTE* MappedAddr = reinterpret_cast(pCurrentBddMod->FrameBuffer.Ptr); + + // Zero any memory at the start that hasn't been zeroed recently + if (NewPhysAddrStart.QuadPart < pCurrentBddMod->ZeroedOutStart.QuadPart) + { + if (NewPhysAddrEnd.QuadPart < pCurrentBddMod->ZeroedOutStart.QuadPart) + { + // No overlap + RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch); + } + else + { + RtlZeroMemory(MappedAddr, (UINT)(pCurrentBddMod->ZeroedOutStart.QuadPart - NewPhysAddrStart.QuadPart)); + } + } + + // Zero any memory at the end that hasn't been zeroed recently + if (NewPhysAddrEnd.QuadPart > pCurrentBddMod->ZeroedOutEnd.QuadPart) + { + if (NewPhysAddrStart.QuadPart > pCurrentBddMod->ZeroedOutEnd.QuadPart) + { + // No overlap + // NOTE: When actual pixels were the most recent thing drawn, ZeroedOutStart & ZeroedOutEnd will both be 0 + // and this is the path that will be used to black out the current screen. + RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch); + } + else + { + RtlZeroMemory(MappedAddr, (UINT)(NewPhysAddrEnd.QuadPart - pCurrentBddMod->ZeroedOutEnd.QuadPart)); + } + } + } + + pCurrentBddMod->ZeroedOutStart.QuadPart = NewPhysAddrStart.QuadPart; + pCurrentBddMod->ZeroedOutEnd.QuadPart = NewPhysAddrEnd.QuadPart; +} + QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod) { m_pQxlDod = pQxlDod; @@ -2822,32 +2871,36 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) return STATUS_UNSUCCESSFUL; } + DbgPrint(TRACE_LEVEL_ERROR, ("%s: ModeCount = %d\n", __FUNCTION__, ModeCount)); + ModeCount += 2; m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VIDEO_MODE_INFORMATION) * ModeCount]); m_ModeNumbers = reinterpret_cast (new (PagedPool) BYTE [sizeof (USHORT) * ModeCount]); m_CurrentMode = 0; + UINT Height = pDispInfo->Height; + UINT Width = pDispInfo->Width; +// UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); for (CurrentMode = 0, SuitableModeCount = 0; CurrentMode < ModeCount; CurrentMode++) { - UINT Height = pDispInfo->Height; - UINT Width = pDispInfo->Width; - UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); QXLMode* tmpModeInfo = &modes->modes[CurrentMode]; + DbgPrint(TRACE_LEVEL_ERROR, ("%s: modes[%d] x_res = %d, y_res = %d, bits = %d\n", __FUNCTION__, CurrentMode, tmpModeInfo->x_res, tmpModeInfo->y_res, tmpModeInfo->bits)); + if (tmpModeInfo->x_res >= Width && - tmpModeInfo->y_res >= Height && - tmpModeInfo->bits == BitsPerPixel) + tmpModeInfo->y_res >= Height/* && + tmpModeInfo->bits == BitsPerPixel*/) { - m_ModeNumbers[SuitableModeCount] = (USHORT)SuitableModeCount; + m_ModeNumbers[SuitableModeCount] = CurrentMode; SetVideoModeInfo(SuitableModeCount, tmpModeInfo); - if (tmpModeInfo->x_res == 1024 && - tmpModeInfo->y_res == 768) - { - m_CurrentMode = (USHORT)SuitableModeCount; - } +// if (tmpModeInfo->x_res == 1024 && +// tmpModeInfo->y_res == 768) +// { +// m_CurrentMode = (USHORT)SuitableModeCount; +// } SuitableModeCount++; } } @@ -2858,6 +2911,7 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) Status = STATUS_UNSUCCESSFUL; } + m_CurrentMode = m_ModeNumbers[0]; m_ModeCount = SuitableModeCount; DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount)); for (ULONG idx = 0; idx < m_ModeCount; idx++) @@ -3044,8 +3098,8 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* Status = GetModeList(pDispInfo); if (!NT_SUCCESS(Status)) { - QXL_LOG_ASSERTION1("GetModeList failed with status 0x%X\n", - Status); + DbgPrint(TRACE_LEVEL_ERROR, ("GetModeList failed with status 0x%X\n", + Status)); return Status; } @@ -3170,6 +3224,40 @@ void QxlDevice::ResetDevice(void) WRITE_PORT_UCHAR(m_IoBase + QXL_IO_MEMSLOT_ADD, 0); } + +NTSTATUS +QxlDevice::ExecutePresentDisplayOnly( + _In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* Moves, + _In_ ULONG NumDirtyRects, + _In_ RECT* DirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, + _In_ const CURRENT_BDD_MODE* pModeCur) +{ + + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + NTSTATUS Status = STATUS_SUCCESS; + return Status; +} + +VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) +{ + PAGED_CODE(); + + UINT ScreenHeight = pCurrentBddMod->DispInfo.Height; + UINT ScreenPitch = pCurrentBddMod->DispInfo.Pitch; + + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + +} + NTSTATUS QxlDevice::HWClose(void) { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 36c8aa1..ee24f9e 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -210,7 +210,7 @@ class HwDeviceIntrface : public BaseObject { public: -// HwDeviceIntrface(_In_ QxlDod* pQxlDod); +// HwDeviceIntrface(_In_ QxlDod* pQxlDod) {m_pQxlDod = pQxlDod;} // virtual ~HwDeviceIntrface(void); virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0; virtual NTSTATUS SetCurrentMode(ULONG Mode) = 0; @@ -223,7 +223,41 @@ public: USHORT GetModeNumber(USHORT idx) {return m_ModeNumbers[idx];} USHORT GetCurrentModeIndex(void) {return m_CurrentMode;} VOID SetCurrentModeIndex(USHORT idx) {m_CurrentMode = idx;} + virtual NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* pMoves, + _In_ ULONG NumDirtyRects, + _In_ RECT* pDirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, + _In_ const CURRENT_BDD_MODE* pModeCur) = 0; + + virtual VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) = 0; protected: +/* + BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect); + VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch); + + VOID CopyBitsGeneric( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + + VOID CopyBits32_32( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + VOID BltBits ( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); +*/ virtual NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; protected: QxlDod* m_pQxlDod; @@ -245,6 +279,18 @@ public: NTSTATUS SetPowerState(POWER_ACTION ActionType); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); + NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* pMoves, + _In_ ULONG NumDirtyRects, + _In_ RECT* pDirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, + _In_ const CURRENT_BDD_MODE* pModeCur); + VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); private: @@ -272,6 +318,18 @@ public: NTSTATUS SetPowerState(POWER_ACTION ActionType); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); + NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* pMoves, + _In_ ULONG NumDirtyRects, + _In_ RECT* pDirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, + _In_ const CURRENT_BDD_MODE* pModeCur); + VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); private: @@ -434,6 +492,7 @@ public: PDXGKRNL_INTERFACE GetDxgkInterrface(void) { return &m_DxgkInterface;} private: VOID CleanUp(VOID); + NTSTATUS CheckHardware(); NTSTATUS WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue); // Set the given source mode on the given path NTSTATUS SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode, @@ -458,42 +517,12 @@ private: NTSTATUS RegisterHWInfo(); - - NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, - _In_ UINT DstBitPerPixel, - _In_ BYTE* SrcAddr, - _In_ UINT SrcBytesPerPixel, - _In_ LONG SrcPitch, - _In_ ULONG NumMoves, - _In_ D3DKMT_MOVE_RECT* pMoves, - _In_ ULONG NumDirtyRects, - _In_ RECT* pDirtyRect, - _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation); - BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect); - VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch); - VOID CopyBitsGeneric( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); - - VOID CopyBits32_32( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); - VOID BltBits ( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); - VOID BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId); }; NTSTATUS MapFrameBuffer( - _In_ PHYSICAL_ADDRESS PhysicalAddress, - _In_ ULONG Length, + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ ULONG Length, _Outptr_result_bytebuffer_(Length) VOID** VirtualAddress); NTSTATUS @@ -501,6 +530,25 @@ UnmapFrameBuffer( _In_reads_bytes_(Length) VOID* VirtualAddress, _In_ ULONG Length); - UINT BPPFromPixelFormat(D3DDDIFORMAT Format); D3DDDIFORMAT PixelFormatFromBPP(UINT BPP); + +VOID CopyBitsGeneric( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + +VOID CopyBits32_32( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); +VOID BltBits ( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + +BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect); +VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch); From 947a854992328e6ac363ab0a2c5b7b1585ac48cd Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Tue, 29 Apr 2014 00:32:32 +1000 Subject: [PATCH 12/46] add memory and resources allocation functions --- qxldod/QxlDod.cpp | 553 +++++++++- qxldod/QxlDod.h | 149 ++- qxldod/mspace.c | 2437 +++++++++++++++++++++++++++++++++++++++++ qxldod/mspace.h | 150 +++ qxldod/qxldod.vcxproj | 1 + 5 files changed, 3276 insertions(+), 14 deletions(-) create mode 100755 qxldod/mspace.c create mode 100755 qxldod/mspace.h diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 3e29478..88a245e 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -96,7 +96,7 @@ NTSTATUS QxlDod::CheckHardware() } Status = STATUS_GRAPHICS_DRIVER_MISMATCH; - if (Header.VendorID == 0x1B36 && + if (Header.VendorID == REDHAT_PCI_VENDOR_ID && Header.DeviceID == 0x0100 && Header.RevisionID == 4) { @@ -2896,11 +2896,11 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) { m_ModeNumbers[SuitableModeCount] = CurrentMode; SetVideoModeInfo(SuitableModeCount, tmpModeInfo); -// if (tmpModeInfo->x_res == 1024 && -// tmpModeInfo->y_res == 768) -// { -// m_CurrentMode = (USHORT)SuitableModeCount; -// } + if (tmpModeInfo->x_res == 1024 && + tmpModeInfo->y_res == 768) + { + m_CurrentMode = (USHORT)SuitableModeCount; + } SuitableModeCount++; } } @@ -2911,7 +2911,7 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) Status = STATUS_UNSUCCESSFUL; } - m_CurrentMode = m_ModeNumbers[0]; +// m_CurrentMode = m_ModeNumbers[0]; m_ModeCount = SuitableModeCount; DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount)); for (ULONG idx = 0; idx < m_ModeCount; idx++) @@ -2937,11 +2937,19 @@ NTSTATUS QxlDevice::QueryCurrentMode(PVIDEO_MODE RequestedMode) NTSTATUS QxlDevice::SetCurrentMode(ULONG Mode) { - NTSTATUS Status = STATUS_SUCCESS; DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s Mode = %x\n", __FUNCTION__, Mode)); - UNREFERENCED_PARAMETER(Mode); +// UNREFERENCED_PARAMETER(Mode); + for (ULONG idx = 0; idx < m_ModeCount; idx++) + { + if (Mode == m_ModeNumbers[idx]) + { + DestroyPrimarySurface(); + CreatePrimarySurface(&m_ModeInfo[idx]); + return STATUS_SUCCESS; + } + } DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); - return Status; + return STATUS_UNSUCCESSFUL; } NTSTATUS QxlDevice::GetCurrentMode(ULONG* pMode) @@ -3161,6 +3169,45 @@ void QxlDevice::DestroyMemSlots(void) m_MemSlots = NULL; } +void QxlDevice::CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo) +{ + QXLSurfaceCreate *primary_surface_create; + primary_surface_create = &m_RamHdr->create_surface; + primary_surface_create->format = pModeInfo->BitsPerPlane; + primary_surface_create->width = pModeInfo->VisScreenWidth; + primary_surface_create->height = pModeInfo->VisScreenHeight; + primary_surface_create->stride = pModeInfo->ScreenStride; + + primary_surface_create->mem = PA( m_RamStart, 0); + + primary_surface_create->flags = QXL_SURF_FLAG_KEEP_DATA; //0; + primary_surface_create->type = QXL_SURF_TYPE_PRIMARY; + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_CREATE_PRIMARY), 0); +} + +void QxlDevice::DestroyPrimarySurface(void) +{ + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_DESTROY_PRIMARY), 0); +} + +_inline QXLPHYSICAL QxlDevice::PA(PVOID virt, UINT8 slot_id) +{ + MemSlot *pSlot = &m_MemSlots[slot_id];; + + return pSlot->high_bits | ((UINT64)virt - pSlot->start_virt_addr); +} + +_inline UINT64 QxlDevice::VA(QXLPHYSICAL paddr, UINT8 slot_id) +{ + UINT64 virt; + MemSlot *pSlot = &m_MemSlots[slot_id];; + + virt = paddr & m_VaSlotMask; + virt += pSlot->start_virt_addr;; + + return virt; +} + void QxlDevice::SetupHWSlot(UINT8 Idx, MemSlot *pSlot) { m_RamHdr->mem_slot.mem_start = pSlot->start_phys_addr; @@ -3179,6 +3226,8 @@ BOOL QxlDevice::CreateEvents() KeInitializeEvent(&m_IoCmdEvent, SynchronizationEvent, FALSE); + KeInitializeSpinLock(&m_MemLock); + return TRUE; } @@ -3218,6 +3267,19 @@ BOOL QxlDevice::CreateMemSlots(void) return TRUE; } +void QxlDevice::InitDeviceMemoryResources(void) +{ + InitMspace(MSPACE_TYPE_DEVRAM, (m_RamStart + m_RomHdr->surface0_area_size), (size_t)((m_VRamPA.QuadPart + m_RomHdr->surface0_area_size) * PAGE_SIZE)); + InitMspace(MSPACE_TYPE_VRAM, m_VRamStart, m_VRamSize); +} + +void QxlDevice::InitMspace(UINT32 mspace_type, UINT8 *start, size_t capacity) +{ + m_MSInfo[mspace_type]._mspace = create_mspace_with_base(start, capacity, 0, this); + m_MSInfo[mspace_type].mspace_start = start; + m_MSInfo[mspace_type].mspace_end = start + capacity; +} + void QxlDevice::ResetDevice(void) { m_RamHdr->int_mask = ~0; @@ -3239,12 +3301,465 @@ QxlDevice::ExecutePresentDisplayOnly( _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, _In_ const CURRENT_BDD_MODE* pModeCur) { - PAGED_CODE(); DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); NTSTATUS Status = STATUS_SUCCESS; - return Status; + + SIZE_T sizeMoves = NumMoves*sizeof(D3DKMT_MOVE_RECT); + SIZE_T sizeRects = NumDirtyRects*sizeof(RECT); + SIZE_T size = sizeof(DoPresentMemory) + sizeMoves + sizeRects; + + DoPresentMemory* ctx = reinterpret_cast + (new (NonPagedPoolNx) BYTE[size]); + + if (!ctx) + { + return STATUS_NO_MEMORY; + } + + RtlZeroMemory(ctx,size); + +// const CURRENT_BDD_MODE* pModeCur = &m_CurrentModes[0]; + ctx->DstAddr = DstAddr; + ctx->DstBitPerPixel = DstBitPerPixel; + ctx->DstStride = pModeCur->DispInfo.Pitch; + ctx->SrcWidth = pModeCur->SrcModeWidth; + ctx->SrcHeight = pModeCur->SrcModeHeight; + ctx->SrcAddr = NULL; + ctx->SrcPitch = SrcPitch; + ctx->Rotation = Rotation; + ctx->NumMoves = NumMoves; + ctx->Moves = Moves; + ctx->NumDirtyRects = NumDirtyRects; + ctx->DirtyRect = DirtyRect; +// ctx->SourceID = m_SourceId; +// ctx->hAdapter = m_DevExt; + ctx->Mdl = NULL; + ctx->DisplaySource = this; + + // Alternate between synch and asynch execution, for demonstrating + // that a real hardware implementation can do either + + { + // Map Source into kernel space, as Blt will be executed by system worker thread + UINT sizeToMap = SrcBytesPerPixel * ctx->SrcWidth * ctx->SrcHeight; + + PMDL mdl = IoAllocateMdl((PVOID)SrcAddr, sizeToMap, FALSE, FALSE, NULL); + if(!mdl) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + KPROCESSOR_MODE AccessMode = static_cast(( SrcAddr <= + (BYTE* const) MM_USER_PROBE_ADDRESS)?UserMode:KernelMode); + __try + { + // Probe and lock the pages of this buffer in physical memory. + // We need only IoReadAccess. + MmProbeAndLockPages(mdl, AccessMode, IoReadAccess); + } + #pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try/except is only able to protect against user-mode errors and these are the only errors we try to catch here"); + __except(EXCEPTION_EXECUTE_HANDLER) + { + Status = GetExceptionCode(); + IoFreeMdl(mdl); + return Status; + } + + // Map the physical pages described by the MDL into system space. + // Note: double mapping the buffer this way causes lot of system + // overhead for large size buffers. + ctx->SrcAddr = reinterpret_cast + (MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority )); + + if(!ctx->SrcAddr) { + Status = STATUS_INSUFFICIENT_RESOURCES; + MmUnlockPages(mdl); + IoFreeMdl(mdl); + return Status; + } + + // Save Mdl to unmap and unlock the pages in worker thread + ctx->Mdl = mdl; + } + + BYTE* rects = reinterpret_cast(ctx+1); + + // copy moves and update pointer + if (Moves) + { + memcpy(rects,Moves,sizeMoves); + ctx->Moves = reinterpret_cast(rects); + rects += sizeMoves; + } + + // copy dirty rects and update pointer + if (DirtyRect) + { + memcpy(rects,DirtyRect,sizeRects); + ctx->DirtyRect = reinterpret_cast(rects); + } + + // Set up destination blt info + BLT_INFO DstBltInfo; + DstBltInfo.pBits = ctx->DstAddr; + DstBltInfo.Pitch = ctx->DstStride; + DstBltInfo.BitsPerPel = ctx->DstBitPerPixel; + DstBltInfo.Offset.x = 0; + DstBltInfo.Offset.y = 0; + DstBltInfo.Rotation = ctx->Rotation; + DstBltInfo.Width = ctx->SrcWidth; + DstBltInfo.Height = ctx->SrcHeight; + + // Set up source blt info + BLT_INFO SrcBltInfo; + SrcBltInfo.pBits = ctx->SrcAddr; + SrcBltInfo.Pitch = ctx->SrcPitch; + SrcBltInfo.BitsPerPel = 32; + SrcBltInfo.Offset.x = 0; + SrcBltInfo.Offset.y = 0; + SrcBltInfo.Rotation = D3DKMDT_VPPR_IDENTITY; + if (ctx->Rotation == D3DKMDT_VPPR_ROTATE90 || + ctx->Rotation == D3DKMDT_VPPR_ROTATE270) + { + SrcBltInfo.Width = DstBltInfo.Height; + SrcBltInfo.Height = DstBltInfo.Width; + } + else + { + SrcBltInfo.Width = DstBltInfo.Width; + SrcBltInfo.Height = DstBltInfo.Height; + } + + + // Copy all the scroll rects from source image to video frame buffer. + for (UINT i = 0; i < ctx->NumMoves; i++) + { + POINT* pSourcePoint = &ctx->Moves[i].SourcePoint; + RECT* pDestRect = &ctx->Moves[i].DestRect; + + DbgPrint(TRACE_LEVEL_FATAL, ("--- %d SourcePoint.x = %d, SourcePoint.y = %d, DestRect.bottom = %d, DestRect.left = %d, DestRect.right = %d, DestRect.top = %d\n", + i , pSourcePoint->x, pSourcePoint->y, pDestRect->bottom, pDestRect->left, pDestRect->right, pDestRect->top)); + + BltBits(&DstBltInfo, + &SrcBltInfo, + 1, // NumRects + &ctx->Moves[i].DestRect); + } + + // Copy all the dirty rects from source image to video frame buffer. + for (UINT i = 0; i < ctx->NumDirtyRects; i++) + { + RECT* pDirtyRect = &ctx->DirtyRect[i]; + DbgPrint(TRACE_LEVEL_FATAL, ("--- %d pDirtyRect->bottom = %d, pDirtyRect->left = %d, pDirtyRect->right = %d, pDirtyRect->top = %d\n", + i, pDirtyRect->bottom, pDirtyRect->left, pDirtyRect->right, pDirtyRect->top)); + + BltBits(&DstBltInfo, + &SrcBltInfo, + 1, // NumRects + &ctx->DirtyRect[i]); + } + + // Unmap unmap and unlock the pages. + if (ctx->Mdl) + { + MmUnlockPages(ctx->Mdl); + IoFreeMdl(ctx->Mdl); + } + delete [] reinterpret_cast(ctx); + + return STATUS_SUCCESS; +} + +static inline +KIRQL +AcquireSpinLock(PVOID pSpinLock) +{ + KIRQL IRQL; + + IRQL = KeGetCurrentIrql(); + + if (DISPATCH_LEVEL == IRQL) + KeAcquireSpinLockAtDpcLevel((KSPIN_LOCK *)pSpinLock); + else + KeAcquireSpinLock((KSPIN_LOCK *)pSpinLock, &IRQL); + + return IRQL; +} + +static inline +VOID +ReleaseSpinLock(PVOID pSpinLock, KIRQL IRQL) +{ + if (DISPATCH_LEVEL == IRQL) + KeReleaseSpinLockFromDpcLevel((KSPIN_LOCK *)pSpinLock); + else + KeReleaseSpinLock((KSPIN_LOCK *)pSpinLock, IRQL); +} + +void QxlDevice::WaitForReleaseRing(void) +{ + int wait; + + DbgPrint(TRACE_LEVEL_VERBOSE, ("%s\n", __FUNCTION__)); + + for (;;) { + LARGE_INTEGER timeout; + + if (SPICE_RING_IS_EMPTY(m_ReleaseRing)) { + QXL_SLEEP(10); + if (!SPICE_RING_IS_EMPTY(m_ReleaseRing)) { + break; + } + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_NOTIFY_OOM), 0); + } + SPICE_RING_CONS_WAIT(m_ReleaseRing, wait); + + if (!wait) { + break; + } + + timeout.QuadPart = -30 * 1000 * 10; //30ms + WAIT_FOR_EVENT(m_DisplayEvent, &timeout); + + if (SPICE_RING_IS_EMPTY(m_ReleaseRing)) { + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_NOTIFY_OOM), 0); + } + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: done\n", __FUNCTION__)); +} + + +void QxlDevice::FlushReleaseRing() +{ + UINT64 output; + int notify; + int num_to_release = 50; + + output = free_outputs; + + while (1) { + while (output != 0) { + output = ReleaseOutput(output); + if (--num_to_release == 0) { + break; + } + } + + if (output != 0 || + SPICE_RING_IS_EMPTY(m_ReleaseRing)) { + break; + } + + output = *SPICE_RING_CONS_ITEM(m_ReleaseRing); + SPICE_RING_POP(m_ReleaseRing, notify); + } + + free_outputs = output; +} + +UINT64 QxlDevice::ReleaseOutput(UINT64 output_id) +{ + QXLOutput *output = (QXLOutput *)output_id; + Resource **now; + Resource **end; + UINT64 next; + + ASSERT(output_id); + DbgPrint(TRACE_LEVEL_VERBOSE, ("%s 0x%x\n", __FUNCTION__, output)); +// DebugShowOutput(pdev, output); + + for (now = output->resources, end = now + output->num_res; now < end; now++) { + RELEASE_RES(*now); + } + next = *(UINT64*)output->data; + FreeMem(MSPACE_TYPE_DEVRAM, output); + DbgPrint(TRACE_LEVEL_VERBOSE, ("%s done\n", __FUNCTION__)); + return next; +} + +void *QxlDevice::AllocMem(UINT32 mspace_type, size_t size, BOOL force) +{ + PVOID ptr; + KIRQL old_irql; + + ASSERT(m_MSInfo[mspace_type]._mspace); + DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: %p(%d) size %u\n", __FUNCTION__, + m_MSInfo[mspace_type]._mspace, + mspace_footprint(m_MSInfo[mspace_type]._mspace), + size)); +#ifdef DBG + mspace_malloc_stats(m_MSInfo[mspace_type]._mspace); +#endif + + while (1) { + /* Release lots of queued resources, before allocating, as we + want to release early to minimize fragmentation risks. */ + FlushReleaseRing(); + + old_irql = AcquireSpinLock(&m_MemLock); + ptr = mspace_malloc(m_MSInfo[mspace_type]._mspace, size); + ReleaseSpinLock(&m_MemLock, old_irql); + if (ptr) { + break; + } + + if (free_outputs != 0 || + !SPICE_RING_IS_EMPTY(m_ReleaseRing)) { + /* We have more things to free, try that */ + continue; + } + + if (force) { + /* Ask spice to free some stuff */ + WaitForReleaseRing(); + } else { + /* Fail */ + break; + } + } + + ASSERT((!ptr && !force) || (ptr >= m_MSInfo[mspace_type].mspace_start && + ptr < m_MSInfo[mspace_type].mspace_end)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: done 0x%x\n", __FUNCTION__, ptr)); + return ptr; +} + +void QxlDevice::FreeMem(UINT32 mspace_type, void *ptr) +{ + KIRQL old_irql; + ASSERT(m_MSInfo[mspace_type]._mspace); +#ifdef DBG + if (!((UINT8 *)ptr >= m_MSInfo[mspace_type].mspace_start && + (UINT8 *)ptr < m_MSInfo[mspace_type].mspace_end)) { + DbgPrint(TRACE_LEVEL_ERROR, ("ASSERT failed @ %s, %p not in [%p, %p) (%d)\n", __FUNCTION__, + ptr, m_MSInfo[mspace_type].mspace_start, + m_MSInfo[mspace_type].mspace_end, mspace_type)); + } +#endif + old_irql = AcquireSpinLock(&m_MemLock); + mspace_free(m_MSInfo[mspace_type]._mspace, ptr); + ReleaseSpinLock(&m_MemLock, old_irql); +} + + +QXLDrawable *QxlDevice::GetDrawable() +{ + QXLOutput *output; + + output = (QXLOutput *)AllocMem(MSPACE_TYPE_DEVRAM, sizeof(QXLOutput) + sizeof(QXLDrawable), TRUE); + output->num_res = 0; + RESOURCE_TYPE(output, RESOURCE_TYPE_DRAWABLE); + ((QXLDrawable *)output->data)->release_info.id = (UINT64)output; + DbgPrint(TRACE_LEVEL_VERBOSE, ("%s 0x%x\n", __FUNCTION__, output)); + return(QXLDrawable *)output->data; +} + +BOOL QxlDevice::SetClip(const RECT *clip, QXLDrawable *drawable) +{ + Resource *rects_res; + + if (clip == NULL) { + drawable->clip.type = SPICE_CLIP_TYPE_NONE; + DbgPrint(TRACE_LEVEL_ERROR, ("%s QXL_CLIP_TYPE_NONE\n", __FUNCTION__)); + return TRUE; + } + + QXLClipRects *rects; + rects_res = (Resource *)AllocMem(MSPACE_TYPE_DEVRAM, sizeof(Resource) + sizeof(QXLClipRects) + + sizeof(QXLRect), TRUE); + rects_res->refs = 1; +//FIXME + rects_res->free = FreeClipRectsEx; + rects_res->ptr = this; + rects = (QXLClipRects *)rects_res->res; + rects->num_rects = 1; + rects->chunk.data_size = sizeof(QXLRect); + rects->chunk.prev_chunk = 0; + rects->chunk.next_chunk = 0; + CopyRect((QXLRect *)rects->chunk.data, clip); + + DrawableAddRes(drawable, rects_res); + drawable->clip.type = SPICE_CLIP_TYPE_RECTS; + drawable->clip.data = PA(rects_res->res, m_MainMemSlot); + return TRUE; +} + +void QxlDevice::AddRes(QXLOutput *output, Resource *res) +{ + res->refs++; + output->resources[output->num_res++] = res; +} + +void QxlDevice::DrawableAddRes(QXLDrawable *drawable, Resource *res) +{ + QXLOutput *output; + + output = (QXLOutput *)((UINT8 *)drawable - sizeof(QXLOutput)); + AddRes(output, res); +} + +void QxlDevice::FreeClipRectsEx(Resource *res) +{ + QxlDevice* pqxl = (QxlDevice*)res->ptr; + pqxl->FreeClipRects(res); +} +void QxlDevice::FreeClipRects(Resource *res) +{ + QXLPHYSICAL chunk_phys; + + chunk_phys = ((QXLClipRects *)res->res)->chunk.next_chunk; + while (chunk_phys) { + QXLDataChunk *chunk = (QXLDataChunk *)VA(chunk_phys, m_MainMemSlot); + chunk_phys = chunk->next_chunk; + FreeMem(MSPACE_TYPE_DEVRAM, chunk); + } + FreeMem(MSPACE_TYPE_DEVRAM, res); +} + +QXLDrawable *QxlDevice::Drawable(UINT8 type, CONST RECT *area, CONST RECT *clip, UINT32 surface_id) +{ + QXLDrawable *drawable; + + ASSERT(area); + + drawable = GetDrawable(); + drawable->surface_id = surface_id; + drawable->type = type; + drawable->effect = QXL_EFFECT_BLEND; + drawable->self_bitmap = 0; + drawable->mm_time = m_RomHdr->mm_clock; + drawable->surfaces_dest[0] = -1; + drawable->surfaces_dest[1] = - 1; + drawable->surfaces_dest[2] = -1; + CopyRect(&drawable->bbox, area); + + if (!SetClip(clip, drawable)) { + DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: set clip failed\n", __FUNCTION__)); + ReleaseOutput(drawable->release_info.id); + drawable = NULL; + } + return drawable; +} + + +VOID QxlDevice::BltBits ( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects) +{ + QXLDrawable *drawable; + + if (!(drawable = Drawable(QXL_DRAW_COPY, pRects, NULL, 0))) { + DbgPrint(TRACE_LEVEL_ERROR, ("Cannot get Drawable.\n")); + } + + for (UINT iRect = 0; iRect < NumRects; iRect++) + { + CONST RECT* pRect = &pRects[iRect]; + } } VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) @@ -3293,3 +3808,17 @@ D3DDDIFORMAT PixelFormatFromBPP(UINT BPP) default: QXL_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not supported.", BPP); return D3DDDIFMT_UNKNOWN; } } + +UINT SpiceFromPixelFormat(D3DDDIFORMAT Format) +{ + switch (Format) + { + case D3DDDIFMT_UNKNOWN: + case D3DDDIFMT_P8: QXL_LOG_ASSERTION1("Bad format type 0x%I64x", Format); return 0; + case D3DDDIFMT_R5G6B5: return SPICE_SURFACE_FMT_16_555; + case D3DDDIFMT_R8G8B8: + case D3DDDIFMT_X8R8G8B8: + case D3DDDIFMT_A8R8G8B8: return SPICE_SURFACE_FMT_32_xRGB; + default: QXL_LOG_ASSERTION1("Unknown D3DDDIFORMAT 0x%I64x", Format); return 0; + } +} diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index ee24f9e..05a84f7 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -1,6 +1,7 @@ #pragma once #include "baseobject.h" #include "qxl_dev.h" +#include "mspace.h" #define MAX_CHILDREN 1 #define MAX_VIEWS 1 @@ -306,6 +307,85 @@ typedef struct _MemSlot { QXLPHYSICAL high_bits; } MemSlot; +typedef struct MspaceInfo { + mspace _mspace; + UINT8 *mspace_start; + UINT8 *mspace_end; +} MspaceInfo; + +enum { + MSPACE_TYPE_DEVRAM, + MSPACE_TYPE_VRAM, + + NUM_MSPACES, +}; + +#define RELEASE_RES(res) if (!--(res)->refs) (res)->free(res); +#define GET_RES(res) (++(res)->refs) + +/* Debug helpers - tag each resource with this enum */ +enum { + RESOURCE_TYPE_DRAWABLE = 1, + RESOURCE_TYPE_SURFACE, + RESOURCE_TYPE_PATH, + RESOURCE_TYPE_CLIP_RECTS, + RESOURCE_TYPE_QUIC_IMAGE, + RESOURCE_TYPE_BITMAP_IMAGE, + RESOURCE_TYPE_SURFACE_IMAGE, + RESOURCE_TYPE_SRING, + RESOURCE_TYPE_CURSOR, + RESOURCE_TYPE_BUF, + RESOURCE_TYPE_UPDATE, +}; + +#ifdef DBG +#define RESOURCE_TYPE(res, val) do { res->type = val; } while (0) +#else +#define RESOURCE_TYPE(res, val) +#endif + +typedef struct Resource Resource; +struct Resource { + UINT32 refs; + void* ptr; +#ifdef DBG + UINT32 type; +#endif + void (*free)(Resource *res); + UINT8 res[0]; +}; + +#define TIMEOUT_TO_MS ((LONGLONG) 1 * 10 * 1000) + +#define WAIT_FOR_EVENT(event, timeout) do { \ + NTSTATUS status; \ + status = KeWaitForSingleObject ( \ + &event, \ + Executive, \ + KernelMode, \ + FALSE, \ + timeout); \ + ASSERT(NT_SUCCESS(status)); \ +} while (0); + +#define QXL_SLEEP(msec) do { \ + LARGE_INTEGER timeout; \ + timeout.QuadPart = -msec * TIMEOUT_TO_MS; \ + KeDelayExecutionThread (KernelMode, FALSE, &timeout);\ +} while (0); + + +#define MAX_OUTPUT_RES 6 + +typedef struct QXLOutput { + UINT32 num_res; +#ifdef DBG + UINT32 type; +#endif + Resource *resources[MAX_OUTPUT_RES]; + UINT8 data[0]; +} QXLOutput; + class QxlDevice : public HwDeviceIntrface { @@ -332,17 +412,44 @@ public: VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); + VOID BltBits ( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + QXLDrawable *Drawable( + UINT8 type, + CONST RECT *area, + CONST RECT *clip, + UINT32 surface_id); + QXLDrawable *GetDrawable(); + void *AllocMem(UINT32 mspace_type, size_t size, BOOL force); private: void UnmapMemory(void); BOOL SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo); BOOL InitMemSlots(void); BOOL CreateMemSlots(void); void DestroyMemSlots(void); + void CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo); + void DestroyPrimarySurface(void); void ResetDevice(void); void SetupHWSlot(UINT8 Idx, MemSlot *pSlot); UINT8 SetupMemSlot(UINT8 Idx, QXLPHYSICAL start, QXLPHYSICAL end); - BOOL CreateEvents(); - BOOL CreateRings(); + BOOL CreateEvents(void); + BOOL CreateRings(void); + UINT64 VA(QXLPHYSICAL paddr, UINT8 slot_id); + QXLPHYSICAL PA(PVOID virt, UINT8 slot_id); + void InitDeviceMemoryResources(void); + void InitMspace(UINT32 mspace_type, UINT8 *start, size_t capacity); + void FlushReleaseRing(); + void FreeMem(UINT32 mspace_type, void *ptr); + UINT64 ReleaseOutput(UINT64 output_id); + void WaitForReleaseRing(void); + BOOL SetClip(const RECT *clip, QXLDrawable *drawable); + void AddRes(QXLOutput *output, Resource *res); + void DrawableAddRes(QXLDrawable *drawable, Resource *res); + void FreeClipRects(Resource *res); + void static FreeClipRectsEx(Resource *res); private: PUCHAR m_IoBase; BOOLEAN m_IoMapped; @@ -378,6 +485,12 @@ private: PUCHAR m_LogPort; PUCHAR m_LogBuf; + + KSPIN_LOCK m_MemLock; + MspaceInfo m_MSInfo[NUM_MSPACES]; + + UINT64 free_outputs; + }; class QxlDod : @@ -517,6 +630,37 @@ private: NTSTATUS RegisterHWInfo(); +/* + NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* pMoves, + _In_ ULONG NumDirtyRects, + _In_ RECT* pDirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation); + BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect); + VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch); + VOID CopyBitsGeneric( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + + VOID CopyBits32_32( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + VOID BltBits ( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + VOID BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId); +*/ }; NTSTATUS @@ -532,6 +676,7 @@ UnmapFrameBuffer( UINT BPPFromPixelFormat(D3DDDIFORMAT Format); D3DDDIFORMAT PixelFormatFromBPP(UINT BPP); +UINT SpiceFromPixelFormat(D3DDDIFORMAT Format); VOID CopyBitsGeneric( BLT_INFO* pDst, diff --git a/qxldod/mspace.c b/qxldod/mspace.c new file mode 100755 index 0000000..d0ba123 --- /dev/null +++ b/qxldod/mspace.c @@ -0,0 +1,2437 @@ +// based on dlmalloc from Doug Lea + + +// quote from the Doug Lea original file + /* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain, as explained at + http://creativecommons.org/licenses/publicdomain. Send questions, + comments, complaints, performance data, etc to dl@cs.oswego.edu + + * Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + */ + + +#include + +#include "mspace.h" + +#pragma warning( disable : 4146 ) /* no "unsigned" warnings */ + +#define MALLOC_ALIGNMENT ((size_t)8U) +#define USE_LOCKS 0 +#define malloc_getpagesize ((size_t)4096U) +#define DEFAULT_GRANULARITY malloc_getpagesize +#define MAX_SIZE_T (~(size_t)0) +#define MALLOC_FAILURE_ACTION +#define MALLINFO_FIELD_TYPE size_t +#define FOOTERS 0 +#define INSECURE 0 +#define PROCEED_ON_ERROR 0 +#define DEBUG 0 +#define ABORT_ON_ASSERT_FAILURE 1 +#define ABORT(user_data) abort_func(user_data) +#define USE_BUILTIN_FFS 0 +#define USE_DEV_RANDOM 0 +#define PRINT(params) print_func params + + +#define MEMCPY(dest, src, n) RtlCopyMemory(dest, src, n) +#define MEMCLEAR(dest, n) RtlZeroMemory(dest, n) + + +#define M_GRANULARITY (-1) + +void default_abort_func(void *user_data) +{ + for (;;); +} + +void default_print_func(void *user_data, char *format, ...) +{ +} + +static mspace_abort_t abort_func = default_abort_func; +static mspace_print_t print_func = default_print_func; + +void mspace_set_abort_func(mspace_abort_t f) +{ + abort_func = f; +} + +void mspace_set_print_func(mspace_print_t f) +{ + print_func = f; +} + +/* ------------------------ Mallinfo declarations ------------------------ */ + +#if !NO_MALLINFO +/* + This version of malloc supports the standard SVID/XPG mallinfo + routine that returns a struct containing usage properties and + statistics. It should work on any system that has a + /usr/include/malloc.h defining struct mallinfo. The main + declaration needed is the mallinfo struct that is returned (by-copy) + by mallinfo(). The malloinfo struct contains a bunch of fields that + are not even meaningful in this version of malloc. These fields are + are instead filled by mallinfo() with other numbers that might be of + interest. + + HAVE_USR_INCLUDE_MALLOC_H should be set if you have a + /usr/include/malloc.h file that includes a declaration of struct + mallinfo. If so, it is included; else a compliant version is + declared below. These must be precisely the same for mallinfo() to + work. The original SVID version of this struct, defined on most + systems with mallinfo, declares all fields as ints. But some others + define as unsigned long. If your system defines the fields using a + type of different width than listed here, you MUST #include your + system version and #define HAVE_USR_INCLUDE_MALLOC_H. +*/ + +/* #define HAVE_USR_INCLUDE_MALLOC_H */ + + +struct mallinfo { + MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ + MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ + MALLINFO_FIELD_TYPE smblks; /* always 0 */ + MALLINFO_FIELD_TYPE hblks; /* always 0 */ + MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ + MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ + MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ + MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ + MALLINFO_FIELD_TYPE fordblks; /* total free space */ + MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ +}; + +#endif /* NO_MALLINFO */ + + + +#ifdef DEBUG +#if ABORT_ON_ASSERT_FAILURE +#define assert(user_data, x) if(!(x)) ABORT(user_data) +#else /* ABORT_ON_ASSERT_FAILURE */ +#include +#endif /* ABORT_ON_ASSERT_FAILURE */ +#else /* DEBUG */ +#define assert(user_data, x) +#endif /* DEBUG */ + +/* ------------------- size_t and alignment properties -------------------- */ + +/* The byte and bit size of a size_t */ +#define SIZE_T_SIZE (sizeof(size_t)) +#define SIZE_T_BITSIZE (sizeof(size_t) << 3) + +/* Some constants coerced to size_t */ +/* Annoying but necessary to avoid errors on some plaftorms */ +#define SIZE_T_ZERO ((size_t)0) +#define SIZE_T_ONE ((size_t)1) +#define SIZE_T_TWO ((size_t)2) +#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) +#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) +#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) +#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) + +/* The bit mask value corresponding to MALLOC_ALIGNMENT */ +#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) + +/* True if address a has acceptable alignment */ +#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) + +/* the number of bytes to offset an address to align it */ +#define align_offset(A)\ + ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\ + ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK)) + +/* --------------------------- Lock preliminaries ------------------------ */ + +#if USE_LOCKS + +/* + When locks are defined, there are up to two global locks: + + * If HAVE_MORECORE, morecore_mutex protects sequences of calls to + MORECORE. In many cases sys_alloc requires two calls, that should + not be interleaved with calls by other threads. This does not + protect against direct calls to MORECORE by other threads not + using this lock, so there is still code to cope the best we can on + interference. + + * magic_init_mutex ensures that mparams.magic and other + unique mparams values are initialized only once. +*/ + + +#define USE_LOCK_BIT (2U) +#else /* USE_LOCKS */ +#define USE_LOCK_BIT (0U) +#define INITIAL_LOCK(l) +#endif /* USE_LOCKS */ + +#if USE_LOCKS +#define ACQUIRE_MAGIC_INIT_LOCK() ACQUIRE_LOCK(&magic_init_mutex); +#define RELEASE_MAGIC_INIT_LOCK() RELEASE_LOCK(&magic_init_mutex); +#else /* USE_LOCKS */ +#define ACQUIRE_MAGIC_INIT_LOCK() +#define RELEASE_MAGIC_INIT_LOCK() +#endif /* USE_LOCKS */ + + + +/* ----------------------- Chunk representations ------------------------ */ + +/* + (The following includes lightly edited explanations by Colin Plumb.) + + The malloc_chunk declaration below is misleading (but accurate and + necessary). It declares a "view" into memory allowing access to + necessary fields at known offsets from a given base. + + Chunks of memory are maintained using a `boundary tag' method as + originally described by Knuth. (See the paper by Paul Wilson + ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such + techniques.) Sizes of free chunks are stored both in the front of + each chunk and at the end. This makes consolidating fragmented + chunks into bigger chunks fast. The head fields also hold bits + representing whether chunks are free or in use. + + Here are some pictures to make it clearer. They are "exploded" to + show that the state of a chunk can be thought of as extending from + the high 31 bits of the head field of its header through the + prev_foot and PINUSE_BIT bit of the following chunk header. + + A chunk that's in use looks like: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk (if P = 1) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| + | Size of this chunk 1| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + +- -+ + | | + +- -+ + | : + +- size - sizeof(size_t) available payload bytes -+ + : | + chunk-> +- -+ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1| + | Size of next chunk (may or may not be in use) | +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + And if it's free, it looks like this: + + chunk-> +- -+ + | User payload (must be in use, or we would have merged!) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| + | Size of this chunk 0| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Prev pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | : + +- size - sizeof(struct chunk) unused bytes -+ + : | + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of this chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0| + | Size of next chunk (must be in use, or we would have merged)| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | : + +- User payload -+ + : | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |0| + +-+ + Note that since we always merge adjacent free chunks, the chunks + adjacent to a free chunk must be in use. + + Given a pointer to a chunk (which can be derived trivially from the + payload pointer) we can, in O(1) time, find out whether the adjacent + chunks are free, and if so, unlink them from the lists that they + are on and merge them with the current chunk. + + Chunks always begin on even word boundaries, so the mem portion + (which is returned to the user) is also on an even word boundary, and + thus at least double-word aligned. + + The P (PINUSE_BIT) bit, stored in the unused low-order bit of the + chunk size (which is always a multiple of two words), is an in-use + bit for the *previous* chunk. If that bit is *clear*, then the + word before the current chunk size contains the previous chunk + size, and can be used to find the front of the previous chunk. + The very first chunk allocated always has this bit set, preventing + access to non-existent (or non-owned) memory. If pinuse is set for + any given chunk, then you CANNOT determine the size of the + previous chunk, and might even get a memory addressing fault when + trying to do so. + + The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of + the chunk size redundantly records whether the current chunk is + inuse. This redundancy enables usage checks within free and realloc, + and reduces indirection when freeing and consolidating chunks. + + Each freshly allocated chunk must have both cinuse and pinuse set. + That is, each allocated chunk borders either a previously allocated + and still in-use chunk, or the base of its memory arena. This is + ensured by making all allocations from the the `lowest' part of any + found chunk. Further, no free chunk physically borders another one, + so each free chunk is known to be preceded and followed by either + inuse chunks or the ends of memory. + + Note that the `foot' of the current chunk is actually represented + as the prev_foot of the NEXT chunk. This makes it easier to + deal with alignments etc but can be very confusing when trying + to extend or adapt this code. + + The exceptions to all this are + + 1. The special chunk `top' is the top-most available chunk (i.e., + the one bordering the end of available memory). It is treated + specially. Top is never included in any bin, is used only if + no other chunk is available, and is released back to the + system if it is very large (see M_TRIM_THRESHOLD). In effect, + the top chunk is treated as larger (and thus less well + fitting) than any other available chunk. The top chunk + doesn't update its trailing size field since there is no next + contiguous chunk that would have to index off it. However, + space is still allocated for it (TOP_FOOT_SIZE) to enable + separation or merging when space is extended. + + 3. Chunks allocated via mmap, which have the lowest-order bit + (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set + PINUSE_BIT in their head fields. Because they are allocated + one-by-one, each must carry its own prev_foot field, which is + also used to hold the offset this chunk has within its mmapped + region, which is needed to preserve alignment. Each mmapped + chunk is trailed by the first two fields of a fake next-chunk + for sake of usage checks. + +*/ + +struct malloc_chunk { + size_t prev_foot; /* Size of previous chunk (if free). */ + size_t head; /* Size and inuse bits. */ + struct malloc_chunk* fd; /* double links -- used only if free. */ + struct malloc_chunk* bk; +}; + +typedef struct malloc_chunk mchunk; +typedef struct malloc_chunk* mchunkptr; +typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */ +typedef unsigned int bindex_t; /* Described below */ +typedef unsigned int binmap_t; /* Described below */ +typedef unsigned int flag_t; /* The type of various bit flag sets */ + + +/* ------------------- Chunks sizes and alignments ----------------------- */ + +#define MCHUNK_SIZE (sizeof(mchunk)) + +#if FOOTERS +#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) +#else /* FOOTERS */ +#define CHUNK_OVERHEAD (SIZE_T_SIZE) +#endif /* FOOTERS */ + +/* The smallest size we can malloc is an aligned minimal chunk */ +#define MIN_CHUNK_SIZE\ + ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) + +/* conversion from malloc headers to user pointers, and back */ +#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES)) +#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES)) +/* chunk associated with aligned address A */ +#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) + +/* Bounds on request (not chunk) sizes. */ +#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) +#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) + +/* pad request bytes into a usable size */ +#define pad_request(req) \ + (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) + +/* pad request, checking for minimum (but not maximum) */ +#define request2size(req) \ + (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req)) + +/* ------------------ Operations on head and foot fields ----------------- */ + +/* + The head field of a chunk is or'ed with PINUSE_BIT when previous + adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in + use. If the chunk was obtained with mmap, the prev_foot field has + IS_MMAPPED_BIT set, otherwise holding the offset of the base of the + mmapped region to the base of the chunk. +*/ + +#define PINUSE_BIT (SIZE_T_ONE) +#define CINUSE_BIT (SIZE_T_TWO) +#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) + +/* Head value for fenceposts */ +#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) + +/* extraction of fields from head words */ +#define cinuse(p) ((p)->head & CINUSE_BIT) +#define pinuse(p) ((p)->head & PINUSE_BIT) +#define chunksize(p) ((p)->head & ~(INUSE_BITS)) + +#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) +#define clear_cinuse(p) ((p)->head &= ~CINUSE_BIT) + +/* Treat space at ptr +/- offset as a chunk */ +#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) +#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) + +/* Ptr to next or previous physical malloc_chunk. */ +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS))) +#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) + +/* extract next chunk's pinuse bit */ +#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) + +/* Get/set size at footer */ +#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot) +#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s)) + +/* Set size, pinuse bit, and foot */ +#define set_size_and_pinuse_of_free_chunk(p, s)\ + ((p)->head = (s|PINUSE_BIT), set_foot(p, s)) + +/* Set size, pinuse bit, foot, and clear next pinuse */ +#define set_free_with_pinuse(p, s, n)\ + (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) + +/* Get the internal overhead associated with chunk p */ +#define overhead_for(p) CHUNK_OVERHEAD + +/* Return true if malloced space is not necessarily cleared */ +#define calloc_must_clear(p) (1) + + +/* ---------------------- Overlaid data structures ----------------------- */ + +/* + When chunks are not in use, they are treated as nodes of either + lists or trees. + + "Small" chunks are stored in circular doubly-linked lists, and look + like this: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space (may be 0 bytes long) . + . . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Larger chunks are kept in a form of bitwise digital trees (aka + tries) keyed on chunksizes. Because malloc_tree_chunks are only for + free chunks greater than 256 bytes, their size doesn't impose any + constraints on user chunk sizes. Each node looks like: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk of same size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk of same size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to left child (child[0]) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to right child (child[1]) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to parent | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | bin index of this chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Each tree holding treenodes is a tree of unique chunk sizes. Chunks + of the same size are arranged in a circularly-linked list, with only + the oldest chunk (the next to be used, in our FIFO ordering) + actually in the tree. (Tree members are distinguished by a non-null + parent pointer.) If a chunk with the same size an an existing node + is inserted, it is linked off the existing node using pointers that + work in the same way as fd/bk pointers of small chunks. + + Each tree contains a power of 2 sized range of chunk sizes (the + smallest is 0x100 <= x < 0x180), which is is divided in half at each + tree level, with the chunks in the smaller half of the range (0x100 + <= x < 0x140 for the top nose) in the left subtree and the larger + half (0x140 <= x < 0x180) in the right subtree. This is, of course, + done by inspecting individual bits. + + Using these rules, each node's left subtree contains all smaller + sizes than its right subtree. However, the node at the root of each + subtree has no particular ordering relationship to either. (The + dividing line between the subtree sizes is based on trie relation.) + If we remove the last chunk of a given size from the interior of the + tree, we need to replace it with a leaf node. The tree ordering + rules permit a node to be replaced by any leaf below it. + + The smallest chunk in a tree (a common operation in a best-fit + allocator) can be found by walking a path to the leftmost leaf in + the tree. Unlike a usual binary tree, where we follow left child + pointers until we reach a null, here we follow the right child + pointer any time the left one is null, until we reach a leaf with + both child pointers null. The smallest chunk in the tree will be + somewhere along that path. + + The worst case number of steps to add, find, or remove a node is + bounded by the number of bits differentiating chunks within + bins. Under current bin calculations, this ranges from 6 up to 21 + (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case + is of course much better. +*/ + +struct malloc_tree_chunk { + /* The first four fields must be compatible with malloc_chunk */ + size_t prev_foot; + size_t head; + struct malloc_tree_chunk* fd; + struct malloc_tree_chunk* bk; + + struct malloc_tree_chunk* child[2]; + struct malloc_tree_chunk* parent; + bindex_t index; +}; + +typedef struct malloc_tree_chunk tchunk; +typedef struct malloc_tree_chunk* tchunkptr; +typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ + +/* A little helper macro for trees */ +#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1]) + +/* ----------------------------- Segments -------------------------------- */ + +/* + Each malloc space may include non-contiguous segments, held in a + list headed by an embedded malloc_segment record representing the + top-most space. Segments also include flags holding properties of + the space. Large chunks that are directly allocated by mmap are not + included in this list. They are instead independently created and + destroyed without otherwise keeping track of them. + + Segment management mainly comes into play for spaces allocated by + MMAP. Any call to MMAP might or might not return memory that is + adjacent to an existing segment. MORECORE normally contiguously + extends the current space, so this space is almost always adjacent, + which is simpler and faster to deal with. (This is why MORECORE is + used preferentially to MMAP when both are available -- see + sys_alloc.) When allocating using MMAP, we don't use any of the + hinting mechanisms (inconsistently) supported in various + implementations of unix mmap, or distinguish reserving from + committing memory. Instead, we just ask for space, and exploit + contiguity when we get it. It is probably possible to do + better than this on some systems, but no general scheme seems + to be significantly better. + + Management entails a simpler variant of the consolidation scheme + used for chunks to reduce fragmentation -- new adjacent memory is + normally prepended or appended to an existing segment. However, + there are limitations compared to chunk consolidation that mostly + reflect the fact that segment processing is relatively infrequent + (occurring only when getting memory from system) and that we + don't expect to have huge numbers of segments: + + * Segments are not indexed, so traversal requires linear scans. (It + would be possible to index these, but is not worth the extra + overhead and complexity for most programs on most platforms.) + * New segments are only appended to old ones when holding top-most + memory; if they cannot be prepended to others, they are held in + different segments. + + Except for the top-most segment of an mstate, each segment record + is kept at the tail of its segment. Segments are added by pushing + segment records onto the list headed by &mstate.seg for the + containing mstate. + + Segment flags control allocation/merge/deallocation policies: + * If EXTERN_BIT set, then we did not allocate this segment, + and so should not try to deallocate or merge with others. + (This currently holds only for the initial segment passed + into create_mspace_with_base.) + * If IS_MMAPPED_BIT set, the segment may be merged with + other surrounding mmapped segments and trimmed/de-allocated + using munmap. + * If neither bit is set, then the segment was obtained using + MORECORE so can be merged with surrounding MORECORE'd segments + and deallocated/trimmed using MORECORE with negative arguments. +*/ + +struct malloc_segment { + char* base; /* base address */ + size_t size; /* allocated size */ + struct malloc_segment* next; /* ptr to next segment */ +}; + +typedef struct malloc_segment msegment; +typedef struct malloc_segment* msegmentptr; + +/* ---------------------------- malloc_state ----------------------------- */ + +/* + A malloc_state holds all of the bookkeeping for a space. + The main fields are: + + Top + The topmost chunk of the currently active segment. Its size is + cached in topsize. The actual size of topmost space is + topsize+TOP_FOOT_SIZE, which includes space reserved for adding + fenceposts and segment records if necessary when getting more + space from the system. The size at which to autotrim top is + cached from mparams in trim_check, except that it is disabled if + an autotrim fails. + + Designated victim (dv) + This is the preferred chunk for servicing small requests that + don't have exact fits. It is normally the chunk split off most + recently to service another small request. Its size is cached in + dvsize. The link fields of this chunk are not maintained since it + is not kept in a bin. + + SmallBins + An array of bin headers for free chunks. These bins hold chunks + with sizes less than MIN_LARGE_SIZE bytes. Each bin contains + chunks of all the same size, spaced 8 bytes apart. To simplify + use in double-linked lists, each bin header acts as a malloc_chunk + pointing to the real first node, if it exists (else pointing to + itself). This avoids special-casing for headers. But to avoid + waste, we allocate only the fd/bk pointers of bins, and then use + repositioning tricks to treat these as the fields of a chunk. + + TreeBins + Treebins are pointers to the roots of trees holding a range of + sizes. There are 2 equally spaced treebins for each power of two + from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything + larger. + + Bin maps + There is one bit map for small bins ("smallmap") and one for + treebins ("treemap). Each bin sets its bit when non-empty, and + clears the bit when empty. Bit operations are then used to avoid + bin-by-bin searching -- nearly all "search" is done without ever + looking at bins that won't be selected. The bit maps + conservatively use 32 bits per map word, even if on 64bit system. + For a good description of some of the bit-based techniques used + here, see Henry S. Warren Jr's book "Hacker's Delight" (and + supplement at http://hackersdelight.org/). Many of these are + intended to reduce the branchiness of paths through malloc etc, as + well as to reduce the number of memory locations read or written. + + Segments + A list of segments headed by an embedded malloc_segment record + representing the initial space. + + Address check support + The least_addr field is the least address ever obtained from + MORECORE or MMAP. Attempted frees and reallocs of any address less + than this are trapped (unless INSECURE is defined). + + Magic tag + A cross-check field that should always hold same value as mparams.magic. + + Flags + Bits recording whether to use MMAP, locks, or contiguous MORECORE + + Statistics + Each space keeps track of current and maximum system memory + obtained via MORECORE or MMAP. + + Locking + If USE_LOCKS is defined, the "mutex" lock is acquired and released + around every public call using this mspace. +*/ + +/* Bin types, widths and sizes */ +#define NSMALLBINS (32U) +#define NTREEBINS (32U) +#define SMALLBIN_SHIFT (3U) +#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) +#define TREEBIN_SHIFT (8U) +#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) +#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) +#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD) + +struct malloc_state { + binmap_t smallmap; + binmap_t treemap; + size_t dvsize; + size_t topsize; + char* least_addr; + mchunkptr dv; + mchunkptr top; + size_t magic; + mchunkptr smallbins[(NSMALLBINS+1)*2]; + tbinptr treebins[NTREEBINS]; + size_t footprint; + size_t max_footprint; + flag_t mflags; + void *user_data; +#if USE_LOCKS + MLOCK_T mutex; /* locate lock among fields that rarely change */ +#endif /* USE_LOCKS */ + msegment seg; +}; + +typedef struct malloc_state* mstate; + +/* ------------- Global malloc_state and malloc_params ------------------- */ + +/* + malloc_params holds global properties, including those that can be + dynamically set using mallopt. There is a single instance, mparams, + initialized in init_mparams. +*/ + +struct malloc_params { + size_t magic; + size_t page_size; + size_t granularity; + flag_t default_mflags; +}; + +static struct malloc_params mparams; + +/* The global malloc_state used for all non-"mspace" calls */ +//static struct malloc_state _gm_; +//#define gm (&_gm_) +//#define is_global(M) ((M) == &_gm_) +#define is_initialized(M) ((M)->top != 0) + +/* -------------------------- system alloc setup ------------------------- */ + +/* Operations on mflags */ + +#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) +#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) +#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) + +#define set_lock(M,L)\ + ((M)->mflags = (L)?\ + ((M)->mflags | USE_LOCK_BIT) :\ + ((M)->mflags & ~USE_LOCK_BIT)) + +/* page-align a size */ +#define page_align(S)\ + (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE)) + +/* granularity-align a size */ +#define granularity_align(S)\ + (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE)) + +#define is_page_aligned(S)\ + (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) +#define is_granularity_aligned(S)\ + (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) + +/* True if segment S holds address A */ +#define segment_holds(S, A)\ + ((char*)(A) >= S->base && (char*)(A) < S->base + S->size) + +/* Return segment holding given address */ +static msegmentptr segment_holding(mstate m, char* addr) { + msegmentptr sp = &m->seg; + for (;;) { + if (addr >= sp->base && addr < sp->base + sp->size) + return sp; + if ((sp = sp->next) == 0) + return 0; + } +} + +/* Return true if segment contains a segment link */ +static int has_segment_link(mstate m, msegmentptr ss) { + msegmentptr sp = &m->seg; + for (;;) { + if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size) + return 1; + if ((sp = sp->next) == 0) + return 0; + } +} + + + +/* + TOP_FOOT_SIZE is padding at the end of a segment, including space + that may be needed to place segment records and fenceposts when new + noncontiguous segments are added. +*/ +#define TOP_FOOT_SIZE\ + (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) + + +/* ------------------------------- Hooks -------------------------------- */ + +/* + PREACTION should be defined to return 0 on success, and nonzero on + failure. If you are not using locking, you can redefine these to do + anything you like. +*/ + +#if USE_LOCKS + +/* Ensure locks are initialized */ +#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams()) + +#define PREACTION(M) ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) +#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); } +#else /* USE_LOCKS */ + +#ifndef PREACTION +#define PREACTION(M) (0) +#endif /* PREACTION */ + +#ifndef POSTACTION +#define POSTACTION(M) +#endif /* POSTACTION */ + +#endif /* USE_LOCKS */ + +/* + CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses. + USAGE_ERROR_ACTION is triggered on detected bad frees and + reallocs. The argument p is an address that might have triggered the + fault. It is ignored by the two predefined actions, but might be + useful in custom actions that try to help diagnose errors. +*/ + +#if PROCEED_ON_ERROR + +/* A count of the number of corruption errors causing resets */ +int malloc_corruption_error_count; + +/* default corruption action */ +static void reset_on_error(mstate m); + +#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m) +#define USAGE_ERROR_ACTION(m, p) + +#else /* PROCEED_ON_ERROR */ + +#ifndef CORRUPTION_ERROR_ACTION +#define CORRUPTION_ERROR_ACTION(m) ABORT(m->user_data) +#endif /* CORRUPTION_ERROR_ACTION */ + +#ifndef USAGE_ERROR_ACTION +#define USAGE_ERROR_ACTION(m,p) ABORT(m->user_data) +#endif /* USAGE_ERROR_ACTION */ + +#endif /* PROCEED_ON_ERROR */ + +/* -------------------------- Debugging setup ---------------------------- */ + +#if ! DEBUG + +#define check_free_chunk(M,P) +#define check_inuse_chunk(M,P) +#define check_malloced_chunk(M,P,N) +#define check_malloc_state(M) +#define check_top_chunk(M,P) + +#else /* DEBUG */ +#define check_free_chunk(M,P) do_check_free_chunk(M,P) +#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P) +#define check_top_chunk(M,P) do_check_top_chunk(M,P) +#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N) +#define check_malloc_state(M) do_check_malloc_state(M) + +static void do_check_any_chunk(mstate m, mchunkptr p); +static void do_check_top_chunk(mstate m, mchunkptr p); +static void do_check_inuse_chunk(mstate m, mchunkptr p); +static void do_check_free_chunk(mstate m, mchunkptr p); +static void do_check_malloced_chunk(mstate m, void* mem, size_t s); +static void do_check_tree(mstate m, tchunkptr t); +static void do_check_treebin(mstate m, bindex_t i); +static void do_check_smallbin(mstate m, bindex_t i); +static void do_check_malloc_state(mstate m); +static int bin_find(mstate m, mchunkptr x); +static size_t traverse_and_check(mstate m); +#endif /* DEBUG */ + +/* ---------------------------- Indexing Bins ---------------------------- */ + +#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) +#define small_index(s) ((s) >> SMALLBIN_SHIFT) +#define small_index2size(i) ((i) << SMALLBIN_SHIFT) +#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) + +/* addressing by index. See above about smallbin repositioning */ +#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) +#define treebin_at(M,i) (&((M)->treebins[i])) + +/* assign tree index for size S to variable I */ +#if defined(__GNUC__) && defined(i386) +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K;\ + __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm" (X));\ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} +#else /* GNUC */ +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int Y = (unsigned int)X;\ + unsigned int N = ((Y - 0x100) >> 16) & 8;\ + unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\ + N += K;\ + N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\ + K = 14 - N + ((Y <<= K) >> 15);\ + I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\ + }\ +} +#endif /* GNUC */ + +/* Bit representing maximum resolved size in a treebin at i */ +#define bit_for_tree_index(i) \ + (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2) + +/* Shift placing maximum resolved bit in a treebin at i as sign bit */ +#define leftshift_for_tree_index(i) \ + ((i == NTREEBINS-1)? 0 : \ + ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) + +/* The size of the smallest chunk held in bin with index i */ +#define minsize_for_tree_index(i) \ + ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ + (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) + +/* ------------------------ Operations on bin maps ----------------------- */ + +/* bit corresponding to given index */ +#define idx2bit(i) ((binmap_t)(1) << (i)) + +/* Mark/Clear bits with given index */ +#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i)) +#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i)) +#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i)) + +#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i)) +#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) +#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) + +/* index corresponding to given bit */ + +#if defined(__GNUC__) && defined(i386) +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\ + I = (bindex_t)J;\ +} + +#else /* GNUC */ +#if USE_BUILTIN_FFS +#define compute_bit2idx(X, I) I = ffs(X)-1 + +#else /* USE_BUILTIN_FFS */ +#define compute_bit2idx(X, I)\ +{\ + unsigned int Y = X - 1;\ + unsigned int K = Y >> (16-4) & 16;\ + unsigned int N = K; Y >>= K;\ + N += K = Y >> (8-3) & 8; Y >>= K;\ + N += K = Y >> (4-2) & 4; Y >>= K;\ + N += K = Y >> (2-1) & 2; Y >>= K;\ + N += K = Y >> (1-0) & 1; Y >>= K;\ + I = (bindex_t)(N + Y);\ +} +#endif /* USE_BUILTIN_FFS */ +#endif /* GNUC */ + +/* isolate the least set bit of a bitmap */ +#define least_bit(x) ((x) & -(x)) + +/* mask with all bits to left of least bit of x on */ +#define left_bits(x) ((x<<1) | -(x<<1)) + +/* mask with all bits to left of or equal to least bit of x on */ +#define same_or_left_bits(x) ((x) | -(x)) + + +/* ----------------------- Runtime Check Support ------------------------- */ + +/* + For security, the main invariant is that malloc/free/etc never + writes to a static address other than malloc_state, unless static + malloc_state itself has been corrupted, which cannot occur via + malloc (because of these checks). In essence this means that we + believe all pointers, sizes, maps etc held in malloc_state, but + check all of those linked or offsetted from other embedded data + structures. These checks are interspersed with main code in a way + that tends to minimize their run-time cost. + + When FOOTERS is defined, in addition to range checking, we also + verify footer fields of inuse chunks, which can be used guarantee + that the mstate controlling malloc/free is intact. This is a + streamlined version of the approach described by William Robertson + et al in "Run-time Detection of Heap-based Overflows" LISA'03 + http://www.usenix.org/events/lisa03/tech/robertson.html The footer + of an inuse chunk holds the xor of its mstate and a random seed, + that is checked upon calls to free() and realloc(). This is + (probablistically) unguessable from outside the program, but can be + computed by any code successfully malloc'ing any chunk, so does not + itself provide protection against code that has already broken + security through some other means. Unlike Robertson et al, we + always dynamically check addresses of all offset chunks (previous, + next, etc). This turns out to be cheaper than relying on hashes. +*/ + +#if !INSECURE +/* Check if address a is at least as high as any from MORECORE or MMAP */ +#define ok_address(M, a) ((char*)(a) >= (M)->least_addr) +/* Check if address of next chunk n is higher than base chunk p */ +#define ok_next(p, n) ((char*)(p) < (char*)(n)) +/* Check if p has its cinuse bit on */ +#define ok_cinuse(p) cinuse(p) +/* Check if p has its pinuse bit on */ +#define ok_pinuse(p) pinuse(p) + +#else /* !INSECURE */ +#define ok_address(M, a) (1) +#define ok_next(b, n) (1) +#define ok_cinuse(p) (1) +#define ok_pinuse(p) (1) +#endif /* !INSECURE */ + +#if (FOOTERS && !INSECURE) +/* Check if (alleged) mstate m has expected magic field */ +#define ok_magic(M) ((M)->magic == mparams.magic) +#else /* (FOOTERS && !INSECURE) */ +#define ok_magic(M) (1) +#endif /* (FOOTERS && !INSECURE) */ + + +/* In gcc, use __builtin_expect to minimize impact of checks */ +#if !INSECURE +#if defined(__GNUC__) && __GNUC__ >= 3 +#define RTCHECK(e) __builtin_expect(e, 1) +#else /* GNUC */ +#define RTCHECK(e) (e) +#endif /* GNUC */ +#else /* !INSECURE */ +#define RTCHECK(e) (1) +#endif /* !INSECURE */ + +/* macros to set up inuse chunks with or without footers */ + +#if !FOOTERS + +#define mark_inuse_foot(M,p,s) + +/* Set cinuse bit and pinuse bit of next chunk */ +#define set_inuse(M,p,s)\ + ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ + ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) + +/* Set cinuse and pinuse of this chunk and pinuse of next chunk */ +#define set_inuse_and_pinuse(M,p,s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) + +/* Set size, cinuse and pinuse bit of this chunk */ +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT)) + +#else /* FOOTERS */ + +/* Set foot of inuse chunk to be xor of mstate and seed */ +#define mark_inuse_foot(M,p,s)\ + (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic)) + +#define get_mstate_for(p)\ + ((mstate)(((mchunkptr)((char*)(p) +\ + (chunksize(p))))->prev_foot ^ mparams.magic)) + +#define set_inuse(M,p,s)\ + ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ + (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \ + mark_inuse_foot(M,p,s)) + +#define set_inuse_and_pinuse(M,p,s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\ + mark_inuse_foot(M,p,s)) + +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + mark_inuse_foot(M, p, s)) + +#endif /* !FOOTERS */ + +/* ---------------------------- setting mparams -------------------------- */ + +/* Initialize mparams */ +static int init_mparams(void) { + if (mparams.page_size == 0) { + size_t s; + + mparams.default_mflags = USE_LOCK_BIT; + +#if (FOOTERS && !INSECURE) + { +#if USE_DEV_RANDOM + int fd; + unsigned char buf[sizeof(size_t)]; + /* Try to use /dev/urandom, else fall back on using time */ + if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && + read(fd, buf, sizeof(buf)) == sizeof(buf)) { + s = *((size_t *) buf); + close(fd); + } + else +#endif /* USE_DEV_RANDOM */ + s = (size_t)(time(0) ^ (size_t)0x55555555U); + + s |= (size_t)8U; /* ensure nonzero */ + s &= ~(size_t)7U; /* improve chances of fault for bad values */ + + } +#else /* (FOOTERS && !INSECURE) */ + s = (size_t)0x58585858U; +#endif /* (FOOTERS && !INSECURE) */ + ACQUIRE_MAGIC_INIT_LOCK(); + if (mparams.magic == 0) { + mparams.magic = s; + /* Set up lock for main malloc area */ + //INITIAL_LOCK(&gm->mutex); + //gm->mflags = mparams.default_mflags; + } + RELEASE_MAGIC_INIT_LOCK(); + + + mparams.page_size = malloc_getpagesize; + mparams.granularity = ((DEFAULT_GRANULARITY != 0)? + DEFAULT_GRANULARITY : mparams.page_size); + + /* Sanity-check configuration: + size_t must be unsigned and as wide as pointer type. + ints must be at least 4 bytes. + alignment must be at least 8. + Alignment, min chunk size, and page size must all be powers of 2. + */ + if ((sizeof(size_t) != sizeof(char*)) || + (MAX_SIZE_T < MIN_CHUNK_SIZE) || + (sizeof(int) < 4) || + (MALLOC_ALIGNMENT < (size_t)8U) || + ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || + ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || + ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) || + ((mparams.page_size & (mparams.page_size-SIZE_T_ONE)) != 0)) + ABORT(NULL); + } + return 0; +} + +/* support for mallopt */ +static int change_mparam(int param_number, int value) { + size_t val = (size_t)value; + init_mparams(); + switch(param_number) { + case M_GRANULARITY: + if (val >= mparams.page_size && ((val & (val-1)) == 0)) { + mparams.granularity = val; + return 1; + } + else + return 0; + default: + return 0; + } +} + +#if DEBUG +/* ------------------------- Debugging Support --------------------------- */ + +/* Check properties of any chunk, whether free, inuse, mmapped etc */ +static void do_check_any_chunk(mstate m, mchunkptr p) { + assert(m->user_data, (is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(m->user_data, ok_address(m, p)); +} + +/* Check properties of top chunk */ +static void do_check_top_chunk(mstate m, mchunkptr p) { + msegmentptr sp = segment_holding(m, (char*)p); + size_t sz = chunksize(p); + assert(m->user_data, sp != 0); + assert(m->user_data, (is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(m->user_data, ok_address(m, p)); + assert(m->user_data, sz == m->topsize); + assert(m->user_data, sz > 0); + assert(m->user_data, sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE); + assert(m->user_data, pinuse(p)); + assert(m->user_data, !next_pinuse(p)); +} + +/* Check properties of inuse chunks */ +static void do_check_inuse_chunk(mstate m, mchunkptr p) { + do_check_any_chunk(m, p); + assert(m->user_data, cinuse(p)); + assert(m->user_data, next_pinuse(p)); + /* If not pinuse, previous chunk has OK offset */ + assert(m->user_data, pinuse(p) || next_chunk(prev_chunk(p)) == p); +} + +/* Check properties of free chunks */ +static void do_check_free_chunk(mstate m, mchunkptr p) { + size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT); + mchunkptr next = chunk_plus_offset(p, sz); + do_check_any_chunk(m, p); + assert(m->user_data, !cinuse(p)); + assert(m->user_data, !next_pinuse(p)); + if (p != m->dv && p != m->top) { + if (sz >= MIN_CHUNK_SIZE) { + assert(m->user_data, (sz & CHUNK_ALIGN_MASK) == 0); + assert(m->user_data, is_aligned(chunk2mem(p))); + assert(m->user_data, next->prev_foot == sz); + assert(m->user_data, pinuse(p)); + assert(m->user_data, next == m->top || cinuse(next)); + assert(m->user_data, p->fd->bk == p); + assert(m->user_data, p->bk->fd == p); + } + else /* markers are always of size SIZE_T_SIZE */ + assert(m->user_data, sz == SIZE_T_SIZE); + } +} + +/* Check properties of malloced chunks at the point they are malloced */ +static void do_check_malloced_chunk(mstate m, void* mem, size_t s) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT); + do_check_inuse_chunk(m, p); + assert(m->user_data, (sz & CHUNK_ALIGN_MASK) == 0); + assert(m->user_data, sz >= MIN_CHUNK_SIZE); + assert(m->user_data, sz >= s); + /* size is less than MIN_CHUNK_SIZE more than request */ + assert(m->user_data, sz < (s + MIN_CHUNK_SIZE)); + } +} + +/* Check a tree and its subtrees. */ +static void do_check_tree(mstate m, tchunkptr t) { + tchunkptr head = 0; + tchunkptr u = t; + bindex_t tindex = t->index; + size_t tsize = chunksize(t); + bindex_t idx; + compute_tree_index(tsize, idx); + assert(m->user_data, tindex == idx); + assert(m->user_data, tsize >= MIN_LARGE_SIZE); + assert(m->user_data, tsize >= minsize_for_tree_index(idx)); + assert(m->user_data, (idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1)))); + + do { /* traverse through chain of same-sized nodes */ + do_check_any_chunk(m, ((mchunkptr)u)); + assert(m->user_data, u->index == tindex); + assert(m->user_data, chunksize(u) == tsize); + assert(m->user_data, !cinuse(u)); + assert(m->user_data, !next_pinuse(u)); + assert(m->user_data, u->fd->bk == u); + assert(m->user_data, u->bk->fd == u); + if (u->parent == 0) { + assert(m->user_data, u->child[0] == 0); + assert(m->user_data, u->child[1] == 0); + } + else { + assert(m->user_data, head == 0); /* only one node on chain has parent */ + head = u; + assert(m->user_data, u->parent != u); + assert(m->user_data, u->parent->child[0] == u || + u->parent->child[1] == u || + *((tbinptr*)(u->parent)) == u); + if (u->child[0] != 0) { + assert(m->user_data, u->child[0]->parent == u); + assert(m->user_data, u->child[0] != u); + do_check_tree(m, u->child[0]); + } + if (u->child[1] != 0) { + assert(m->user_data, u->child[1]->parent == u); + assert(m->user_data, u->child[1] != u); + do_check_tree(m, u->child[1]); + } + if (u->child[0] != 0 && u->child[1] != 0) { + assert(m->user_data, chunksize(u->child[0]) < chunksize(u->child[1])); + } + } + u = u->fd; + } while (u != t); + assert(m->user_data, head != 0); +} + +/* Check all the chunks in a treebin. */ +static void do_check_treebin(mstate m, bindex_t i) { + tbinptr* tb = treebin_at(m, i); + tchunkptr t = *tb; + int empty = (m->treemap & (1U << i)) == 0; + if (t == 0) + assert(m->user_data, empty); + if (!empty) + do_check_tree(m, t); +} + +/* Check all the chunks in a smallbin. */ +static void do_check_smallbin(mstate m, bindex_t i) { + sbinptr b = smallbin_at(m, i); + mchunkptr p = b->bk; + unsigned int empty = (m->smallmap & (1U << i)) == 0; + if (p == b) + assert(m->user_data, empty); + if (!empty) { + for (; p != b; p = p->bk) { + size_t size = chunksize(p); + mchunkptr q; + /* each chunk claims to be free */ + do_check_free_chunk(m, p); + /* chunk belongs in bin */ + assert(m->user_data, small_index(size) == i); + assert(m->user_data, p->bk == b || chunksize(p->bk) == chunksize(p)); + /* chunk is followed by an inuse chunk */ + q = next_chunk(p); + if (q->head != FENCEPOST_HEAD) + do_check_inuse_chunk(m, q); + } + } +} + +/* Find x in a bin. Used in other check functions. */ +static int bin_find(mstate m, mchunkptr x) { + size_t size = chunksize(x); + if (is_small(size)) { + bindex_t sidx = small_index(size); + sbinptr b = smallbin_at(m, sidx); + if (smallmap_is_marked(m, sidx)) { + mchunkptr p = b; + do { + if (p == x) + return 1; + } while ((p = p->fd) != b); + } + } + else { + bindex_t tidx; + compute_tree_index(size, tidx); + if (treemap_is_marked(m, tidx)) { + tchunkptr t = *treebin_at(m, tidx); + size_t sizebits = size << leftshift_for_tree_index(tidx); + while (t != 0 && chunksize(t) != size) { + t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; + sizebits <<= 1; + } + if (t != 0) { + tchunkptr u = t; + do { + if (u == (tchunkptr)x) + return 1; + } while ((u = u->fd) != t); + } + } + } + return 0; +} + +/* Traverse each chunk and check it; return total */ +static size_t traverse_and_check(mstate m) { + size_t sum = 0; + if (is_initialized(m)) { + msegmentptr s = &m->seg; + sum += m->topsize + TOP_FOOT_SIZE; + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + mchunkptr lastq = 0; + assert(m->user_data, pinuse(q)); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + sum += chunksize(q); + if (cinuse(q)) { + assert(m->user_data, !bin_find(m, q)); + do_check_inuse_chunk(m, q); + } + else { + assert(m->user_data, q == m->dv || bin_find(m, q)); + assert(m->user_data, lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */ + do_check_free_chunk(m, q); + } + lastq = q; + q = next_chunk(q); + } + s = s->next; + } + } + return sum; +} + +/* Check all properties of malloc_state. */ +static void do_check_malloc_state(mstate m) { + bindex_t i; + size_t total; + /* check bins */ + for (i = 0; i < NSMALLBINS; ++i) + do_check_smallbin(m, i); + for (i = 0; i < NTREEBINS; ++i) + do_check_treebin(m, i); + + if (m->dvsize != 0) { /* check dv chunk */ + do_check_any_chunk(m, m->dv); + assert(m->user_data, m->dvsize == chunksize(m->dv)); + assert(m->user_data, m->dvsize >= MIN_CHUNK_SIZE); + assert(m->user_data, bin_find(m, m->dv) == 0); + } + + if (m->top != 0) { /* check top chunk */ + do_check_top_chunk(m, m->top); + assert(m->user_data, m->topsize == chunksize(m->top)); + assert(m->user_data, m->topsize > 0); + assert(m->user_data, bin_find(m, m->top) == 0); + } + + total = traverse_and_check(m); + assert(m->user_data, total <= m->footprint); + assert(m->user_data, m->footprint <= m->max_footprint); +} +#endif /* DEBUG */ + +/* ----------------------------- statistics ------------------------------ */ + +#if !NO_MALLINFO +static struct mallinfo internal_mallinfo(mstate m) { + struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + if (!PREACTION(m)) { + check_malloc_state(m); + if (is_initialized(m)) { + size_t nfree = SIZE_T_ONE; /* top always free */ + size_t mfree = m->topsize + TOP_FOOT_SIZE; + size_t sum = mfree; + msegmentptr s = &m->seg; + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + size_t sz = chunksize(q); + sum += sz; + if (!cinuse(q)) { + mfree += sz; + ++nfree; + } + q = next_chunk(q); + } + s = s->next; + } + + nm.arena = sum; + nm.ordblks = nfree; + nm.hblkhd = m->footprint - sum; + nm.usmblks = m->max_footprint; + nm.uordblks = m->footprint - mfree; + nm.fordblks = mfree; + nm.keepcost = m->topsize; + } + + POSTACTION(m); + } + return nm; +} +#endif /* !NO_MALLINFO */ + +static void internal_malloc_stats(mstate m) { + if (!PREACTION(m)) { + size_t maxfp = 0; + size_t fp = 0; + size_t used = 0; + check_malloc_state(m); + if (is_initialized(m)) { + msegmentptr s = &m->seg; + maxfp = m->max_footprint; + fp = m->footprint; + used = fp - (m->topsize + TOP_FOOT_SIZE); + + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + if (!cinuse(q)) + used -= chunksize(q); + q = next_chunk(q); + } + s = s->next; + } + } + + PRINT((m->user_data, "max system bytes = %10lu\n", (unsigned long)(maxfp))); + PRINT((m->user_data, "system bytes = %10lu\n", (unsigned long)(fp))); + PRINT((m->user_data, "in use bytes = %10lu\n", (unsigned long)(used))); + + POSTACTION(m); + } +} + +/* ----------------------- Operations on smallbins ----------------------- */ + +/* + Various forms of linking and unlinking are defined as macros. Even + the ones for trees, which are very long but have very short typical + paths. This is ugly but reduces reliance on inlining support of + compilers. +*/ + +/* Link a free chunk into a smallbin */ +#define insert_small_chunk(M, P, S) {\ + bindex_t I = small_index(S);\ + mchunkptr B = smallbin_at(M, I);\ + mchunkptr F = B;\ + assert((M)->user_data, S >= MIN_CHUNK_SIZE);\ + if (!smallmap_is_marked(M, I))\ + mark_smallmap(M, I);\ + else if (RTCHECK(ok_address(M, B->fd)))\ + F = B->fd;\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + B->fd = P;\ + F->bk = P;\ + P->fd = F;\ + P->bk = B;\ +} + +/* Unlink a chunk from a smallbin */ +#define unlink_small_chunk(M, P, S) {\ + mchunkptr F = P->fd;\ + mchunkptr B = P->bk;\ + bindex_t I = small_index(S);\ + assert((M)->user_data, P != B);\ + assert((M)->user_data, P != F);\ + assert((M)->user_data, chunksize(P) == small_index2size(I));\ + if (F == B)\ + clear_smallmap(M, I);\ + else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\ + (B == smallbin_at(M,I) || ok_address(M, B)))) {\ + F->bk = B;\ + B->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ +} + +/* Unlink the first chunk from a smallbin */ +#define unlink_first_small_chunk(M, B, P, I) {\ + mchunkptr F = P->fd;\ + assert((M)->user_data, P != B);\ + assert((M)->user_data, P != F);\ + assert((M)->user_data, chunksize(P) == small_index2size(I));\ + if (B == F)\ + clear_smallmap(M, I);\ + else if (RTCHECK(ok_address(M, F))) {\ + B->fd = F;\ + F->bk = B;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ +} + +/* Replace dv node, binning the old one */ +/* Used only when dvsize known to be small */ +#define replace_dv(M, P, S) {\ + size_t DVS = M->dvsize;\ + if (DVS != 0) {\ + mchunkptr DV = M->dv;\ + assert((M)->user_data, is_small(DVS));\ + insert_small_chunk(M, DV, DVS);\ + }\ + M->dvsize = S;\ + M->dv = P;\ +} + + +/* ------------------------- Operations on trees ------------------------- */ + +/* Insert chunk into tree */ +#define insert_large_chunk(M, X, S) {\ + tbinptr* H;\ + bindex_t I;\ + compute_tree_index(S, I);\ + H = treebin_at(M, I);\ + X->index = I;\ + X->child[0] = X->child[1] = 0;\ + if (!treemap_is_marked(M, I)) {\ + mark_treemap(M, I);\ + *H = X;\ + X->parent = (tchunkptr)H;\ + X->fd = X->bk = X;\ + }\ + else {\ + tchunkptr T = *H;\ + size_t K = S << leftshift_for_tree_index(I);\ + for (;;) {\ + if (chunksize(T) != S) {\ + tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\ + K <<= 1;\ + if (*C != 0)\ + T = *C;\ + else if (RTCHECK(ok_address(M, C))) {\ + *C = X;\ + X->parent = T;\ + X->fd = X->bk = X;\ + break;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + break;\ + }\ + }\ + else {\ + tchunkptr F = T->fd;\ + if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\ + T->fd = F->bk = X;\ + X->fd = F;\ + X->bk = T;\ + X->parent = 0;\ + break;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + break;\ + }\ + }\ + }\ + }\ +} + +/* + Unlink steps: + + 1. If x is a chained node, unlink it from its same-sized fd/bk links + and choose its bk node as its replacement. + 2. If x was the last node of its size, but not a leaf node, it must + be replaced with a leaf node (not merely one with an open left or + right), to make sure that lefts and rights of descendents + correspond properly to bit masks. We use the rightmost descendent + of x. We could use any other leaf, but this is easy to locate and + tends to counteract removal of leftmosts elsewhere, and so keeps + paths shorter than minimally guaranteed. This doesn't loop much + because on average a node in a tree is near the bottom. + 3. If x is the base of a chain (i.e., has parent links) relink + x's parent and children to x's replacement (or null if none). +*/ + +#define unlink_large_chunk(M, X) {\ + tchunkptr XP = X->parent;\ + tchunkptr R;\ + if (X->bk != X) {\ + tchunkptr F = X->fd;\ + R = X->bk;\ + if (RTCHECK(ok_address(M, F))) {\ + F->bk = R;\ + R->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else {\ + tchunkptr* RP;\ + if (((R = *(RP = &(X->child[1]))) != 0) ||\ + ((R = *(RP = &(X->child[0]))) != 0)) {\ + tchunkptr* CP;\ + while ((*(CP = &(R->child[1])) != 0) ||\ + (*(CP = &(R->child[0])) != 0)) {\ + R = *(RP = CP);\ + }\ + if (RTCHECK(ok_address(M, RP)))\ + *RP = 0;\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + }\ + if (XP != 0) {\ + tbinptr* H = treebin_at(M, X->index);\ + if (X == *H) {\ + if ((*H = R) == 0) \ + clear_treemap(M, X->index);\ + }\ + else if (RTCHECK(ok_address(M, XP))) {\ + if (XP->child[0] == X) \ + XP->child[0] = R;\ + else \ + XP->child[1] = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + if (R != 0) {\ + if (RTCHECK(ok_address(M, R))) {\ + tchunkptr C0, C1;\ + R->parent = XP;\ + if ((C0 = X->child[0]) != 0) {\ + if (RTCHECK(ok_address(M, C0))) {\ + R->child[0] = C0;\ + C0->parent = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + if ((C1 = X->child[1]) != 0) {\ + if (RTCHECK(ok_address(M, C1))) {\ + R->child[1] = C1;\ + C1->parent = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ +} + +/* Relays to large vs small bin operations */ + +#define insert_chunk(M, P, S)\ + if (is_small(S)) insert_small_chunk(M, P, S)\ + else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); } + +#define unlink_chunk(M, P, S)\ + if (is_small(S)) unlink_small_chunk(M, P, S)\ + else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); } + + +/* Relays to internal calls to malloc/free from realloc, memalign etc */ + +#define internal_malloc(m, b) mspace_malloc(m, b) +#define internal_free(m, mem) mspace_free(m,mem); + + +/* -------------------------- mspace management -------------------------- */ + +/* Initialize top chunk and its size */ +static void init_top(mstate m, mchunkptr p, size_t psize) { + /* Ensure alignment */ + size_t offset = align_offset(chunk2mem(p)); + p = (mchunkptr)((char*)p + offset); + psize -= offset; + + m->top = p; + m->topsize = psize; + p->head = psize | PINUSE_BIT; + /* set size of fake trailing chunk holding overhead space only once */ + chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE; +} + +/* Initialize bins for a new mstate that is otherwise zeroed out */ +static void init_bins(mstate m) { + /* Establish circular links for smallbins */ + bindex_t i; + for (i = 0; i < NSMALLBINS; ++i) { + sbinptr bin = smallbin_at(m,i); + bin->fd = bin->bk = bin; + } +} + +#if PROCEED_ON_ERROR + +/* default corruption action */ +static void reset_on_error(mstate m) { + int i; + ++malloc_corruption_error_count; + /* Reinitialize fields to forget about all memory */ + m->smallbins = m->treebins = 0; + m->dvsize = m->topsize = 0; + m->seg.base = 0; + m->seg.size = 0; + m->seg.next = 0; + m->top = m->dv = 0; + for (i = 0; i < NTREEBINS; ++i) + *treebin_at(m, i) = 0; + init_bins(m); +} +#endif /* PROCEED_ON_ERROR */ + +/* Allocate chunk and prepend remainder with chunk in successor base. */ +static void* prepend_alloc(mstate m, char* newbase, char* oldbase, + size_t nb) { + mchunkptr p = align_as_chunk(newbase); + mchunkptr oldfirst = align_as_chunk(oldbase); + size_t psize = (char*)oldfirst - (char*)p; + mchunkptr q = chunk_plus_offset(p, nb); + size_t qsize = psize - nb; + set_size_and_pinuse_of_inuse_chunk(m, p, nb); + + assert(m->user_data, (char*)oldfirst > (char*)q); + assert(m->user_data, pinuse(oldfirst)); + assert(m->user_data, qsize >= MIN_CHUNK_SIZE); + + /* consolidate remainder with first chunk of old base */ + if (oldfirst == m->top) { + size_t tsize = m->topsize += qsize; + m->top = q; + q->head = tsize | PINUSE_BIT; + check_top_chunk(m, q); + } + else if (oldfirst == m->dv) { + size_t dsize = m->dvsize += qsize; + m->dv = q; + set_size_and_pinuse_of_free_chunk(q, dsize); + } + else { + if (!cinuse(oldfirst)) { + size_t nsize = chunksize(oldfirst); + unlink_chunk(m, oldfirst, nsize); + oldfirst = chunk_plus_offset(oldfirst, nsize); + qsize += nsize; + } + set_free_with_pinuse(q, qsize, oldfirst); + insert_chunk(m, q, qsize); + check_free_chunk(m, q); + } + + check_malloced_chunk(m, chunk2mem(p), nb); + return chunk2mem(p); +} + +/* -------------------------- System allocation -------------------------- */ + +/* Get memory from system using MORECORE or MMAP */ +static void* sys_alloc(mstate m, size_t nb) { + MALLOC_FAILURE_ACTION; + return 0; +} + +/* ---------------------------- malloc support --------------------------- */ + +/* allocate a large request from the best fitting chunk in a treebin */ +static void* tmalloc_large(mstate m, size_t nb) { + tchunkptr v = 0; + size_t rsize = -nb; /* Unsigned negation */ + tchunkptr t; + bindex_t idx; + compute_tree_index(nb, idx); + + if ((t = *treebin_at(m, idx)) != 0) { + /* Traverse tree for this bin looking for node with size == nb */ + size_t sizebits = nb << leftshift_for_tree_index(idx); + tchunkptr rst = 0; /* The deepest untaken right subtree */ + for (;;) { + tchunkptr rt; + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + v = t; + if ((rsize = trem) == 0) + break; + } + rt = t->child[1]; + t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; + if (rt != 0 && rt != t) + rst = rt; + if (t == 0) { + t = rst; /* set t to least subtree holding sizes > nb */ + break; + } + sizebits <<= 1; + } + } + + if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ + binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; + if (leftbits != 0) { + bindex_t i; + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + t = *treebin_at(m, i); + } + } + + while (t != 0) { /* find smallest of tree or subtree */ + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + rsize = trem; + v = t; + } + t = leftmost_child(t); + } + + /* If dv is a better fit, return 0 so malloc will use it */ + if (v != 0 && rsize < (size_t)(m->dvsize - nb)) { + if (RTCHECK(ok_address(m, v))) { /* split */ + mchunkptr r = chunk_plus_offset(v, nb); + assert(m->user_data, chunksize(v) == rsize + nb); + if (RTCHECK(ok_next(v, r))) { + unlink_large_chunk(m, v); + if (rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(m, v, (rsize + nb)); + else { + set_size_and_pinuse_of_inuse_chunk(m, v, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + insert_chunk(m, r, rsize); + } + return chunk2mem(v); + } + } + CORRUPTION_ERROR_ACTION(m); + } + return 0; +} + +/* allocate a small request from the best fitting chunk in a treebin */ +static void* tmalloc_small(mstate m, size_t nb) { + tchunkptr t, v; + size_t rsize; + bindex_t i; + binmap_t leastbit = least_bit(m->treemap); + compute_bit2idx(leastbit, i); + + v = t = *treebin_at(m, i); + rsize = chunksize(t) - nb; + + while ((t = leftmost_child(t)) != 0) { + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + rsize = trem; + v = t; + } + } + + if (RTCHECK(ok_address(m, v))) { + mchunkptr r = chunk_plus_offset(v, nb); + assert(m->user_data, chunksize(v) == rsize + nb); + if (RTCHECK(ok_next(v, r))) { + unlink_large_chunk(m, v); + if (rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(m, v, (rsize + nb)); + else { + set_size_and_pinuse_of_inuse_chunk(m, v, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(m, r, rsize); + } + return chunk2mem(v); + } + } + + CORRUPTION_ERROR_ACTION(m); + return 0; +} + +/* --------------------------- realloc support --------------------------- */ + +static void* internal_realloc(mstate m, void* oldmem, size_t bytes) { + if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + return 0; + } + if (!PREACTION(m)) { + mchunkptr oldp = mem2chunk(oldmem); + size_t oldsize = chunksize(oldp); + mchunkptr next = chunk_plus_offset(oldp, oldsize); + mchunkptr newp = 0; + void* extra = 0; + + /* Try to either shrink or extend into top. Else malloc-copy-free */ + + if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) && + ok_next(oldp, next) && ok_pinuse(next))) { + size_t nb = request2size(bytes); + if (oldsize >= nb) { /* already big enough */ + size_t rsize = oldsize - nb; + newp = oldp; + if (rsize >= MIN_CHUNK_SIZE) { + mchunkptr remainder = chunk_plus_offset(newp, nb); + set_inuse(m, newp, nb); + set_inuse(m, remainder, rsize); + extra = chunk2mem(remainder); + } + } + else if (next == m->top && oldsize + m->topsize > nb) { + /* Expand into top */ + size_t newsize = oldsize + m->topsize; + size_t newtopsize = newsize - nb; + mchunkptr newtop = chunk_plus_offset(oldp, nb); + set_inuse(m, oldp, nb); + newtop->head = newtopsize |PINUSE_BIT; + m->top = newtop; + m->topsize = newtopsize; + newp = oldp; + } + } + else { + USAGE_ERROR_ACTION(m, oldmem); + POSTACTION(m); + return 0; + } + + POSTACTION(m); + + if (newp != 0) { + if (extra != 0) { + internal_free(m, extra); + } + check_inuse_chunk(m, newp); + return chunk2mem(newp); + } + else { + void* newmem = internal_malloc(m, bytes); + if (newmem != 0) { + size_t oc = oldsize - overhead_for(oldp); + MEMCPY(newmem, oldmem, (oc < bytes)? oc : bytes); + internal_free(m, oldmem); + } + return newmem; + } + } + return 0; +} + +/* --------------------------- memalign support -------------------------- */ + +static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { + if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */ + return internal_malloc(m, bytes); + if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ + alignment = MIN_CHUNK_SIZE; + if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ + size_t a = MALLOC_ALIGNMENT << 1; + while (a < alignment) a <<= 1; + alignment = a; + } + + if (bytes >= MAX_REQUEST - alignment) { + if (m != 0) { /* Test isn't needed but avoids compiler warning */ + MALLOC_FAILURE_ACTION; + } + } + else { + size_t nb = request2size(bytes); + size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; + char* mem = (char*)internal_malloc(m, req); + if (mem != 0) { + void* leader = 0; + void* trailer = 0; + mchunkptr p = mem2chunk(mem); + + if (PREACTION(m)) return 0; + if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */ + /* + Find an aligned spot inside chunk. Since we need to give + back leading space in a chunk of at least MIN_CHUNK_SIZE, if + the first calculation places us at a spot with less than + MIN_CHUNK_SIZE leader, we can move to the next aligned spot. + We've allocated enough total room so that this is always + possible. + */ + char* br = (char*)mem2chunk((size_t)(((size_t)(mem + + alignment - + SIZE_T_ONE)) & + -alignment)); + char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? + br : br+alignment; + mchunkptr newp = (mchunkptr)pos; + size_t leadsize = pos - (char*)(p); + size_t newsize = chunksize(p) - leadsize; + + /* Otherwise, give back leader, use the rest */ + set_inuse(m, newp, newsize); + set_inuse(m, p, leadsize); + leader = chunk2mem(p); + + p = newp; + } + + assert(m->user_data, chunksize(p) >= nb); + assert(m->user_data, (((size_t)(chunk2mem(p))) % alignment) == 0); + check_inuse_chunk(m, p); + POSTACTION(m); + if (leader != 0) { + internal_free(m, leader); + } + if (trailer != 0) { + internal_free(m, trailer); + } + return chunk2mem(p); + } + } + return 0; +} + +/* ----------------------------- user mspaces ---------------------------- */ + +static mstate init_user_mstate(char* tbase, size_t tsize, void *user_data) { + size_t msize = pad_request(sizeof(struct malloc_state)); + mchunkptr mn; + mchunkptr msp = align_as_chunk(tbase); + mstate m = (mstate)(chunk2mem(msp)); + MEMCLEAR(m, msize); + INITIAL_LOCK(&m->mutex); + msp->head = (msize|PINUSE_BIT|CINUSE_BIT); + m->seg.base = m->least_addr = tbase; + m->seg.size = m->footprint = m->max_footprint = tsize; + m->magic = mparams.magic; + m->mflags = mparams.default_mflags; + m->user_data = user_data; + init_bins(m); + mn = next_chunk(mem2chunk(m)); + init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE); + check_top_chunk(m, m->top); + return m; +} + +mspace create_mspace_with_base(void* base, size_t capacity, int locked, void *user_data) { + mstate m = 0; + size_t msize = pad_request(sizeof(struct malloc_state)); + init_mparams(); /* Ensure pagesize etc initialized */ + + if (capacity > msize + TOP_FOOT_SIZE && + capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { + m = init_user_mstate((char*)base, capacity, user_data); + set_lock(m, locked); + } + return (mspace)m; +} + +/* + mspace versions of routines are near-clones of the global + versions. This is not so nice but better than the alternatives. +*/ + + +void* mspace_malloc(mspace msp, size_t bytes) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (!PREACTION(ms)) { + void* mem; + size_t nb; + if (bytes <= MAX_SMALL_REQUEST) { + bindex_t idx; + binmap_t smallbits; + nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); + idx = small_index(nb); + smallbits = ms->smallmap >> idx; + + if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ + mchunkptr b, p; + idx += ~smallbits & 1; /* Uses next bin if idx empty */ + b = smallbin_at(ms, idx); + p = b->fd; + assert(ms->user_data, chunksize(p) == small_index2size(idx)); + unlink_first_small_chunk(ms, b, p, idx); + set_inuse_and_pinuse(ms, p, small_index2size(idx)); + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (nb > ms->dvsize) { + if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ + mchunkptr b, p, r; + size_t rsize; + bindex_t i; + binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + b = smallbin_at(ms, i); + p = b->fd; + assert(ms->user_data, chunksize(p) == small_index2size(i)); + unlink_first_small_chunk(ms, b, p, i); + rsize = small_index2size(i) - nb; + /* Fit here cannot be remainderless if 4byte sizes */ + if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(ms, p, small_index2size(i)); + else { + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + r = chunk_plus_offset(p, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(ms, r, rsize); + } + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) { + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + } + } + else if (bytes >= MAX_REQUEST) + nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ + else { + nb = pad_request(bytes); + if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) { + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + } + + if (nb <= ms->dvsize) { + size_t rsize = ms->dvsize - nb; + mchunkptr p = ms->dv; + if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ + mchunkptr r = ms->dv = chunk_plus_offset(p, nb); + ms->dvsize = rsize; + set_size_and_pinuse_of_free_chunk(r, rsize); + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + } + else { /* exhaust dv */ + size_t dvs = ms->dvsize; + ms->dvsize = 0; + ms->dv = 0; + set_inuse_and_pinuse(ms, p, dvs); + } + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (nb < ms->topsize) { /* Split top */ + size_t rsize = ms->topsize -= nb; + mchunkptr p = ms->top; + mchunkptr r = ms->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + mem = chunk2mem(p); + check_top_chunk(ms, ms->top); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + mem = sys_alloc(ms, nb); + + postaction: + POSTACTION(ms); + return mem; + } + + return 0; +} + +void mspace_free(mspace msp, void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); +#if FOOTERS + mstate fm = get_mstate_for(p); +#else /* FOOTERS */ + mstate fm = (mstate)msp; +#endif /* FOOTERS */ + if (!ok_magic(fm)) { + USAGE_ERROR_ACTION(fm, p); + return; + } + if (!PREACTION(fm)) { + check_inuse_chunk(fm, p); + if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) { + size_t psize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + size_t prevsize = p->prev_foot; + + mchunkptr prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ + if (p != fm->dv) { + unlink_chunk(fm, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + fm->dvsize = psize; + set_free_with_pinuse(p, psize, next); + goto postaction; + } + } + else + goto erroraction; + } + + if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == fm->top) { + size_t tsize = fm->topsize += psize; + fm->top = p; + p->head = tsize | PINUSE_BIT; + if (p == fm->dv) { + fm->dv = 0; + fm->dvsize = 0; + } + goto postaction; + } + else if (next == fm->dv) { + size_t dsize = fm->dvsize += psize; + fm->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + goto postaction; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(fm, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == fm->dv) { + fm->dvsize = psize; + goto postaction; + } + } + } + else + set_free_with_pinuse(p, psize, next); + insert_chunk(fm, p, psize); + check_free_chunk(fm, p); + goto postaction; + } + } + erroraction: + USAGE_ERROR_ACTION(fm, p); + postaction: + POSTACTION(fm); + } + } +} + +void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) { + void* mem; + size_t req = 0; + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (n_elements != 0) { + req = n_elements * elem_size; + if (((n_elements | elem_size) & ~(size_t)0xffff) && + (req / n_elements != elem_size)) + req = MAX_SIZE_T; /* force downstream failure on overflow */ + } + mem = internal_malloc(ms, req); + if (mem != 0 && calloc_must_clear(mem2chunk(mem))) + MEMCLEAR(mem, req); + return mem; +} + +void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) { + if (oldmem == 0) + return mspace_malloc(msp, bytes); +#ifdef REALLOC_ZERO_BYTES_FREES + if (bytes == 0) { + mspace_free(msp, oldmem); + return 0; + } +#endif /* REALLOC_ZERO_BYTES_FREES */ + else { +#if FOOTERS + mchunkptr p = mem2chunk(oldmem); + mstate ms = get_mstate_for(p); +#else /* FOOTERS */ + mstate ms = (mstate)msp; +#endif /* FOOTERS */ + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + return internal_realloc(ms, oldmem, bytes); + } +} + +void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + return internal_memalign(ms, alignment, bytes); +} + +void mspace_malloc_stats(mspace msp) { + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + internal_malloc_stats(ms); + } + else { + USAGE_ERROR_ACTION(ms,ms); + } +} + +size_t mspace_footprint(mspace msp) { + size_t result; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + result = ms->footprint; + } else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + + +size_t mspace_max_footprint(mspace msp) { + size_t result; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + result = ms->max_footprint; + } else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + + +#if !NO_MALLINFO +struct mallinfo mspace_mallinfo(mspace msp) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + } + return internal_mallinfo(ms); +} +#endif /* NO_MALLINFO */ + +int mspace_mallopt(int param_number, int value) { + return change_mparam(param_number, value); +} + diff --git a/qxldod/mspace.h b/qxldod/mspace.h new file mode 100755 index 0000000..16e20bf --- /dev/null +++ b/qxldod/mspace.h @@ -0,0 +1,150 @@ +#ifndef _H_MSPACE +#define _H_MSPACE + +#define NO_MALLINFO 1 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +//typedef unsigned long size_t; +typedef void (*mspace_abort_t)(void *user_data); +typedef void (*mspace_print_t)(void *user_data, char *format, ...); + +void mspace_set_abort_func(mspace_abort_t f); +void mspace_set_print_func(mspace_print_t f); + +/* + mspace is an opaque type representing an independent + region of space that supports mspace_malloc, etc. +*/ +typedef void* mspace; + +/* + create_mspace creates and returns a new independent space with the + given initial capacity, or, if 0, the default granularity size. It + returns null if there is no system memory available to create the + space. If argument locked is non-zero, the space uses a separate + lock to control access. The capacity of the space will grow + dynamically as needed to service mspace_malloc requests. You can + control the sizes of incremental increases of this space by + compiling with a different DEFAULT_GRANULARITY or dynamically + setting with mallopt(M_GRANULARITY, value). +*/ +//mspace create_mspace(size_t capacity, int locked); + +/* + destroy_mspace destroys the given space, and attempts to return all + of its memory back to the system, returning the total number of + bytes freed. After destruction, the results of access to all memory + used by the space become undefined. +*/ +//size_t destroy_mspace(mspace msp); + +/* + create_mspace_with_base uses the memory supplied as the initial base + of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this + space is used for bookkeeping, so the capacity must be at least this + large. (Otherwise 0 is returned.) When this initial space is + exhausted, additional memory will be obtained from the system. + Destroying this space will deallocate all additionally allocated + space (if possible) but not the initial base. +*/ +mspace create_mspace_with_base(void* base, size_t capacity, int locked, void *user_data); + +/* + mspace_malloc behaves as malloc, but operates within + the given space. +*/ +void* mspace_malloc(mspace msp, size_t bytes); + +/* + mspace_free behaves as free, but operates within + the given space. + + If compiled with FOOTERS==1, mspace_free is not actually needed. + free may be called instead of mspace_free because freed chunks from + any space are handled by their originating spaces. +*/ +void mspace_free(mspace msp, void* mem); + +/* + mspace_realloc behaves as realloc, but operates within + the given space. + + If compiled with FOOTERS==1, mspace_realloc is not actually + needed. realloc may be called instead of mspace_realloc because + realloced chunks from any space are handled by their originating + spaces. +*/ +void* mspace_realloc(mspace msp, void* mem, size_t newsize); + +/* + mspace_calloc behaves as calloc, but operates within + the given space. +*/ +void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); + +/* + mspace_memalign behaves as memalign, but operates within + the given space. +*/ +void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); + +/* + mspace_independent_calloc behaves as independent_calloc, but + operates within the given space. +*/ +//void** mspace_independent_calloc(mspace msp, size_t n_elements, +// size_t elem_size, void* chunks[]); + +/* + mspace_independent_comalloc behaves as independent_comalloc, but + operates within the given space. +*/ +//void** mspace_independent_comalloc(mspace msp, size_t n_elements, +// size_t sizes[], void* chunks[]); + +/* + mspace_footprint() returns the number of bytes obtained from the + system for this space. +*/ +size_t mspace_footprint(mspace msp); + +/* + mspace_max_footprint() returns the peak number of bytes obtained from the + system for this space. +*/ +size_t mspace_max_footprint(mspace msp); + + +#if !NO_MALLINFO +/* + mspace_mallinfo behaves as mallinfo, but reports properties of + the given space. +*/ +struct mallinfo mspace_mallinfo(mspace msp); +#endif /* NO_MALLINFO */ + +/* + mspace_malloc_stats behaves as malloc_stats, but reports + properties of the given space. +*/ +void mspace_malloc_stats(mspace msp); + +/* + mspace_trim behaves as malloc_trim, but + operates within the given space. +*/ +//int mspace_trim(mspace msp, size_t pad); + +/* + An alias for mallopt. +*/ +int mspace_mallopt(int, int); + +#ifdef __cplusplus +}; /* end of extern "C" */ +#endif /* __cplusplus */ + +#endif diff --git a/qxldod/qxldod.vcxproj b/qxldod/qxldod.vcxproj index 12e6938..76b510f 100755 --- a/qxldod/qxldod.vcxproj +++ b/qxldod/qxldod.vcxproj @@ -156,6 +156,7 @@ + From e9449a561027d4fb4f4e2f14e8f32a7a694b0fae Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 12 May 2014 23:10:30 +1000 Subject: [PATCH 13/46] add isr, dpc, and bliting support sunctions --- qxldod/QxlDod.cpp | 358 +++++++++++++++++++++++++++++++--- qxldod/QxlDod.h | 71 ++++--- qxldod/qxldod.vcxproj.filters | 3 + 3 files changed, 380 insertions(+), 52 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 88a245e..28f4131 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -1640,22 +1640,21 @@ NTSTATUS QxlDod::UpdateActiveVidPnPresentPath(_In_ CONST DXGKARG_UPDATEACTIVEVID VOID QxlDod::DpcRoutine(VOID) { DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + m_pHWDevice->DpcRoutine(); m_DxgkInterface.DxgkCbNotifyDpc((HANDLE)m_DxgkInterface.DeviceHandle); DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); } BOOLEAN QxlDod::InterruptRoutine(_In_ ULONG MessageNumber) { - UNREFERENCED_PARAMETER(MessageNumber); - - DbgPrint(TRACE_LEVEL_INFORMATION, ("---> 0 %s\n", __FUNCTION__)); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); - return TRUE; + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--> 0 %s\n", __FUNCTION__)); + return m_pHWDevice->InterruptRoutine(&m_DxgkInterface, MessageNumber); } VOID QxlDod::ResetDevice(VOID) { DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); + m_pHWDevice->ResetDevice(); } // Must be Non-Paged, as it sets up the display for a bugcheck @@ -2724,21 +2723,30 @@ VgaDevice::ExecutePresentDisplayOnly( // Copy all the scroll rects from source image to video frame buffer. for (UINT i = 0; i < ctx->NumMoves; i++) { + POINT* pSourcePoint = &ctx->Moves[i].SourcePoint; + RECT* pDestRect = &ctx->Moves[i].DestRect; + +// DbgPrint(TRACE_LEVEL_FATAL, ("--- %d SourcePoint.x = %ld, SourcePoint.y = %ld, DestRect.bottom = %ld, DestRect.left = %ld, DestRect.right = %ld, DestRect.top = %ld\n", +// i , pSourcePoint->x, pSourcePoint->y, pDestRect->bottom, pDestRect->left, pDestRect->right, pDestRect->top)); + BltBits(&DstBltInfo, &SrcBltInfo, 1, // NumRects - &ctx->Moves[i].DestRect); + pDestRect); } // Copy all the dirty rects from source image to video frame buffer. for (UINT i = 0; i < ctx->NumDirtyRects; i++) { + RECT* pDirtyRect = &ctx->DirtyRect[i]; +// DbgPrint(TRACE_LEVEL_FATAL, ("--- %d pDirtyRect->bottom = %ld, pDirtyRect->left = %ld, pDirtyRect->right = %ld, pDirtyRect->top = %ld\n", +// i, pDirtyRect->bottom, pDirtyRect->left, pDirtyRect->right, pDirtyRect->top)); BltBits(&DstBltInfo, &SrcBltInfo, 1, // NumRects - &ctx->DirtyRect[i]); - } + pDirtyRect); + } // Unmap unmap and unlock the pages. if (ctx->Mdl) @@ -2801,6 +2809,21 @@ VOID VgaDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) pCurrentBddMod->ZeroedOutEnd.QuadPart = NewPhysAddrEnd.QuadPart; } +BOOLEAN VgaDevice::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber) +{ + UNREFERENCED_PARAMETER(pDxgkInterface); + UNREFERENCED_PARAMETER(MessageNumber); + return FALSE; +} + +VOID VgaDevice::DpcRoutine(VOID) +{ +} + +VOID VgaDevice::ResetDevice(VOID) +{ +} + QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod) { m_pQxlDod = pQxlDod; @@ -2808,6 +2831,8 @@ QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod) m_ModeCount = 0; m_ModeNumbers = NULL; m_CurrentMode = 0; + m_FreeOutputs = 0; + m_Pending = 0; } QxlDevice::~QxlDevice(void) @@ -3113,7 +3138,10 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* CreateEvents(); CreateRings(); + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_RESET), 0); + m_RamHdr->int_mask = QXL_INTERRUPT_MASK; CreateMemSlots(); + InitDeviceMemoryResources(); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; @@ -3148,6 +3176,7 @@ void QxlDevice::UnmapMemory(void) BOOL QxlDevice::InitMemSlots(void) { + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); m_NumMemSlots = m_RomHdr->slots_end; m_SlotGenBits = m_RomHdr->slot_gen_bits; m_SlotIdBits = m_RomHdr->slot_id_bits; @@ -3160,18 +3189,22 @@ BOOL QxlDevice::InitMemSlots(void) RtlZeroMemory(m_MemSlots, size); return TRUE; } + DbgPrint(TRACE_LEVEL_ERROR, ("---> %s Failed to init mem slot\n", __FUNCTION__)); return FALSE; } void QxlDevice::DestroyMemSlots(void) { + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); delete [] reinterpret_cast(m_MemSlots); m_MemSlots = NULL; + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } void QxlDevice::CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo) { QXLSurfaceCreate *primary_surface_create; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); primary_surface_create = &m_RamHdr->create_surface; primary_surface_create->format = pModeInfo->BitsPerPlane; primary_surface_create->width = pModeInfo->VisScreenWidth; @@ -3183,17 +3216,20 @@ void QxlDevice::CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo) primary_surface_create->flags = QXL_SURF_FLAG_KEEP_DATA; //0; primary_surface_create->type = QXL_SURF_TYPE_PRIMARY; WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_CREATE_PRIMARY), 0); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } void QxlDevice::DestroyPrimarySurface(void) { + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_DESTROY_PRIMARY), 0); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } _inline QXLPHYSICAL QxlDevice::PA(PVOID virt, UINT8 slot_id) { + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s\n", __FUNCTION__)); MemSlot *pSlot = &m_MemSlots[slot_id];; - return pSlot->high_bits | ((UINT64)virt - pSlot->start_virt_addr); } @@ -3202,6 +3238,7 @@ _inline UINT64 QxlDevice::VA(QXLPHYSICAL paddr, UINT8 slot_id) UINT64 virt; MemSlot *pSlot = &m_MemSlots[slot_id];; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); virt = paddr & m_VaSlotMask; virt += pSlot->start_virt_addr;; @@ -3210,13 +3247,16 @@ _inline UINT64 QxlDevice::VA(QXLPHYSICAL paddr, UINT8 slot_id) void QxlDevice::SetupHWSlot(UINT8 Idx, MemSlot *pSlot) { + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); m_RamHdr->mem_slot.mem_start = pSlot->start_phys_addr; m_RamHdr->mem_slot.mem_end = pSlot->end_phys_addr; WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_MEMSLOT_ADD), Idx); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); } BOOL QxlDevice::CreateEvents() { + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); KeInitializeEvent(&m_DisplayEvent, SynchronizationEvent, FALSE); @@ -3228,14 +3268,17 @@ BOOL QxlDevice::CreateEvents() FALSE); KeInitializeSpinLock(&m_MemLock); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return TRUE; } BOOL QxlDevice::CreateRings() { + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); m_CommandRing = &(m_RamHdr->cmd_ring); m_CursorRing = &(m_RamHdr->cursor_ring); m_ReleaseRing = &(m_RamHdr->release_ring); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return TRUE; } @@ -3245,6 +3288,7 @@ UINT8 QxlDevice::SetupMemSlot(UINT8 Idx, QXLPHYSICAL start, QXLPHYSICAL end) MemSlot *pSlot; UINT8 slot_index; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); slot_index = m_RomHdr->slots_start + Idx; pSlot = &m_MemSlots[slot_index]; pSlot->start_phys_addr = start; @@ -3257,33 +3301,42 @@ UINT8 QxlDevice::SetupMemSlot(UINT8 Idx, QXLPHYSICAL start, QXLPHYSICAL end) high_bits |= pSlot->generation; high_bits <<= (64 - (m_SlotGenBits + m_SlotIdBits)); pSlot->high_bits = high_bits; + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return slot_index; } BOOL QxlDevice::CreateMemSlots(void) { + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); m_MainMemSlot= SetupMemSlot(0, (QXLPHYSICAL)m_VRamStart, (QXLPHYSICAL)(m_VRamStart + m_RomHdr->ram_header_offset)); m_SurfaceMemSlot = SetupMemSlot(1, (QXLPHYSICAL)m_RamStart, (QXLPHYSICAL)(m_RamStart + m_RamSize)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return TRUE; } void QxlDevice::InitDeviceMemoryResources(void) { - InitMspace(MSPACE_TYPE_DEVRAM, (m_RamStart + m_RomHdr->surface0_area_size), (size_t)((m_VRamPA.QuadPart + m_RomHdr->surface0_area_size) * PAGE_SIZE)); + 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_VRamPA.QuadPart + m_RomHdr->surface0_area_size)*/m_RomHdr->num_pages * PAGE_SIZE)); InitMspace(MSPACE_TYPE_VRAM, m_VRamStart, m_VRamSize); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } 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)); m_MSInfo[mspace_type]._mspace = create_mspace_with_base(start, capacity, 0, this); m_MSInfo[mspace_type].mspace_start = start; m_MSInfo[mspace_type].mspace_end = start + capacity; + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s _mspace = %p\n", __FUNCTION__, m_MSInfo[mspace_type]._mspace)); } void QxlDevice::ResetDevice(void) { + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); m_RamHdr->int_mask = ~0; WRITE_PORT_UCHAR(m_IoBase + QXL_IO_MEMSLOT_ADD, 0); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -3439,26 +3492,26 @@ QxlDevice::ExecutePresentDisplayOnly( POINT* pSourcePoint = &ctx->Moves[i].SourcePoint; RECT* pDestRect = &ctx->Moves[i].DestRect; - DbgPrint(TRACE_LEVEL_FATAL, ("--- %d SourcePoint.x = %d, SourcePoint.y = %d, DestRect.bottom = %d, DestRect.left = %d, DestRect.right = %d, DestRect.top = %d\n", + DbgPrint(TRACE_LEVEL_FATAL, ("--- %d SourcePoint.x = %ld, SourcePoint.y = %ld, DestRect.bottom = %ld, DestRect.left = %ld, DestRect.right = %ld, DestRect.top = %ld\n", i , pSourcePoint->x, pSourcePoint->y, pDestRect->bottom, pDestRect->left, pDestRect->right, pDestRect->top)); BltBits(&DstBltInfo, &SrcBltInfo, 1, // NumRects - &ctx->Moves[i].DestRect); + pDestRect); } // Copy all the dirty rects from source image to video frame buffer. for (UINT i = 0; i < ctx->NumDirtyRects; i++) { RECT* pDirtyRect = &ctx->DirtyRect[i]; - DbgPrint(TRACE_LEVEL_FATAL, ("--- %d pDirtyRect->bottom = %d, pDirtyRect->left = %d, pDirtyRect->right = %d, pDirtyRect->top = %d\n", + DbgPrint(TRACE_LEVEL_FATAL, ("--- %d pDirtyRect->bottom = %ld, pDirtyRect->left = %ld, pDirtyRect->right = %ld, pDirtyRect->top = %ld\n", i, pDirtyRect->bottom, pDirtyRect->left, pDirtyRect->right, pDirtyRect->top)); BltBits(&DstBltInfo, &SrcBltInfo, 1, // NumRects - &ctx->DirtyRect[i]); + pDirtyRect); } // Unmap unmap and unlock the pages. @@ -3502,7 +3555,7 @@ void QxlDevice::WaitForReleaseRing(void) { int wait; - DbgPrint(TRACE_LEVEL_VERBOSE, ("%s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("--->%s\n", __FUNCTION__)); for (;;) { LARGE_INTEGER timeout; @@ -3527,7 +3580,7 @@ void QxlDevice::WaitForReleaseRing(void) WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_NOTIFY_OOM), 0); } } - DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: done\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: <---\n", __FUNCTION__)); } @@ -3537,7 +3590,9 @@ void QxlDevice::FlushReleaseRing() int notify; int num_to_release = 50; - output = free_outputs; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + output = m_FreeOutputs; while (1) { while (output != 0) { @@ -3556,7 +3611,8 @@ void QxlDevice::FlushReleaseRing() SPICE_RING_POP(m_ReleaseRing, notify); } - free_outputs = output; + m_FreeOutputs = output; + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } UINT64 QxlDevice::ReleaseOutput(UINT64 output_id) @@ -3567,15 +3623,14 @@ UINT64 QxlDevice::ReleaseOutput(UINT64 output_id) UINT64 next; ASSERT(output_id); - DbgPrint(TRACE_LEVEL_VERBOSE, ("%s 0x%x\n", __FUNCTION__, output)); -// DebugShowOutput(pdev, output); + DbgPrint(TRACE_LEVEL_VERBOSE, ("--->%s 0x%x\n", __FUNCTION__, output)); for (now = output->resources, end = now + output->num_res; now < end; now++) { RELEASE_RES(*now); } next = *(UINT64*)output->data; FreeMem(MSPACE_TYPE_DEVRAM, output); - DbgPrint(TRACE_LEVEL_VERBOSE, ("%s done\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---%s\n", __FUNCTION__)); return next; } @@ -3585,7 +3640,7 @@ void *QxlDevice::AllocMem(UINT32 mspace_type, size_t size, BOOL force) KIRQL old_irql; ASSERT(m_MSInfo[mspace_type]._mspace); - DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: %p(%d) size %u\n", __FUNCTION__, + DbgPrint(TRACE_LEVEL_VERBOSE, ("--->%s: %p(%d) size %u\n", __FUNCTION__, m_MSInfo[mspace_type]._mspace, mspace_footprint(m_MSInfo[mspace_type]._mspace), size)); @@ -3605,7 +3660,7 @@ void *QxlDevice::AllocMem(UINT32 mspace_type, size_t size, BOOL force) break; } - if (free_outputs != 0 || + if (m_FreeOutputs != 0 || !SPICE_RING_IS_EMPTY(m_ReleaseRing)) { /* We have more things to free, try that */ continue; @@ -3622,7 +3677,7 @@ void *QxlDevice::AllocMem(UINT32 mspace_type, size_t size, BOOL force) ASSERT((!ptr && !force) || (ptr >= m_MSInfo[mspace_type].mspace_start && ptr < m_MSInfo[mspace_type].mspace_end)); - DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: done 0x%x\n", __FUNCTION__, ptr)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---%s: ptr 0x%x\n", __FUNCTION__, ptr)); return ptr; } @@ -3630,6 +3685,8 @@ void QxlDevice::FreeMem(UINT32 mspace_type, void *ptr) { KIRQL old_irql; ASSERT(m_MSInfo[mspace_type]._mspace); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + #ifdef DBG if (!((UINT8 *)ptr >= m_MSInfo[mspace_type].mspace_start && (UINT8 *)ptr < m_MSInfo[mspace_type].mspace_end)) { @@ -3641,6 +3698,7 @@ void QxlDevice::FreeMem(UINT32 mspace_type, void *ptr) old_irql = AcquireSpinLock(&m_MemLock); mspace_free(m_MSInfo[mspace_type]._mspace, ptr); ReleaseSpinLock(&m_MemLock, old_irql); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -3652,7 +3710,7 @@ QXLDrawable *QxlDevice::GetDrawable() output->num_res = 0; RESOURCE_TYPE(output, RESOURCE_TYPE_DRAWABLE); ((QXLDrawable *)output->data)->release_info.id = (UINT64)output; - DbgPrint(TRACE_LEVEL_VERBOSE, ("%s 0x%x\n", __FUNCTION__, output)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s 0x%x\n", __FUNCTION__, output)); return(QXLDrawable *)output->data; } @@ -3705,9 +3763,11 @@ void QxlDevice::FreeClipRectsEx(Resource *res) QxlDevice* pqxl = (QxlDevice*)res->ptr; pqxl->FreeClipRects(res); } + void QxlDevice::FreeClipRects(Resource *res) { QXLPHYSICAL chunk_phys; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); chunk_phys = ((QXLClipRects *)res->res)->chunk.next_chunk; while (chunk_phys) { @@ -3716,6 +3776,32 @@ void QxlDevice::FreeClipRects(Resource *res) FreeMem(MSPACE_TYPE_DEVRAM, chunk); } FreeMem(MSPACE_TYPE_DEVRAM, res); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); +} + +void QxlDevice::FreeBitmapImageEx(Resource *res) +{ + QxlDevice* pqxl = (QxlDevice*)res->ptr; + pqxl->FreeBitmapImage(res); +} + +void QxlDevice::FreeBitmapImage(Resource *res) +{ + InternalImage *internal; + QXLPHYSICAL chunk_phys; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + internal = (InternalImage *)res->res; + + chunk_phys = ((QXLDataChunk *)(&internal->image.bitmap + 1))->next_chunk; + while (chunk_phys) { + QXLDataChunk *chunk = (QXLDataChunk *)VA(chunk_phys, m_MainMemSlot); + chunk_phys = chunk->next_chunk; + FreeMem(MSPACE_TYPE_DEVRAM, chunk); + } + + FreeMem(MSPACE_TYPE_DEVRAM, res); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } QXLDrawable *QxlDevice::Drawable(UINT8 type, CONST RECT *area, CONST RECT *clip, UINT32 surface_id) @@ -3723,6 +3809,7 @@ QXLDrawable *QxlDevice::Drawable(UINT8 type, CONST RECT *area, CONST RECT *clip, QXLDrawable *drawable; ASSERT(area); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); drawable = GetDrawable(); drawable->surface_id = surface_id; @@ -3740,9 +3827,21 @@ QXLDrawable *QxlDevice::Drawable(UINT8 type, CONST RECT *area, CONST RECT *clip, ReleaseOutput(drawable->release_info.id); drawable = NULL; } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return drawable; } +void QxlDevice::PushDrawable(QXLDrawable *drawable) { + QXLCommand *cmd; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + WaitForCmdRing(); + cmd = SPICE_RING_PROD_ITEM(m_CommandRing); + cmd->type = QXL_CMD_DRAW; + cmd->data = PA(drawable, m_MainMemSlot); + PushCmd(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); +} VOID QxlDevice::BltBits ( BLT_INFO* pDst, @@ -3751,17 +3850,150 @@ VOID QxlDevice::BltBits ( _In_reads_(NumRects) CONST RECT *pRects) { QXLDrawable *drawable; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); if (!(drawable = Drawable(QXL_DRAW_COPY, pRects, NULL, 0))) { DbgPrint(TRACE_LEVEL_ERROR, ("Cannot get Drawable.\n")); } - for (UINT iRect = 0; iRect < NumRects; iRect++) - { - CONST RECT* pRect = &pRects[iRect]; + drawable->effect = QXL_EFFECT_OPAQUE; + drawable->u.copy.scale_mode = SPICE_IMAGE_SCALE_MODE_NEAREST; + drawable->u.copy.mask.bitmap = 0; + drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT; + + CONST RECT* pRect = &pRects[0]; + drawable->u.copy.src_area.top = pRect->top; + drawable->u.copy.src_area.bottom = pRect->bottom; + drawable->u.copy.src_area.left = pRect->left; + drawable->u.copy.src_area.right = pRect->right; + + CopyRect(&drawable->u.copy.src_area, pRect); + + drawable->surfaces_dest[0] = 0; + drawable->surfaces_rects[0].left = pRect->left; + drawable->surfaces_rects[0].right = pRect->right; + drawable->surfaces_rects[0].top = pRect->top; + drawable->surfaces_rects[0].bottom = pRect->bottom; + + drawable->self_bitmap = TRUE; + drawable->self_bitmap_area.bottom = pRect->bottom; + drawable->self_bitmap_area.left = pRect->left; + drawable->self_bitmap_area.top = pRect->top; + drawable->self_bitmap_area.right = pRect->right; + + Resource *image_res; + InternalImage *internal; + size_t alloc_size; + QXLDataChunk *chunk; + UINT32 line_size; + LONG width; + LONG height; + + height = pRect->bottom - pRect->top; + width = pRect->right - pRect->left; + line_size = width * 4; + + alloc_size = BITMAP_ALLOC_BASE + BITS_BUF_MAX - BITS_BUF_MAX % line_size; + alloc_size = MIN(BITMAP_ALLOC_BASE + height * line_size, alloc_size); + image_res = (Resource*)AllocMem(MSPACE_TYPE_DEVRAM, alloc_size, TRUE); + + image_res->refs = 1; + image_res->free = FreeBitmapImageEx; + + internal = (InternalImage *)image_res->res; +//FIXME +// SetImageId(internal, FALSE, width, height, SPICE_BITMAP_FMT_32BIT, 0); + internal->image.descriptor.flags = 0; + internal->image.descriptor.type = SPICE_IMAGE_TYPE_BITMAP; + chunk = (QXLDataChunk *)(&internal->image.bitmap + 1); + chunk->data_size = 0; + chunk->prev_chunk = 0; + chunk->next_chunk = 0; + internal->image.bitmap.data = PA(chunk, m_MainMemSlot); + internal->image.bitmap.flags = 0; + internal->image.descriptor.width = internal->image.bitmap.x = width; + internal->image.descriptor.height = internal->image.bitmap.y = height; + internal->image.bitmap.format = SPICE_BITMAP_FMT_RGBA; + internal->image.bitmap.stride = line_size; + + UINT8* src = (UINT8*)pSrc->pBits+ + (pRect->top) * pSrc->Pitch + + (pRect->left * 4); + UINT8* src_end = src - pSrc->Pitch; + src += pSrc->Pitch * (height - 1); + UINT8* dest = chunk->data; + UINT8* dest_end = (UINT8 *)image_res + alloc_size; + alloc_size = height * line_size; + + for (; src != src_end; src -= pSrc->Pitch, alloc_size -= line_size) { + PutBytesAlign(&chunk, &dest, &dest_end, src, + line_size, alloc_size, line_size); } + +//GetPallette + internal->image.bitmap.palette = 0; + + drawable->u.copy.src_bitmap = PA(&internal->image, m_MainMemSlot); + DrawableAddRes(drawable, image_res); + RELEASE_RES(image_res); + + DbgPrint(TRACE_LEVEL_FATAL, ("%s drawable= %p Dest right(%d) left(%d) top(%d) bottom(%d) src_bitmap= %p.\n", __FUNCTION__, + drawable, drawable->surfaces_rects[0].right, drawable->surfaces_rects[0].left, + drawable->surfaces_rects[0].top, drawable->surfaces_rects[0].bottom, + drawable->u.copy.src_bitmap)); + + +// for (UINT iRect = 0; iRect < NumRects; iRect++) +// { +// CONST RECT* pRect = &pRects[iRect]; +// } + + PushDrawable(drawable); + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } +VOID QxlDevice::PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, + UINT8 **end_ptr, UINT8 *src, int size, + size_t alloc_size, uint32_t alignment) +{ + QXLDataChunk *chunk = *chunk_ptr; + UINT8 *now = *now_ptr; + UINT8 *end = *end_ptr; + int offset; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + while (size) { + int cp_size = (int)MIN(end - now, size); + if (!cp_size) { + size_t aligned_size; + aligned_size = (int)MIN(alloc_size + alignment - 1, BITS_BUF_MAX); + aligned_size -= aligned_size % alignment; + + void *ptr = AllocMem(MSPACE_TYPE_DEVRAM, size + sizeof(QXLDataChunk), TRUE); + chunk->next_chunk = PA(ptr, m_MainMemSlot); + ((QXLDataChunk *)ptr)->prev_chunk = PA(chunk, m_MainMemSlot); + chunk = (QXLDataChunk *)ptr; + chunk->data_size = 0; + chunk->next_chunk = 0; + now = chunk->data; + end = now + size; + + cp_size = (int)MIN(end - now, size); + } + RtlCopyMemory(now, src, cp_size); + src += cp_size; + now += cp_size; + chunk->data_size += cp_size; + size -= cp_size; + } + *chunk_ptr = chunk; + *now_ptr = now; + *end_ptr = end; + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); +} + + VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) { PAGED_CODE(); @@ -3782,6 +4014,76 @@ NTSTATUS QxlDevice::HWClose(void) return STATUS_SUCCESS; } +VOID QxlDevice::WaitForCmdRing() +{ + int wait; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + for (;;) { + SPICE_RING_PROD_WAIT(m_CommandRing, wait); + + if (!wait) { + break; + } + WAIT_FOR_EVENT(m_DisplayEvent, NULL); + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); +} + +VOID QxlDevice::PushCmd() +{ + int notify; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + SPICE_RING_PUSH(m_CommandRing, notify); + if (notify) { + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_NOTIFY_CMD), 0); + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s notify = %d\n", __FUNCTION__, notify)); +} + +BOOLEAN QxlDevice::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber) +{ + UNREFERENCED_PARAMETER(MessageNumber); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + if (!(m_RamHdr->int_pending & m_RamHdr->int_mask)) { + return FALSE; + } + m_RamHdr->int_mask = 0; + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_IRQ), 0); + m_Pending |= m_RamHdr->int_pending; + m_RamHdr->int_pending = 0; + + DXGKARGCB_NOTIFY_INTERRUPT_DATA notifyInt;// = {0}; + notifyInt.InterruptType = DXGK_INTERRUPT_DISPLAYONLY_PRESENT_PROGRESS; + notifyInt.DisplayOnlyPresentProgress.VidPnSourceId = 0;//FIXME pPath->VidPnSourceId; + + pDxgkInterface->DxgkCbNotifyInterrupt(pDxgkInterface->DeviceHandle,¬ifyInt); + if (!pDxgkInterface->DxgkCbQueueDpc(pDxgkInterface->DeviceHandle)) { + m_RamHdr->int_mask = QXL_INTERRUPT_MASK; + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_IRQ), 0); + } + return TRUE; +} + +VOID QxlDevice::DpcRoutine(VOID) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + m_RamHdr->int_mask = QXL_INTERRUPT_MASK; + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_IRQ), 0); + if (m_Pending & QXL_INTERRUPT_DISPLAY) { + KeSetEvent (&m_DisplayEvent, IO_NO_INCREMENT, FALSE); + } + if (m_Pending & QXL_INTERRUPT_CURSOR) { + KeSetEvent (&m_CursorEvent, IO_NO_INCREMENT, FALSE); + } + if (m_Pending & QXL_INTERRUPT_IO_CMD) { + KeSetEvent (&m_IoCmdEvent, IO_NO_INCREMENT, FALSE); + } + + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); +} + + UINT BPPFromPixelFormat(D3DDDIFORMAT Format) { switch (Format) diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 05a84f7..574363b 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -219,6 +219,10 @@ public: virtual NTSTATUS SetPowerState(POWER_ACTION ActionType) = 0; virtual NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; virtual NTSTATUS HWClose(void) = 0; + virtual BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber) = 0; + virtual VOID DpcRoutine(VOID) = 0; + virtual VOID ResetDevice(void) = 0; + ULONG GetModeCount(void) {return m_ModeCount;} PVIDEO_MODE_INFORMATION GetModeInfo(UINT idx) {return &m_ModeInfo[idx];} USHORT GetModeNumber(USHORT idx) {return m_ModeNumbers[idx];} @@ -238,27 +242,6 @@ public: virtual VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) = 0; protected: -/* - BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect); - VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch); - - VOID CopyBitsGeneric( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); - - VOID CopyBits32_32( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); - VOID BltBits ( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); -*/ virtual NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; protected: QxlDod* m_pQxlDod; @@ -292,6 +275,9 @@ public: _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, _In_ const CURRENT_BDD_MODE* pModeCur); VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod); + BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber); + VOID DpcRoutine(VOID); + VOID ResetDevice(VOID); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); private: @@ -386,6 +372,32 @@ typedef struct QXLOutput { UINT8 data[0]; } QXLOutput; +typedef struct Ring RingItem; +typedef struct Ring { + RingItem *prev; + RingItem *next; +} Ring; + +typedef struct CacheImage { + struct CacheImage *next; + RingItem lru_link; + UINT32 key; + UINT32 hits; + UINT8 format; + UINT32 width; + UINT32 height; + struct InternalImage *image; +} CacheImage; + +typedef struct InternalImage { + CacheImage *cache; + QXLImage image; +} InternalImage; + +#define BITMAP_ALLOC_BASE (sizeof(Resource) + sizeof(InternalImage) + sizeof(QXLDataChunk)) +#define BITS_BUF_MAX (64 * 1024) +#define MIN(x, y) (((x) <= (y)) ? (x) : (y)) + class QxlDevice : public HwDeviceIntrface { @@ -410,6 +422,9 @@ public: _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, _In_ const CURRENT_BDD_MODE* pModeCur); VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod); + BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber); + VOID DpcRoutine(VOID); + VOID ResetDevice(VOID); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); VOID BltBits ( @@ -422,6 +437,7 @@ protected: CONST RECT *area, CONST RECT *clip, UINT32 surface_id); + void PushDrawable(QXLDrawable *drawable); QXLDrawable *GetDrawable(); void *AllocMem(UINT32 mspace_type, size_t size, BOOL force); private: @@ -432,7 +448,6 @@ private: void DestroyMemSlots(void); void CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo); void DestroyPrimarySurface(void); - void ResetDevice(void); void SetupHWSlot(UINT8 Idx, MemSlot *pSlot); UINT8 SetupMemSlot(UINT8 Idx, QXLPHYSICAL start, QXLPHYSICAL end); BOOL CreateEvents(void); @@ -450,6 +465,14 @@ private: void DrawableAddRes(QXLDrawable *drawable, Resource *res); void FreeClipRects(Resource *res); void static FreeClipRectsEx(Resource *res); + void FreeBitmapImage(Resource *res); + void static FreeBitmapImageEx(Resource *res); + void WaitForCmdRing(void); + void PushCmd(void); + void PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, + UINT8 **end_ptr, UINT8 *src, int size, + size_t alloc_size, uint32_t alignment); + private: PUCHAR m_IoBase; BOOLEAN m_IoMapped; @@ -489,8 +512,8 @@ private: KSPIN_LOCK m_MemLock; MspaceInfo m_MSInfo[NUM_MSPACES]; - UINT64 free_outputs; - + UINT64 m_FreeOutputs; + UINT32 m_Pending; }; class QxlDod : diff --git a/qxldod/qxldod.vcxproj.filters b/qxldod/qxldod.vcxproj.filters index db5df31..4b444ed 100755 --- a/qxldod/qxldod.vcxproj.filters +++ b/qxldod/qxldod.vcxproj.filters @@ -47,6 +47,9 @@ Source Files + + Source Files + From 2dffd51c87757489ae0911247648d0a464eeb201 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Thu, 5 Jun 2014 22:27:10 +1000 Subject: [PATCH 14/46] fix blt path --- qxldod/QxlDod.cpp | 145 ++++++++++++++++++++++++++++------------------ qxldod/QxlDod.h | 49 +++++++++------- qxldod/driver.cpp | 4 +- 3 files changed, 119 insertions(+), 79 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 28f4131..70b61b8 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -3211,10 +3211,12 @@ void QxlDevice::CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo) primary_surface_create->height = pModeInfo->VisScreenHeight; primary_surface_create->stride = pModeInfo->ScreenStride; - primary_surface_create->mem = PA( m_RamStart, 0); + primary_surface_create->mem = PA( m_RamStart, m_MainMemSlot); primary_surface_create->flags = QXL_SURF_FLAG_KEEP_DATA; //0; primary_surface_create->type = QXL_SURF_TYPE_PRIMARY; + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s format = %d, width = %d, height = %d, stride = %d\n", __FUNCTION__, pModeInfo->BitsPerPlane, pModeInfo->VisScreenWidth, pModeInfo->VisScreenHeight, + pModeInfo->ScreenStride)); WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_CREATE_PRIMARY), 0); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -3282,7 +3284,7 @@ BOOL QxlDevice::CreateRings() return TRUE; } -UINT8 QxlDevice::SetupMemSlot(UINT8 Idx, QXLPHYSICAL start, QXLPHYSICAL end) +UINT8 QxlDevice::SetupMemSlot(UINT8 Idx, UINT64 pastart, UINT64 paend, UINT64 vastart, UINT64 vaend) { UINT64 high_bits; MemSlot *pSlot; @@ -3291,10 +3293,12 @@ UINT8 QxlDevice::SetupMemSlot(UINT8 Idx, QXLPHYSICAL start, QXLPHYSICAL end) DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); slot_index = m_RomHdr->slots_start + Idx; pSlot = &m_MemSlots[slot_index]; - pSlot->start_phys_addr = start; - pSlot->end_phys_addr = end; + pSlot->start_phys_addr = pastart; + pSlot->end_phys_addr = paend; + pSlot->start_virt_addr = vastart; + pSlot->end_virt_addr = vaend; - SetupHWSlot(Idx, pSlot); + SetupHWSlot(Idx + 1, pSlot); pSlot->generation = m_RomHdr->slot_generation; high_bits = slot_index << m_SlotGenBits; @@ -3307,9 +3311,19 @@ UINT8 QxlDevice::SetupMemSlot(UINT8 Idx, QXLPHYSICAL start, QXLPHYSICAL end) BOOL QxlDevice::CreateMemSlots(void) { - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - m_MainMemSlot= SetupMemSlot(0, (QXLPHYSICAL)m_VRamStart, (QXLPHYSICAL)(m_VRamStart + m_RomHdr->ram_header_offset)); - m_SurfaceMemSlot = SetupMemSlot(1, (QXLPHYSICAL)m_RamStart, (QXLPHYSICAL)(m_RamStart + m_RamSize)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s 3\n", __FUNCTION__)); + UINT64 len = m_RomHdr->surface0_area_size + m_RomHdr->num_pages * PAGE_SIZE; + m_MainMemSlot = SetupMemSlot(0, + (UINT64)m_RamPA.QuadPart, + (UINT64)(m_RamPA.QuadPart + len), + (UINT64)m_RamStart, + (UINT64)(m_RamStart + len)); + len = m_VRamSize; + m_SurfaceMemSlot = SetupMemSlot(1, + (UINT64)m_VRamPA.QuadPart, + (UINT64)(m_VRamPA.QuadPart + len), + (UINT64)m_VRamStart, + (UINT64)(m_VRamStart + len)); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return TRUE; } @@ -3317,11 +3331,12 @@ BOOL QxlDevice::CreateMemSlots(void) void QxlDevice::InitDeviceMemoryResources(void) { 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_VRamPA.QuadPart + m_RomHdr->surface0_area_size)*/m_RomHdr->num_pages * PAGE_SIZE)); + 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::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)); @@ -3492,7 +3507,7 @@ QxlDevice::ExecutePresentDisplayOnly( POINT* pSourcePoint = &ctx->Moves[i].SourcePoint; RECT* pDestRect = &ctx->Moves[i].DestRect; - DbgPrint(TRACE_LEVEL_FATAL, ("--- %d SourcePoint.x = %ld, SourcePoint.y = %ld, DestRect.bottom = %ld, DestRect.left = %ld, DestRect.right = %ld, DestRect.top = %ld\n", + DbgPrint(TRACE_LEVEL_INFORMATION, ("--- %d SourcePoint.x = %ld, SourcePoint.y = %ld, DestRect.bottom = %ld, DestRect.left = %ld, DestRect.right = %ld, DestRect.top = %ld\n", i , pSourcePoint->x, pSourcePoint->y, pDestRect->bottom, pDestRect->left, pDestRect->right, pDestRect->top)); BltBits(&DstBltInfo, @@ -3505,7 +3520,7 @@ QxlDevice::ExecutePresentDisplayOnly( for (UINT i = 0; i < ctx->NumDirtyRects; i++) { RECT* pDirtyRect = &ctx->DirtyRect[i]; - DbgPrint(TRACE_LEVEL_FATAL, ("--- %d pDirtyRect->bottom = %ld, pDirtyRect->left = %ld, pDirtyRect->right = %ld, pDirtyRect->top = %ld\n", + DbgPrint(TRACE_LEVEL_INFORMATION, ("--- %d pDirtyRect->bottom = %ld, pDirtyRect->left = %ld, pDirtyRect->right = %ld, pDirtyRect->top = %ld\n", i, pDirtyRect->bottom, pDirtyRect->left, pDirtyRect->right, pDirtyRect->top)); BltBits(&DstBltInfo, @@ -3720,7 +3735,7 @@ BOOL QxlDevice::SetClip(const RECT *clip, QXLDrawable *drawable) if (clip == NULL) { drawable->clip.type = SPICE_CLIP_TYPE_NONE; - DbgPrint(TRACE_LEVEL_ERROR, ("%s QXL_CLIP_TYPE_NONE\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("%s QXL_CLIP_TYPE_NONE\n", __FUNCTION__)); return TRUE; } @@ -3728,7 +3743,6 @@ BOOL QxlDevice::SetClip(const RECT *clip, QXLDrawable *drawable) rects_res = (Resource *)AllocMem(MSPACE_TYPE_DEVRAM, sizeof(Resource) + sizeof(QXLClipRects) + sizeof(QXLRect), TRUE); rects_res->refs = 1; -//FIXME rects_res->free = FreeClipRectsEx; rects_res->ptr = this; rects = (QXLClipRects *)rects_res->res; @@ -3760,6 +3774,7 @@ void QxlDevice::DrawableAddRes(QXLDrawable *drawable, Resource *res) void QxlDevice::FreeClipRectsEx(Resource *res) { + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s\n", __FUNCTION__)); QxlDevice* pqxl = (QxlDevice*)res->ptr; pqxl->FreeClipRects(res); } @@ -3781,6 +3796,7 @@ void QxlDevice::FreeClipRects(Resource *res) void QxlDevice::FreeBitmapImageEx(Resource *res) { + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s\n", __FUNCTION__)); QxlDevice* pqxl = (QxlDevice*)res->ptr; pqxl->FreeBitmapImage(res); } @@ -3814,7 +3830,7 @@ QXLDrawable *QxlDevice::Drawable(UINT8 type, CONST RECT *area, CONST RECT *clip, drawable = GetDrawable(); drawable->surface_id = surface_id; drawable->type = type; - drawable->effect = QXL_EFFECT_BLEND; + drawable->effect = QXL_EFFECT_OPAQUE; drawable->self_bitmap = 0; drawable->mm_time = m_RomHdr->mm_clock; drawable->surfaces_dest[0] = -1; @@ -3843,6 +3859,26 @@ void QxlDevice::PushDrawable(QXLDrawable *drawable) { DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } +VOID QxlDevice::SetImageId(InternalImage *internal, + BOOL cache_me, + LONG width, + LONG height, + UINT8 format, UINT32 key) +{ + UINT32 image_info = IMAGE_HASH_INIT_VAL(width, height, format); + + if (cache_me) { + QXL_SET_IMAGE_ID(&internal->image, ((UINT32)QXL_IMAGE_GROUP_DRIVER << 30) | + image_info, key); + internal->image.descriptor.flags = QXL_IMAGE_CACHE; + } else { + QXL_SET_IMAGE_ID(&internal->image, ((UINT32)QXL_IMAGE_GROUP_DRIVER_DONT_CACHE << 30) | + image_info, key); + internal->image.descriptor.flags = 0; + } +} + + VOID QxlDevice::BltBits ( BLT_INFO* pDst, CONST BLT_INFO* pSrc, @@ -3850,37 +3886,6 @@ VOID QxlDevice::BltBits ( _In_reads_(NumRects) CONST RECT *pRects) { QXLDrawable *drawable; - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - - if (!(drawable = Drawable(QXL_DRAW_COPY, pRects, NULL, 0))) { - DbgPrint(TRACE_LEVEL_ERROR, ("Cannot get Drawable.\n")); - } - - drawable->effect = QXL_EFFECT_OPAQUE; - drawable->u.copy.scale_mode = SPICE_IMAGE_SCALE_MODE_NEAREST; - drawable->u.copy.mask.bitmap = 0; - drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT; - - CONST RECT* pRect = &pRects[0]; - drawable->u.copy.src_area.top = pRect->top; - drawable->u.copy.src_area.bottom = pRect->bottom; - drawable->u.copy.src_area.left = pRect->left; - drawable->u.copy.src_area.right = pRect->right; - - CopyRect(&drawable->u.copy.src_area, pRect); - - drawable->surfaces_dest[0] = 0; - drawable->surfaces_rects[0].left = pRect->left; - drawable->surfaces_rects[0].right = pRect->right; - drawable->surfaces_rects[0].top = pRect->top; - drawable->surfaces_rects[0].bottom = pRect->bottom; - - drawable->self_bitmap = TRUE; - drawable->self_bitmap_area.bottom = pRect->bottom; - drawable->self_bitmap_area.left = pRect->left; - drawable->self_bitmap_area.top = pRect->top; - drawable->self_bitmap_area.right = pRect->right; - Resource *image_res; InternalImage *internal; size_t alloc_size; @@ -3889,20 +3894,44 @@ VOID QxlDevice::BltBits ( LONG width; LONG height; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + if (!(drawable = Drawable(QXL_DRAW_COPY, pRects, NULL, 0))) { + DbgPrint(TRACE_LEVEL_ERROR, ("Cannot get Drawable.\n")); + } + + CONST RECT* pRect = &pRects[0]; + + drawable->u.copy.scale_mode = SPICE_IMAGE_SCALE_MODE_NEAREST; + drawable->u.copy.mask.bitmap = 0; + drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT; + + drawable->surfaces_dest[0] = 0; + CopyRect(&drawable->surfaces_rects[0], pRect); + + drawable->self_bitmap = TRUE; + CopyRect(&drawable->self_bitmap_area, pRect); + height = pRect->bottom - pRect->top; width = pRect->right - pRect->left; line_size = width * 4; + drawable->u.copy.src_area.bottom = height; + drawable->u.copy.src_area.left = 0; + drawable->u.copy.src_area.top = 0; + drawable->u.copy.src_area.right = width; + + alloc_size = BITMAP_ALLOC_BASE + BITS_BUF_MAX - BITS_BUF_MAX % line_size; alloc_size = MIN(BITMAP_ALLOC_BASE + height * line_size, alloc_size); image_res = (Resource*)AllocMem(MSPACE_TYPE_DEVRAM, alloc_size, TRUE); image_res->refs = 1; image_res->free = FreeBitmapImageEx; + image_res->ptr = this; internal = (InternalImage *)image_res->res; -//FIXME -// SetImageId(internal, FALSE, width, height, SPICE_BITMAP_FMT_32BIT, 0); + SetImageId(internal, FALSE, width, height, SPICE_BITMAP_FMT_32BIT, 0); internal->image.descriptor.flags = 0; internal->image.descriptor.type = SPICE_IMAGE_TYPE_BITMAP; chunk = (QXLDataChunk *)(&internal->image.bitmap + 1); @@ -3930,24 +3959,19 @@ VOID QxlDevice::BltBits ( line_size, alloc_size, line_size); } -//GetPallette internal->image.bitmap.palette = 0; drawable->u.copy.src_bitmap = PA(&internal->image, m_MainMemSlot); + + CopyRect(&drawable->surfaces_rects[1], pRect); DrawableAddRes(drawable, image_res); RELEASE_RES(image_res); - DbgPrint(TRACE_LEVEL_FATAL, ("%s drawable= %p Dest right(%d) left(%d) top(%d) bottom(%d) src_bitmap= %p.\n", __FUNCTION__, - drawable, drawable->surfaces_rects[0].right, drawable->surfaces_rects[0].left, + DbgPrint(TRACE_LEVEL_INFORMATION, ("%s drawable= %p type = %d, effect = %d Dest right(%d) left(%d) top(%d) bottom(%d) src_bitmap= %p.\n", __FUNCTION__, + drawable, drawable->type, drawable->effect, drawable->surfaces_rects[0].right, drawable->surfaces_rects[0].left, drawable->surfaces_rects[0].top, drawable->surfaces_rects[0].bottom, drawable->u.copy.src_bitmap)); - -// for (UINT iRect = 0; iRect < NumRects; iRect++) -// { -// CONST RECT* pRect = &pRects[iRect]; -// } - PushDrawable(drawable); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); @@ -4083,6 +4107,15 @@ VOID QxlDevice::DpcRoutine(VOID) DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } +VOID QxlDevice::UpdateArea(RECTL *area, UINT32 surface_id) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + CopyRect(&m_RamHdr->update_area, area); + m_RamHdr->update_surface = surface_id; + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_AREA), 0); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); +} + UINT BPPFromPixelFormat(D3DDDIFORMAT Format) { diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 574363b..fae38ef 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -360,6 +360,9 @@ struct Resource { KeDelayExecutionThread (KernelMode, FALSE, &timeout);\ } while (0); +#define IMAGE_HASH_INIT_VAL(width, height, format) \ + ((UINT32)((width) & 0x1FFF) | ((UINT32)((height) & 0x1FFF) << 13) |\ + ((UINT32)(format) << 26)) #define MAX_OUTPUT_RES 6 @@ -411,35 +414,39 @@ public: NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, - _In_ UINT DstBitPerPixel, - _In_ BYTE* SrcAddr, - _In_ UINT SrcBytesPerPixel, - _In_ LONG SrcPitch, - _In_ ULONG NumMoves, - _In_ D3DKMT_MOVE_RECT* pMoves, - _In_ ULONG NumDirtyRects, - _In_ RECT* pDirtyRect, - _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, - _In_ const CURRENT_BDD_MODE* pModeCur); + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* pMoves, + _In_ ULONG NumDirtyRects, + _In_ RECT* pDirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, + _In_ const CURRENT_BDD_MODE* pModeCur); VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod); BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber); VOID DpcRoutine(VOID); VOID ResetDevice(VOID); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); - VOID BltBits ( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); - QXLDrawable *Drawable( - UINT8 type, - CONST RECT *area, - CONST RECT *clip, - UINT32 surface_id); + VOID BltBits (BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + QXLDrawable *Drawable(UINT8 type, + CONST RECT *area, + CONST RECT *clip, + UINT32 surface_id); void PushDrawable(QXLDrawable *drawable); QXLDrawable *GetDrawable(); void *AllocMem(UINT32 mspace_type, size_t size, BOOL force); + VOID UpdateArea(RECTL *area, UINT32 surface_id); + VOID SetImageId(InternalImage *internal, + BOOL cache_me, + LONG width, + LONG height, + UINT8 format, UINT32 key); private: void UnmapMemory(void); BOOL SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo); @@ -449,7 +456,7 @@ private: void CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo); void DestroyPrimarySurface(void); void SetupHWSlot(UINT8 Idx, MemSlot *pSlot); - UINT8 SetupMemSlot(UINT8 Idx, QXLPHYSICAL start, QXLPHYSICAL end); + UINT8 SetupMemSlot(UINT8 Idx, UINT64 pastart, UINT64 paend, UINT64 vastart, UINT64 vaend); BOOL CreateEvents(void); BOOL CreateRings(void); UINT64 VA(QXLPHYSICAL paddr, UINT8 slot_id); diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp index a92ab17..59222de 100755 --- a/qxldod/driver.cpp +++ b/qxldod/driver.cpp @@ -9,7 +9,7 @@ // Driver Entry point // -int nDebugLevel = TRACE_LEVEL_INFORMATION; +int nDebugLevel = TRACE_LEVEL_ERROR; extern "C" @@ -20,7 +20,7 @@ DriverEntry( { PAGED_CODE(); - DbgPrint(TRACE_LEVEL_INFORMATION, ("---> KMDOD build on on %s %s\n", __DATE__, __TIME__)); + DbgPrint(TRACE_LEVEL_FATAL, ("---> KMDOD build on on %s %s\n", __DATE__, __TIME__)); #ifdef DBG // KdBreakPoint(); From 054d00dbd73df71197889f74ffc8c32b6ccb0f96 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 9 Jun 2014 08:46:10 +1000 Subject: [PATCH 15/46] warning level 3 --- qxldod/qxldod.vcxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qxldod/qxldod.vcxproj b/qxldod/qxldod.vcxproj index 76b510f..ba73247 100755 --- a/qxldod/qxldod.vcxproj +++ b/qxldod/qxldod.vcxproj @@ -107,6 +107,7 @@ %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH);.\Include + Level3 Inf2Cat /driver:$(OutDir) /os:8_X86 @@ -135,6 +136,7 @@ %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH);.\Include + Level3 Inf2Cat /driver:$(OutDir) /os:8_X64 From e04e2d683e42bd24f0064c81dd47d8075884a60f Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Wed, 11 Jun 2014 22:14:20 +1000 Subject: [PATCH 16/46] fix dpc routine --- qxldod/QxlDod.cpp | 50 ++++++++++++++++++++++++++++++++++++++--------- qxldod/QxlDod.h | 17 +++++++++++----- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 70b61b8..be8dcc9 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -1640,7 +1640,7 @@ NTSTATUS QxlDod::UpdateActiveVidPnPresentPath(_In_ CONST DXGKARG_UPDATEACTIVEVID VOID QxlDod::DpcRoutine(VOID) { DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); - m_pHWDevice->DpcRoutine(); + m_pHWDevice->DpcRoutine(&m_DxgkInterface); m_DxgkInterface.DxgkCbNotifyDpc((HANDLE)m_DxgkInterface.DeviceHandle); DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); } @@ -2816,7 +2816,7 @@ BOOLEAN VgaDevice::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ return FALSE; } -VOID VgaDevice::DpcRoutine(VOID) +VOID VgaDevice::DpcRoutine(PVOID) { } @@ -4085,24 +4085,41 @@ BOOLEAN QxlDevice::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ if (!pDxgkInterface->DxgkCbQueueDpc(pDxgkInterface->DeviceHandle)) { m_RamHdr->int_mask = QXL_INTERRUPT_MASK; WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_IRQ), 0); + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s DxgkCbQueueDpc failed\n", __FUNCTION__)); } return TRUE; } -VOID QxlDevice::DpcRoutine(VOID) +VOID QxlDevice::DpcRoutine(PVOID ptr) { - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - m_RamHdr->int_mask = QXL_INTERRUPT_MASK; - WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_IRQ), 0); - if (m_Pending & QXL_INTERRUPT_DISPLAY) { + PDXGKRNL_INTERFACE pDxgkInterface = (PDXGKRNL_INTERFACE)ptr; + + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + DPC_CB_CONTEXT ctx; + BOOLEAN dummy; + ctx.ptr = this; + NTSTATUS Status = pDxgkInterface->DxgkCbSynchronizeExecution( + pDxgkInterface->DeviceHandle, + DpcCallbackEx, + &ctx, + 0, + &dummy); + ASSERT(Status == STATUS_SUCCESS); + + if (ctx.data & QXL_INTERRUPT_DISPLAY) { + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s m_DisplayEvent\n", __FUNCTION__)); KeSetEvent (&m_DisplayEvent, IO_NO_INCREMENT, FALSE); } - if (m_Pending & QXL_INTERRUPT_CURSOR) { + if (ctx.data & QXL_INTERRUPT_CURSOR) { + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s m_CursorEvent\n", __FUNCTION__)); KeSetEvent (&m_CursorEvent, IO_NO_INCREMENT, FALSE); } - if (m_Pending & QXL_INTERRUPT_IO_CMD) { + if (ctx.data & QXL_INTERRUPT_IO_CMD) { + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s m_IoCmdEvent\n", __FUNCTION__)); KeSetEvent (&m_IoCmdEvent, IO_NO_INCREMENT, FALSE); } + m_RamHdr->int_mask = QXL_INTERRUPT_MASK; + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_IRQ), 0); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -4116,6 +4133,21 @@ VOID QxlDevice::UpdateArea(RECTL *area, UINT32 surface_id) DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } +BOOLEAN QxlDevice:: DpcCallbackEx(PVOID ptr) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s\n", __FUNCTION__)); + PDPC_CB_CONTEXT ctx = (PDPC_CB_CONTEXT) ptr; + QxlDevice* pqxl = (QxlDevice*)ctx->ptr; + pqxl->DpcCallback(ctx); + return TRUE; +} + +VOID QxlDevice::DpcCallback(PDPC_CB_CONTEXT ctx) +{ + ctx->data = m_Pending; + m_Pending = 0; + +} UINT BPPFromPixelFormat(D3DDDIFORMAT Format) { diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index fae38ef..ae45320 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -211,8 +211,6 @@ class HwDeviceIntrface : public BaseObject { public: -// HwDeviceIntrface(_In_ QxlDod* pQxlDod) {m_pQxlDod = pQxlDod;} -// virtual ~HwDeviceIntrface(void); virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0; virtual NTSTATUS SetCurrentMode(ULONG Mode) = 0; virtual NTSTATUS GetCurrentMode(ULONG* Mode) = 0; @@ -220,7 +218,7 @@ public: virtual NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; virtual NTSTATUS HWClose(void) = 0; virtual BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber) = 0; - virtual VOID DpcRoutine(VOID) = 0; + virtual VOID DpcRoutine(PVOID) = 0; virtual VOID ResetDevice(void) = 0; ULONG GetModeCount(void) {return m_ModeCount;} @@ -276,7 +274,7 @@ public: _In_ const CURRENT_BDD_MODE* pModeCur); VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod); BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber); - VOID DpcRoutine(VOID); + VOID DpcRoutine(PVOID); VOID ResetDevice(VOID); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); @@ -397,6 +395,13 @@ typedef struct InternalImage { QXLImage image; } InternalImage; + + +typedef struct DpcCbContext { + void* ptr; + UINT32 data; +} DPC_CB_CONTEXT,* PDPC_CB_CONTEXT; + #define BITMAP_ALLOC_BASE (sizeof(Resource) + sizeof(InternalImage) + sizeof(QXLDataChunk)) #define BITS_BUF_MAX (64 * 1024) #define MIN(x, y) (((x) <= (y)) ? (x) : (y)) @@ -426,7 +431,7 @@ public: _In_ const CURRENT_BDD_MODE* pModeCur); VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod); BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber); - VOID DpcRoutine(VOID); + VOID DpcRoutine(PVOID); VOID ResetDevice(VOID); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); @@ -479,6 +484,8 @@ private: void PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, UINT8 **end_ptr, UINT8 *src, int size, size_t alloc_size, uint32_t alignment); + BOOLEAN static DpcCallbackEx(PVOID); + void DpcCallback(PDPC_CB_CONTEXT); private: PUCHAR m_IoBase; From c43d7065b69c27ecb9000778ed6dbedef6b2b42f Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Thu, 12 Jun 2014 23:34:25 +1000 Subject: [PATCH 17/46] replace spinlocks with mutex --- qxldod/QxlDod.cpp | 83 +++++++++++++++++++++++------------------------ qxldod/QxlDod.h | 4 ++- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index be8dcc9..d8b01fc 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -2318,7 +2318,7 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosAllocateBuffer failed with Status: 0x%X\n", Status)); return Status; } - DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosAllocateBuffer 0x%x (%x.%x)\n", VbeInfo.VideoModePtr, m_Segment, m_Offset)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("x86BiosAllocateBuffer 0x%x (%x.%x)\n", VbeInfo.VideoModePtr, m_Segment, m_Offset)); Status = x86BiosWriteMemory (m_Segment, m_Offset, "VBE2", 4); @@ -2351,9 +2351,9 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) return STATUS_UNSUCCESSFUL; } - DbgPrint(TRACE_LEVEL_ERROR, ("VBE BIOS Present (%d.%d, %8ld Kb)\n", VbeInfo.Version / 0x100, VbeInfo.Version & 0xFF, VbeInfo.TotalMemory * 64)); - DbgPrint(TRACE_LEVEL_ERROR, ("Capabilities = 0x%x\n", VbeInfo.Capabilities)); - DbgPrint(TRACE_LEVEL_ERROR, ("VideoModePtr = 0x%x (0x%x.0x%x)\n", VbeInfo.VideoModePtr, HIWORD( VbeInfo.VideoModePtr), LOWORD( VbeInfo.VideoModePtr))); + DbgPrint(TRACE_LEVEL_INFORMATION, ("VBE BIOS Present (%d.%d, %8ld Kb)\n", VbeInfo.Version / 0x100, VbeInfo.Version & 0xFF, VbeInfo.TotalMemory * 64)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("Capabilities = 0x%x\n", VbeInfo.Capabilities)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("VideoModePtr = 0x%x (0x%x.0x%x)\n", VbeInfo.VideoModePtr, HIWORD( VbeInfo.VideoModePtr), LOWORD( VbeInfo.VideoModePtr))); for (ModeCount = 0; ; ModeCount++) { @@ -2376,12 +2376,12 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) } } - DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount %d\n", ModeCount)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("ModeCount %d\n", ModeCount)); m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VIDEO_MODE_INFORMATION) * ModeCount]); m_ModeNumbers = reinterpret_cast (new (PagedPool) BYTE [sizeof (USHORT) * ModeCount]); m_CurrentMode = 0; - DbgPrint(TRACE_LEVEL_ERROR, ("m_ModeInfo = 0x%p, m_ModeNumbers = 0x%p\n", m_ModeInfo, m_ModeNumbers)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("m_ModeInfo = 0x%p, m_ModeNumbers = 0x%p\n", m_ModeInfo, m_ModeNumbers)); for (CurrentMode = 0, SuitableModeCount = 0; CurrentMode < ModeCount; CurrentMode++) @@ -2398,7 +2398,7 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) break; } - DbgPrint(TRACE_LEVEL_ERROR, ("ModeTemp = 0x%X\n", ModeTemp)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("ModeTemp = 0x%X\n", ModeTemp)); RtlZeroMemory(®s, sizeof(regs)); regs.Eax = 0x4F01; regs.Ecx = ModeTemp; @@ -2442,7 +2442,7 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) } m_ModeCount = SuitableModeCount; - DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("ModeCount filtered %d\n", m_ModeCount)); for (ULONG idx = 0; idx < m_ModeCount; idx++) { DbgPrint(TRACE_LEVEL_ERROR, ("type %x, XRes = %d, YRes = %d, BPP = %d\n", @@ -3268,7 +3268,8 @@ BOOL QxlDevice::CreateEvents() KeInitializeEvent(&m_IoCmdEvent, SynchronizationEvent, FALSE); - KeInitializeSpinLock(&m_MemLock); + KeInitializeMutex(&m_MemLock,1); + KeInitializeMutex(&m_CmdLock,1); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return TRUE; @@ -3540,32 +3541,6 @@ QxlDevice::ExecutePresentDisplayOnly( return STATUS_SUCCESS; } -static inline -KIRQL -AcquireSpinLock(PVOID pSpinLock) -{ - KIRQL IRQL; - - IRQL = KeGetCurrentIrql(); - - if (DISPATCH_LEVEL == IRQL) - KeAcquireSpinLockAtDpcLevel((KSPIN_LOCK *)pSpinLock); - else - KeAcquireSpinLock((KSPIN_LOCK *)pSpinLock, &IRQL); - - return IRQL; -} - -static inline -VOID -ReleaseSpinLock(PVOID pSpinLock, KIRQL IRQL) -{ - if (DISPATCH_LEVEL == IRQL) - KeReleaseSpinLockFromDpcLevel((KSPIN_LOCK *)pSpinLock); - else - KeReleaseSpinLock((KSPIN_LOCK *)pSpinLock, IRQL); -} - void QxlDevice::WaitForReleaseRing(void) { int wait; @@ -3652,7 +3627,6 @@ UINT64 QxlDevice::ReleaseOutput(UINT64 output_id) void *QxlDevice::AllocMem(UINT32 mspace_type, size_t size, BOOL force) { PVOID ptr; - KIRQL old_irql; ASSERT(m_MSInfo[mspace_type]._mspace); DbgPrint(TRACE_LEVEL_VERBOSE, ("--->%s: %p(%d) size %u\n", __FUNCTION__, @@ -3663,14 +3637,21 @@ void *QxlDevice::AllocMem(UINT32 mspace_type, size_t size, BOOL force) mspace_malloc_stats(m_MSInfo[mspace_type]._mspace); #endif + KeWaitForSingleObject + ( + &m_MemLock, + Executive, + KernelMode, + FALSE, + NULL + ); + while (1) { /* Release lots of queued resources, before allocating, as we want to release early to minimize fragmentation risks. */ FlushReleaseRing(); - old_irql = AcquireSpinLock(&m_MemLock); ptr = mspace_malloc(m_MSInfo[mspace_type]._mspace, size); - ReleaseSpinLock(&m_MemLock, old_irql); if (ptr) { break; } @@ -3689,6 +3670,7 @@ void *QxlDevice::AllocMem(UINT32 mspace_type, size_t size, BOOL force) break; } } + KeReleaseMutex(&m_MemLock,FALSE); ASSERT((!ptr && !force) || (ptr >= m_MSInfo[mspace_type].mspace_start && ptr < m_MSInfo[mspace_type].mspace_end)); @@ -3698,7 +3680,6 @@ void *QxlDevice::AllocMem(UINT32 mspace_type, size_t size, BOOL force) void QxlDevice::FreeMem(UINT32 mspace_type, void *ptr) { - KIRQL old_irql; ASSERT(m_MSInfo[mspace_type]._mspace); DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); @@ -3710,9 +3691,16 @@ void QxlDevice::FreeMem(UINT32 mspace_type, void *ptr) m_MSInfo[mspace_type].mspace_end, mspace_type)); } #endif - old_irql = AcquireSpinLock(&m_MemLock); + KeWaitForSingleObject + ( + &m_MemLock, + Executive, + KernelMode, + FALSE, + NULL + ); mspace_free(m_MSInfo[mspace_type]._mspace, ptr); - ReleaseSpinLock(&m_MemLock, old_irql); + KeReleaseMutex(&m_MemLock,FALSE); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -3851,11 +3839,20 @@ void QxlDevice::PushDrawable(QXLDrawable *drawable) { QXLCommand *cmd; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + KeWaitForSingleObject + ( + &m_CmdLock, + Executive, + KernelMode, + FALSE, + NULL + ); WaitForCmdRing(); cmd = SPICE_RING_PROD_ITEM(m_CommandRing); cmd->type = QXL_CMD_DRAW; cmd->data = PA(drawable, m_MainMemSlot); PushCmd(); + KeReleaseMutex(&m_CmdLock,FALSE); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -4094,7 +4091,7 @@ VOID QxlDevice::DpcRoutine(PVOID ptr) { PDXGKRNL_INTERFACE pDxgkInterface = (PDXGKRNL_INTERFACE)ptr; - DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); DPC_CB_CONTEXT ctx; BOOLEAN dummy; ctx.ptr = this; @@ -4121,7 +4118,7 @@ VOID QxlDevice::DpcRoutine(PVOID ptr) m_RamHdr->int_mask = QXL_INTERRUPT_MASK; WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_IRQ), 0); - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); } VOID QxlDevice::UpdateArea(RECTL *area, UINT32 surface_id) diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index ae45320..dc52e13 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -523,7 +523,9 @@ private: PUCHAR m_LogPort; PUCHAR m_LogBuf; - KSPIN_LOCK m_MemLock; + KMUTEX m_MemLock; + KMUTEX m_CmdLock; + MspaceInfo m_MSInfo[NUM_MSPACES]; UINT64 m_FreeOutputs; From 29e0336de5687f5b425be163c4b6fe3fcde258f1 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Thu, 12 Jun 2014 23:36:15 +1000 Subject: [PATCH 18/46] fix resolution problem --- qxldod/QxlDod.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index d8b01fc..9f04d72 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -2905,7 +2905,7 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) UINT Height = pDispInfo->Height; UINT Width = pDispInfo->Width; -// UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); + UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); for (CurrentMode = 0, SuitableModeCount = 0; CurrentMode < ModeCount; CurrentMode++) @@ -2913,11 +2913,11 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) QXLMode* tmpModeInfo = &modes->modes[CurrentMode]; - DbgPrint(TRACE_LEVEL_ERROR, ("%s: modes[%d] x_res = %d, y_res = %d, bits = %d\n", __FUNCTION__, CurrentMode, tmpModeInfo->x_res, tmpModeInfo->y_res, tmpModeInfo->bits)); + DbgPrint(TRACE_LEVEL_ERROR, ("%s: modes[%d] x_res = %d, y_res = %d, bits = %d BitsPerPixel = %d\n", __FUNCTION__, CurrentMode, tmpModeInfo->x_res, tmpModeInfo->y_res, tmpModeInfo->bits, BitsPerPixel)); if (tmpModeInfo->x_res >= Width && - tmpModeInfo->y_res >= Height/* && - tmpModeInfo->bits == BitsPerPixel*/) + tmpModeInfo->y_res >= Height && + tmpModeInfo->bits == 32) { m_ModeNumbers[SuitableModeCount] = CurrentMode; SetVideoModeInfo(SuitableModeCount, tmpModeInfo); From eb3d96691333767e3be17d6e63f22575e69c97e9 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Sat, 14 Jun 2014 13:25:00 +1000 Subject: [PATCH 19/46] sync io access --- qxldod/QxlDod.cpp | 53 +++++++++++++++++++++++++++++++++++++++-------- qxldod/QxlDod.h | 6 ++++-- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 9f04d72..843bd0b 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -3136,9 +3136,9 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* return Status; } + WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_RESET), 0); CreateEvents(); CreateRings(); - WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_RESET), 0); m_RamHdr->int_mask = QXL_INTERRUPT_MASK; CreateMemSlots(); InitDeviceMemoryResources(); @@ -3217,14 +3217,16 @@ void QxlDevice::CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo) primary_surface_create->type = QXL_SURF_TYPE_PRIMARY; DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s format = %d, width = %d, height = %d, stride = %d\n", __FUNCTION__, pModeInfo->BitsPerPlane, pModeInfo->VisScreenWidth, pModeInfo->VisScreenHeight, pModeInfo->ScreenStride)); - WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_CREATE_PRIMARY), 0); +// AsyncIo(QXL_IO_CREATE_PRIMARY_ASYNC, 0); + SyncIo(QXL_IO_CREATE_PRIMARY, 0); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } void QxlDevice::DestroyPrimarySurface(void) { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_DESTROY_PRIMARY), 0); +// AsyncIo(QXL_IO_DESTROY_PRIMARY_ASYNC, 0); + SyncIo(QXL_IO_DESTROY_PRIMARY, 0); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -3270,6 +3272,7 @@ BOOL QxlDevice::CreateEvents() FALSE); KeInitializeMutex(&m_MemLock,1); KeInitializeMutex(&m_CmdLock,1); + KeInitializeMutex(&m_IoLock,1); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return TRUE; @@ -3285,6 +3288,37 @@ BOOL QxlDevice::CreateRings() return TRUE; } +void QxlDevice::AsyncIo(UCHAR Port, UCHAR Value) +{ + LARGE_INTEGER timeout; + KeWaitForSingleObject + ( + &m_IoLock, + Executive, + KernelMode, + FALSE, + NULL + ); + WRITE_PORT_UCHAR(m_IoBase + Port, Value); + timeout.QuadPart = -60000L * 1000 * 10; + WAIT_FOR_EVENT(m_IoCmdEvent, &timeout); + KeReleaseMutex(&m_IoLock,FALSE); +} + +void QxlDevice::SyncIo(UCHAR Port, UCHAR Value) +{ + KeWaitForSingleObject + ( + &m_IoLock, + Executive, + KernelMode, + FALSE, + NULL + ); + WRITE_PORT_UCHAR(m_IoBase + Port, Value); + KeReleaseMutex(&m_IoLock,FALSE); +} + UINT8 QxlDevice::SetupMemSlot(UINT8 Idx, UINT64 pastart, UINT64 paend, UINT64 vastart, UINT64 vaend) { UINT64 high_bits; @@ -3555,7 +3589,7 @@ void QxlDevice::WaitForReleaseRing(void) if (!SPICE_RING_IS_EMPTY(m_ReleaseRing)) { break; } - WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_NOTIFY_OOM), 0); + SyncIo(QXL_IO_NOTIFY_OOM, 0); } SPICE_RING_CONS_WAIT(m_ReleaseRing, wait); @@ -3567,7 +3601,7 @@ void QxlDevice::WaitForReleaseRing(void) WAIT_FOR_EVENT(m_DisplayEvent, &timeout); if (SPICE_RING_IS_EMPTY(m_ReleaseRing)) { - WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_NOTIFY_OOM), 0); + SyncIo(QXL_IO_NOTIFY_OOM, 0); } } DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: <---\n", __FUNCTION__)); @@ -3898,7 +3932,7 @@ VOID QxlDevice::BltBits ( } CONST RECT* pRect = &pRects[0]; - + UpdateArea(pRect, 0); drawable->u.copy.scale_mode = SPICE_IMAGE_SCALE_MODE_NEAREST; drawable->u.copy.mask.bitmap = 0; drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT; @@ -4057,7 +4091,7 @@ VOID QxlDevice::PushCmd() DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); SPICE_RING_PUSH(m_CommandRing, notify); if (notify) { - WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_NOTIFY_CMD), 0); + SyncIo(QXL_IO_NOTIFY_CMD, 0); } DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s notify = %d\n", __FUNCTION__, notify)); } @@ -4121,12 +4155,13 @@ VOID QxlDevice::DpcRoutine(PVOID ptr) DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); } -VOID QxlDevice::UpdateArea(RECTL *area, UINT32 surface_id) +VOID QxlDevice::UpdateArea(CONST RECT* area, UINT32 surface_id) { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); CopyRect(&m_RamHdr->update_area, area); m_RamHdr->update_surface = surface_id; - WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_AREA), 0); +// AsyncIo(QXL_IO_UPDATE_AREA_ASYNC, 0); + SyncIo(QXL_IO_UPDATE_AREA, 0); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index dc52e13..6b6bd90 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -446,7 +446,7 @@ protected: void PushDrawable(QXLDrawable *drawable); QXLDrawable *GetDrawable(); void *AllocMem(UINT32 mspace_type, size_t size, BOOL force); - VOID UpdateArea(RECTL *area, UINT32 surface_id); + VOID UpdateArea(CONST RECT* area, UINT32 surface_id); VOID SetImageId(InternalImage *internal, BOOL cache_me, LONG width, @@ -486,7 +486,8 @@ private: size_t alloc_size, uint32_t alignment); BOOLEAN static DpcCallbackEx(PVOID); void DpcCallback(PDPC_CB_CONTEXT); - + void AsyncIo(UCHAR Port, UCHAR Value); + void SyncIo(UCHAR Port, UCHAR Value); private: PUCHAR m_IoBase; BOOLEAN m_IoMapped; @@ -525,6 +526,7 @@ private: KMUTEX m_MemLock; KMUTEX m_CmdLock; + KMUTEX m_IoLock; MspaceInfo m_MSInfo[NUM_MSPACES]; From 1f7a5e66f39b7c2ccefed76dac03d8a0e1beb6a4 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Sat, 14 Jun 2014 17:43:27 +1000 Subject: [PATCH 20/46] add qxl BlackOutScreen placeholder --- qxldod/QxlDod.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 843bd0b..1a690cf 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -4051,13 +4051,29 @@ VOID QxlDevice::PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) { + QXLDrawable *drawable; + RECT Rect; PAGED_CODE(); - UINT ScreenHeight = pCurrentBddMod->DispInfo.Height; - UINT ScreenPitch = pCurrentBddMod->DispInfo.Pitch; + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + Rect.bottom = pCurrentBddMod->SrcModeHeight; + Rect.top = 0; + Rect.left = 0; + Rect.right = pCurrentBddMod->SrcModeWidth; + if (!(drawable = Drawable(QXL_DRAW_FILL, &Rect, NULL, 0))) { + DbgPrint(TRACE_LEVEL_ERROR, ("Cannot get Drawable.\n")); + } - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + drawable->u.fill.brush.type = SPICE_BRUSH_TYPE_SOLID; + drawable->u.fill.brush.u.color = 0; + drawable->u.fill.rop_descriptor = SPICE_ROPD_OP_PUT; + drawable->u.fill.mask.flags = 0; + drawable->u.fill.mask.pos.x = 0; + drawable->u.fill.mask.pos.y = 0; + drawable->u.fill.mask.bitmap = 0; + PushDrawable(drawable); + DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); } NTSTATUS QxlDevice::HWClose(void) From 81b623f09682f0d80099a562b75048274b69fc31 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 16 Jun 2014 21:26:18 +1000 Subject: [PATCH 21/46] cursor shape and move support funtions --- qxldod/QxlDod.cpp | 231 +++++++++++++++++++++++++++++++++++++++++++--- qxldod/QxlDod.h | 31 ++++--- 2 files changed, 234 insertions(+), 28 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 1a690cf..d8ab0ee 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -395,12 +395,12 @@ NTSTATUS QxlDod::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAda pDriverCaps->WDDMVersion = DXGKDDI_WDDMv1_2; pDriverCaps->HighestAcceptableAddress.QuadPart = -1; -/* + pDriverCaps->MaxPointerWidth = 64; pDriverCaps->MaxPointerHeight = 64; pDriverCaps->PointerCaps.Monochrome = 1; - pDriverCaps->PointerCaps.Color = 1; -*/ +// pDriverCaps->PointerCaps.Color = 1; + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s 1\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -427,7 +427,7 @@ NTSTATUS QxlDod::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetP DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s Cursor is not visible\n", __FUNCTION__)); return STATUS_SUCCESS; } - return STATUS_UNSUCCESSFUL; + return m_pHWDevice->SetPointerPosition(pSetPointerPosition); } // Basic Sample Display Driver does not support hardware cursors, and reports such @@ -439,7 +439,7 @@ NTSTATUS QxlDod::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointer DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s Height = %d, Width = %d, XHot= %d, YHot = %d SourceId = %d\n", __FUNCTION__, pSetPointerShape->Height, pSetPointerShape->Width, pSetPointerShape->XHot, pSetPointerShape->YHot, pSetPointerShape->VidPnSourceId)); - return STATUS_NOT_SUPPORTED; + return m_pHWDevice->SetPointerShape(pSetPointerShape); } NTSTATUS QxlDod::Escape(_In_ CONST DXGKARG_ESCAPE* pEscape) @@ -1577,7 +1577,6 @@ NTSTATUS QxlDod::IsVidPnPathFieldsValid(CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) return STATUS_SUCCESS; } - NTSTATUS QxlDod::IsVidPnSourceModeFieldsValid(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const { PAGED_CODE(); @@ -2824,6 +2823,16 @@ VOID VgaDevice::ResetDevice(VOID) { } +NTSTATUS VgaDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) +{ + return STATUS_NOT_SUPPORTED; +} + +NTSTATUS VgaDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) +{ + return STATUS_SUCCESS; +} + QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod) { m_pQxlDod = pQxlDod; @@ -2963,7 +2972,6 @@ NTSTATUS QxlDevice::QueryCurrentMode(PVIDEO_MODE RequestedMode) NTSTATUS QxlDevice::SetCurrentMode(ULONG Mode) { DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s Mode = %x\n", __FUNCTION__, Mode)); -// UNREFERENCED_PARAMETER(Mode); for (ULONG idx = 0; idx < m_ModeCount; idx++) { if (Mode == m_ModeNumbers[idx]) @@ -3213,7 +3221,7 @@ void QxlDevice::CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo) primary_surface_create->mem = PA( m_RamStart, m_MainMemSlot); - primary_surface_create->flags = QXL_SURF_FLAG_KEEP_DATA; //0; + primary_surface_create->flags = QXL_SURF_FLAG_KEEP_DATA; primary_surface_create->type = QXL_SURF_TYPE_PRIMARY; DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s format = %d, width = %d, height = %d, stride = %d\n", __FUNCTION__, pModeInfo->BitsPerPlane, pModeInfo->VisScreenWidth, pModeInfo->VisScreenHeight, pModeInfo->ScreenStride)); @@ -3273,6 +3281,7 @@ BOOL QxlDevice::CreateEvents() KeInitializeMutex(&m_MemLock,1); KeInitializeMutex(&m_CmdLock,1); KeInitializeMutex(&m_IoLock,1); + KeInitializeMutex(&m_CrsLock,1); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return TRUE; @@ -3371,7 +3380,6 @@ void QxlDevice::InitDeviceMemoryResources(void) DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } - 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)); @@ -3389,7 +3397,6 @@ void QxlDevice::ResetDevice(void) DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } - NTSTATUS QxlDevice::ExecutePresentDisplayOnly( _In_ BYTE* DstAddr, @@ -3607,7 +3614,6 @@ void QxlDevice::WaitForReleaseRing(void) DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: <---\n", __FUNCTION__)); } - void QxlDevice::FlushReleaseRing() { UINT64 output; @@ -3738,7 +3744,6 @@ void QxlDevice::FreeMem(UINT32 mspace_type, void *ptr) DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } - QXLDrawable *QxlDevice::GetDrawable() { QXLOutput *output; @@ -3751,6 +3756,21 @@ QXLDrawable *QxlDevice::GetDrawable() return(QXLDrawable *)output->data; } +QXLCursorCmd *QxlDevice::CursorCmd() +{ + QXLCursorCmd *cursor_cmd; + QXLOutput *output; + + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + output = (QXLOutput *)AllocMem(MSPACE_TYPE_DEVRAM, sizeof(QXLOutput) + sizeof(QXLCursorCmd), TRUE); + output->num_res = 0; + RESOURCE_TYPE(output, RESOURCE_TYPE_CURSOR); + cursor_cmd = (QXLCursorCmd *)output->data; + cursor_cmd->release_info.id = (UINT64)output; + DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + return cursor_cmd; +} + BOOL QxlDevice::SetClip(const RECT *clip, QXLDrawable *drawable) { Resource *rects_res; @@ -3794,6 +3814,14 @@ void QxlDevice::DrawableAddRes(QXLDrawable *drawable, Resource *res) AddRes(output, res); } +void QxlDevice::CursorCmdAddRes(QXLCursorCmd *cmd, Resource *res) +{ + QXLOutput *output; + + output = (QXLOutput *)((UINT8 *)cmd - sizeof(QXLOutput)); + AddRes(output, res); +} + void QxlDevice::FreeClipRectsEx(Resource *res) { DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s\n", __FUNCTION__)); @@ -3842,6 +3870,29 @@ void QxlDevice::FreeBitmapImage(Resource *res) DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } +void QxlDevice::FreeCursorEx(Resource *res) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s\n", __FUNCTION__)); + QxlDevice* pqxl = (QxlDevice*)res->ptr; + pqxl->FreeCursor(res); +} + +void QxlDevice::FreeCursor(Resource *res) +{ + QXLPHYSICAL chunk_phys; + + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + chunk_phys = ((InternalCursor *)res->res)->cursor.chunk.next_chunk; + while (chunk_phys) { + QXLDataChunk *chunk = (QXLDataChunk *)VA(chunk_phys, m_MainMemSlot); + chunk_phys = chunk->next_chunk; + FreeMem(MSPACE_TYPE_DEVRAM, chunk); + } + + FreeMem(MSPACE_TYPE_DEVRAM, res); + DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); +} + QXLDrawable *QxlDevice::Drawable(UINT8 type, CONST RECT *area, CONST RECT *clip, UINT32 surface_id) { QXLDrawable *drawable; @@ -3890,6 +3941,29 @@ void QxlDevice::PushDrawable(QXLDrawable *drawable) { DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } +void QxlDevice::PushCursorCmd(QXLCursorCmd *cursor_cmd) +{ + QXLCommand *cmd; + + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + + KeWaitForSingleObject + ( + &m_CrsLock, + Executive, + KernelMode, + FALSE, + NULL + ); + WaitForCursorRing(); + cmd = SPICE_RING_PROD_ITEM(m_CursorRing); + cmd->type = QXL_CMD_CURSOR; + cmd->data = PA(cursor_cmd, m_MainMemSlot); + PushCursor(); + KeReleaseMutex(&m_CrsLock,FALSE); + DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); +} + VOID QxlDevice::SetImageId(InternalImage *internal, BOOL cache_me, LONG width, @@ -3909,7 +3983,6 @@ VOID QxlDevice::SetImageId(InternalImage *internal, } } - VOID QxlDevice::BltBits ( BLT_INFO* pDst, CONST BLT_INFO* pSrc, @@ -3952,7 +4025,6 @@ VOID QxlDevice::BltBits ( drawable->u.copy.src_area.top = 0; drawable->u.copy.src_area.right = width; - alloc_size = BITMAP_ALLOC_BASE + BITS_BUF_MAX - BITS_BUF_MAX % line_size; alloc_size = MIN(BITMAP_ALLOC_BASE + height * line_size, alloc_size); image_res = (Resource*)AllocMem(MSPACE_TYPE_DEVRAM, alloc_size, TRUE); @@ -4048,7 +4120,6 @@ VOID QxlDevice::PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } - VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) { QXLDrawable *drawable; @@ -4085,6 +4156,103 @@ NTSTATUS QxlDevice::HWClose(void) return STATUS_SUCCESS; } +NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) +{ + QXLCursorCmd *cursor_cmd; + InternalCursor *internal; + QXLCursor *cursor; + Resource *res; + QXLDataChunk *chunk; + ULONG unique; + UINT8 *src; + UINT8 *src_end; + UINT8 *now; + UINT8 *end; + int line_size; + + DbgPrint(TRACE_LEVEL_FATAL, ("<--> %s flag = %d pitch = %d, pixels = %p, id = %d, w = %d, h = %d, x = %d, y = %d\n", __FUNCTION__, + pSetPointerShape->Flags.Value, + pSetPointerShape->Pitch, + pSetPointerShape->pPixels, + pSetPointerShape->VidPnSourceId, + pSetPointerShape->Width, + pSetPointerShape->Height, + pSetPointerShape->XHot, + pSetPointerShape->YHot)); + if (!pSetPointerShape->Flags.Monochrome) + return STATUS_UNSUCCESSFUL; + cursor_cmd = CursorCmd(); + cursor_cmd->type = QXL_CURSOR_SET; + + cursor_cmd->u.set.visible = TRUE; + cursor_cmd->u.set.position.x = (INT16)pSetPointerShape->XHot; + cursor_cmd->u.set.position.y = (INT16)pSetPointerShape->YHot; + + res = (Resource *)AllocMem(MSPACE_TYPE_DEVRAM, CURSOR_ALLOC_SIZE, TRUE); + res->refs = 1; + res->free = FreeCursorEx; + res->ptr = this; + RESOURCE_TYPE(res, RESOURCE_TYPE_CURSOR); + + internal = (InternalCursor *)res->res; + + cursor = &internal->cursor; + cursor->header.type = SPICE_CURSOR_TYPE_MONO; + cursor->header.unique = 0; + cursor->header.width = (UINT16)pSetPointerShape->Width; + cursor->header.height = (UINT16)pSetPointerShape->Height; + cursor->header.hot_spot_x = (UINT16)pSetPointerShape->XHot; + cursor->header.hot_spot_y = (UINT16)pSetPointerShape->YHot; + + line_size = pSetPointerShape->Pitch; + cursor->data_size = line_size * pSetPointerShape->Width; + + chunk = &cursor->chunk; + chunk->data_size = cursor->data_size; + chunk->prev_chunk = 0; + chunk->next_chunk = 0; + + src = (UINT8*)pSetPointerShape->pPixels; + now = chunk->data; + end = (UINT8 *)res + CURSOR_ALLOC_SIZE; + + +// src_end = src + (local_surf->lDelta * local_surf->sizlBitmap.cy); +// for (; src != src_end; src += local_surf->lDelta) { +// PutBytesAlign(&chunk, &now, &end, src, line_size, +// PAGE_SIZE, 1); +// } + memcpy(chunk->data, src, chunk->data_size); + CursorCmdAddRes(cursor_cmd, res); + RELEASE_RES(res); + cursor_cmd->u.set.shape = PA(&internal->cursor, m_MainMemSlot); + PushCursorCmd(cursor_cmd); + DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + + return STATUS_SUCCESS; +} + +NTSTATUS QxlDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) +{ + QXLCursorCmd *cursor_cmd; + DbgPrint(TRACE_LEVEL_FATAL, ("<--> %s flag = %d id = %d, x = %d, y = %d\n", __FUNCTION__, + pSetPointerPosition->Flags.Value, + pSetPointerPosition->VidPnSourceId, + pSetPointerPosition->X, + pSetPointerPosition->Y)); + cursor_cmd = CursorCmd(); + if (pSetPointerPosition->X < 0) { + cursor_cmd->type = QXL_CURSOR_HIDE; + } else { + cursor_cmd->type = QXL_CURSOR_MOVE; + cursor_cmd->u.position.x = (INT16)pSetPointerPosition->X; + cursor_cmd->u.position.y = (INT16)pSetPointerPosition->Y; + } + PushCursorCmd(cursor_cmd); + DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + VOID QxlDevice::WaitForCmdRing() { int wait; @@ -4112,6 +4280,39 @@ VOID QxlDevice::PushCmd() DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s notify = %d\n", __FUNCTION__, notify)); } +VOID QxlDevice::WaitForCursorRing(VOID) +{ + int wait; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + for (;;) { + SPICE_RING_PROD_WAIT(m_CursorRing, wait); + + if (!wait) { + break; + } + + LARGE_INTEGER timeout; // 1 => 100 nanoseconds + timeout.QuadPart = -1 * (1000 * 1000 * 10); //negative => relative // 1s + WAIT_FOR_EVENT(m_CursorEvent, &timeout); + + if (SPICE_RING_IS_FULL(m_CursorRing)) { + DbgPrint(TRACE_LEVEL_ERROR, ("%s: timeout\n", __FUNCTION__)); + } + } +} + +VOID QxlDevice::PushCursor(VOID) +{ + int notify; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + SPICE_RING_PUSH(m_CursorRing, notify); + if (notify) { + SyncIo(QXL_IO_NOTIFY_CURSOR, 0); + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s notify = %d\n", __FUNCTION__, notify)); +} + BOOLEAN QxlDevice::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber) { UNREFERENCED_PARAMETER(MessageNumber); diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 6b6bd90..b734bbb 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -239,6 +239,8 @@ public: _In_ const CURRENT_BDD_MODE* pModeCur) = 0; virtual VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) = 0; + virtual NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) = 0; + virtual NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) = 0; protected: virtual NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; protected: @@ -276,6 +278,8 @@ public: BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber); VOID DpcRoutine(PVOID); VOID ResetDevice(VOID); + NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape); + NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); private: @@ -379,23 +383,15 @@ typedef struct Ring { RingItem *next; } Ring; -typedef struct CacheImage { - struct CacheImage *next; - RingItem lru_link; - UINT32 key; - UINT32 hits; - UINT8 format; - UINT32 width; - UINT32 height; - struct InternalImage *image; -} CacheImage; - typedef struct InternalImage { - CacheImage *cache; QXLImage image; } InternalImage; +typedef struct InternalCursor { + QXLCursor cursor; +} InternalCursor; +#define CURSOR_ALLOC_SIZE (PAGE_SIZE << 1) typedef struct DpcCbContext { void* ptr; @@ -433,6 +429,8 @@ public: BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber); VOID DpcRoutine(PVOID); VOID ResetDevice(VOID); + NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape); + NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); VOID BltBits (BLT_INFO* pDst, @@ -444,7 +442,9 @@ protected: CONST RECT *clip, UINT32 surface_id); void PushDrawable(QXLDrawable *drawable); + void PushCursorCmd(QXLCursorCmd *cursor_cmd); QXLDrawable *GetDrawable(); + QXLCursorCmd *CursorCmd(); void *AllocMem(UINT32 mspace_type, size_t size, BOOL force); VOID UpdateArea(CONST RECT* area, UINT32 surface_id); VOID SetImageId(InternalImage *internal, @@ -475,12 +475,17 @@ private: BOOL SetClip(const RECT *clip, QXLDrawable *drawable); void AddRes(QXLOutput *output, Resource *res); void DrawableAddRes(QXLDrawable *drawable, Resource *res); + void CursorCmdAddRes(QXLCursorCmd *cmd, Resource *res); void FreeClipRects(Resource *res); void static FreeClipRectsEx(Resource *res); void FreeBitmapImage(Resource *res); void static FreeBitmapImageEx(Resource *res); + void static FreeCursorEx(Resource *res); + void FreeCursor(Resource *res); void WaitForCmdRing(void); void PushCmd(void); + void WaitForCursorRing(void); + void PushCursor(void); void PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, UINT8 **end_ptr, UINT8 *src, int size, size_t alloc_size, uint32_t alignment); @@ -527,7 +532,7 @@ private: KMUTEX m_MemLock; KMUTEX m_CmdLock; KMUTEX m_IoLock; - + KMUTEX m_CrsLock; MspaceInfo m_MSInfo[NUM_MSPACES]; UINT64 m_FreeOutputs; From 81866f50f0e082e8643a76b32e1266ccfd97541e Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Sun, 22 Jun 2014 19:18:15 +1000 Subject: [PATCH 22/46] add support for color cursor --- qxldod/QxlDod.cpp | 73 +++++++++++++++++++++++++++++++---------------- qxldod/QxlDod.h | 2 ++ 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index d8ab0ee..7d9c10a 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -399,7 +399,7 @@ NTSTATUS QxlDod::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAda pDriverCaps->MaxPointerWidth = 64; pDriverCaps->MaxPointerHeight = 64; pDriverCaps->PointerCaps.Monochrome = 1; -// pDriverCaps->PointerCaps.Color = 1; + pDriverCaps->PointerCaps.Color = 1; DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s 1\n", __FUNCTION__)); return STATUS_SUCCESS; @@ -3645,6 +3645,22 @@ void QxlDevice::FlushReleaseRing() DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } +void QxlDevice::EmptyReleaseRing() +{ + KeWaitForSingleObject + ( + &m_MemLock, + Executive, + KernelMode, + FALSE, + NULL + ); + while (m_FreeOutputs || !SPICE_RING_IS_EMPTY(m_ReleaseRing)) { + FlushReleaseRing(); + } + KeReleaseMutex(&m_MemLock,FALSE); +} + UINT64 QxlDevice::ReleaseOutput(UINT64 output_id) { QXLOutput *output = (QXLOutput *)output_id; @@ -3761,13 +3777,13 @@ QXLCursorCmd *QxlDevice::CursorCmd() QXLCursorCmd *cursor_cmd; QXLOutput *output; - DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); output = (QXLOutput *)AllocMem(MSPACE_TYPE_DEVRAM, sizeof(QXLOutput) + sizeof(QXLCursorCmd), TRUE); output->num_res = 0; RESOURCE_TYPE(output, RESOURCE_TYPE_CURSOR); cursor_cmd = (QXLCursorCmd *)output->data; cursor_cmd->release_info.id = (UINT64)output; - DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return cursor_cmd; } @@ -3881,7 +3897,7 @@ void QxlDevice::FreeCursor(Resource *res) { QXLPHYSICAL chunk_phys; - DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); chunk_phys = ((InternalCursor *)res->res)->cursor.chunk.next_chunk; while (chunk_phys) { QXLDataChunk *chunk = (QXLDataChunk *)VA(chunk_phys, m_MainMemSlot); @@ -3890,7 +3906,7 @@ void QxlDevice::FreeCursor(Resource *res) } FreeMem(MSPACE_TYPE_DEVRAM, res); - DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } QXLDrawable *QxlDevice::Drawable(UINT8 type, CONST RECT *area, CONST RECT *clip, UINT32 surface_id) @@ -3945,7 +3961,7 @@ void QxlDevice::PushCursorCmd(QXLCursorCmd *cursor_cmd) { QXLCommand *cmd; - DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); KeWaitForSingleObject ( @@ -3961,7 +3977,7 @@ void QxlDevice::PushCursorCmd(QXLCursorCmd *cursor_cmd) cmd->data = PA(cursor_cmd, m_MainMemSlot); PushCursor(); KeReleaseMutex(&m_CrsLock,FALSE); - DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } VOID QxlDevice::SetImageId(InternalImage *internal, @@ -4170,7 +4186,8 @@ NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPoi UINT8 *end; int line_size; - DbgPrint(TRACE_LEVEL_FATAL, ("<--> %s flag = %d pitch = %d, pixels = %p, id = %d, w = %d, h = %d, x = %d, y = %d\n", __FUNCTION__, + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s flag = %x\n", __FUNCTION__, pSetPointerShape->Flags.Value)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--> %s flag = %d pitch = %d, pixels = %p, id = %d, w = %d, h = %d, x = %d, y = %d\n", __FUNCTION__, pSetPointerShape->Flags.Value, pSetPointerShape->Pitch, pSetPointerShape->pPixels, @@ -4179,14 +4196,14 @@ NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPoi pSetPointerShape->Height, pSetPointerShape->XHot, pSetPointerShape->YHot)); - if (!pSetPointerShape->Flags.Monochrome) + if (!pSetPointerShape->Flags.Monochrome && !pSetPointerShape->Flags.Color) return STATUS_UNSUCCESSFUL; cursor_cmd = CursorCmd(); cursor_cmd->type = QXL_CURSOR_SET; cursor_cmd->u.set.visible = TRUE; - cursor_cmd->u.set.position.x = (INT16)pSetPointerShape->XHot; - cursor_cmd->u.set.position.y = (INT16)pSetPointerShape->YHot; + cursor_cmd->u.set.position.x = 0; + cursor_cmd->u.set.position.y = 0; res = (Resource *)AllocMem(MSPACE_TYPE_DEVRAM, CURSOR_ALLOC_SIZE, TRUE); res->refs = 1; @@ -4197,18 +4214,25 @@ NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPoi internal = (InternalCursor *)res->res; cursor = &internal->cursor; - cursor->header.type = SPICE_CURSOR_TYPE_MONO; + cursor->header.type = pSetPointerShape->Flags.Monochrome ? SPICE_CURSOR_TYPE_MONO : SPICE_CURSOR_TYPE_ALPHA; cursor->header.unique = 0; cursor->header.width = (UINT16)pSetPointerShape->Width; cursor->header.height = (UINT16)pSetPointerShape->Height; + if (cursor->header.type == SPICE_CURSOR_TYPE_MONO) { + cursor->header.height >>= 1; + line_size = ALIGN(cursor->header.width, 8) >> 3; + } else { + line_size = cursor->header.width << 2; + } + cursor->header.hot_spot_x = (UINT16)pSetPointerShape->XHot; cursor->header.hot_spot_y = (UINT16)pSetPointerShape->YHot; - line_size = pSetPointerShape->Pitch; - cursor->data_size = line_size * pSetPointerShape->Width; + cursor->data_size = line_size * pSetPointerShape->Height; + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--> %s %d::%d::%d::%d::%d\n", __FUNCTION__, cursor->header.width, cursor->header.height, cursor->header.hot_spot_x, cursor->header.hot_spot_y, cursor->data_size)); chunk = &cursor->chunk; - chunk->data_size = cursor->data_size; + chunk->data_size = 0; chunk->prev_chunk = 0; chunk->next_chunk = 0; @@ -4216,18 +4240,16 @@ NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPoi now = chunk->data; end = (UINT8 *)res + CURSOR_ALLOC_SIZE; - -// src_end = src + (local_surf->lDelta * local_surf->sizlBitmap.cy); -// for (; src != src_end; src += local_surf->lDelta) { -// PutBytesAlign(&chunk, &now, &end, src, line_size, -// PAGE_SIZE, 1); -// } - memcpy(chunk->data, src, chunk->data_size); + src_end = src + (pSetPointerShape->Pitch * pSetPointerShape->Height); + for (; src != src_end; src += pSetPointerShape->Pitch) { + PutBytesAlign(&chunk, &now, &end, src, line_size, + PAGE_SIZE, 1); + } CursorCmdAddRes(cursor_cmd, res); RELEASE_RES(res); cursor_cmd->u.set.shape = PA(&internal->cursor, m_MainMemSlot); PushCursorCmd(cursor_cmd); - DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -4235,7 +4257,8 @@ NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPoi NTSTATUS QxlDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) { QXLCursorCmd *cursor_cmd; - DbgPrint(TRACE_LEVEL_FATAL, ("<--> %s flag = %d id = %d, x = %d, y = %d\n", __FUNCTION__, + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--> %s flag = %d id = %d, x = %d, y = %d\n", __FUNCTION__, pSetPointerPosition->Flags.Value, pSetPointerPosition->VidPnSourceId, pSetPointerPosition->X, @@ -4249,7 +4272,7 @@ NTSTATUS QxlDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pS cursor_cmd->u.position.y = (INT16)pSetPointerPosition->Y; } PushCursorCmd(cursor_cmd); - DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index b734bbb..f018704 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -401,6 +401,8 @@ typedef struct DpcCbContext { #define BITMAP_ALLOC_BASE (sizeof(Resource) + sizeof(InternalImage) + sizeof(QXLDataChunk)) #define BITS_BUF_MAX (64 * 1024) #define MIN(x, y) (((x) <= (y)) ? (x) : (y)) +#define MAX(x, y) (((x) >= (y)) ? (x) : (y)) +#define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1)) class QxlDevice : public HwDeviceIntrface From a64e05f525a5ef89e293ad881066fcf0b4e0b8b9 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 30 Jun 2014 21:41:18 +1000 Subject: [PATCH 23/46] cleanup --- qxldod/BaseObject.cpp | 10 ---------- qxldod/BaseObject.h | 11 ----------- qxldod/QxlDod.h | 41 ++--------------------------------------- 3 files changed, 2 insertions(+), 60 deletions(-) diff --git a/qxldod/BaseObject.cpp b/qxldod/BaseObject.cpp index 0405541..da9dfc8 100755 --- a/qxldod/BaseObject.cpp +++ b/qxldod/BaseObject.cpp @@ -68,13 +68,3 @@ void __cdecl operator delete[](void* pObject) ExFreePool(pObject); } } - - -BaseObject::BaseObject(void) -{ -} - - -BaseObject::~BaseObject(void) -{ -} diff --git a/qxldod/BaseObject.h b/qxldod/BaseObject.h index fc4ca59..66e66e4 100755 --- a/qxldod/BaseObject.h +++ b/qxldod/BaseObject.h @@ -57,14 +57,3 @@ _When_((PoolType & NonPagedPoolMustSucceed) != 0, void* __cdecl operator new[](size_t Size, POOL_TYPE PoolType = PagedPool); void __cdecl operator delete(void* pObject); void __cdecl operator delete[](void* pObject); - -// Pool allocation tag for the Sample Display Driver. All allocations use this tag. - - -class BaseObject -{ -public: - BaseObject(void); - ~BaseObject(void); -}; - diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index f018704..f5686cd 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -207,8 +207,7 @@ typedef struct _CURRENT_BDD_MODE class QxlDod; -class HwDeviceIntrface : - public BaseObject +class HwDeviceIntrface { public: virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0; @@ -304,7 +303,6 @@ typedef struct MspaceInfo { enum { MSPACE_TYPE_DEVRAM, MSPACE_TYPE_VRAM, - NUM_MSPACES, }; @@ -541,9 +539,7 @@ private: UINT32 m_Pending; }; -class QxlDod : - public BaseObject -{ +class QxlDod { private: DEVICE_OBJECT* m_pPhysicalDevice; DXGKRNL_INTERFACE m_DxgkInterface; @@ -675,40 +671,7 @@ private: D3DDDI_VIDEO_PRESENT_SOURCE_ID FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero); NTSTATUS IsVidPnSourceModeFieldsValid(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const; NTSTATUS IsVidPnPathFieldsValid(CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) const; - - NTSTATUS RegisterHWInfo(); -/* - NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, - _In_ UINT DstBitPerPixel, - _In_ BYTE* SrcAddr, - _In_ UINT SrcBytesPerPixel, - _In_ LONG SrcPitch, - _In_ ULONG NumMoves, - _In_ D3DKMT_MOVE_RECT* pMoves, - _In_ ULONG NumDirtyRects, - _In_ RECT* pDirtyRect, - _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation); - BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect); - VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch); - VOID CopyBitsGeneric( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); - - VOID CopyBits32_32( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); - VOID BltBits ( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); - VOID BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId); -*/ }; NTSTATUS From 6a37c24fcebd6c211fd3a53eeed5eb9858440585 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 30 Jun 2014 21:46:52 +1000 Subject: [PATCH 24/46] fix pointer activation handler --- qxldod/QxlDod.cpp | 13 +++++++------ qxldod/QxlDod.h | 17 ++++++++++++++--- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 7d9c10a..d11de27 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -290,7 +290,7 @@ NTSTATUS QxlDod::SetPowerState(_In_ ULONG HardwareUid, m_AdapterPowerState = DevicePowerState; // There is nothing to do to specifically power up/down the display adapter - return STATUS_SUCCESS; + return m_pHWDevice->SetPowerState(DevicePowerState, &(m_CurrentModes[0].DispInfo)); } // TODO: This is where the specified monitor should be powered up/down m_pHWDevice->SetPowerState(ActionType); @@ -396,11 +396,12 @@ NTSTATUS QxlDod::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAda pDriverCaps->WDDMVersion = DXGKDDI_WDDMv1_2; pDriverCaps->HighestAcceptableAddress.QuadPart = -1; - pDriverCaps->MaxPointerWidth = 64; - pDriverCaps->MaxPointerHeight = 64; - pDriverCaps->PointerCaps.Monochrome = 1; - pDriverCaps->PointerCaps.Color = 1; - + if (m_pHWDevice->GetType() == DEVICE_QXL) { + pDriverCaps->MaxPointerWidth = POINTER_SIZE; + pDriverCaps->MaxPointerHeight = POINTER_SIZE; + pDriverCaps->PointerCaps.Monochrome = 1; + pDriverCaps->PointerCaps.Color = 1; + } DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s 1\n", __FUNCTION__)); return STATUS_SUCCESS; } diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index f5686cd..a1a0063 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -7,6 +7,8 @@ #define MAX_VIEWS 1 #define BITS_PER_BYTE 8 +#define POINTER_SIZE 64 + typedef struct _QXL_FLAGS { UINT DriverStarted : 1; // ( 1) 1 after StartDevice and 0 after StopDevice @@ -206,9 +208,14 @@ typedef struct _CURRENT_BDD_MODE } CURRENT_BDD_MODE; class QxlDod; - -class HwDeviceIntrface -{ + +enum DevType { + DEVICE_INTERFACE, + DEVICE_VGA, + DEVICE_QXL +}; + +class HwDeviceIntrface { public: virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0; virtual NTSTATUS SetCurrentMode(ULONG Mode) = 0; @@ -225,6 +232,7 @@ public: USHORT GetModeNumber(USHORT idx) {return m_ModeNumbers[idx];} USHORT GetCurrentModeIndex(void) {return m_CurrentMode;} VOID SetCurrentModeIndex(USHORT idx) {m_CurrentMode = idx;} + DevType GetType(void) { return DEVICE_INTERFACE;} virtual NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, _In_ UINT DstBitPerPixel, _In_ BYTE* SrcAddr, @@ -262,6 +270,7 @@ public: NTSTATUS SetPowerState(POWER_ACTION ActionType); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); + DevType GetType(void) { return DEVICE_VGA;} NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, _In_ UINT DstBitPerPixel, _In_ BYTE* SrcAddr, @@ -414,6 +423,7 @@ public: NTSTATUS SetPowerState(POWER_ACTION ActionType); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); + DevType GetType(void) { return DEVICE_QXL;} NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, _In_ UINT DstBitPerPixel, _In_ BYTE* SrcAddr, @@ -472,6 +482,7 @@ private: void FreeMem(UINT32 mspace_type, void *ptr); UINT64 ReleaseOutput(UINT64 output_id); void WaitForReleaseRing(void); + void EmptyReleaseRing(void); BOOL SetClip(const RECT *clip, QXLDrawable *drawable); void AddRes(QXLOutput *output, Resource *res); void DrawableAddRes(QXLDrawable *drawable, Resource *res); From 818fbe3d54ef88a64d5ca15356fca273b75d73f3 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 30 Jun 2014 21:52:18 +1000 Subject: [PATCH 25/46] fix PM handlers --- qxldod/QxlDod.cpp | 61 +++++++++++++++++++++++++++++++---------------- qxldod/QxlDod.h | 8 ++++--- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index d11de27..55ce897 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -293,7 +293,7 @@ NTSTATUS QxlDod::SetPowerState(_In_ ULONG HardwareUid, return m_pHWDevice->SetPowerState(DevicePowerState, &(m_CurrentModes[0].DispInfo)); } // TODO: This is where the specified monitor should be powered up/down - m_pHWDevice->SetPowerState(ActionType); + return STATUS_SUCCESS; } @@ -2517,21 +2517,20 @@ NTSTATUS VgaDevice::HWClose(void) return STATUS_SUCCESS; } -NTSTATUS VgaDevice::SetPowerState(POWER_ACTION ActionType) +NTSTATUS VgaDevice::SetPowerState(_In_ DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo) { DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); X86BIOS_REGISTERS regs = {0}; regs.Eax = 0x4F10; - regs.Ebx = 1; - switch (ActionType) + regs.Ebx = 0; + switch (DevicePowerState) { - case PowerActionNone: break; - case PowerActionSleep: regs.Ebx |= 0x100; break; - case PowerActionHibernate: regs.Ebx |= 0x200; break; - case PowerActionShutdown: - case PowerActionShutdownReset: - case PowerActionShutdownOff: regs.Ebx |= 0x400; break; + case PowerDeviceUnspecified: + case PowerDeviceD0: regs.Ebx |= 0x1; break; + case PowerDeviceD1: + case PowerDeviceD2: + case PowerDeviceD3: regs.Ebx |= 0x400; break; } if (!x86BiosCall (0x10, ®s)) { @@ -2995,10 +2994,17 @@ NTSTATUS QxlDevice::GetCurrentMode(ULONG* pMode) return Status; } -NTSTATUS QxlDevice::SetPowerState(POWER_ACTION ActionType) +NTSTATUS QxlDevice::SetPowerState(_In_ DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo) { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - UNREFERENCED_PARAMETER(ActionType); + switch (DevicePowerState) + { + case PowerDeviceUnspecified: + case PowerDeviceD0: QxlInit(pDispInfo); break; + case PowerDeviceD1: + case PowerDeviceD2: + case PowerDeviceD3: QxlClose(); break; + } DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -3127,17 +3133,30 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* m_RamStart == NULL || m_RamSize == 0 || m_VRamStart == NULL || m_VRamSize == 0 || (m_RamHdr = (QXLRam *)(m_RamStart + m_RomHdr->ram_header_offset)) == NULL || - m_RamHdr->magic != QXL_RAM_MAGIC || !InitMemSlots()) + m_RamHdr->magic != QXL_RAM_MAGIC) { UnmapMemory(); - DestroyMemSlots(); return STATUS_UNSUCCESSFUL; } m_LogBuf = m_RamHdr->log_buf; m_LogPort = m_IoBase + QXL_IO_LOG; - Status = GetModeList(pDispInfo); + CreateEvents(); + + return QxlInit(pDispInfo); +} + +NTSTATUS QxlDevice::QxlInit(DXGK_DISPLAY_INFORMATION* pDispInfo) +{ + NTSTATUS Status = STATUS_SUCCESS; + + if (!InitMemSlots()) { + DestroyMemSlots(); + return STATUS_UNSUCCESSFUL; + } + + Status = GetModeList(pDispInfo); if (!NT_SUCCESS(Status)) { DbgPrint(TRACE_LEVEL_ERROR, ("GetModeList failed with status 0x%X\n", @@ -3146,14 +3165,16 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* } WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_RESET), 0); - CreateEvents(); CreateRings(); m_RamHdr->int_mask = QXL_INTERRUPT_MASK; CreateMemSlots(); InitDeviceMemoryResources(); + return Status; +} - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); - return STATUS_SUCCESS; +void QxlDevice::QxlClose() +{ + DestroyMemSlots(); } void QxlDevice::UnmapMemory(void) @@ -4142,7 +4163,7 @@ VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) QXLDrawable *drawable; RECT Rect; PAGED_CODE(); - +return; DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); Rect.bottom = pCurrentBddMod->SrcModeHeight; Rect.top = 0; @@ -4167,8 +4188,8 @@ VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) NTSTATUS QxlDevice::HWClose(void) { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + QxlClose(); UnmapMemory(); - DestroyMemSlots(); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index a1a0063..8131482 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -220,7 +220,7 @@ public: virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0; virtual NTSTATUS SetCurrentMode(ULONG Mode) = 0; virtual NTSTATUS GetCurrentMode(ULONG* Mode) = 0; - virtual NTSTATUS SetPowerState(POWER_ACTION ActionType) = 0; + virtual NTSTATUS SetPowerState(DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; virtual NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; virtual NTSTATUS HWClose(void) = 0; virtual BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber) = 0; @@ -267,7 +267,7 @@ public: NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); NTSTATUS SetCurrentMode(ULONG Mode); NTSTATUS GetCurrentMode(ULONG* Mode); - NTSTATUS SetPowerState(POWER_ACTION ActionType); + NTSTATUS SetPowerState(DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); DevType GetType(void) { return DEVICE_VGA;} @@ -420,7 +420,7 @@ public: NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); NTSTATUS SetCurrentMode(ULONG Mode); NTSTATUS GetCurrentMode(ULONG* Mode); - NTSTATUS SetPowerState(POWER_ACTION ActionType); + NTSTATUS SetPowerState(DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); DevType GetType(void) { return DEVICE_QXL;} @@ -463,6 +463,8 @@ protected: LONG height, UINT8 format, UINT32 key); private: + NTSTATUS QxlInit(DXGK_DISPLAY_INFORMATION* pDispInfo); + void QxlClose(void); void UnmapMemory(void); BOOL SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo); BOOL InitMemSlots(void); From 7a701b755e0ccb95dbfa2f8c0472a9ed621d3b95 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Tue, 8 Jul 2014 14:06:27 +1000 Subject: [PATCH 26/46] disable UpdateArea --- qxldod/QxlDod.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 55ce897..efbe209 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -4043,7 +4043,7 @@ VOID QxlDevice::BltBits ( } CONST RECT* pRect = &pRects[0]; - UpdateArea(pRect, 0); +// UpdateArea(pRect, 0); drawable->u.copy.scale_mode = SPICE_IMAGE_SCALE_MODE_NEAREST; drawable->u.copy.mask.bitmap = 0; drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT; From d2d1b4ddd5650b6003c88ff0a98603761473872f Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 18 Aug 2014 23:08:42 +1000 Subject: [PATCH 27/46] disable HW pointer acceleration --- qxldod/QxlDod.cpp | 46 ++++++++++++++++++++++++---------------------- qxldod/QxlDod.h | 12 +++--------- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index efbe209..90c4b77 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -396,7 +396,7 @@ NTSTATUS QxlDod::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAda pDriverCaps->WDDMVersion = DXGKDDI_WDDMv1_2; pDriverCaps->HighestAcceptableAddress.QuadPart = -1; - if (m_pHWDevice->GetType() == DEVICE_QXL) { + if (m_pHWDevice->EnablePointer()) { pDriverCaps->MaxPointerWidth = POINTER_SIZE; pDriverCaps->MaxPointerHeight = POINTER_SIZE; pDriverCaps->PointerCaps.Monochrome = 1; @@ -4196,6 +4196,19 @@ NTSTATUS QxlDevice::HWClose(void) NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) { + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s flag = %x\n", __FUNCTION__, pSetPointerShape->Flags.Value)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--> %s flag = %d pitch = %d, pixels = %p, id = %d, w = %d, h = %d, x = %d, y = %d\n", __FUNCTION__, + pSetPointerShape->Flags.Value, + pSetPointerShape->Pitch, + pSetPointerShape->pPixels, + pSetPointerShape->VidPnSourceId, + pSetPointerShape->Width, + pSetPointerShape->Height, + pSetPointerShape->XHot, + pSetPointerShape->YHot)); + if (!EnablePointer() || (!pSetPointerShape->Flags.Monochrome && !pSetPointerShape->Flags.Color)) + return STATUS_UNSUCCESSFUL; + QXLCursorCmd *cursor_cmd; InternalCursor *internal; QXLCursor *cursor; @@ -4208,18 +4221,6 @@ NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPoi UINT8 *end; int line_size; - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s flag = %x\n", __FUNCTION__, pSetPointerShape->Flags.Value)); - DbgPrint(TRACE_LEVEL_INFORMATION, ("<--> %s flag = %d pitch = %d, pixels = %p, id = %d, w = %d, h = %d, x = %d, y = %d\n", __FUNCTION__, - pSetPointerShape->Flags.Value, - pSetPointerShape->Pitch, - pSetPointerShape->pPixels, - pSetPointerShape->VidPnSourceId, - pSetPointerShape->Width, - pSetPointerShape->Height, - pSetPointerShape->XHot, - pSetPointerShape->YHot)); - if (!pSetPointerShape->Flags.Monochrome && !pSetPointerShape->Flags.Color) - return STATUS_UNSUCCESSFUL; cursor_cmd = CursorCmd(); cursor_cmd->type = QXL_CURSOR_SET; @@ -4278,22 +4279,23 @@ NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPoi NTSTATUS QxlDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) { - QXLCursorCmd *cursor_cmd; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); DbgPrint(TRACE_LEVEL_INFORMATION, ("<--> %s flag = %d id = %d, x = %d, y = %d\n", __FUNCTION__, pSetPointerPosition->Flags.Value, pSetPointerPosition->VidPnSourceId, pSetPointerPosition->X, pSetPointerPosition->Y)); - cursor_cmd = CursorCmd(); - if (pSetPointerPosition->X < 0) { - cursor_cmd->type = QXL_CURSOR_HIDE; - } else { - cursor_cmd->type = QXL_CURSOR_MOVE; - cursor_cmd->u.position.x = (INT16)pSetPointerPosition->X; - cursor_cmd->u.position.y = (INT16)pSetPointerPosition->Y; + if (EnablePointer()) { + QXLCursorCmd *cursor_cmd = CursorCmd(); + if (pSetPointerPosition->X < 0) { + cursor_cmd->type = QXL_CURSOR_HIDE; + } else { + cursor_cmd->type = QXL_CURSOR_MOVE; + cursor_cmd->u.position.x = (INT16)pSetPointerPosition->X; + cursor_cmd->u.position.y = (INT16)pSetPointerPosition->Y; + } + PushCursorCmd(cursor_cmd); } - PushCursorCmd(cursor_cmd); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 8131482..ae0b4c0 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -209,12 +209,6 @@ typedef struct _CURRENT_BDD_MODE class QxlDod; -enum DevType { - DEVICE_INTERFACE, - DEVICE_VGA, - DEVICE_QXL -}; - class HwDeviceIntrface { public: virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0; @@ -232,7 +226,7 @@ public: USHORT GetModeNumber(USHORT idx) {return m_ModeNumbers[idx];} USHORT GetCurrentModeIndex(void) {return m_CurrentMode;} VOID SetCurrentModeIndex(USHORT idx) {m_CurrentMode = idx;} - DevType GetType(void) { return DEVICE_INTERFACE;} + virtual BOOLEAN EnablePointer(void) = 0; virtual NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, _In_ UINT DstBitPerPixel, _In_ BYTE* SrcAddr, @@ -270,7 +264,7 @@ public: NTSTATUS SetPowerState(DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); - DevType GetType(void) { return DEVICE_VGA;} + BOOLEAN EnablePointer(void) { return FALSE; } NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, _In_ UINT DstBitPerPixel, _In_ BYTE* SrcAddr, @@ -423,7 +417,7 @@ public: NTSTATUS SetPowerState(DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); - DevType GetType(void) { return DEVICE_QXL;} + BOOLEAN EnablePointer(void) { return FALSE; } NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, _In_ UINT DstBitPerPixel, _In_ BYTE* SrcAddr, From 400f7ad7c5c75e98966c53b5d6b21c97360c5c63 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 18 Aug 2014 23:14:54 +1000 Subject: [PATCH 28/46] update build to VS2012 --- qxldod Package/qxldod Package.vcxproj | 72 ++++++++------- qxldod.sln | 30 ++++++- qxldod/buildAll.bat | 4 +- qxldod/checkWin8Tools.bat | 10 +-- qxldod/qxldod.vcxproj | 122 +++++++++++++++++++++++++- 5 files changed, 198 insertions(+), 40 deletions(-) diff --git a/qxldod Package/qxldod Package.vcxproj b/qxldod Package/qxldod Package.vcxproj index d783186..f71e4c6 100755 --- a/qxldod Package/qxldod Package.vcxproj +++ b/qxldod Package/qxldod Package.vcxproj @@ -1,10 +1,18 @@  + + Win8.1 Debug + Win32 + Win8 Debug Win32 + + Win8.1 Release + Win32 + Win8 Release Win32 @@ -17,18 +25,18 @@ Win7 Release Win32 - - Vista Debug - Win32 - - - Vista Release - Win32 + + Win8.1 Debug + x64 Win8 Debug x64 + + Win8.1 Release + x64 + Win8 Release x64 @@ -41,14 +49,6 @@ Win7 Release x64 - - Vista Debug - x64 - - - Vista Release - x64 - {B8C04B51-4207-491D-A7DD-C54861E8B528} @@ -63,59 +63,70 @@ $(VCTargetsPath11) - WindowsKernelModeDriver8.0 Utility Package true + + WindowsV6.3 + true + WindowsKernelModeDriver8.1 + Windows8 true + WindowsKernelModeDriver8.1 + + + WindowsV6.3 + false + WindowsKernelModeDriver8.1 Windows8 false + WindowsKernelModeDriver8.1 Windows7 true + WindowsKernelModeDriver8.1 Windows7 false + WindowsKernelModeDriver8.1 - - Vista + + WindowsV6.3 true - - - Vista - false + WindowsKernelModeDriver8.1 Windows8 true + WindowsKernelModeDriver8.1 + + + WindowsV6.3 + false + WindowsKernelModeDriver8.1 Windows8 false + WindowsKernelModeDriver8.1 Windows7 true + WindowsKernelModeDriver8.1 Windows7 false - - - Vista - true - - - Vista - false + WindowsKernelModeDriver8.1 @@ -137,7 +148,6 @@ True 133563 - $(OutDir)qxldod Package diff --git a/qxldod.sln b/qxldod.sln index 2b74fb7..494614b 100755 --- a/qxldod.sln +++ b/qxldod.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qxldod", "qxldod\qxldod.vcxproj", "{A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}" @@ -10,12 +10,40 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qxldod Package", "qxldod Pa EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Win8.1 Debug|Win32 = Win8.1 Debug|Win32 + Win8.1 Debug|x64 = Win8.1 Debug|x64 + Win8.1 Release|Win32 = Win8.1 Release|Win32 + Win8.1 Release|x64 = Win8.1 Release|x64 Win8 Debug|Win32 = Win8 Debug|Win32 Win8 Debug|x64 = Win8 Debug|x64 Win8 Release|Win32 = Win8 Release|Win32 Win8 Release|x64 = Win8 Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|Win32.ActiveCfg = Win8.1 Debug|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|Win32.Build.0 = Win8.1 Debug|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|Win32.Deploy.0 = Win8.1 Debug|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|Win32.ActiveCfg = Win8.1 Release|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|Win32.Build.0 = Win8.1 Release|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|Win32.Deploy.0 = Win8.1 Release|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|Win32.ActiveCfg = Win8.1 Debug|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|Win32.Build.0 = Win8.1 Debug|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|Win32.Deploy.0 = Win8.1 Debug|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|Win32.ActiveCfg = Win8.1 Release|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|Win32.Build.0 = Win8.1 Release|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|Win32.Deploy.0 = Win8.1 Release|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32 {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32 {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32 diff --git a/qxldod/buildAll.bat b/qxldod/buildAll.bat index eed3b82..072a2b4 100755 --- a/qxldod/buildAll.bat +++ b/qxldod/buildAll.bat @@ -5,7 +5,7 @@ call clean.bat rem WIN8_64 setlocal if exist Install\win8\amd64 rmdir Install\win8\amd64 /s /q -call callVisualStudio.bat 11 qxldod.vcxproj /Rebuild "Win8 Release|x64" /Out buildfre_win8_amd64.log +call callVisualStudio.bat 12 qxldod.vcxproj /Rebuild "Win8 Release|x64" /Out buildfre_win8_amd64.log mkdir .\Install\Win8\x64 del /Q .\Install\Win8\x64\* copy /Y objfre_win8_amd64\amd64\qxldod.sys .\Install\Win8\x64 @@ -18,7 +18,7 @@ if %ERRORLEVEL% NEQ 0 goto :eof rem WIN8_32 setlocal if exist Install\win8\x86 rmdir Install\win8\x86 /s /q -call callVisualStudio.bat 11 qxldod.vcxproj /Rebuild "Win8 Release|Win32" /Out buildfre_win8_x86.log +call callVisualStudio.bat 12 qxldod.vcxproj /Rebuild "Win8 Release|Win32" /Out buildfre_win8_x86.log mkdir .\Install\Win8\x86 del /Q .\Install\Win8\x86\* copy /Y objfre_win8_x86\i386\qxldod.sys .\Install\Win8\x86 diff --git a/qxldod/checkWin8Tools.bat b/qxldod/checkWin8Tools.bat index c95d30b..992142c 100755 --- a/qxldod/checkWin8Tools.bat +++ b/qxldod/checkWin8Tools.bat @@ -1,16 +1,16 @@ @echo off reg query "HKLM\Software\Microsoft\Windows Kits\WDK" /v WDKProductVersion >nul 2>nul -if %ERRORLEVEL% EQU 0 goto checkVS11 +if %ERRORLEVEL% EQU 0 goto checkVS12 reg query "HKLM\Software\Wow6432Node\Microsoft\Windows Kits\WDK" /v WDKProductVersion > nul 2>nul -if %ERRORLEVEL% EQU 0 goto checkVS11 +if %ERRORLEVEL% EQU 0 goto checkVS12 echo ERROR building Win8 drivers: Win8 WDK is not installed exit /b 1 -:checkVS11 -reg query HKLM\Software\Microsoft\VisualStudio\11.0 /v InstallDir > nul 2>nul +:checkVS12 +reg query HKLM\Software\Microsoft\VisualStudio\12.0 /v InstallDir > nul 2>nul if %ERRORLEVEL% EQU 0 exit /b 0 -reg query HKLM\Software\Wow6432Node\Microsoft\VisualStudio\11.0 /v InstallDir > nul 2>nul +reg query HKLM\Software\Wow6432Node\Microsoft\VisualStudio\12.0 /v InstallDir > nul 2>nul if %ERRORLEVEL% EQU 0 exit /b 0 echo ERROR building Win8 drivers: VS11 is not installed exit /b 2 \ No newline at end of file diff --git a/qxldod/qxldod.vcxproj b/qxldod/qxldod.vcxproj index ba73247..510d748 100755 --- a/qxldod/qxldod.vcxproj +++ b/qxldod/qxldod.vcxproj @@ -1,18 +1,34 @@  + + Win8.1 Debug + Win32 + Win8 Debug Win32 + + Win8.1 Release + Win32 + Win8 Release Win32 + + Win8.1 Debug + x64 + Win8 Debug x64 + + Win8.1 Release + x64 + Win8 Release x64 @@ -31,26 +47,49 @@ $(VCTargetsPath11) - WindowsKernelModeDriver8.0 Driver WDM + + WindowsV6.3 + true + WindowsKernelModeDriver8.1 + Windows8 true + WindowsKernelModeDriver8.1 + + + WindowsV6.3 + false + WindowsKernelModeDriver8.1 Windows8 false + WindowsKernelModeDriver8.1 + + + WindowsV6.3 + true + WindowsKernelModeDriver8.1 Windows8 true + WindowsKernelModeDriver8.1 + + + WindowsV6.3 + false + WindowsKernelModeDriver8.1 Windows8 false + WindowsKernelModeDriver8.1 @@ -59,6 +98,11 @@ + + objchk_win8_x86\i386\ + objchk_win8_x86\i386\ + qxldod + objchk_win8_x86\i386\ objchk_win8_x86\i386\ @@ -67,21 +111,53 @@ DbgengKernelDebugger + + objfre_win8_x86\i386\ + objfre_win8_x86\i386\ + qxldod + objfre_win8_x86\i386\ objfre_win8_x86\i386\ qxldod + + objfre_win8_amd64\amd64\ + objfre_win8_amd64\amd64\ + qxldod + objfre_win8_amd64\amd64\ objfre_win8_amd64\amd64\ qxldod + + objchk_win8_amd64\amd64\ + objchk_win8_amd64\amd64\ + qxldod + objchk_win8_amd64\amd64\ objchk_win8_amd64\amd64\ qxldod + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH);.\Include + Level3 + + + + + Inf2Cat /driver:$(OutDir) /os:8_X86 + + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib @@ -98,6 +174,21 @@ Inf2Cat /driver:$(OutDir) /os:8_X86 + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH);.\Include + Level3 + + + Inf2Cat /driver:$(OutDir) /os:8_X86 + + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib @@ -113,6 +204,20 @@ Inf2Cat /driver:$(OutDir) /os:8_X86 + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH);.\Include + + + Inf2Cat /driver:$(OutDir) /os:8_X64 + + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib @@ -127,6 +232,21 @@ Inf2Cat /driver:$(OutDir) /os:8_X64 + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH);.\Include + Level3 + + + Inf2Cat /driver:$(OutDir) /os:8_X64 + + %(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib From 8ffc5298ad7226f1e239df18a26644956e8a0ec5 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Sun, 24 Aug 2014 20:02:56 +1000 Subject: [PATCH 29/46] fix compatebility issue --- qxldod/QxlDod.cpp | 6 +++--- qxldod/driver.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 90c4b77..0514643 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -383,15 +383,15 @@ NTSTATUS QxlDod::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAda { case DXGKQAITYPE_DRIVERCAPS: { - if (pQueryAdapterInfo->OutputDataSize < sizeof(DXGK_DRIVERCAPS)) + if (!pQueryAdapterInfo->OutputDataSize/* < sizeof(DXGK_DRIVERCAPS)*/) { - DbgPrint(TRACE_LEVEL_ERROR, ("pQueryAdapterInfo->OutputDataSize (0x%I64x) is smaller than sizeof(DXGK_DRIVERCAPS) (0x%I64x)", pQueryAdapterInfo->OutputDataSize, sizeof(DXGK_DRIVERCAPS))); + DbgPrint(TRACE_LEVEL_ERROR, ("pQueryAdapterInfo->OutputDataSize (0x%u) is smaller than sizeof(DXGK_DRIVERCAPS) (0x%u)\n", pQueryAdapterInfo->OutputDataSize, sizeof(DXGK_DRIVERCAPS))); return STATUS_BUFFER_TOO_SMALL; } DXGK_DRIVERCAPS* pDriverCaps = (DXGK_DRIVERCAPS*)pQueryAdapterInfo->pOutputData; - RtlZeroMemory(pDriverCaps, sizeof(DXGK_DRIVERCAPS)); + RtlZeroMemory(pDriverCaps, pQueryAdapterInfo->OutputDataSize/*sizeof(DXGK_DRIVERCAPS)*/); pDriverCaps->WDDMVersion = DXGKDDI_WDDMv1_2; pDriverCaps->HighestAcceptableAddress.QuadPart = -1; diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp index 59222de..e8f48f2 100755 --- a/qxldod/driver.cpp +++ b/qxldod/driver.cpp @@ -28,7 +28,7 @@ DriverEntry( // Initialize DDI function pointers and dxgkrnl KMDDOD_INITIALIZATION_DATA InitialData = {0}; - InitialData.Version = DXGKDDI_INTERFACE_VERSION_WIN8; + InitialData.Version = DXGKDDI_INTERFACE_VERSION; InitialData.DxgkDdiAddDevice = DodAddDevice; InitialData.DxgkDdiStartDevice = DodStartDevice; From 2885958174f9a742cc351c124c17610acde7dfd8 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Sat, 6 Dec 2014 09:20:04 +1100 Subject: [PATCH 30/46] publish qxl device id --- qxldod/QxlDod.cpp | 46 ++++++++++++++++++++++++++++++++-------------- qxldod/QxlDod.h | 4 +++- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 0514643..26c19c3 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -132,14 +132,6 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, return Status; } - Status = RegisterHWInfo(); - if (!NT_SUCCESS(Status)) - { - QXL_LOG_ASSERTION1("RegisterHWInfo failed with status 0x%X\n", - Status); - return Status; - } - // This sample driver only uses the frame buffer of the POST device. DxgkCbAcquirePostDisplayOwnership // gives you the frame buffer address and ensures that no one else is drawing to it. Be sure to give it back! Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &(m_CurrentModes[0].DispInfo)); @@ -169,6 +161,14 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, return Status; } + Status = RegisterHWInfo(m_pHWDevice->GetId()); + if (!NT_SUCCESS(Status)) + { + QXL_LOG_ASSERTION1("RegisterHWInfo failed with status 0x%X\n", + Status); + return Status; + } + *pNumberOfViews = MAX_VIEWS; *pNumberOfChildren = MAX_CHILDREN; m_Flags.DriverStarted = TRUE; @@ -1805,7 +1805,7 @@ NTSTATUS QxlDod::WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR psz return Status; } -NTSTATUS QxlDod::RegisterHWInfo() +NTSTATUS QxlDod::RegisterHWInfo(ULONG Id) { PAGED_CODE(); @@ -1866,6 +1866,21 @@ NTSTATUS QxlDod::RegisterHWInfo() return Status; } + UNICODE_STRING ValueQxlDeviceID; + RtlInitUnicodeString(&ValueQxlDeviceID, L"QxlDeviceID"); + DWORD DeviceId = Id; // BDD has no access to video memory + Status = ZwSetValueKey(DevInstRegKeyHandle, + &ValueQxlDeviceID, + 0, + REG_BINARY, + &DeviceId, + sizeof(DeviceId)); + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("ZwSetValueKey for MemorySize failed with Status: 0x%X\n", Status)); + return Status; + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return Status; } @@ -2246,6 +2261,7 @@ VgaDevice::VgaDevice(_In_ QxlDod* pQxlDod) m_ModeCount = 0; m_ModeNumbers = NULL; m_CurrentMode = 0; + m_Id = 0; } VgaDevice::~VgaDevice(void) @@ -2256,6 +2272,7 @@ VgaDevice::~VgaDevice(void) m_ModeNumbers = NULL; m_CurrentMode = 0; m_ModeCount = 0; + m_Id = 0; } BOOL VgaDevice::SetVideoModeInfo(UINT Idx, PVBE_MODEINFO pModeInfo) @@ -3000,7 +3017,7 @@ NTSTATUS QxlDevice::SetPowerState(_In_ DEVICE_POWER_STATE DevicePowerState, DXGK switch (DevicePowerState) { case PowerDeviceUnspecified: - case PowerDeviceD0: QxlInit(pDispInfo); break; + case PowerDeviceD0: QxlInit(pDispInfo); break; case PowerDeviceD1: case PowerDeviceD2: case PowerDeviceD3: QxlClose(); break; @@ -3141,6 +3158,7 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* m_LogBuf = m_RamHdr->log_buf; m_LogPort = m_IoBase + QXL_IO_LOG; + m_Id = m_RomHdr->id; CreateEvents(); @@ -3152,11 +3170,11 @@ NTSTATUS QxlDevice::QxlInit(DXGK_DISPLAY_INFORMATION* pDispInfo) NTSTATUS Status = STATUS_SUCCESS; if (!InitMemSlots()) { - DestroyMemSlots(); - return STATUS_UNSUCCESSFUL; - } + DestroyMemSlots(); + return STATUS_UNSUCCESSFUL; + } - Status = GetModeList(pDispInfo); + Status = GetModeList(pDispInfo); if (!NT_SUCCESS(Status)) { DbgPrint(TRACE_LEVEL_ERROR, ("GetModeList failed with status 0x%X\n", diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index ae0b4c0..075564b 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -242,6 +242,7 @@ public: virtual VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) = 0; virtual NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) = 0; virtual NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) = 0; + ULONG GetId(void) { return m_Id; } protected: virtual NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; protected: @@ -250,6 +251,7 @@ protected: ULONG m_ModeCount; PUSHORT m_ModeNumbers; USHORT m_CurrentMode; + ULONG m_Id; }; class VgaDevice : @@ -678,7 +680,7 @@ private: D3DDDI_VIDEO_PRESENT_SOURCE_ID FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero); NTSTATUS IsVidPnSourceModeFieldsValid(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const; NTSTATUS IsVidPnPathFieldsValid(CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) const; - NTSTATUS RegisterHWInfo(); + NTSTATUS RegisterHWInfo(_In_ ULONG Id); }; NTSTATUS From 861b2d2d444f2fc60b58fd2eb1ee8b812a701ce6 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Sat, 6 Dec 2014 15:44:28 +1100 Subject: [PATCH 31/46] add multi-monitor support in QXL mode --- qxldod/QxlDod.cpp | 49 ++++++++++++++++++++++++++++++----------------- qxldod/QxlDod.h | 2 ++ 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 26c19c3..2b4208c 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -132,18 +132,6 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, return Status; } - // This sample driver only uses the frame buffer of the POST device. DxgkCbAcquirePostDisplayOwnership - // gives you the frame buffer address and ensures that no one else is drawing to it. Be sure to give it back! - Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &(m_CurrentModes[0].DispInfo)); - if (!NT_SUCCESS(Status) || m_CurrentModes[0].DispInfo.Width == 0) - { - // The most likely cause of failure is that the driver is simply not running on a POST device, or we are running - // after a pre-WDDM 1.2 driver. Since we can't draw anything, we should fail to start. - DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbAcquirePostDisplayOwnership failed with status 0x%X Width = %d\n", - Status, m_CurrentModes[0].DispInfo.Width)); - return STATUS_UNSUCCESSFUL; - } - Status = CheckHardware(); if (NT_SUCCESS(Status)) { @@ -169,6 +157,27 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, return Status; } + if (m_pHWDevice->GetId() == 0) + { + Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &(m_CurrentModes[0].DispInfo)); + } + + if (!NT_SUCCESS(Status) ) + { + DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbAcquirePostDisplayOwnership failed with status 0x%X Width = %d\n", + Status, m_CurrentModes[0].DispInfo.Width)); + return STATUS_UNSUCCESSFUL; + } + + if (m_CurrentModes[0].DispInfo.Width == 0) + { + m_CurrentModes[0].DispInfo.Width = MIN_WIDTH_SIZE; + m_CurrentModes[0].DispInfo.Height = MIN_HEIGHT_SIZE; + m_CurrentModes[0].DispInfo.Pitch = BPPFromPixelFormat(D3DDDIFMT_R8G8B8) / 8; + m_CurrentModes[0].DispInfo.ColorFormat = D3DDDIFMT_R8G8B8; + m_CurrentModes[0].DispInfo.TargetId = 0; + } + *pNumberOfViews = MAX_VIEWS; *pNumberOfChildren = MAX_CHILDREN; m_Flags.DriverStarted = TRUE; @@ -307,13 +316,14 @@ NTSTATUS QxlDod::QueryChildRelations(_Out_writes_bytes_(ChildRelationsSize) DXGK // The last DXGK_CHILD_DESCRIPTOR in the array of pChildRelations must remain zeroed out, so we subtract this from the count ULONG ChildRelationsCount = (ChildRelationsSize / sizeof(DXGK_CHILD_DESCRIPTOR)) - 1; + ULONG DeviceId = m_pHWDevice->GetId(); QXL_ASSERT(ChildRelationsCount <= MAX_CHILDREN); for (UINT ChildIndex = 0; ChildIndex < ChildRelationsCount; ++ChildIndex) { pChildRelations[ChildIndex].ChildDeviceType = TypeVideoOutput; - pChildRelations[ChildIndex].ChildCapabilities.HpdAwareness = HpdAwarenessAlwaysConnected; - pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = D3DKMDT_VOT_INTERNAL; + pChildRelations[ChildIndex].ChildCapabilities.HpdAwareness = (DeviceId == 0) ? HpdAwarenessAlwaysConnected : HpdAwarenessInterruptible; + pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = (DeviceId == 0) ? D3DKMDT_VOT_INTERNAL : D3DKMDT_VOT_HD15; pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_NONE; pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.SupportsSdtvModes = FALSE; // TODO: Replace 0 with the actual ACPI ID of the child device, if available @@ -2443,8 +2453,8 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) { m_ModeNumbers[SuitableModeCount] = ModeTemp; SetVideoModeInfo(SuitableModeCount, &tmpModeInfo); - if (tmpModeInfo.XResolution == 1024 && - tmpModeInfo.YResolution == 768) + if (tmpModeInfo.XResolution == MIN_WIDTH_SIZE && + tmpModeInfo.YResolution == MIN_HEIGHT_SIZE) { m_CurrentMode = (USHORT)SuitableModeCount; } @@ -2947,8 +2957,8 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) { m_ModeNumbers[SuitableModeCount] = CurrentMode; SetVideoModeInfo(SuitableModeCount, tmpModeInfo); - if (tmpModeInfo->x_res == 1024 && - tmpModeInfo->y_res == 768) + if (tmpModeInfo->x_res == MIN_WIDTH_SIZE && + tmpModeInfo->y_res == MIN_HEIGHT_SIZE) { m_CurrentMode = (USHORT)SuitableModeCount; } @@ -3111,6 +3121,9 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* m_RamPA = pResDescriptor->u.Memory.Start; m_RamStart = (UINT8*)MemBase; m_RamSize = MemLength; + if (pDispInfo->PhysicAddress.QuadPart == 0L) { + pDispInfo->PhysicAddress.QuadPart = m_RamPA.QuadPart; + } pci_range = QXL_VRAM_RANGE_INDEX; break; case QXL_VRAM_RANGE_INDEX: diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 075564b..fbbe542 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -8,6 +8,8 @@ #define BITS_PER_BYTE 8 #define POINTER_SIZE 64 +#define MIN_WIDTH_SIZE 1024 +#define MIN_HEIGHT_SIZE 768 typedef struct _QXL_FLAGS { From af54beffe165a2b8c5b7714bf2e3c704e42698ba Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Sun, 14 Dec 2014 21:47:02 +1100 Subject: [PATCH 32/46] add Win8.1 as a build target --- qxldod Package/qxldod Package.vcxproj | 40 ++++++++++++++++++++++++++- qxldod/qxldod.vcxproj | 16 +++++------ 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/qxldod Package/qxldod Package.vcxproj b/qxldod Package/qxldod Package.vcxproj index f71e4c6..2935ed7 100755 --- a/qxldod Package/qxldod Package.vcxproj +++ b/qxldod Package/qxldod Package.vcxproj @@ -149,7 +149,45 @@ 133563 - + + + 8_x86,6_3_x86 + + + + + 8_x86,6_3_x86 + + + + + 8_x86,6_3_x86 + + + + + 8_x86,6_3_x86 + + + + + 8_x64,Server8_x64,Server6_3_x64,6_3_x64 + + + + + 8_x64,Server8_x64,Server6_3_x64,6_3_x64 + + + + + 8_x64,Server8_x64,Server6_3_x64,6_3_x64 + + + + + 8_x64,Server8_x64,Server6_3_x64,6_3_x64 + diff --git a/qxldod/qxldod.vcxproj b/qxldod/qxldod.vcxproj index 510d748..0a82ee1 100755 --- a/qxldod/qxldod.vcxproj +++ b/qxldod/qxldod.vcxproj @@ -155,7 +155,7 @@ - Inf2Cat /driver:$(OutDir) /os:8_X86 + Inf2Cat /driver:$(OutDir) /os:8_X86,6_3_X86 @@ -171,7 +171,7 @@ - Inf2Cat /driver:$(OutDir) /os:8_X86 + Inf2Cat /driver:$(OutDir) /os:8_X86,6_3_X86 @@ -186,7 +186,7 @@ Level3 - Inf2Cat /driver:$(OutDir) /os:8_X86 + Inf2Cat /driver:$(OutDir) /os:8_X86,6_3_X86 @@ -201,7 +201,7 @@ Level3 - Inf2Cat /driver:$(OutDir) /os:8_X86 + Inf2Cat /driver:$(OutDir) /os:8_X86,6_3_X86 @@ -215,7 +215,7 @@ %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH);.\Include - Inf2Cat /driver:$(OutDir) /os:8_X64 + Inf2Cat /driver:$(OutDir) /os:8_X64,Server8_X64,Server6_3_X64,6_3_X64 @@ -229,7 +229,7 @@ %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH);.\Include - Inf2Cat /driver:$(OutDir) /os:8_X64 + Inf2Cat /driver:$(OutDir) /os:8_X64,Server8_X64,Server6_3_X64,6_3_X64 @@ -244,7 +244,7 @@ Level3 - Inf2Cat /driver:$(OutDir) /os:8_X64 + Inf2Cat /driver:$(OutDir) /os:8_X64,Server8_X64,Server6_3_X64,6_3_X64 @@ -259,7 +259,7 @@ Level3 - Inf2Cat /driver:$(OutDir) /os:8_X64 + Inf2Cat /driver:$(OutDir) /os:8_X64,Server8_X64,Server6_3_X64,6_3_X64 From 024b2b30b95efd93cedb71f5423f053280eeffa0 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 15 Dec 2014 20:31:09 +1100 Subject: [PATCH 33/46] trivial cleanup --- qxldod/QxlDod.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 2b4208c..f2d9fd9 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -2533,6 +2533,7 @@ NTSTATUS VgaDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); UNREFERENCED_PARAMETER(pResList); + UNREFERENCED_PARAMETER(pDispInfo); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return GetModeList(pDispInfo); } @@ -2554,7 +2555,7 @@ NTSTATUS VgaDevice::SetPowerState(_In_ DEVICE_POWER_STATE DevicePowerState, DXG switch (DevicePowerState) { case PowerDeviceUnspecified: - case PowerDeviceD0: regs.Ebx |= 0x1; break; + case PowerDeviceD0: regs.Ebx |= 0x1; break; case PowerDeviceD1: case PowerDeviceD2: case PowerDeviceD3: regs.Ebx |= 0x400; break; @@ -2749,7 +2750,7 @@ VgaDevice::ExecutePresentDisplayOnly( // Copy all the scroll rects from source image to video frame buffer. for (UINT i = 0; i < ctx->NumMoves; i++) { - POINT* pSourcePoint = &ctx->Moves[i].SourcePoint; +// POINT* pSourcePoint = &ctx->Moves[i].SourcePoint; RECT* pDestRect = &ctx->Moves[i].DestRect; // DbgPrint(TRACE_LEVEL_FATAL, ("--- %d SourcePoint.x = %ld, SourcePoint.y = %ld, DestRect.bottom = %ld, DestRect.left = %ld, DestRect.right = %ld, DestRect.top = %ld\n", @@ -2852,11 +2853,13 @@ VOID VgaDevice::ResetDevice(VOID) NTSTATUS VgaDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) { + UNREFERENCED_PARAMETER(pSetPointerShape); return STATUS_NOT_SUPPORTED; } NTSTATUS VgaDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) { + UNREFERENCED_PARAMETER(pSetPointerPosition); return STATUS_SUCCESS; } @@ -3039,7 +3042,7 @@ NTSTATUS QxlDevice::SetPowerState(_In_ DEVICE_POWER_STATE DevicePowerState, DXGK NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo) { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - NTSTATUS Status = STATUS_SUCCESS; +// NTSTATUS Status = STATUS_SUCCESS; PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod->GetDxgkInterrface(); UINT pci_range = QXL_RAM_RANGE_INDEX; for (ULONG i = 0; i < pResList->Count; ++i) @@ -4068,6 +4071,8 @@ VOID QxlDevice::BltBits ( LONG height; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + UNREFERENCED_PARAMETER(NumRects); + UNREFERENCED_PARAMETER(pDst); if (!(drawable = Drawable(QXL_DRAW_COPY, pRects, NULL, 0))) { DbgPrint(TRACE_LEVEL_ERROR, ("Cannot get Drawable.\n")); @@ -4156,7 +4161,7 @@ VOID QxlDevice::PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, QXLDataChunk *chunk = *chunk_ptr; UINT8 *now = *now_ptr; UINT8 *end = *end_ptr; - int offset; +// int offset; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); while (size) { @@ -4245,7 +4250,7 @@ NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPoi QXLCursor *cursor; Resource *res; QXLDataChunk *chunk; - ULONG unique; +// ULONG unique; UINT8 *src; UINT8 *src_end; UINT8 *now; From e4480e7d50e73c4d5fcf5ae1f59c5cd72a8fa8dc Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 5 Jan 2015 21:30:55 +1100 Subject: [PATCH 34/46] fix VS 12 checking batch --- qxldod/checkWin8Tools.bat | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/qxldod/checkWin8Tools.bat b/qxldod/checkWin8Tools.bat index 992142c..66a9436 100755 --- a/qxldod/checkWin8Tools.bat +++ b/qxldod/checkWin8Tools.bat @@ -1,16 +1,8 @@ @echo off -reg query "HKLM\Software\Microsoft\Windows Kits\WDK" /v WDKProductVersion >nul 2>nul -if %ERRORLEVEL% EQU 0 goto checkVS12 -reg query "HKLM\Software\Wow6432Node\Microsoft\Windows Kits\WDK" /v WDKProductVersion > nul 2>nul -if %ERRORLEVEL% EQU 0 goto checkVS12 -echo ERROR building Win8 drivers: Win8 WDK is not installed -exit /b 1 - -:checkVS12 reg query HKLM\Software\Microsoft\VisualStudio\12.0 /v InstallDir > nul 2>nul if %ERRORLEVEL% EQU 0 exit /b 0 reg query HKLM\Software\Wow6432Node\Microsoft\VisualStudio\12.0 /v InstallDir > nul 2>nul if %ERRORLEVEL% EQU 0 exit /b 0 -echo ERROR building Win8 drivers: VS11 is not installed +echo ERROR building Win8 drivers: VS12 is not installed exit /b 2 \ No newline at end of file From 170be1696a3f6830d3e63e0f28095cd3f028dd84 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Sun, 8 Feb 2015 21:04:39 +1100 Subject: [PATCH 35/46] implement Escape handler --- qxldod/QxlDod.cpp | 100 +++++++++++++++++++++++++++++++++++++++++----- qxldod/QxlDod.h | 9 ++++- qxldod/driver.cpp | 4 +- 3 files changed, 99 insertions(+), 14 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index f2d9fd9..8206e63 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -1,5 +1,6 @@ #include "driver.h" #include "qxldod.h" +#include "qxl_windows.h" #pragma code_seg(push) #pragma code_seg() @@ -217,7 +218,7 @@ NTSTATUS QxlDod::DispatchIoRequest(_In_ ULONG VidPnSourceId, UNREFERENCED_PARAMETER(VidPnSourceId); UNREFERENCED_PARAMETER(pVideoRequestPacket); - DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -458,9 +459,9 @@ NTSTATUS QxlDod::Escape(_In_ CONST DXGKARG_ESCAPE* pEscape) PAGED_CODE(); QXL_ASSERT(pEscape != NULL); - DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s Flags = %d\n", __FUNCTION__, pEscape->Flags)); + DbgPrint(TRACE_LEVEL_FATAL, ("<---> %s Flags = %d\n", __FUNCTION__, pEscape->Flags)); - return STATUS_NOT_IMPLEMENTED; + return m_pHWDevice->Escape(pEscape); } @@ -2863,6 +2864,13 @@ NTSTATUS VgaDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pS return STATUS_SUCCESS; } +NTSTATUS VgaDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_NOT_IMPLEMENTED; +} + QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod) { m_pQxlDod = pQxlDod; @@ -2870,6 +2878,7 @@ QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod) m_ModeCount = 0; m_ModeNumbers = NULL; m_CurrentMode = 0; + m_CustomMode = 0; m_FreeOutputs = 0; m_Pending = 0; } @@ -2917,13 +2926,38 @@ BOOL QxlDevice::SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo) return TRUE; } +BOOL QxlDevice::UpdateVideoModeInfo(UINT Idx, UINT xres, UINT yres, UINT bpp) +{ + PVIDEO_MODE_INFORMATION pMode = NULL; + UINT bytes_pp = (bpp + 7) / 8; + ULONG color_bits; + PAGED_CODE(); + + if (xres < MIN_WIDTH_SIZE || yres < MIN_HEIGHT_SIZE || bpp != 32) + return FALSE; + pMode = &m_ModeInfo[Idx]; + pMode->VisScreenWidth = xres; + pMode->VisScreenHeight = yres; + pMode->ScreenStride = (xres * bytes_pp + 3) & ~0x3; + pMode->BitsPerPlane = bpp; + color_bits = (bpp == 16) ? 5 : 8; + pMode->NumberRedBits = color_bits; + pMode->NumberGreenBits = color_bits; + pMode->NumberBlueBits = color_bits; + + pMode->BlueMask = (1 << color_bits) - 1; + pMode->GreenMask = pMode->BlueMask << color_bits; + pMode->RedMask = pMode->GreenMask << color_bits; + return TRUE; +} + NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) { PAGED_CODE(); NTSTATUS Status = STATUS_SUCCESS; QXLModes *modes; ULONG ModeCount; - ULONG SuitableModeCount; + USHORT SuitableModeCount; USHORT CurrentMode; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); @@ -2946,7 +2980,7 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) UINT Width = pDispInfo->Width; UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); for (CurrentMode = 0, SuitableModeCount = 0; - CurrentMode < ModeCount; + CurrentMode < modes->n_modes; CurrentMode++) { @@ -2958,12 +2992,12 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) tmpModeInfo->y_res >= Height && tmpModeInfo->bits == 32) { - m_ModeNumbers[SuitableModeCount] = CurrentMode; + m_ModeNumbers[SuitableModeCount] = SuitableModeCount;//CurrentMode; SetVideoModeInfo(SuitableModeCount, tmpModeInfo); if (tmpModeInfo->x_res == MIN_WIDTH_SIZE && tmpModeInfo->y_res == MIN_HEIGHT_SIZE) { - m_CurrentMode = (USHORT)SuitableModeCount; + m_CurrentMode = SuitableModeCount; } SuitableModeCount++; } @@ -2976,9 +3010,17 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) } // m_CurrentMode = m_ModeNumbers[0]; - m_ModeCount = SuitableModeCount; + m_CustomMode = SuitableModeCount; + for (CurrentMode = SuitableModeCount; + CurrentMode < SuitableModeCount + 2; + CurrentMode++) + { + m_ModeNumbers[CurrentMode] = CurrentMode; + memcpy(&m_ModeInfo[CurrentMode], &m_ModeInfo[m_CurrentMode], sizeof(VIDEO_MODE_INFORMATION)); + } + m_ModeCount = SuitableModeCount + 2; DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount)); - for (ULONG idx = 0; idx < m_ModeCount; idx++) + for (ULONG idx = 0; idx < GetModeCount(); idx++) { DbgPrint(TRACE_LEVEL_ERROR, ("type %x, XRes = %d, YRes = %d, BPP = %d\n", m_ModeNumbers[idx], @@ -3002,7 +3044,7 @@ NTSTATUS QxlDevice::QueryCurrentMode(PVIDEO_MODE RequestedMode) NTSTATUS QxlDevice::SetCurrentMode(ULONG Mode) { DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s Mode = %x\n", __FUNCTION__, Mode)); - for (ULONG idx = 0; idx < m_ModeCount; idx++) + for (ULONG idx = 0; idx < GetModeCount(); idx++) { if (Mode == m_ModeNumbers[idx]) { @@ -4325,7 +4367,7 @@ NTSTATUS QxlDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pS QXLCursorCmd *cursor_cmd = CursorCmd(); if (pSetPointerPosition->X < 0) { cursor_cmd->type = QXL_CURSOR_HIDE; - } else { + } else { cursor_cmd->type = QXL_CURSOR_MOVE; cursor_cmd->u.position.x = (INT16)pSetPointerPosition->X; cursor_cmd->u.position.y = (INT16)pSetPointerPosition->Y; @@ -4336,6 +4378,42 @@ NTSTATUS QxlDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pS return STATUS_SUCCESS; } +NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + QXLEscapeSetCustomDisplay *custom_display; + UINT xres; + UINT yres; + UINT bpp; + + if (pEscap->PrivateDriverDataSize != sizeof(QXLEscapeSetCustomDisplay)) { + DbgPrint(TRACE_LEVEL_FATAL, ("<--> %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; + yres = custom_display->yres; + bpp = custom_display->bpp; + + /* alternate custom mode index */ + 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_FATAL, ("%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; + } + if (!UpdateVideoModeInfo(m_CustomMode, xres, yres, bpp)) { + return ERROR_INVALID_DATA; + } + DbgPrint(TRACE_LEVEL_FATAL, ("<--> %s xres %d yres %d bpp %d\n", __FUNCTION__, xres, yres, bpp)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS;// SetCurrentMode(m_CustomMode); +} + VOID QxlDevice::WaitForCmdRing() { int wait; diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index fbbe542..3a6d009 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -223,7 +223,7 @@ public: virtual VOID DpcRoutine(PVOID) = 0; virtual VOID ResetDevice(void) = 0; - ULONG GetModeCount(void) {return m_ModeCount;} + virtual ULONG GetModeCount(void) = 0; PVIDEO_MODE_INFORMATION GetModeInfo(UINT idx) {return &m_ModeInfo[idx];} USHORT GetModeNumber(USHORT idx) {return m_ModeNumbers[idx];} USHORT GetCurrentModeIndex(void) {return m_CurrentMode;} @@ -244,6 +244,7 @@ public: virtual VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) = 0; virtual NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) = 0; virtual NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) = 0; + virtual NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscap) = 0; ULONG GetId(void) { return m_Id; } protected: virtual NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; @@ -253,6 +254,7 @@ protected: ULONG m_ModeCount; PUSHORT m_ModeNumbers; USHORT m_CurrentMode; + USHORT m_CustomMode; ULONG m_Id; }; @@ -265,6 +267,7 @@ public: NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); NTSTATUS SetCurrentMode(ULONG Mode); NTSTATUS GetCurrentMode(ULONG* Mode); + ULONG GetModeCount(void) {return m_ModeCount;} NTSTATUS SetPowerState(DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); @@ -286,6 +289,7 @@ public: VOID ResetDevice(VOID); NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape); NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition); + NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscap); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); private: @@ -418,6 +422,7 @@ public: NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); NTSTATUS SetCurrentMode(ULONG Mode); NTSTATUS GetCurrentMode(ULONG* Mode); + ULONG GetModeCount(void) {return m_ModeCount/* - 2*/;} NTSTATUS SetPowerState(DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); @@ -439,6 +444,7 @@ public: VOID ResetDevice(VOID); NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape); NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition); + NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscap); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); VOID BltBits (BLT_INFO* pDst, @@ -465,6 +471,7 @@ private: void QxlClose(void); void UnmapMemory(void); BOOL SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo); + BOOL UpdateVideoModeInfo(UINT Idx, UINT xres, UINT yres, UINT bpp); BOOL InitMemSlots(void); BOOL CreateMemSlots(void); void DestroyMemSlots(void); diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp index e8f48f2..3758735 100755 --- a/qxldod/driver.cpp +++ b/qxldod/driver.cpp @@ -28,7 +28,7 @@ DriverEntry( // Initialize DDI function pointers and dxgkrnl KMDDOD_INITIALIZATION_DATA InitialData = {0}; - InitialData.Version = DXGKDDI_INTERFACE_VERSION; + InitialData.Version = DXGKDDI_INTERFACE_VERSION; InitialData.DxgkDdiAddDevice = DodAddDevice; InitialData.DxgkDdiStartDevice = DodStartDevice; @@ -465,7 +465,7 @@ DodEnumVidPnCofuncModality( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_FATAL, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) From 7693d4153cfa5d855998cc6cc49c53d8e8a2b35b Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Wed, 18 Feb 2015 20:57:00 +1100 Subject: [PATCH 36/46] publish adding a new resolution --- qxldod/QxlDod.cpp | 62 ++++++++++++++++++++++++++++++----------------- qxldod/QxlDod.h | 3 ++- qxldod/driver.cpp | 2 +- 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 8206e63..005cfe3 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -218,7 +218,7 @@ NTSTATUS QxlDod::DispatchIoRequest(_In_ ULONG VidPnSourceId, UNREFERENCED_PARAMETER(VidPnSourceId); UNREFERENCED_PARAMETER(pVideoRequestPacket); - DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -457,11 +457,27 @@ NTSTATUS QxlDod::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointer NTSTATUS QxlDod::Escape(_In_ CONST DXGKARG_ESCAPE* pEscape) { PAGED_CODE(); + NTSTATUS Status = STATUS_SUCCESS; QXL_ASSERT(pEscape != NULL); - DbgPrint(TRACE_LEVEL_FATAL, ("<---> %s Flags = %d\n", __FUNCTION__, pEscape->Flags)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s Flags = %d\n", __FUNCTION__, pEscape->Flags)); - return m_pHWDevice->Escape(pEscape); + 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; } @@ -2473,7 +2489,7 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) DbgPrint(TRACE_LEVEL_INFORMATION, ("ModeCount filtered %d\n", m_ModeCount)); for (ULONG idx = 0; idx < m_ModeCount; idx++) { - DbgPrint(TRACE_LEVEL_ERROR, ("type %x, XRes = %d, YRes = %d, BPP = %d\n", + DbgPrint(TRACE_LEVEL_INFORMATION, ("type %x, XRes = %d, YRes = %d, BPP = %d\n", m_ModeNumbers[idx], m_ModeInfo[idx].VisScreenWidth, m_ModeInfo[idx].VisScreenHeight, @@ -2926,15 +2942,13 @@ BOOL QxlDevice::SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo) return TRUE; } -BOOL QxlDevice::UpdateVideoModeInfo(UINT Idx, UINT xres, UINT yres, UINT bpp) +void QxlDevice::UpdateVideoModeInfo(UINT Idx, UINT xres, UINT yres, UINT bpp) { PVIDEO_MODE_INFORMATION pMode = NULL; UINT bytes_pp = (bpp + 7) / 8; ULONG color_bits; PAGED_CODE(); - if (xres < MIN_WIDTH_SIZE || yres < MIN_HEIGHT_SIZE || bpp != 32) - return FALSE; pMode = &m_ModeInfo[Idx]; pMode->VisScreenWidth = xres; pMode->VisScreenHeight = yres; @@ -2948,7 +2962,6 @@ BOOL QxlDevice::UpdateVideoModeInfo(UINT Idx, UINT xres, UINT yres, UINT bpp) pMode->BlueMask = (1 << color_bits) - 1; pMode->GreenMask = pMode->BlueMask << color_bits; pMode->RedMask = pMode->GreenMask << color_bits; - return TRUE; } NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) @@ -2969,7 +2982,7 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) return STATUS_UNSUCCESSFUL; } - DbgPrint(TRACE_LEVEL_ERROR, ("%s: ModeCount = %d\n", __FUNCTION__, ModeCount)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("%s: ModeCount = %d\n", __FUNCTION__, ModeCount)); ModeCount += 2; m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VIDEO_MODE_INFORMATION) * ModeCount]); @@ -2986,11 +2999,11 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) QXLMode* tmpModeInfo = &modes->modes[CurrentMode]; - DbgPrint(TRACE_LEVEL_ERROR, ("%s: modes[%d] x_res = %d, y_res = %d, bits = %d BitsPerPixel = %d\n", __FUNCTION__, CurrentMode, tmpModeInfo->x_res, tmpModeInfo->y_res, tmpModeInfo->bits, BitsPerPixel)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("%s: modes[%d] x_res = %d, y_res = %d, bits = %d BitsPerPixel = %d\n", __FUNCTION__, CurrentMode, tmpModeInfo->x_res, tmpModeInfo->y_res, tmpModeInfo->bits, BitsPerPixel)); if (tmpModeInfo->x_res >= Width && tmpModeInfo->y_res >= Height && - tmpModeInfo->bits == 32) + tmpModeInfo->bits == QXL_BPP) { m_ModeNumbers[SuitableModeCount] = SuitableModeCount;//CurrentMode; SetVideoModeInfo(SuitableModeCount, tmpModeInfo); @@ -3019,10 +3032,10 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) memcpy(&m_ModeInfo[CurrentMode], &m_ModeInfo[m_CurrentMode], sizeof(VIDEO_MODE_INFORMATION)); } m_ModeCount = SuitableModeCount + 2; - DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("ModeCount filtered %d\n", m_ModeCount)); for (ULONG idx = 0; idx < GetModeCount(); idx++) { - DbgPrint(TRACE_LEVEL_ERROR, ("type %x, XRes = %d, YRes = %d, BPP = %d\n", + DbgPrint(TRACE_LEVEL_INFORMATION, ("type %x, XRes = %d, YRes = %d, BPP = %d\n", m_ModeNumbers[idx], m_ModeInfo[idx].VisScreenWidth, m_ModeInfo[idx].VisScreenHeight, @@ -4394,8 +4407,16 @@ NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap) xres = custom_display->xres; yres = custom_display->yres; bpp = custom_display->bpp; + if (bpp != QXL_BPP) + { + bpp = QXL_BPP; + } + if (xres < MIN_WIDTH_SIZE || yres < MIN_HEIGHT_SIZE) + { + DbgPrint(TRACE_LEVEL_FATAL, ("%s: xres = %d, yres = %d\n", __FUNCTION__, xres, yres)); + return ERROR_INVALID_DATA; + } - /* alternate custom mode index */ if (m_CustomMode == (m_ModeCount - 1)) m_CustomMode = (USHORT)(m_ModeCount - 2); else @@ -4406,12 +4427,9 @@ NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap) __FUNCTION__, xres, yres, bpp, m_RomHdr->surface0_area_size)); return ERROR_NOT_ENOUGH_MEMORY; } - if (!UpdateVideoModeInfo(m_CustomMode, xres, yres, bpp)) { - return ERROR_INVALID_DATA; - } - DbgPrint(TRACE_LEVEL_FATAL, ("<--> %s xres %d yres %d bpp %d\n", __FUNCTION__, xres, yres, bpp)); + UpdateVideoModeInfo(m_CustomMode, xres, yres, bpp); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); - return STATUS_SUCCESS;// SetCurrentMode(m_CustomMode); + return STATUS_SUCCESS; } VOID QxlDevice::WaitForCmdRing() @@ -4516,15 +4534,15 @@ VOID QxlDevice::DpcRoutine(PVOID ptr) ASSERT(Status == STATUS_SUCCESS); if (ctx.data & QXL_INTERRUPT_DISPLAY) { - DbgPrint(TRACE_LEVEL_FATAL, ("---> %s m_DisplayEvent\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s m_DisplayEvent\n", __FUNCTION__)); KeSetEvent (&m_DisplayEvent, IO_NO_INCREMENT, FALSE); } if (ctx.data & QXL_INTERRUPT_CURSOR) { - DbgPrint(TRACE_LEVEL_FATAL, ("---> %s m_CursorEvent\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s m_CursorEvent\n", __FUNCTION__)); KeSetEvent (&m_CursorEvent, IO_NO_INCREMENT, FALSE); } if (ctx.data & QXL_INTERRUPT_IO_CMD) { - DbgPrint(TRACE_LEVEL_FATAL, ("---> %s m_IoCmdEvent\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s m_IoCmdEvent\n", __FUNCTION__)); KeSetEvent (&m_IoCmdEvent, IO_NO_INCREMENT, FALSE); } m_RamHdr->int_mask = QXL_INTERRUPT_MASK; diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 3a6d009..1e7c1a8 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -10,6 +10,7 @@ #define POINTER_SIZE 64 #define MIN_WIDTH_SIZE 1024 #define MIN_HEIGHT_SIZE 768 +#define QXL_BPP 32 typedef struct _QXL_FLAGS { @@ -471,7 +472,7 @@ private: void QxlClose(void); void UnmapMemory(void); BOOL SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo); - BOOL UpdateVideoModeInfo(UINT Idx, UINT xres, UINT yres, UINT bpp); + void UpdateVideoModeInfo(UINT Idx, UINT xres, UINT yres, UINT bpp); BOOL InitMemSlots(void); BOOL CreateMemSlots(void); void DestroyMemSlots(void); diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp index 3758735..48bf346 100755 --- a/qxldod/driver.cpp +++ b/qxldod/driver.cpp @@ -465,7 +465,7 @@ DodEnumVidPnCofuncModality( { PAGED_CODE(); QXL_ASSERT_CHK(hAdapter != NULL); - DbgPrint(TRACE_LEVEL_FATAL, ("<---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__)); QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) From b2a0aef4a553fd2bb1e4db910f86464a2e66660b Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Thu, 19 Feb 2015 21:07:24 +1100 Subject: [PATCH 37/46] fix resolution mismatch when switching between VGA and QXL modes --- qxldod/QxlDod.cpp | 63 +++++++++++++++++++++++++++++------------------ qxldod/QxlDod.h | 1 + qxldod/driver.cpp | 2 +- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 005cfe3..b8fb4b7 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -2351,7 +2351,9 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) VBE_INFO VbeInfo = {0}; ULONG Length; VBE_MODEINFO tmpModeInfo; - + UINT Height = pDispInfo->Height; + UINT Width = pDispInfo->Width; + UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); NTSTATUS Status = STATUS_SUCCESS; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); //Get VBE Mode List @@ -2398,6 +2400,7 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) DbgPrint(TRACE_LEVEL_INFORMATION, ("VBE BIOS Present (%d.%d, %8ld Kb)\n", VbeInfo.Version / 0x100, VbeInfo.Version & 0xFF, VbeInfo.TotalMemory * 64)); DbgPrint(TRACE_LEVEL_INFORMATION, ("Capabilities = 0x%x\n", VbeInfo.Capabilities)); DbgPrint(TRACE_LEVEL_INFORMATION, ("VideoModePtr = 0x%x (0x%x.0x%x)\n", VbeInfo.VideoModePtr, HIWORD( VbeInfo.VideoModePtr), LOWORD( VbeInfo.VideoModePtr))); + DbgPrint(TRACE_LEVEL_INFORMATION, ("pDispInfo = %p %dx%d@%d\n", pDispInfo, Width, Height, BitsPerPixel)); for (ModeCount = 0; ; ModeCount++) { @@ -2425,7 +2428,13 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VIDEO_MODE_INFORMATION) * ModeCount]); m_ModeNumbers = reinterpret_cast (new (PagedPool) BYTE [sizeof (USHORT) * ModeCount]); m_CurrentMode = 0; - DbgPrint(TRACE_LEVEL_INFORMATION, ("m_ModeInfo = 0x%p, m_ModeNumbers = 0x%p\n", m_ModeInfo, m_ModeNumbers)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("m_ModeInfo = 0x%p, m_ModeNumbers = 0x%p\n", m_ModeInfo, m_ModeNumbers)); + if (Width == 0 || Height == 0 || BitsPerPixel != VGA_BPP) + { + Width = MIN_WIDTH_SIZE; + Height = MIN_HEIGHT_SIZE; + BitsPerPixel = VGA_BPP; + } for (CurrentMode = 0, SuitableModeCount = 0; CurrentMode < ModeCount; CurrentMode++) @@ -2442,7 +2451,6 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) break; } - DbgPrint(TRACE_LEVEL_INFORMATION, ("ModeTemp = 0x%X\n", ModeTemp)); RtlZeroMemory(®s, sizeof(regs)); regs.Eax = 0x4F01; regs.Ecx = ModeTemp; @@ -2459,9 +2467,7 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) &tmpModeInfo, sizeof(VBE_MODEINFO)); - UINT Height = pDispInfo->Height; - UINT Width = pDispInfo->Width; - UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); + DbgPrint(TRACE_LEVEL_INFORMATION, ("ModeTemp = 0x%X %dx%d@%d\n", ModeTemp, tmpModeInfo.XResolution, tmpModeInfo.YResolution, tmpModeInfo.BitsPerPixel)); if (tmpModeInfo.XResolution >= Width && tmpModeInfo.YResolution >= Height && @@ -2992,6 +2998,13 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) UINT Height = pDispInfo->Height; UINT Width = pDispInfo->Width; UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); + if (Width == 0 || Height == 0 || BitsPerPixel != QXL_BPP) + { + Width = MIN_WIDTH_SIZE; + Height = MIN_HEIGHT_SIZE; + BitsPerPixel = QXL_BPP; + } + for (CurrentMode = 0, SuitableModeCount = 0; CurrentMode < modes->n_modes; CurrentMode++) @@ -3022,7 +3035,6 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) Status = STATUS_UNSUCCESSFUL; } -// m_CurrentMode = m_ModeNumbers[0]; m_CustomMode = SuitableModeCount; for (CurrentMode = SuitableModeCount; CurrentMode < SuitableModeCount + 2; @@ -4254,25 +4266,28 @@ VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) QXLDrawable *drawable; RECT Rect; PAGED_CODE(); -return; + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); - Rect.bottom = pCurrentBddMod->SrcModeHeight; - Rect.top = 0; - Rect.left = 0; - Rect.right = pCurrentBddMod->SrcModeWidth; - if (!(drawable = Drawable(QXL_DRAW_FILL, &Rect, NULL, 0))) { - DbgPrint(TRACE_LEVEL_ERROR, ("Cannot get Drawable.\n")); + if (pCurrentBddMod->Flags.FrameBufferIsActive) + { + Rect.bottom = pCurrentBddMod->SrcModeHeight; + Rect.top = 0; + Rect.left = 0; + Rect.right = pCurrentBddMod->SrcModeWidth; + if (!(drawable = Drawable(QXL_DRAW_FILL, &Rect, NULL, 0))) + { + DbgPrint(TRACE_LEVEL_ERROR, ("Cannot get Drawable.\n")); + return; + } + drawable->u.fill.brush.type = SPICE_BRUSH_TYPE_SOLID; + drawable->u.fill.brush.u.color = 0; + drawable->u.fill.rop_descriptor = SPICE_ROPD_OP_PUT; + drawable->u.fill.mask.flags = 0; + drawable->u.fill.mask.pos.x = 0; + drawable->u.fill.mask.pos.y = 0; + drawable->u.fill.mask.bitmap = 0; + PushDrawable(drawable); } - - drawable->u.fill.brush.type = SPICE_BRUSH_TYPE_SOLID; - drawable->u.fill.brush.u.color = 0; - drawable->u.fill.rop_descriptor = SPICE_ROPD_OP_PUT; - drawable->u.fill.mask.flags = 0; - drawable->u.fill.mask.pos.x = 0; - drawable->u.fill.mask.pos.y = 0; - drawable->u.fill.mask.bitmap = 0; - PushDrawable(drawable); - DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); } diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 1e7c1a8..6e3af2a 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -11,6 +11,7 @@ #define MIN_WIDTH_SIZE 1024 #define MIN_HEIGHT_SIZE 768 #define QXL_BPP 32 +#define VGA_BPP 24 typedef struct _QXL_FLAGS { diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp index 48bf346..f7c5fb3 100755 --- a/qxldod/driver.cpp +++ b/qxldod/driver.cpp @@ -9,7 +9,7 @@ // Driver Entry point // -int nDebugLevel = TRACE_LEVEL_ERROR; +int nDebugLevel = TRACE_LEVEL_INFORMATION; extern "C" From 2317e7c1d468be932fb5654104db484481fa402a Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 23 Feb 2015 22:21:14 +1100 Subject: [PATCH 38/46] align arbitrary resolution --- qxldod/QxlDod.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index b8fb4b7..d128a86 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -3018,7 +3018,7 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) tmpModeInfo->y_res >= Height && tmpModeInfo->bits == QXL_BPP) { - m_ModeNumbers[SuitableModeCount] = SuitableModeCount;//CurrentMode; + m_ModeNumbers[SuitableModeCount] = SuitableModeCount; SetVideoModeInfo(SuitableModeCount, tmpModeInfo); if (tmpModeInfo->x_res == MIN_WIDTH_SIZE && tmpModeInfo->y_res == MIN_HEIGHT_SIZE) @@ -4419,8 +4419,8 @@ NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap) return STATUS_INVALID_BUFFER_SIZE; } custom_display = (QXLEscapeSetCustomDisplay*)pEscap->pPrivateDriverData; - xres = custom_display->xres; - yres = custom_display->yres; + xres = (custom_display->xres + 3) & ~0x3; + yres = (custom_display->yres +3) & ~0x3; bpp = custom_display->bpp; if (bpp != QXL_BPP) { From 5f7bba4cbc1b0f2ad5b589e43d3f7a435969b44c Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Wed, 18 Mar 2015 22:58:25 +1100 Subject: [PATCH 39/46] fix resize problem (reported and fixed by Sandy Stutsman --- qxldod/QxlDod.cpp | 10 +++++----- qxldod/QxlDod.h | 2 +- qxldod/driver.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index d128a86..09ee73f 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -3267,7 +3267,7 @@ NTSTATUS QxlDevice::QxlInit(DXGK_DISPLAY_INFORMATION* pDispInfo) WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_RESET), 0); CreateRings(); - m_RamHdr->int_mask = QXL_INTERRUPT_MASK; + m_RamHdr->int_mask = ~0; CreateMemSlots(); InitDeviceMemoryResources(); return Status; @@ -4419,8 +4419,8 @@ NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap) return STATUS_INVALID_BUFFER_SIZE; } custom_display = (QXLEscapeSetCustomDisplay*)pEscap->pPrivateDriverData; - xres = (custom_display->xres + 3) & ~0x3; - yres = (custom_display->yres +3) & ~0x3; + xres = custom_display->xres & ~0x3; + yres = custom_display->yres & ~0x3; bpp = custom_display->bpp; if (bpp != QXL_BPP) { @@ -4525,7 +4525,7 @@ BOOLEAN QxlDevice::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ pDxgkInterface->DxgkCbNotifyInterrupt(pDxgkInterface->DeviceHandle,¬ifyInt); if (!pDxgkInterface->DxgkCbQueueDpc(pDxgkInterface->DeviceHandle)) { - m_RamHdr->int_mask = QXL_INTERRUPT_MASK; + m_RamHdr->int_mask = ~0; WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_IRQ), 0); DbgPrint(TRACE_LEVEL_FATAL, ("---> %s DxgkCbQueueDpc failed\n", __FUNCTION__)); } @@ -4560,7 +4560,7 @@ VOID QxlDevice::DpcRoutine(PVOID ptr) DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s m_IoCmdEvent\n", __FUNCTION__)); KeSetEvent (&m_IoCmdEvent, IO_NO_INCREMENT, FALSE); } - m_RamHdr->int_mask = QXL_INTERRUPT_MASK; + m_RamHdr->int_mask = ~0; WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_IRQ), 0); DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 6e3af2a..c00b5cb 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -424,7 +424,7 @@ public: NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); NTSTATUS SetCurrentMode(ULONG Mode); NTSTATUS GetCurrentMode(ULONG* Mode); - ULONG GetModeCount(void) {return m_ModeCount/* - 2*/;} + ULONG GetModeCount(void) {return m_ModeCount;} NTSTATUS SetPowerState(DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp index f7c5fb3..48bf346 100755 --- a/qxldod/driver.cpp +++ b/qxldod/driver.cpp @@ -9,7 +9,7 @@ // Driver Entry point // -int nDebugLevel = TRACE_LEVEL_INFORMATION; +int nDebugLevel = TRACE_LEVEL_ERROR; extern "C" From 4fc48d370f35ff4ffc30375b3306472ae4f67b16 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Tue, 24 Mar 2015 16:41:58 +1100 Subject: [PATCH 40/46] fix crashes when verifier is running --- qxldod.sln | 61 +++++++++--------- qxldod/BaseObject.cpp | 14 +++-- qxldod/QxlDod.cpp | 143 ++++++++++++++++++++---------------------- qxldod/QxlDod.h | 44 +++++++++---- 4 files changed, 139 insertions(+), 123 deletions(-) diff --git a/qxldod.sln b/qxldod.sln index 494614b..14f4cd6 100755 --- a/qxldod.sln +++ b/qxldod.sln @@ -1,6 +1,7 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qxldod", "qxldod\qxldod.vcxproj", "{A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qxldod Package", "qxldod Package\qxldod Package.vcxproj", "{B8C04B51-4207-491D-A7DD-C54861E8B528}" @@ -10,40 +11,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qxldod Package", "qxldod Pa EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Win8.1 Debug|Win32 = Win8.1 Debug|Win32 - Win8.1 Debug|x64 = Win8.1 Debug|x64 - Win8.1 Release|Win32 = Win8.1 Release|Win32 - Win8.1 Release|x64 = Win8.1 Release|x64 Win8 Debug|Win32 = Win8 Debug|Win32 Win8 Debug|x64 = Win8 Debug|x64 Win8 Release|Win32 = Win8 Release|Win32 Win8 Release|x64 = Win8 Release|x64 + Win8.1 Debug|Win32 = Win8.1 Debug|Win32 + Win8.1 Debug|x64 = Win8.1 Debug|x64 + Win8.1 Release|Win32 = Win8.1 Release|Win32 + Win8.1 Release|x64 = Win8.1 Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|Win32.ActiveCfg = Win8.1 Debug|Win32 - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|Win32.Build.0 = Win8.1 Debug|Win32 - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|Win32.Deploy.0 = Win8.1 Debug|Win32 - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|Win32.ActiveCfg = Win8.1 Release|Win32 - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|Win32.Build.0 = Win8.1 Release|Win32 - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|Win32.Deploy.0 = Win8.1 Release|Win32 - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 - {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 - {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|Win32.ActiveCfg = Win8.1 Debug|Win32 - {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|Win32.Build.0 = Win8.1 Debug|Win32 - {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|Win32.Deploy.0 = Win8.1 Debug|Win32 - {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 - {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 - {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 - {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|Win32.ActiveCfg = Win8.1 Release|Win32 - {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|Win32.Build.0 = Win8.1 Release|Win32 - {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|Win32.Deploy.0 = Win8.1 Release|Win32 - {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 - {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 - {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32 {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32 {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32 @@ -56,6 +33,18 @@ Global {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|x64.Build.0 = Win8 Release|x64 {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|x64.Deploy.0 = Win8 Release|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|Win32.ActiveCfg = Win8.1 Debug|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|Win32.Build.0 = Win8.1 Debug|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|Win32.Deploy.0 = Win8.1 Debug|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|Win32.ActiveCfg = Win8.1 Release|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|Win32.Build.0 = Win8.1 Release|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|Win32.Deploy.0 = Win8.1 Release|Win32 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 + {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32 {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32 {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32 @@ -68,6 +57,18 @@ Global {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|x64.Build.0 = Win8 Release|x64 {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|x64.Deploy.0 = Win8 Release|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|Win32.ActiveCfg = Win8.1 Debug|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|Win32.Build.0 = Win8.1 Debug|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|Win32.Deploy.0 = Win8.1 Debug|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|Win32.ActiveCfg = Win8.1 Release|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|Win32.Build.0 = Win8.1 Release|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|Win32.Deploy.0 = Win8.1 Release|Win32 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 + {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/qxldod/BaseObject.cpp b/qxldod/BaseObject.cpp index da9dfc8..ac270fd 100755 --- a/qxldod/BaseObject.cpp +++ b/qxldod/BaseObject.cpp @@ -18,13 +18,14 @@ void* __cdecl operator new(size_t Size, POOL_TYPE PoolType) void* pObject = ExAllocatePoolWithTag(PoolType, Size, QXLTAG); -#if DBG if (pObject != NULL) { +#if DBG RtlFillMemory(pObject, Size, 0xCD); - } +#else + RtlZeroMemory(pObject, Size); #endif // DBG - + } return pObject; } @@ -39,13 +40,14 @@ void* __cdecl operator new[](size_t Size, POOL_TYPE PoolType) void* pObject = ExAllocatePoolWithTag(PoolType, Size, QXLTAG); -#if DBG if (pObject != NULL) { +#if DBG RtlFillMemory(pObject, Size, 0xCD); - } +#else + RtlZeroMemory(pObject, Size); #endif // DBG - + } return pObject; } diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 09ee73f..193dbeb 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -136,11 +136,18 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, Status = CheckHardware(); if (NT_SUCCESS(Status)) { - m_pHWDevice = new(PagedPool) QxlDevice(this); + m_pHWDevice = new(NonPagedPoolNx) QxlDevice(this); } else { - m_pHWDevice = new(PagedPool) VgaDevice(this); + m_pHWDevice = new(NonPagedPoolNx) VgaDevice(this); + } + + if (!m_pHWDevice) + { + Status = STATUS_NO_MEMORY; + DbgPrint(TRACE_LEVEL_ERROR, ("HWInit failed to allocate memory\n")); + return Status; } Status = m_pHWDevice->HWInit(m_DeviceInfo.TranslatedResourceList, &m_CurrentModes[0].DispInfo); @@ -401,9 +408,7 @@ NTSTATUS QxlDod::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAda } DXGK_DRIVERCAPS* pDriverCaps = (DXGK_DRIVERCAPS*)pQueryAdapterInfo->pOutputData; - - RtlZeroMemory(pDriverCaps, pQueryAdapterInfo->OutputDataSize/*sizeof(DXGK_DRIVERCAPS)*/); - + RtlZeroMemory(pDriverCaps, pQueryAdapterInfo->OutputDataSize/*sizeof(DXGK_DRIVERCAPS)*/); pDriverCaps->WDDMVersion = DXGKDDI_WDDMv1_2; pDriverCaps->HighestAcceptableAddress.QuadPart = -1; @@ -549,7 +554,7 @@ NTSTATUS QxlDod::QueryInterface(_In_ CONST PQUERY_INTERFACE pQueryInterface) DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s Version = %d\n", __FUNCTION__, pQueryInterface->Version)); - return STATUS_NOT_IMPLEMENTED; + return STATUS_NOT_SUPPORTED; } NTSTATUS QxlDod::StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, @@ -2426,7 +2431,23 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) DbgPrint(TRACE_LEVEL_INFORMATION, ("ModeCount %d\n", ModeCount)); m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VIDEO_MODE_INFORMATION) * ModeCount]); + if (!m_ModeInfo) + { + Status = STATUS_NO_MEMORY; + DbgPrint(TRACE_LEVEL_ERROR, ("VgaDevice::GetModeList failed to allocate m_ModeInfo memory\n")); + return Status; + } + RtlZeroMemory(m_ModeInfo, sizeof (VIDEO_MODE_INFORMATION) * ModeCount); + m_ModeNumbers = reinterpret_cast (new (PagedPool) BYTE [sizeof (USHORT) * ModeCount]); + if (!m_ModeNumbers) + { + Status = STATUS_NO_MEMORY; + DbgPrint(TRACE_LEVEL_ERROR, ("VgaDevice::GetModeList failed to allocate m_ModeNumbers memory\n")); + return Status; + } + RtlZeroMemory(m_ModeNumbers, sizeof (USHORT) * ModeCount); + m_CurrentMode = 0; DbgPrint(TRACE_LEVEL_INFORMATION, ("m_ModeInfo = 0x%p, m_ModeNumbers = 0x%p\n", m_ModeInfo, m_ModeNumbers)); if (Width == 0 || Height == 0 || BitsPerPixel != VGA_BPP) @@ -2992,7 +3013,23 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) ModeCount += 2; m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VIDEO_MODE_INFORMATION) * ModeCount]); + if (!m_ModeInfo) + { + Status = STATUS_NO_MEMORY; + DbgPrint(TRACE_LEVEL_ERROR, ("QxlDevice::GetModeList failed to allocate m_ModeInfo memory\n")); + return Status; + } + RtlZeroMemory(m_ModeInfo, sizeof (VIDEO_MODE_INFORMATION) * ModeCount); + m_ModeNumbers = reinterpret_cast (new (PagedPool) BYTE [sizeof (USHORT) * ModeCount]); + if (!m_ModeNumbers) + { + Status = STATUS_NO_MEMORY; + DbgPrint(TRACE_LEVEL_ERROR, ("QxlDevice::GetModeList failed to allocate m_ModeNumbers memory\n")); + return Status; + } + RtlZeroMemory(m_ModeNumbers, sizeof (USHORT) * ModeCount); + m_CurrentMode = 0; UINT Height = pDispInfo->Height; @@ -3423,32 +3460,20 @@ BOOL QxlDevice::CreateRings() void QxlDevice::AsyncIo(UCHAR Port, UCHAR Value) { LARGE_INTEGER timeout; - KeWaitForSingleObject - ( - &m_IoLock, - Executive, - KernelMode, - FALSE, - NULL - ); + BOOLEAN locked = FALSE; + locked = WaitForObject(&m_IoLock, NULL); WRITE_PORT_UCHAR(m_IoBase + Port, Value); timeout.QuadPart = -60000L * 1000 * 10; - WAIT_FOR_EVENT(m_IoCmdEvent, &timeout); - KeReleaseMutex(&m_IoLock,FALSE); + WaitForObject(&m_IoCmdEvent, &timeout); + ReleaseMutex(&m_IoLock, locked); } void QxlDevice::SyncIo(UCHAR Port, UCHAR Value) { - KeWaitForSingleObject - ( - &m_IoLock, - Executive, - KernelMode, - FALSE, - NULL - ); + BOOLEAN locked = FALSE; + locked = WaitForObject(&m_IoLock, NULL); WRITE_PORT_UCHAR(m_IoBase + Port, Value); - KeReleaseMutex(&m_IoLock,FALSE); + ReleaseMutex(&m_IoLock, locked); } UINT8 QxlDevice::SetupMemSlot(UINT8 Idx, UINT64 pastart, UINT64 paend, UINT64 vastart, UINT64 vaend) @@ -3728,7 +3753,7 @@ void QxlDevice::WaitForReleaseRing(void) } timeout.QuadPart = -30 * 1000 * 10; //30ms - WAIT_FOR_EVENT(m_DisplayEvent, &timeout); + WaitForObject(&m_DisplayEvent, &timeout); if (SPICE_RING_IS_EMPTY(m_ReleaseRing)) { SyncIo(QXL_IO_NOTIFY_OOM, 0); @@ -3770,18 +3795,12 @@ void QxlDevice::FlushReleaseRing() void QxlDevice::EmptyReleaseRing() { - KeWaitForSingleObject - ( - &m_MemLock, - Executive, - KernelMode, - FALSE, - NULL - ); + BOOLEAN locked = FALSE; + locked = WaitForObject(&m_MemLock, NULL); while (m_FreeOutputs || !SPICE_RING_IS_EMPTY(m_ReleaseRing)) { FlushReleaseRing(); } - KeReleaseMutex(&m_MemLock,FALSE); + ReleaseMutex(&m_MemLock, locked); } UINT64 QxlDevice::ReleaseOutput(UINT64 output_id) @@ -3806,6 +3825,7 @@ UINT64 QxlDevice::ReleaseOutput(UINT64 output_id) void *QxlDevice::AllocMem(UINT32 mspace_type, size_t size, BOOL force) { PVOID ptr; + BOOLEAN locked = FALSE; ASSERT(m_MSInfo[mspace_type]._mspace); DbgPrint(TRACE_LEVEL_VERBOSE, ("--->%s: %p(%d) size %u\n", __FUNCTION__, @@ -3816,14 +3836,7 @@ void *QxlDevice::AllocMem(UINT32 mspace_type, size_t size, BOOL force) mspace_malloc_stats(m_MSInfo[mspace_type]._mspace); #endif - KeWaitForSingleObject - ( - &m_MemLock, - Executive, - KernelMode, - FALSE, - NULL - ); + locked = WaitForObject(&m_MemLock, NULL); while (1) { /* Release lots of queued resources, before allocating, as we @@ -3849,7 +3862,7 @@ void *QxlDevice::AllocMem(UINT32 mspace_type, size_t size, BOOL force) break; } } - KeReleaseMutex(&m_MemLock,FALSE); + ReleaseMutex(&m_MemLock, locked); ASSERT((!ptr && !force) || (ptr >= m_MSInfo[mspace_type].mspace_start && ptr < m_MSInfo[mspace_type].mspace_end)); @@ -3870,16 +3883,10 @@ void QxlDevice::FreeMem(UINT32 mspace_type, void *ptr) m_MSInfo[mspace_type].mspace_end, mspace_type)); } #endif - KeWaitForSingleObject - ( - &m_MemLock, - Executive, - KernelMode, - FALSE, - NULL - ); + BOOLEAN locked = FALSE; + locked = WaitForObject(&m_MemLock, NULL); mspace_free(m_MSInfo[mspace_type]._mspace, ptr); - KeReleaseMutex(&m_MemLock,FALSE); + ReleaseMutex(&m_MemLock, locked); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -4063,20 +4070,14 @@ void QxlDevice::PushDrawable(QXLDrawable *drawable) { QXLCommand *cmd; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - KeWaitForSingleObject - ( - &m_CmdLock, - Executive, - KernelMode, - FALSE, - NULL - ); + BOOLEAN locked = FALSE; + locked = WaitForObject(&m_CmdLock, NULL); WaitForCmdRing(); cmd = SPICE_RING_PROD_ITEM(m_CommandRing); cmd->type = QXL_CMD_DRAW; cmd->data = PA(drawable, m_MainMemSlot); PushCmd(); - KeReleaseMutex(&m_CmdLock,FALSE); + ReleaseMutex(&m_CmdLock, locked); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -4086,20 +4087,14 @@ void QxlDevice::PushCursorCmd(QXLCursorCmd *cursor_cmd) DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - KeWaitForSingleObject - ( - &m_CrsLock, - Executive, - KernelMode, - FALSE, - NULL - ); + BOOLEAN locked = FALSE; + locked = WaitForObject(&m_CrsLock, NULL); WaitForCursorRing(); cmd = SPICE_RING_PROD_ITEM(m_CursorRing); cmd->type = QXL_CMD_CURSOR; cmd->data = PA(cursor_cmd, m_MainMemSlot); PushCursor(); - KeReleaseMutex(&m_CrsLock,FALSE); + ReleaseMutex(&m_CrsLock, locked); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -4440,7 +4435,7 @@ NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap) if ((xres * yres * bpp / 8) > m_RomHdr->surface0_area_size) { DbgPrint(TRACE_LEVEL_FATAL, ("%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; + return STATUS_INVALID_PARAMETER; } UpdateVideoModeInfo(m_CustomMode, xres, yres, bpp); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); @@ -4458,7 +4453,7 @@ VOID QxlDevice::WaitForCmdRing() if (!wait) { break; } - WAIT_FOR_EVENT(m_DisplayEvent, NULL); + WaitForObject(&m_DisplayEvent, NULL); } DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } @@ -4488,7 +4483,7 @@ VOID QxlDevice::WaitForCursorRing(VOID) LARGE_INTEGER timeout; // 1 => 100 nanoseconds timeout.QuadPart = -1 * (1000 * 1000 * 10); //negative => relative // 1s - WAIT_FOR_EVENT(m_CursorEvent, &timeout); + WaitForObject(&m_CursorEvent, &timeout); if (SPICE_RING_IS_FULL(m_CursorRing)) { DbgPrint(TRACE_LEVEL_ERROR, ("%s: timeout\n", __FUNCTION__)); diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index c00b5cb..1076eec 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -356,20 +356,38 @@ struct Resource { #define TIMEOUT_TO_MS ((LONGLONG) 1 * 10 * 1000) -#define WAIT_FOR_EVENT(event, timeout) do { \ - NTSTATUS status; \ - status = KeWaitForSingleObject ( \ - &event, \ - Executive, \ - KernelMode, \ - FALSE, \ - timeout); \ - ASSERT(NT_SUCCESS(status)); \ -} while (0); +BOOLEAN +FORCEINLINE +WaitForObject( + PVOID Object, + PLARGE_INTEGER Timeout) +{ + NTSTATUS status; + status = KeWaitForSingleObject ( + Object, + Executive, + KernelMode, + FALSE, + Timeout); + ASSERT(NT_SUCCESS(status)); + return (status == STATUS_SUCCESS); +} -#define QXL_SLEEP(msec) do { \ - LARGE_INTEGER timeout; \ - timeout.QuadPart = -msec * TIMEOUT_TO_MS; \ +VOID +FORCEINLINE +ReleaseMutex( + PKMUTEX Mutex, + BOOLEAN locked) +{ + if (locked) + { + KeReleaseMutex(Mutex, FALSE); + } +} + +#define QXL_SLEEP(msec) do { \ + LARGE_INTEGER timeout; \ + timeout.QuadPart = -msec * TIMEOUT_TO_MS; \ KeDelayExecutionThread (KernelMode, FALSE, &timeout);\ } while (0); From 4b168bbbef084510e2b67f4f44c73ea88236933e Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Tue, 24 Mar 2015 17:22:45 +1100 Subject: [PATCH 41/46] trivial cleanups --- qxldod/QxlDod.cpp | 56 ++++++++++++++--------------------------------- qxldod/QxlDod.h | 1 - qxldod/driver.cpp | 3 --- 3 files changed, 16 insertions(+), 44 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 193dbeb..addf884 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -762,7 +762,7 @@ NTSTATUS QxlDod::AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFAC D3DKMDT_VIDPN_TARGET_MODE* pVidPnTargetModeInfo = NULL; NTSTATUS Status = STATUS_SUCCESS; -//FIXME !!!!!! + for (UINT ModeIndex = 0; ModeIndex < m_pHWDevice->GetModeCount(); ++ModeIndex) { PVIDEO_MODE_INFORMATION pModeInfo = m_pHWDevice->GetModeInfo(SourceId); @@ -894,11 +894,11 @@ NTSTATUS QxlDod::AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* pMonitorSourceMode->VideoSignalInfo.HSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED; pMonitorSourceMode->VideoSignalInfo.HSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED; pMonitorSourceMode->VideoSignalInfo.PixelRate = D3DKMDT_FREQUENCY_NOTSPECIFIED; - pMonitorSourceMode->VideoSignalInfo.ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE; //??? + pMonitorSourceMode->VideoSignalInfo.ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE; - pMonitorSourceMode->Origin = D3DKMDT_MCO_DRIVER; // ???? - pMonitorSourceMode->Preference = D3DKMDT_MP_NOTPREFERRED; // TODO... - pMonitorSourceMode->ColorBasis = D3DKMDT_CB_SRGB; // ???? + pMonitorSourceMode->Origin = D3DKMDT_MCO_DRIVER; + pMonitorSourceMode->Preference = D3DKMDT_MP_NOTPREFERRED; + pMonitorSourceMode->ColorBasis = D3DKMDT_CB_SRGB; pMonitorSourceMode->ColorCoeffDynamicRanges.FirstChannel = 8; pMonitorSourceMode->ColorCoeffDynamicRanges.SecondChannel = 8; pMonitorSourceMode->ColorCoeffDynamicRanges.ThirdChannel = 8; @@ -939,7 +939,7 @@ NTSTATUS QxlDod::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODAL CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface = NULL; CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface = NULL; CONST D3DKMDT_VIDPN_PRESENT_PATH* pVidPnPresentPath = NULL; - CONST D3DKMDT_VIDPN_PRESENT_PATH* pVidPnPresentPathTemp = NULL; // Used for AcquireNextPathInfo + CONST D3DKMDT_VIDPN_PRESENT_PATH* pVidPnPresentPathTemp = NULL; CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnPinnedSourceModeInfo = NULL; CONST D3DKMDT_VIDPN_TARGET_MODE* pVidPnPinnedTargetModeInfo = NULL; @@ -1285,7 +1285,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\n", __FUNCTION__)); QXL_ASSERT(pSetVidPnSourceVisibility != NULL); QXL_ASSERT((pSetVidPnSourceVisibility->VidPnSourceId < MAX_VIEWS) || (pSetVidPnSourceVisibility->VidPnSourceId == D3DDDI_ID_ALL)); @@ -1308,7 +1308,7 @@ NTSTATUS QxlDod::SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIB m_CurrentModes[SourceId].Flags.SourceNotVisible = !(pSetVidPnSourceVisibility->Visible); } -// DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -1787,7 +1787,7 @@ VOID QxlDod::SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VO BltBits(&DstBltInfo, &SrcBltInfo, - 1, // NumRects + 1, &Rect); } @@ -1844,7 +1844,6 @@ NTSTATUS QxlDod::RegisterHWInfo(ULONG Id) NTSTATUS Status; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - // TODO: Replace these strings with proper information PCSTR StrHWInfoChipType = "QEMU QXL"; PCSTR StrHWInfoDacType = "QXL 1B36"; PCSTR StrHWInfoAdapterString = "QXL"; @@ -2314,7 +2313,7 @@ BOOL VgaDevice::SetVideoModeInfo(UINT Idx, PVBE_MODEINFO pModeInfo) pMode = &m_ModeInfo[Idx]; pMode->Length = sizeof(VIDEO_MODE_INFORMATION); - pMode->ModeIndex = Idx;//m_ModeNumbers[Idx]; + pMode->ModeIndex = Idx; pMode->VisScreenWidth = pModeInfo->XResolution; pMode->VisScreenHeight = pModeInfo->YResolution; pMode->ScreenStride = pModeInfo->LinBytesPerScanLine; @@ -2361,7 +2360,7 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); NTSTATUS Status = STATUS_SUCCESS; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); -//Get VBE Mode List + Length = 0x400; Status = x86BiosAllocateBuffer (&Length, &m_Segment, &m_Offset); if (!NT_SUCCESS (Status)) @@ -2537,7 +2536,6 @@ NTSTATUS VgaDevice::QueryCurrentMode(PVIDEO_MODE RequestedMode) NTSTATUS Status = STATUS_SUCCESS; UNREFERENCED_PARAMETER(RequestedMode); -// PVBE_MODEINFO VBEMode = &m_ModeInfo[m_CurrentMode]; return Status; } @@ -2674,7 +2672,6 @@ VgaDevice::ExecutePresentDisplayOnly( RtlZeroMemory(ctx,size); -// const CURRENT_BDD_MODE* pModeCur = &m_CurrentModes[0]; ctx->DstAddr = DstAddr; ctx->DstBitPerPixel = DstBitPerPixel; ctx->DstStride = pModeCur->DispInfo.Pitch; @@ -2687,8 +2684,6 @@ VgaDevice::ExecutePresentDisplayOnly( ctx->Moves = Moves; ctx->NumDirtyRects = NumDirtyRects; ctx->DirtyRect = DirtyRect; -// ctx->SourceID = m_SourceId; -// ctx->hAdapter = m_DevExt; ctx->Mdl = NULL; ctx->DisplaySource = this; @@ -2755,10 +2750,6 @@ VgaDevice::ExecutePresentDisplayOnly( ctx->DirtyRect = reinterpret_cast(rects); } - -// HwExecutePresentDisplayOnly((PVOID)ctx); - - // Set up destination blt info BLT_INFO DstBltInfo; DstBltInfo.pBits = ctx->DstAddr; @@ -2794,12 +2785,7 @@ VgaDevice::ExecutePresentDisplayOnly( // Copy all the scroll rects from source image to video frame buffer. for (UINT i = 0; i < ctx->NumMoves; i++) { -// POINT* pSourcePoint = &ctx->Moves[i].SourcePoint; RECT* pDestRect = &ctx->Moves[i].DestRect; - -// DbgPrint(TRACE_LEVEL_FATAL, ("--- %d SourcePoint.x = %ld, SourcePoint.y = %ld, DestRect.bottom = %ld, DestRect.left = %ld, DestRect.right = %ld, DestRect.top = %ld\n", -// i , pSourcePoint->x, pSourcePoint->y, pDestRect->bottom, pDestRect->left, pDestRect->right, pDestRect->top)); - BltBits(&DstBltInfo, &SrcBltInfo, 1, // NumRects @@ -2810,9 +2796,6 @@ VgaDevice::ExecutePresentDisplayOnly( for (UINT i = 0; i < ctx->NumDirtyRects; i++) { RECT* pDirtyRect = &ctx->DirtyRect[i]; -// DbgPrint(TRACE_LEVEL_FATAL, ("--- %d pDirtyRect->bottom = %ld, pDirtyRect->left = %ld, pDirtyRect->right = %ld, pDirtyRect->top = %ld\n", -// i, pDirtyRect->bottom, pDirtyRect->left, pDirtyRect->right, pDirtyRect->top)); - BltBits(&DstBltInfo, &SrcBltInfo, 1, // NumRects @@ -2944,7 +2927,7 @@ BOOL QxlDevice::SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo) pMode = &m_ModeInfo[Idx]; pMode->Length = sizeof(VIDEO_MODE_INFORMATION); - pMode->ModeIndex = Idx;//m_ModeNumbers[Idx]; + pMode->ModeIndex = Idx; pMode->VisScreenWidth = pModeInfo->x_res; pMode->VisScreenHeight = pModeInfo->y_res; pMode->ScreenStride = pModeInfo->stride; @@ -3146,7 +3129,6 @@ NTSTATUS QxlDevice::SetPowerState(_In_ DEVICE_POWER_STATE DevicePowerState, DXGK NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo) { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); -// NTSTATUS Status = STATUS_SUCCESS; PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod->GetDxgkInterrface(); UINT pci_range = QXL_RAM_RANGE_INDEX; for (ULONG i = 0; i < pResList->Count; ++i) @@ -3578,7 +3560,6 @@ QxlDevice::ExecutePresentDisplayOnly( RtlZeroMemory(ctx,size); -// const CURRENT_BDD_MODE* pModeCur = &m_CurrentModes[0]; ctx->DstAddr = DstAddr; ctx->DstBitPerPixel = DstBitPerPixel; ctx->DstStride = pModeCur->DispInfo.Pitch; @@ -3591,8 +3572,6 @@ QxlDevice::ExecutePresentDisplayOnly( ctx->Moves = Moves; ctx->NumDirtyRects = NumDirtyRects; ctx->DirtyRect = DirtyRect; -// ctx->SourceID = m_SourceId; -// ctx->hAdapter = m_DevExt; ctx->Mdl = NULL; ctx->DisplaySource = this; @@ -3702,7 +3681,7 @@ QxlDevice::ExecutePresentDisplayOnly( BltBits(&DstBltInfo, &SrcBltInfo, - 1, // NumRects + 1, pDestRect); } @@ -3715,7 +3694,7 @@ QxlDevice::ExecutePresentDisplayOnly( BltBits(&DstBltInfo, &SrcBltInfo, - 1, // NumRects + 1, pDirtyRect); } @@ -4141,7 +4120,6 @@ VOID QxlDevice::BltBits ( } CONST RECT* pRect = &pRects[0]; -// UpdateArea(pRect, 0); drawable->u.copy.scale_mode = SPICE_IMAGE_SCALE_MODE_NEAREST; drawable->u.copy.mask.bitmap = 0; drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT; @@ -4223,7 +4201,6 @@ VOID QxlDevice::PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, QXLDataChunk *chunk = *chunk_ptr; UINT8 *now = *now_ptr; UINT8 *end = *end_ptr; -// int offset; DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); while (size) { @@ -4315,7 +4292,6 @@ NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPoi QXLCursor *cursor; Resource *res; QXLDataChunk *chunk; -// ULONG unique; UINT8 *src; UINT8 *src_end; UINT8 *now; @@ -4514,9 +4490,9 @@ BOOLEAN QxlDevice::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ m_Pending |= m_RamHdr->int_pending; m_RamHdr->int_pending = 0; - DXGKARGCB_NOTIFY_INTERRUPT_DATA notifyInt;// = {0}; + DXGKARGCB_NOTIFY_INTERRUPT_DATA notifyInt; notifyInt.InterruptType = DXGK_INTERRUPT_DISPLAYONLY_PRESENT_PROGRESS; - notifyInt.DisplayOnlyPresentProgress.VidPnSourceId = 0;//FIXME pPath->VidPnSourceId; + notifyInt.DisplayOnlyPresentProgress.VidPnSourceId = 0; pDxgkInterface->DxgkCbNotifyInterrupt(pDxgkInterface->DeviceHandle,¬ifyInt); if (!pDxgkInterface->DxgkCbQueueDpc(pDxgkInterface->DeviceHandle)) { diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 1076eec..c511f43 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -48,7 +48,6 @@ typedef struct ULONG OemProductNamePtr; ULONG OemProductRevPtr; CHAR Reserved[222]; -// CHAR OemData[256]; } VBE_INFO, *PVBE_INFO; typedef struct diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp index 48bf346..daa3088 100755 --- a/qxldod/driver.cpp +++ b/qxldod/driver.cpp @@ -22,9 +22,6 @@ DriverEntry( DbgPrint(TRACE_LEVEL_FATAL, ("---> KMDOD build on on %s %s\n", __DATE__, __TIME__)); -#ifdef DBG -// KdBreakPoint(); -#endif // Initialize DDI function pointers and dxgkrnl KMDDOD_INITIALIZATION_DATA InitialData = {0}; From 205c4b09efb9d4bb7e76273fe162054c19577b6d Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Tue, 24 Mar 2015 20:11:25 +1100 Subject: [PATCH 42/46] add missing file --- qxldod/include/qxl_windows.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100755 qxldod/include/qxl_windows.h diff --git a/qxldod/include/qxl_windows.h b/qxldod/include/qxl_windows.h new file mode 100755 index 0000000..237ffd8 --- /dev/null +++ b/qxldod/include/qxl_windows.h @@ -0,0 +1,14 @@ +#ifndef _H_QXL_WINDOWS +#define _H_QXL_WINDOWS + +enum { + QXL_ESCAPE_SET_CUSTOM_DISPLAY = 0x10001, +}; + +typedef struct QXLEscapeSetCustomDisplay { + uint32_t xres; + uint32_t yres; + uint32_t bpp; +} QXLEscapeSetCustomDisplay; + +#endif /* _H_QXL_WINDOWS */ From fefcf839d4a24a3039e768bf16192850316bf2ab Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 30 Mar 2015 22:55:33 +1100 Subject: [PATCH 43/46] replace inf with inx file --- qxldod/{qxldod.inf => qxldod.inx} | Bin 4140 -> 4230 bytes qxldod/qxldod.vcxproj | 55 ++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) rename qxldod/{qxldod.inf => qxldod.inx} (60%) diff --git a/qxldod/qxldod.inf b/qxldod/qxldod.inx similarity index 60% rename from qxldod/qxldod.inf rename to qxldod/qxldod.inx index af324eaab23226c8d7100ce947e568a478b878f6..2e0be8337a4737d5689f9ab889f05e76f18bd990 100755 GIT binary patch literal 4230 zcmd6qTTfd@6ovP5rT&K_6i033Pz<5B$PWe^uwoNplU@RqMQlT>0H(H~Nvr<#w%?lV z@wwoWsCkNxIG!`J?`zGT;opCr+Nb?|Zl4jMzZ2WFiQU*co7!)7VZYkk68pl2_9efY zwqZ5fvd4?jHgi22+lb!-I}5UHyGD9_VJ}*3*lU}yK1FKC@ArlE1Ph5t_nhBzd|zT$ zqX{~RJ>zT2>X`Y&u9zK#^%0UY;=RP~J60yhT!zsL`^h@Yj6x=NK|h=6r;mxEJ+U7` z8%VS!N{GXI*twepxoEy3WX}py`;Tx+m0a9C$8CMc@*u z_mp`@PcrAM-V(`tso^pSF)Fi-5YdYeZ8JnWSY|P^0b1Ih&g!VM8FXScC%G&f@i)Y9 zi07*irAJf4pL|xZslD_D^hZQcv1)kM7W|RjGMll!F~fY7XY5C@(KD0P7-QOX^7(wI z&K^sbOs=V-YN?*$J7K!0a+X{5CC{phJ<(uh7w$b+#&WWhS-&Ual}ar-F6#k1@mV}^ zfmPJ{xH_@HhgwF}u8|CqyDTea3ShMRq})($!yip3;~u z^&_+0Uw-XA-c>Mq8;}xO{%nGMzNUFAgK+vqj^rgAz=ViLSsrD!9l8AK zG5hm|Y-1nj!@?dsY=cb;U(dq#A@2@fP1f3hyS+u%?i1G;wVHFAd&;RE$ee_Ut)-s>eQ7HEu1V%Hp>ZkXMwtCAhsBr%8o< zxN1L?)wLW6uWXi&_jxfOI`!;TNUrC&{Qv#u^*x#cu1B2&(XX>e!?>k^QXBL-4RZ~WU}CE7k?M@g%N08F3yuQ zw#b?pHf~|!4SHge?v>fNn%r-Ma5Kd7P3azf-@Y%_C4tEo)Iwe83eSFKzb48tzWr8O z_D(C7k4!g~6hG|_oz>oV+`m?z2J4S3`)GITPI8I-pZt0px{qXSWHlZIPb1{hliPW> zMy2vM^LQgx4^DTNGSv+`b`*KnZ93jv66)>N{T>-_Y~G<(pMf6}LEidm3qnM3>i-Lu zFRSEX$T120`iDUB%zo;Y==oi>sMp}kKgQc?Uw%dx zb;>$x8sk=A%6+{yaW}YQbcnM_ebpP4Q+m57>Xe@csrKs3$~tzc=R2q9F{|fYUZ+SW z6YYon$);{x>T;>S)z!@U+eM=d9y$&4KE0wsK6cJ7$aR9OuzQ6cJ+Y#G5AYkD##zn# WJ-4W*|9t$(>ZP5hC?EZJW&Q)Cnr4## delta 978 zcmb_bL2DC17=6j^rlx6#v z75Tus9;Fu>(EgDA1HA|$=tc0LzL}=lhV&-O%ziuHH*em1^X>Egb#?3auL1`6B+-pR zYgQOV4Hc|l5djp&;Nu~qi)~ekIfa{8V_nJY@UVa?=3f4IZ4F{j^3j~5P=u2C=m%$% zK*Qo%XO8A@nj5q5IL>m;A#dU=a#FJj^2IuNXfNzAfi;;>e7jH9>{ID1aa|tEHO%4; z%7)~UsdA-e_sb{yU>iz^$E+?QE91_2IIO}t#Q6*GP=^IsR4&#T)n{8ZCoXcVxnr6C(ZZ2yU5Vp zNnB^e2uYMM&XJLC&Pt2C*GBn2Q{127@xSe|AH`5MV#j1FHY4Ai-h@YgcW&@=+)b6~ zz#Ls$rSv)id6Y=Y8>=_38|oU(2$}PZzlz4}_B1r!Hi$OM$XF%sVkcy?>uGc5z}<+v zwYo<%Oo=5SbVK;Oc152njFt$zeK}>u0YMf>M1v`|P{8amzp9w$-W~A1l*imI!tx|> zM83vVM;WiW4tH38A)B$Dh$kOyxA{K49+97k2SeL^$NvKv9&m%ohj4|lKDcvdo4<(_ VB}&l_WhB*;mPYbYb0fJG{R3mBwx$38 diff --git a/qxldod/qxldod.vcxproj b/qxldod/qxldod.vcxproj index 0a82ee1..84e7cc3 100755 --- a/qxldod/qxldod.vcxproj +++ b/qxldod/qxldod.vcxproj @@ -55,21 +55,25 @@ WindowsV6.3 true WindowsKernelModeDriver8.1 + 1 Windows8 true WindowsKernelModeDriver8.1 + 1 WindowsV6.3 false WindowsKernelModeDriver8.1 + 1 Windows8 false WindowsKernelModeDriver8.1 + 1 WindowsV6.3 @@ -90,6 +94,7 @@ Windows8 false WindowsKernelModeDriver8.1 + 1 @@ -157,6 +162,11 @@ Inf2Cat /driver:$(OutDir) /os:8_X86,6_3_X86 + + true + + + @@ -173,6 +183,15 @@ Inf2Cat /driver:$(OutDir) /os:8_X86,6_3_X86 + + + + + + + + true + @@ -188,6 +207,11 @@ Inf2Cat /driver:$(OutDir) /os:8_X86,6_3_X86 + + true + + + @@ -203,6 +227,11 @@ Inf2Cat /driver:$(OutDir) /os:8_X86,6_3_X86 + + true + + + @@ -217,6 +246,11 @@ Inf2Cat /driver:$(OutDir) /os:8_X64,Server8_X64,Server6_3_X64,6_3_X64 + + true + + + @@ -231,6 +265,11 @@ Inf2Cat /driver:$(OutDir) /os:8_X64,Server8_X64,Server6_3_X64,6_3_X64 + + true + + + @@ -246,6 +285,11 @@ Inf2Cat /driver:$(OutDir) /os:8_X64,Server8_X64,Server6_3_X64,6_3_X64 + + true + + + @@ -261,10 +305,12 @@ Inf2Cat /driver:$(OutDir) /os:8_X64,Server8_X64,Server6_3_X64,6_3_X64 + + true + + + - - - @@ -284,6 +330,9 @@ + + + From 165b53d48bccae89d0c103ba6503be34896da531 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 30 Mar 2015 22:57:12 +1100 Subject: [PATCH 44/46] fix BSOD when disabling device --- qxldod/QxlDod.cpp | 84 ++++++++++++++++++++++++++--------------------- qxldod/QxlDod.h | 6 ++-- qxldod/driver.cpp | 28 ++++++++-------- qxldod/driver.h | 2 +- 4 files changed, 65 insertions(+), 55 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index addf884..94f2d18 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -64,11 +64,9 @@ QxlDod::QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pP QxlDod::~QxlDod(void) { PAGED_CODE(); - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); CleanUp(); delete m_pHWDevice; m_pHWDevice = NULL; - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } NTSTATUS QxlDod::CheckHardware() @@ -113,8 +111,8 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, _Out_ ULONG* pNumberOfViews, _Out_ ULONG* pNumberOfChildren) { + PHYSICAL_ADDRESS PhysicAddress; PAGED_CODE(); - DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); QXL_ASSERT(pDxgkStartInfo != NULL); QXL_ASSERT(pDxgkInterface != NULL); QXL_ASSERT(pNumberOfViews != NULL); @@ -165,6 +163,7 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, return Status; } + PhysicAddress.QuadPart = m_CurrentModes[0].DispInfo.PhysicAddress.QuadPart; if (m_pHWDevice->GetId() == 0) { Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &(m_CurrentModes[0].DispInfo)); @@ -184,6 +183,10 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, m_CurrentModes[0].DispInfo.Pitch = BPPFromPixelFormat(D3DDDIFMT_R8G8B8) / 8; m_CurrentModes[0].DispInfo.ColorFormat = D3DDDIFMT_R8G8B8; m_CurrentModes[0].DispInfo.TargetId = 0; + if (PhysicAddress.QuadPart != 0L) { + m_CurrentModes[0].DispInfo.PhysicAddress.QuadPart = PhysicAddress.QuadPart; + } + } *pNumberOfViews = MAX_VIEWS; @@ -196,16 +199,13 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, NTSTATUS QxlDod::StopDevice(VOID) { PAGED_CODE(); - DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); m_Flags.DriverStarted = FALSE; - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } VOID QxlDod::CleanUp(VOID) { PAGED_CODE(); - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); for (UINT Source = 0; Source < MAX_VIEWS; ++Source) { if (m_CurrentModes[Source].FrameBuffer.Ptr) @@ -740,7 +740,7 @@ NTSTATUS QxlDod::AddSingleSourceMode(_In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFAC if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET) { - DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%X, hVidPnSourceModeSet = 0x%I64x, pVidPnSourceModeInfo = 0x%I64x", Status, hVidPnSourceModeSet, pVidPnSourceModeInfo)); + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%X, hVidPnSourceModeSet = 0x%I64x, pVidPnSourceModeInfo = %p", Status, hVidPnSourceModeSet, pVidPnSourceModeInfo)); return Status; } } @@ -771,7 +771,7 @@ NTSTATUS QxlDod::AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFAC if (!NT_SUCCESS(Status)) { // If failed to create a new mode info, mode doesn't need to be released since it was never created - DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewModeInfo failed with Status = 0x%I64x, hVidPnTargetModeSet = 0x%I64x", Status, hVidPnTargetModeSet)); + DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewModeInfo failed with Status = 0x%X, hVidPnTargetModeSet = 0x%I64x", Status, hVidPnTargetModeSet)); return Status; } pVidPnTargetModeInfo->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER; @@ -792,7 +792,7 @@ NTSTATUS QxlDod::AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFAC { if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET) { - DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%I64x, hVidPnTargetModeSet = 0x%I64x, pVidPnTargetModeInfo = 0x%I64x", Status, hVidPnTargetModeSet, pVidPnTargetModeInfo)); + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%X, hVidPnTargetModeSet = 0x%I64x, pVidPnTargetModeInfo = %p", Status, hVidPnTargetModeSet, pVidPnTargetModeInfo)); } // If adding the mode failed, release the mode, if this doesn't work there is nothing that can be done, some memory will get leaked @@ -876,7 +876,7 @@ NTSTATUS QxlDod::AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* if (!NT_SUCCESS(Status)) { // If failed to create a new mode info, mode doesn't need to be released since it was never created - DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewModeInfo failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x", Status, pRecommendMonitorModes->hMonitorSourceModeSet)); + DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewModeInfo failed with Status = 0x%X, hMonitorSourceModeSet = 0x%I64x", Status, pRecommendMonitorModes->hMonitorSourceModeSet)); return Status; } @@ -909,7 +909,7 @@ NTSTATUS QxlDod::AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* { if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET) { - DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x, pMonitorSourceMode = 0x%I64x", + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%X, hMonitorSourceModeSet = 0x%I64x, pMonitorSourceMode = 0x%p", Status, pRecommendMonitorModes->hMonitorSourceModeSet, pMonitorSourceMode)); } @@ -1114,7 +1114,7 @@ NTSTATUS QxlDod::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODAL Status = pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pVidPnPinnedTargetModeInfo); if (!NT_SUCCESS(Status)) { - DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleaseModeInfo failed with Status = 0x%X, hVidPnTargetModeSet = 0x%I64x, pVidPnPinnedTargetModeInfo = 0x%I64x", + DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleaseModeInfo failed with Status = 0x%X, hVidPnTargetModeSet = 0x%I64x, pVidPnPinnedTargetModeInfo = %p", Status, hVidPnTargetModeSet, pVidPnPinnedTargetModeInfo)); break; } @@ -1138,7 +1138,7 @@ NTSTATUS QxlDod::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODAL Status = pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hVidPnSourceModeSet, pVidPnPinnedSourceModeInfo); if (!NT_SUCCESS(Status)) { - DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleaseModeInfo failed with Status = 0x%X, hVidPnSourceModeSet = 0x%I64x, pVidPnPinnedSourceModeInfo = 0x%I64x", + DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleaseModeInfo failed with Status = 0x%X, hVidPnSourceModeSet = 0x%I64x, pVidPnPinnedSourceModeInfo = %p", Status, hVidPnSourceModeSet, pVidPnPinnedSourceModeInfo)); break; } @@ -1212,7 +1212,7 @@ NTSTATUS QxlDod::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODAL Status = pVidPnTopologyInterface->pfnAcquireNextPathInfo(hVidPnTopology, pVidPnPresentPathTemp, &pVidPnPresentPath); if (!NT_SUCCESS(Status)) { - DbgPrint(TRACE_LEVEL_ERROR, ("pfnAcquireNextPathInfo failed with Status = 0x%X, hVidPnTopology = 0x%I64x, pVidPnPresentPathTemp = 0x%I64x", Status, hVidPnTopology, pVidPnPresentPathTemp)); + DbgPrint(TRACE_LEVEL_ERROR, ("pfnAcquireNextPathInfo failed with Status = 0x%X, hVidPnTopology = 0x%I64x, pVidPnPresentPathTemp = %p", Status, hVidPnTopology, pVidPnPresentPathTemp)); break; } @@ -1220,7 +1220,7 @@ NTSTATUS QxlDod::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODAL NTSTATUS TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPathTemp); if (!NT_SUCCESS(TempStatus)) { - DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleasePathInfo failed with Status = 0x%X, hVidPnTopology = 0x%I64x, pVidPnPresentPathTemp = 0x%I64x", TempStatus, hVidPnTopology, pVidPnPresentPathTemp)); + DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleasePathInfo failed with Status = 0x%X, hVidPnTopology = 0x%I64x, pVidPnPresentPathTemp = %p", TempStatus, hVidPnTopology, pVidPnPresentPathTemp)); Status = TempStatus; break; } @@ -1463,7 +1463,7 @@ NTSTATUS QxlDod::CommitVidPn(_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn) Status = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPath); if (!NT_SUCCESS(Status)) { - DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleasePathInfo failed with Status = 0x%X, hVidPnTopoogy = 0x%I64x, pVidPnPresentPath = 0x%I64x", + DbgPrint(TRACE_LEVEL_ERROR, ("pfnReleasePathInfo failed with Status = 0x%X, hVidPnTopoogy = 0x%I64x, pVidPnPresentPath = %p", Status, hVidPnTopology, pVidPnPresentPath)); goto CommitVidPnExit; } @@ -1507,7 +1507,6 @@ NTSTATUS QxlDod::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMo CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) { PAGED_CODE(); - DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s SourceId = %d\n", __FUNCTION__, pPath->VidPnSourceId)); NTSTATUS Status = STATUS_SUCCESS; @@ -1543,8 +1542,6 @@ NTSTATUS QxlDod::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMo for (USHORT ModeIndex = 0; ModeIndex < m_pHWDevice->GetModeCount(); ++ModeIndex) { PVIDEO_MODE_INFORMATION pModeInfo = m_pHWDevice->GetModeInfo(ModeIndex); - DbgPrint(TRACE_LEVEL_INFORMATION, ("%d\t%d x %d\t%d x %d\n", ModeIndex, pCurrentBddMode->DispInfo.Width, pCurrentBddMode->DispInfo.Height, - pModeInfo->VisScreenWidth, pModeInfo->VisScreenHeight)); if (pCurrentBddMode->DispInfo.Width == pModeInfo->VisScreenWidth && pCurrentBddMode->DispInfo.Height == pModeInfo->VisScreenHeight ) { @@ -1558,7 +1555,6 @@ NTSTATUS QxlDod::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMo } } - DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); return Status; } @@ -1853,7 +1849,7 @@ NTSTATUS QxlDod::RegisterHWInfo(ULONG Id) Status = IoOpenDeviceRegistryKey(m_pPhysicalDevice, PLUGPLAY_REGKEY_DRIVER, KEY_SET_VALUE, &DevInstRegKeyHandle); if (!NT_SUCCESS(Status)) { - DbgPrint(TRACE_LEVEL_ERROR, ("IoOpenDeviceRegistryKey failed for PDO: 0x%I64x, Status: 0x%I64x", m_pPhysicalDevice, Status)); + DbgPrint(TRACE_LEVEL_ERROR, ("IoOpenDeviceRegistryKey failed for PDO: 0x%I64x, Status: 0x%X", m_pPhysicalDevice, Status)); return Status; } @@ -1957,7 +1953,7 @@ MapFrameBuffer( (Length == 0) || (VirtualAddress == NULL)) { - DbgPrint(TRACE_LEVEL_ERROR, ("One of PhysicalAddress.QuadPart (0x%I64x), Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0", + DbgPrint(TRACE_LEVEL_ERROR, ("One of PhysicalAddress.QuadPart (0x%I64x), Length (%lu), VirtualAddress (%p) is NULL or 0\n", PhysicalAddress.QuadPart, Length, VirtualAddress)); return STATUS_INVALID_PARAMETER; } @@ -1975,7 +1971,7 @@ MapFrameBuffer( MmNonCached); if (*VirtualAddress == NULL) { - DbgPrint(TRACE_LEVEL_ERROR, ("MmMapIoSpace returned a NULL buffer when trying to allocate 0x%I64x bytes", Length)); + DbgPrint(TRACE_LEVEL_ERROR, ("MmMapIoSpace returned a NULL buffer when trying to allocate %lu bytes", Length)); return STATUS_NO_MEMORY; } } @@ -2001,7 +1997,7 @@ UnmapFrameBuffer( } else if ((VirtualAddress == NULL) || (Length == 0)) { - DbgPrint(TRACE_LEVEL_ERROR, ("Only one of Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0", + DbgPrint(TRACE_LEVEL_ERROR, ("Only one of Length (%lu), VirtualAddress (%p) is NULL or 0", Length, VirtualAddress)); return STATUS_INVALID_PARAMETER; } @@ -2297,6 +2293,7 @@ VgaDevice::VgaDevice(_In_ QxlDod* pQxlDod) VgaDevice::~VgaDevice(void) { + HWClose(); delete [] reinterpret_cast(m_ModeInfo); delete [] reinterpret_cast(m_ModeNumbers); m_ModeInfo = NULL; @@ -2429,6 +2426,11 @@ NTSTATUS VgaDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) DbgPrint(TRACE_LEVEL_INFORMATION, ("ModeCount %d\n", ModeCount)); + delete [] reinterpret_cast(m_ModeInfo); + delete [] reinterpret_cast(m_ModeNumbers); + m_ModeInfo = NULL; + m_ModeNumbers = NULL; + m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VIDEO_MODE_INFORMATION) * ModeCount]); if (!m_ModeInfo) { @@ -2911,6 +2913,7 @@ QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod) QxlDevice::~QxlDevice(void) { + HWClose(); delete [] reinterpret_cast(m_ModeInfo); delete [] reinterpret_cast(m_ModeNumbers); m_ModeInfo = NULL; @@ -2992,7 +2995,10 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) return STATUS_UNSUCCESSFUL; } - DbgPrint(TRACE_LEVEL_INFORMATION, ("%s: ModeCount = %d\n", __FUNCTION__, ModeCount)); + delete [] reinterpret_cast(m_ModeInfo); + delete [] reinterpret_cast(m_ModeNumbers); + m_ModeInfo = NULL; + m_ModeNumbers = NULL; ModeCount += 2; m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VIDEO_MODE_INFORMATION) * ModeCount]); @@ -3088,7 +3094,7 @@ NTSTATUS QxlDevice::QueryCurrentMode(PVIDEO_MODE RequestedMode) NTSTATUS QxlDevice::SetCurrentMode(ULONG Mode) { - DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s Mode = %x\n", __FUNCTION__, Mode)); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s Mode = %x\n", __FUNCTION__, Mode)); for (ULONG idx = 0; idx < GetModeCount(); idx++) { if (Mode == m_ModeNumbers[idx]) @@ -3144,7 +3150,7 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* PVOID IoBase = NULL; ULONG IoLength = pResDescriptor->u.Port.Length; NTSTATUS Status = STATUS_SUCCESS; - DbgPrint(TRACE_LEVEL_INFORMATION, ("IO Port Info [%08I64X-%08I64X]\n", + DbgPrint(TRACE_LEVEL_VERBOSE, ("IO Port Info [%08I64X-%08I64X]\n", pResDescriptor->u.Port.Start.QuadPart, pResDescriptor->u.Port.Start.QuadPart + pResDescriptor->u.Port.Length)); @@ -3166,7 +3172,7 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* } else { - DbgPrint(TRACE_LEVEL_INFORMATION, ("DxgkCbMapMemor failed with status 0x%X\n", Status)); + DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbMapMemor (CmResourceTypePort) failed with status 0x%X\n", Status)); } } else @@ -3174,7 +3180,7 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* m_IoBase = (PUCHAR)(ULONG_PTR)pResDescriptor->u.Port.Start.QuadPart; m_IoSize = pResDescriptor->u.Port.Length; } - DbgPrint(TRACE_LEVEL_INFORMATION, ("io_base [%X-%X]\n", + DbgPrint(TRACE_LEVEL_VERBOSE, ("io_base [%X-%X]\n", m_IoBase, m_IoBase + m_IoSize)); @@ -3190,7 +3196,7 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* PVOID MemBase = NULL; ULONG MemLength = pResDescriptor->u.Memory.Length; NTSTATUS Status = STATUS_SUCCESS; - DbgPrint( TRACE_LEVEL_INFORMATION, ("Memory mapped: (%x:%x) Length:(%x)\n", + DbgPrint( TRACE_LEVEL_VERBOSE, ("Memory mapped: (%x:%x) Length:(%x)\n", pResDescriptor->u.Memory.Start.LowPart, pResDescriptor->u.Memory.Start.HighPart, pResDescriptor->u.Memory.Length)); @@ -3230,6 +3236,11 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* break; } } + else + { + DbgPrint(TRACE_LEVEL_INFORMATION, ("DxgkCbMapMemor (CmResourceTypeMemory) failed with status 0x%X\n", Status)); + } + } break; case CmResourceTypeDma: @@ -3255,6 +3266,7 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* m_RamHdr->magic != QXL_RAM_MAGIC) { UnmapMemory(); + DbgPrint(TRACE_LEVEL_ERROR, ("%s failed asslocateing HW resources\n", __FUNCTION__)); return STATUS_UNSUCCESSFUL; } @@ -3273,6 +3285,7 @@ NTSTATUS QxlDevice::QxlInit(DXGK_DISPLAY_INFORMATION* pDispInfo) if (!InitMemSlots()) { DestroyMemSlots(); + DbgPrint(TRACE_LEVEL_ERROR, ("%s failed init mem slots\n", __FUNCTION__)); return STATUS_UNSUCCESSFUL; } @@ -4238,8 +4251,6 @@ VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) QXLDrawable *drawable; RECT Rect; PAGED_CODE(); - - DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); if (pCurrentBddMod->Flags.FrameBufferIsActive) { Rect.bottom = pCurrentBddMod->SrcModeHeight; @@ -4260,15 +4271,12 @@ VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) drawable->u.fill.mask.bitmap = 0; PushDrawable(drawable); } - DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); } NTSTATUS QxlDevice::HWClose(void) { - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); QxlClose(); UnmapMemory(); - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -4386,7 +4394,7 @@ NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap) UINT bpp; if (pEscap->PrivateDriverDataSize != sizeof(QXLEscapeSetCustomDisplay)) { - DbgPrint(TRACE_LEVEL_FATAL, ("<--> %s Incorrect buffer size %d instead of %d\n", __FUNCTION__, 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; @@ -4399,7 +4407,7 @@ NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap) } if (xres < MIN_WIDTH_SIZE || yres < MIN_HEIGHT_SIZE) { - DbgPrint(TRACE_LEVEL_FATAL, ("%s: xres = %d, yres = %d\n", __FUNCTION__, xres, yres)); + DbgPrint(TRACE_LEVEL_ERROR, ("%s: xres = %d, yres = %d\n", __FUNCTION__, xres, yres)); return ERROR_INVALID_DATA; } @@ -4409,7 +4417,7 @@ NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap) m_CustomMode = (USHORT)(m_ModeCount - 1); if ((xres * yres * bpp / 8) > m_RomHdr->surface0_area_size) { - DbgPrint(TRACE_LEVEL_FATAL, ("%s: Mode (%dx%d#%d) doesn't fit in memory (%d)\n", + 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; } diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index c511f43..eb9bea7 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -214,6 +214,8 @@ class QxlDod; class HwDeviceIntrface { public: +// HwDeviceIntrface(_In_ QxlDod* pQxlDod) {;} + virtual ~HwDeviceIntrface() {;} virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0; virtual NTSTATUS SetCurrentMode(ULONG Mode) = 0; virtual NTSTATUS GetCurrentMode(ULONG* Mode) = 0; @@ -264,7 +266,7 @@ class VgaDevice : { public: VgaDevice(_In_ QxlDod* pQxlDod); - virtual ~VgaDevice(void); + ~VgaDevice(void); NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); NTSTATUS SetCurrentMode(ULONG Mode); NTSTATUS GetCurrentMode(ULONG* Mode); @@ -437,7 +439,7 @@ class QxlDevice : { public: QxlDevice(_In_ QxlDod* pQxlDod); - virtual ~QxlDevice(void); + ~QxlDevice(void); NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); NTSTATUS SetCurrentMode(ULONG Mode); NTSTATUS GetCurrentMode(ULONG* Mode); diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp index daa3088..4d1913c 100755 --- a/qxldod/driver.cpp +++ b/qxldod/driver.cpp @@ -249,7 +249,7 @@ DodQueryDeviceDescriptor( // The first call queues a worker thread item indicating that it now has a child device, the second queues a worker thread // item that it no longer has any child device. This function gets called based on the first worker thread item, but after // the driver has been stopped. Therefore instead of asserting like other functions, we only warn. - DbgPrint(TRACE_LEVEL_WARNING, ("QXL (0x%I64x) is being called when not active!", pQxl)); + DbgPrint(TRACE_LEVEL_WARNING, ("QXL (%p) is being called when not active!", pQxl)); return STATUS_UNSUCCESSFUL; } return pQxl->QueryDeviceDescriptor(ChildUid, pDeviceDescriptor); @@ -287,7 +287,7 @@ DodSetPointerPosition( QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) { - QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl); return STATUS_UNSUCCESSFUL; } return pQxl->SetPointerPosition(pSetPointerPosition); @@ -306,7 +306,7 @@ DodSetPointerShape( QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) { - QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl); return STATUS_UNSUCCESSFUL; } return pQxl->SetPointerShape(pSetPointerShape); @@ -354,7 +354,7 @@ DodPresentDisplayOnly( QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) { - QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl); return STATUS_UNSUCCESSFUL; } return pQxl->PresentDisplayOnly(pPresentDisplayOnly); @@ -391,7 +391,7 @@ DodIsSupportedVidPn( // This path might hit because win32k/dxgport doesn't check that an adapter is active when taking the adapter lock. // The adapter lock is the main thing QXL Fallback relies on to not be called while it's inactive. It is still a rare // timing issue around PnpStart/Stop and isn't expected to have any effect on the stability of the system. - DbgPrint(TRACE_LEVEL_WARNING, ("QXL (0x%I64x) is being called when not active!", pQxl)); + DbgPrint(TRACE_LEVEL_WARNING, ("QXL (%p) is being called when not active!", pQxl)); return STATUS_UNSUCCESSFUL; } return pQxl->IsSupportedVidPn(pIsSupportedVidPn); @@ -410,7 +410,7 @@ DodRecommendFunctionalVidPn( QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) { - QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl); return STATUS_UNSUCCESSFUL; } return pQxl->RecommendFunctionalVidPn(pRecommendFunctionalVidPn); @@ -429,7 +429,7 @@ DodRecommendVidPnTopology( QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) { - QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl); return STATUS_UNSUCCESSFUL; } return pQxl->RecommendVidPnTopology(pRecommendVidPnTopology); @@ -448,7 +448,7 @@ DodRecommendMonitorModes( QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) { - QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl); return STATUS_UNSUCCESSFUL; } return pQxl->RecommendMonitorModes(pRecommendMonitorModes); @@ -467,7 +467,7 @@ DodEnumVidPnCofuncModality( QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) { - QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl); return STATUS_UNSUCCESSFUL; } return pQxl->EnumVidPnCofuncModality(pEnumCofuncModality); @@ -486,7 +486,7 @@ DodSetVidPnSourceVisibility( QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) { - QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl); return STATUS_UNSUCCESSFUL; } return pQxl->SetVidPnSourceVisibility(pSetVidPnSourceVisibility); @@ -505,7 +505,7 @@ DodCommitVidPn( QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) { - QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl); return STATUS_UNSUCCESSFUL; } return pQxl->CommitVidPn(pCommitVidPn); @@ -524,7 +524,7 @@ DodUpdateActiveVidPnPresentPath( QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) { - QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl); return STATUS_UNSUCCESSFUL; } return pQxl->UpdateActiveVidPnPresentPath(pUpdateActiveVidPnPresentPath); @@ -543,7 +543,7 @@ DodQueryVidPnHWCapability( QxlDod* pQxl = reinterpret_cast(hAdapter); if (!pQxl->IsDriverActive()) { - QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl); return STATUS_UNSUCCESSFUL; } return pQxl->QueryVidPnHWCapability(pVidPnHWCaps); @@ -566,7 +566,7 @@ DodDpcRoutine( QxlDod* pQxl = reinterpret_cast(pDeviceContext); if (!pQxl->IsDriverActive()) { - QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl); + QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl); return; } pQxl->DpcRoutine(); diff --git a/qxldod/driver.h b/qxldod/driver.h index 72a8b46..75b11c3 100755 --- a/qxldod/driver.h +++ b/qxldod/driver.h @@ -207,7 +207,7 @@ DodSystemDisplayWrite( _In_ UINT PositionX, _In_ UINT PositionY); - +#define DBG 1 #if DBG From 7887cc20416e5b1e00706e124ccfd120991e0754 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 30 Mar 2015 22:59:54 +1100 Subject: [PATCH 45/46] disable dbg printout --- qxldod/driver.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/qxldod/driver.h b/qxldod/driver.h index 75b11c3..e64c098 100755 --- a/qxldod/driver.h +++ b/qxldod/driver.h @@ -207,8 +207,6 @@ DodSystemDisplayWrite( _In_ UINT PositionX, _In_ UINT PositionY); -#define DBG 1 - #if DBG extern int nDebugLevel; From e5bf7c5246d3627e21b070b3c1d0fcb92785bbeb Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Fri, 10 Apr 2015 12:23:48 +1000 Subject: [PATCH 46/46] cosmetic changes in inx file --- qxldod/qxldod.inx | Bin 4230 -> 3784 bytes qxldod/qxldod.vcxproj.filters | 116 +++++++++++++++++----------------- 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/qxldod/qxldod.inx b/qxldod/qxldod.inx index 2e0be8337a4737d5689f9ab889f05e76f18bd990..0c154979a1d52e519b51795132e5cc31a428fba3 100755 GIT binary patch delta 136 zcmZouJR!^U|KG$lMvOWW@5*nsVv=HHG@TsEJah6n7O}|_SbF@U8JrpN8S)rP7>a;& z4ucyICo-fn6f?v!@G@{QSTndXR4^n1MN1h{7*c`qAa%J6!9aEn5GMn5Dlpgru@*@E bh+oo9m|DQF(076|NEazq50;&R$6Pb)An#t8eIMxgb42}#*48;s33`Goy49P&+ z3aktvuK-k|z~IS{$B+i3(-<-tau`y*uLvlc3KUmh$Ysc9NCC^I096(< z6aYmN87hG?`9L)}U{)YQL_LEKP$&hcF_WPTYyiTAbO}ldEZOKU&&X&zIiGRnB<8ls zVN5cU<(PUlw=r*GWYuHvV+fgS&Z;fz2J}=SFf>bnUQA^O28Jvsv{D&t8Qd5wH^;JO Ga{>UlHB^QG diff --git a/qxldod/qxldod.vcxproj.filters b/qxldod/qxldod.vcxproj.filters index 4b444ed..1ba05af 100755 --- a/qxldod/qxldod.vcxproj.filters +++ b/qxldod/qxldod.vcxproj.filters @@ -1,59 +1,59 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {8E41214B-6785-4CFE-B992-037D68949A14} - inf;inv;inx;mof;mc; - - - - - Driver Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Resource Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {8E41214B-6785-4CFE-B992-037D68949A14} + inf;inv;inx;mof;mc; + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + + + Driver Files + + \ No newline at end of file