summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Rozenfeld <vrozenfe@redhat.com>2013-12-30 23:02:44 +1100
committerVadim Rozenfeld <vrozenfe@redhat.com>2013-12-30 23:02:44 +1100
commit10be00160db5ec6205b00b46f45a8e36d00ff6ec (patch)
tree7f21c9ae3d6e9fd99792aac633e728398038ea8b
parent52500420a892ac10f0f187fdf7c612df69cdee49 (diff)
add resolutions and PM support
-rwxr-xr-xqxldod/QxlDod.cpp1907
-rwxr-xr-xqxldod/QxlDod.h206
-rwxr-xr-xqxldod/driver.cpp66
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;
- }
- else if ((ActionType >= PowerActionShutdown) &&
- (ActionType < PowerActionWarmEject) &&
- (DevicePowerState > PowerDeviceD0))
- {
- ActionType = PowerActionShutdown;
+ // There is nothing to do to specifically power up/down the display adapter
+ return STATUS_SUCCESS;
}
-
- 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<BYTE*>(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();
@@ -468,23 +661,143 @@ 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;
+ }
+
+ // 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;
+ }
-//FIXME
-
- pVidPnPresentPathTemp = NULL; // Successfully released it
+ // ...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;
+ }
+
+ // 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:
-//FIXME
+ 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<DoPresentMemory*>
+ (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<KPROCESSOR_MODE>(( 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<BYTE*>
+ (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<BYTE*>(ctx+1);
+
+ // copy moves and update pointer
+ if (Moves)
+ {
+ memcpy(rects,Moves,sizeMoves);
+ ctx->Moves = reinterpret_cast<D3DKMT_MOVE_RECT*>(rects);
+ rects += sizeMoves;
+ }
+
+ // copy dirty rects and update pointer
+ if (DirtyRect)
+ {
+ memcpy(rects,DirtyRect,sizeRects);
+ ctx->DirtyRect = reinterpret_cast<RECT*>(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<BYTE*>(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<PVBE_MODEINFO> (new (PagedPool) BYTE[sizeof (VBE_MODEINFO) * ModeCount]);
+ m_ModeInfo = reinterpret_cast<PVBE_MODEINFO> (new (PagedPool) BYTE[sizeof (VBE_MODEINFO) * ModeCount]);
m_ModeNumbers = reinterpret_cast<PUSHORT> (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(&regs, sizeof(regs));
- regs.Eax = 0x4F01;
- regs.Ecx = ModeTemp;
- regs.Edi = m_Offset + sizeof (VbeInfo);
- regs.SegEs = m_Segment;
+ RtlZeroMemory(&regs, sizeof(regs));
+ regs.Eax = 0x4F01;
+ regs.Ecx = ModeTemp;
+ regs.Edi = m_Offset + sizeof (VbeInfo);
+ regs.SegEs = m_Segment;
if (!x86BiosCall (0x10, &regs))
{
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, &regs))
{
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 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, &regs))
+ {
+ 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)
+{
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, &regs))
{
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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(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<QxlDod*>(pDeviceContext);
return pQxl->SystemDisplayEnable(TargetId, Flags, Width, Height, ColorFormat);