qxl-wddm-dod/qxldod/driver.cpp

788 lines
25 KiB
C++
Raw Normal View History

/*
* Copyright 2013-2016 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*/
2013-12-09 11:55:42 +01:00
#include "driver.h"
#include "QxlDod.h"
#pragma code_seg(push)
#pragma code_seg("INIT")
// BEGIN: Init Code
//
// Driver Entry point
//
int nDebugLevel = TRACE_LEVEL_ERROR;
2013-12-09 11:55:42 +01:00
// registry-based configuration is intended to be manual only
// for VSync suppression during support and troubleshooting
// and not expected to be made default
static void QueryVSyncSetting(BOOLEAN& b, const UNICODE_STRING *path)
{
PAGED_CODE();
WCHAR buffer[MAX_PATH];
ULONG val = b;
RTL_QUERY_REGISTRY_TABLE QueryTable[3] = {};
if (path->Length >= sizeof(buffer))
return;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
QueryTable[0].Name = L"Parameters";
QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[1].Name = L"EnableVSync";
QueryTable[1].DefaultType = REG_DWORD << 24;
QueryTable[1].EntryContext = &val;
RtlCopyMemory(buffer, path->Buffer, path->Length);
buffer[path->Length/2] = 0;
NTSTATUS status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, buffer, QueryTable, NULL, NULL);
if (NT_SUCCESS(status))
{
DbgPrint(TRACE_LEVEL_INFORMATION, ("%s: val = %d\n", __FUNCTION__, val));
b = !!val;
}
else
{
DbgPrint(TRACE_LEVEL_INFORMATION, ("%s: status = %X\n", __FUNCTION__, status));
}
}
2013-12-09 11:55:42 +01:00
extern "C"
NTSTATUS
DriverEntry(
_In_ DRIVER_OBJECT* pDriverObject,
_In_ UNICODE_STRING* pRegistryPath)
{
PAGED_CODE();
2014-06-05 14:27:10 +02:00
DbgPrint(TRACE_LEVEL_FATAL, ("---> KMDOD build on on %s %s\n", __DATE__, __TIME__));
2013-12-09 11:55:42 +01:00
RTL_OSVERSIONINFOW versionInfo;
versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
RtlGetVersion(&versionInfo);
// VSync control is NOT planned to be enabled on Win10 builds
// before RS1. Enabling it on DOD driver causes OS to stop the driver
// with error 43 when the system turns off display due to idle setting.
// On Windows 8.1 (9200 and 9600) till now no problem observed
// (OS does not send VSync enable command)
// On Windows 10RS1 (14393) enabling VSync control activates
// watchdog policy and creates high sensitivity to long (> 2 sec)
// processing in PresentDisplayOnly callback (stop with error 43)
if (versionInfo.dwBuildNumber >= 14393 || versionInfo.dwBuildNumber <= 9600)
{
// we will uncomment the line below after we address all the problems
// related to enabled VSync control in Win10RS1
//g_bSupportVSync = TRUE;
// for support/troubleshooting be able to disable VSync on specific machine
QueryVSyncSetting(g_bSupportVSync, pRegistryPath);
}
DbgPrint(TRACE_LEVEL_WARNING, ("VSync support %sabled for %d.%d.%d\n",
g_bSupportVSync ? "en" : "dis",
versionInfo.dwMajorVersion, versionInfo.dwMinorVersion, versionInfo.dwBuildNumber));
2013-12-09 11:55:42 +01:00
// Initialize DDI function pointers and dxgkrnl
KMDDOD_INITIALIZATION_DATA InitialData = {0};
2015-02-08 11:04:39 +01:00
InitialData.Version = DXGKDDI_INTERFACE_VERSION;
2013-12-09 11:55:42 +01:00
InitialData.DxgkDdiAddDevice = DodAddDevice;
InitialData.DxgkDdiStartDevice = DodStartDevice;
InitialData.DxgkDdiStopDevice = DodStopDevice;
InitialData.DxgkDdiResetDevice = DodResetDevice;
InitialData.DxgkDdiRemoveDevice = DodRemoveDevice;
InitialData.DxgkDdiDispatchIoRequest = DodDispatchIoRequest;
InitialData.DxgkDdiInterruptRoutine = DodInterruptRoutine;
InitialData.DxgkDdiDpcRoutine = DodDpcRoutine;
InitialData.DxgkDdiQueryChildRelations = DodQueryChildRelations;
InitialData.DxgkDdiQueryChildStatus = DodQueryChildStatus;
InitialData.DxgkDdiQueryDeviceDescriptor = DodQueryDeviceDescriptor;
InitialData.DxgkDdiSetPowerState = DodSetPowerState;
InitialData.DxgkDdiUnload = DodUnload;
InitialData.DxgkDdiQueryInterface = DodQueryInterface;
InitialData.DxgkDdiQueryAdapterInfo = DodQueryAdapterInfo;
InitialData.DxgkDdiSetPointerPosition = DodSetPointerPosition;
InitialData.DxgkDdiSetPointerShape = DodSetPointerShape;
InitialData.DxgkDdiEscape = DodEscape;
InitialData.DxgkDdiIsSupportedVidPn = DodIsSupportedVidPn;
InitialData.DxgkDdiRecommendFunctionalVidPn = DodRecommendFunctionalVidPn;
InitialData.DxgkDdiEnumVidPnCofuncModality = DodEnumVidPnCofuncModality;
InitialData.DxgkDdiSetVidPnSourceVisibility = DodSetVidPnSourceVisibility;
InitialData.DxgkDdiCommitVidPn = DodCommitVidPn;
InitialData.DxgkDdiUpdateActiveVidPnPresentPath = DodUpdateActiveVidPnPresentPath;
InitialData.DxgkDdiRecommendMonitorModes = DodRecommendMonitorModes;
InitialData.DxgkDdiQueryVidPnHWCapability = DodQueryVidPnHWCapability;
InitialData.DxgkDdiPresentDisplayOnly = DodPresentDisplayOnly;
InitialData.DxgkDdiStopDeviceAndReleasePostDisplayOwnership = DodStopDeviceAndReleasePostDisplayOwnership;
InitialData.DxgkDdiSystemDisplayEnable = DodSystemDisplayEnable;
InitialData.DxgkDdiSystemDisplayWrite = DodSystemDisplayWrite;
if (g_bSupportVSync)
{
InitialData.DxgkDdiControlInterrupt = DodControlInterrupt;
InitialData.DxgkDdiGetScanLine = DodGetScanLine;
}
2013-12-09 11:55:42 +01:00
NTSTATUS Status = DxgkInitializeDisplayOnlyDriver(pDriverObject, pRegistryPath, &InitialData);
if (!NT_SUCCESS(Status))
{
DbgPrint(TRACE_LEVEL_ERROR, ("DxgkInitializeDisplayOnlyDriver failed with Status: 0x%X\n", Status));
}
DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__));
return Status;
}
// END: Init Code
#pragma code_seg(pop)
#pragma code_seg(push)
#pragma code_seg("PAGE")
//
// PnP DDIs
//
VOID
DodUnload(VOID)
{
PAGED_CODE();
DbgPrint(TRACE_LEVEL_INFORMATION, ("<--> %s\n", __FUNCTION__));
}
NTSTATUS
DodAddDevice(
_In_ DEVICE_OBJECT* pPhysicalDeviceObject,
_Outptr_ PVOID* ppDeviceContext)
{
PAGED_CODE();
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
if ((pPhysicalDeviceObject == NULL) ||
(ppDeviceContext == NULL))
{
DbgPrint(TRACE_LEVEL_ERROR, ("One of pPhysicalDeviceObject (0x%I64x), ppDeviceContext (0x%I64x) is NULL",
pPhysicalDeviceObject, ppDeviceContext));
return STATUS_INVALID_PARAMETER;
}
*ppDeviceContext = NULL;
QxlDod* pQxl = new(NonPagedPoolNx) QxlDod(pPhysicalDeviceObject);
if (pQxl == NULL)
{
DbgPrint(TRACE_LEVEL_ERROR, ("pQxl failed to be allocated"));
return STATUS_NO_MEMORY;
}
*ppDeviceContext = pQxl;
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
return STATUS_SUCCESS;
}
NTSTATUS
DodRemoveDevice(
_In_ VOID* pDeviceContext)
{
PAGED_CODE();
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
delete pQxl;
2013-12-09 11:55:42 +01:00
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
return STATUS_SUCCESS;
}
NTSTATUS
DodStartDevice(
_In_ VOID* pDeviceContext,
_In_ DXGK_START_INFO* pDxgkStartInfo,
_In_ DXGKRNL_INTERFACE* pDxgkInterface,
_Out_ ULONG* pNumberOfViews,
_Out_ ULONG* pNumberOfChildren)
{
PAGED_CODE();
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
return pQxl->StartDevice(pDxgkStartInfo, pDxgkInterface, pNumberOfViews, pNumberOfChildren);
}
NTSTATUS
DodStopDevice(
_In_ VOID* pDeviceContext)
{
PAGED_CODE();
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
return pQxl->StopDevice();
}
NTSTATUS
DodDispatchIoRequest(
_In_ VOID* pDeviceContext,
_In_ ULONG VidPnSourceId,
_In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket)
{
PAGED_CODE();
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
if (!pQxl->IsDriverActive())
{
QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
return STATUS_UNSUCCESSFUL;
}
return pQxl->DispatchIoRequest(VidPnSourceId, pVideoRequestPacket);
}
NTSTATUS
DodSetPowerState(
_In_ VOID* pDeviceContext,
_In_ ULONG HardwareUid,
_In_ DEVICE_POWER_STATE DevicePowerState,
_In_ POWER_ACTION ActionType)
{
PAGED_CODE();
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
if (!pQxl->IsDriverActive())
{
// If the driver isn't active, SetPowerState can still be called, however in QXL's case
// this shouldn't do anything, as it could for instance be called on QXL Fallback after
// Fallback has been stopped and QXL PnP is being started. Fallback doesn't have control
// of the hardware in this case.
return STATUS_SUCCESS;
}
return pQxl->SetPowerState(HardwareUid, DevicePowerState, ActionType);
}
NTSTATUS
DodQueryChildRelations(
_In_ VOID* pDeviceContext,
_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
_In_ ULONG ChildRelationsSize)
{
PAGED_CODE();
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
return pQxl->QueryChildRelations(pChildRelations, ChildRelationsSize);
}
NTSTATUS
DodQueryChildStatus(
_In_ VOID* pDeviceContext,
_Inout_ DXGK_CHILD_STATUS* pChildStatus,
_In_ BOOLEAN NonDestructiveOnly)
{
PAGED_CODE();
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
return pQxl->QueryChildStatus(pChildStatus, NonDestructiveOnly);
}
NTSTATUS
DodQueryDeviceDescriptor(
_In_ VOID* pDeviceContext,
_In_ ULONG ChildUid,
_Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor)
{
PAGED_CODE();
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
if (!pQxl->IsDriverActive())
{
// During stress testing of PnPStop, it is possible for QXL Fallback to get called to start then stop in quick succession.
// The first call queues a worker thread item indicating that it now has a child device, the second queues a worker thread
// item that it no longer has any child device. This function gets called based on the first worker thread item, but after
// the driver has been stopped. Therefore instead of asserting like other functions, we only warn.
2015-03-30 13:57:12 +02:00
DbgPrint(TRACE_LEVEL_WARNING, ("QXL (%p) is being called when not active!", pQxl));
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->QueryDeviceDescriptor(ChildUid, pDeviceDescriptor);
}
//
// WDDM Display Only Driver DDIs
//
NTSTATUS
APIENTRY
DodQueryAdapterInfo(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
return pQxl->QueryAdapterInfo(pQueryAdapterInfo);
}
NTSTATUS
APIENTRY
DodSetPointerPosition(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (!pQxl->IsDriverActive())
{
2015-03-30 13:57:12 +02:00
QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl);
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->SetPointerPosition(pSetPointerPosition);
}
NTSTATUS
APIENTRY
DodSetPointerShape(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (!pQxl->IsDriverActive())
{
2015-03-30 13:57:12 +02:00
QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl);
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->SetPointerShape(pSetPointerShape);
}
NTSTATUS
APIENTRY
DodEscape(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_ESCAPE* pEscape
)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
return pQxl->Escape(pEscape);
}
NTSTATUS
DodQueryInterface(
_In_ CONST PVOID pDeviceContext,
_In_ CONST PQUERY_INTERFACE QueryInterface
)
{
PAGED_CODE();
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
return pQxl->QueryInterface(QueryInterface);
}
NTSTATUS
APIENTRY
DodPresentDisplayOnly(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (!pQxl->IsDriverActive())
{
2015-03-30 13:57:12 +02:00
QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl);
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->PresentDisplayOnly(pPresentDisplayOnly);
}
NTSTATUS
APIENTRY
DodStopDeviceAndReleasePostDisplayOwnership(
_In_ VOID* pDeviceContext,
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
_Out_ DXGK_DISPLAY_INFORMATION* DisplayInfo)
{
PAGED_CODE();
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
return pQxl->StopDeviceAndReleasePostDisplayOwnership(TargetId, DisplayInfo);
}
NTSTATUS
APIENTRY
DodIsSupportedVidPn(
_In_ CONST HANDLE hAdapter,
_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (!pQxl->IsDriverActive())
{
// This path might hit because win32k/dxgport doesn't check that an adapter is active when taking the adapter lock.
// The adapter lock is the main thing QXL Fallback relies on to not be called while it's inactive. It is still a rare
// timing issue around PnpStart/Stop and isn't expected to have any effect on the stability of the system.
2015-03-30 13:57:12 +02:00
DbgPrint(TRACE_LEVEL_WARNING, ("QXL (%p) is being called when not active!", pQxl));
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->IsSupportedVidPn(pIsSupportedVidPn);
}
NTSTATUS
APIENTRY
DodRecommendFunctionalVidPn(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (!pQxl->IsDriverActive())
{
2015-03-30 13:57:12 +02:00
QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl);
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->RecommendFunctionalVidPn(pRecommendFunctionalVidPn);
}
NTSTATUS
APIENTRY
DodRecommendVidPnTopology(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (!pQxl->IsDriverActive())
{
2015-03-30 13:57:12 +02:00
QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl);
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->RecommendVidPnTopology(pRecommendVidPnTopology);
}
NTSTATUS
APIENTRY
DodRecommendMonitorModes(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (!pQxl->IsDriverActive())
{
2015-03-30 13:57:12 +02:00
QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl);
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->RecommendMonitorModes(pRecommendMonitorModes);
}
NTSTATUS
APIENTRY
DodEnumVidPnCofuncModality(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2015-02-18 10:57:00 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (!pQxl->IsDriverActive())
{
2015-03-30 13:57:12 +02:00
QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl);
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->EnumVidPnCofuncModality(pEnumCofuncModality);
}
NTSTATUS
APIENTRY
DodSetVidPnSourceVisibility(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (!pQxl->IsDriverActive())
{
2015-03-30 13:57:12 +02:00
QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl);
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->SetVidPnSourceVisibility(pSetVidPnSourceVisibility);
}
NTSTATUS
APIENTRY
DodCommitVidPn(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (!pQxl->IsDriverActive())
{
2015-03-30 13:57:12 +02:00
QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl);
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->CommitVidPn(pCommitVidPn);
}
NTSTATUS
APIENTRY
DodUpdateActiveVidPnPresentPath(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (!pQxl->IsDriverActive())
{
2015-03-30 13:57:12 +02:00
QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl);
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->UpdateActiveVidPnPresentPath(pUpdateActiveVidPnPresentPath);
}
NTSTATUS
APIENTRY
DodQueryVidPnHWCapability(
_In_ CONST HANDLE hAdapter,
_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps)
{
PAGED_CODE();
QXL_ASSERT_CHK(hAdapter != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (!pQxl->IsDriverActive())
{
2015-03-30 13:57:12 +02:00
QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl);
2013-12-09 11:55:42 +01:00
return STATUS_UNSUCCESSFUL;
}
return pQxl->QueryVidPnHWCapability(pVidPnHWCaps);
}
NTSTATUS
APIENTRY
DodControlInterrupt(
IN_CONST_HANDLE hAdapter,
IN_CONST_DXGK_INTERRUPT_TYPE InterruptType,
IN_BOOLEAN EnableInterrupt
)
{
PAGED_CODE();
QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
if (InterruptType == DXGK_INTERRUPT_DISPLAYONLY_VSYNC)
{
pQxl->EnableVsync(EnableInterrupt);
return STATUS_SUCCESS;
}
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
APIENTRY
DodGetScanLine(
IN_CONST_HANDLE hAdapter,
INOUT_PDXGKARG_GETSCANLINE pGetScanLine
)
{
PAGED_CODE();
// Currently we do not see any practical use case when this procedure is called
// IDirectDraw has an interface for querying scan line
// Leave it not implemented like remote desktop does
// until we recognize use case for more intelligent implementation
DbgPrint(TRACE_LEVEL_ERROR, ("<---> %s\n", __FUNCTION__));
return STATUS_NOT_IMPLEMENTED;
}
2013-12-09 11:55:42 +01:00
//END: Paged Code
#pragma code_seg(pop)
#pragma code_seg(push)
#pragma code_seg()
// BEGIN: Non-Paged Code
VOID
DodDpcRoutine(
_In_ VOID* pDeviceContext)
{
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
if (!pQxl->IsDriverActive())
{
2015-03-30 13:57:12 +02:00
QXL_LOG_ASSERTION1("QXL (%p) is being called when not active!", pQxl);
2013-12-09 11:55:42 +01:00
return;
}
pQxl->DpcRoutine();
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
}
BOOLEAN
DodInterruptRoutine(
_In_ VOID* pDeviceContext,
_In_ ULONG MessageNumber)
{
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
return pQxl->InterruptRoutine(MessageNumber);
}
VOID
DodResetDevice(
_In_ VOID* pDeviceContext)
{
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
pQxl->ResetDevice();
}
NTSTATUS
APIENTRY
DodSystemDisplayEnable(
_In_ VOID* pDeviceContext,
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
_In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
_Out_ UINT* Width,
_Out_ UINT* Height,
_Out_ D3DDDIFORMAT* ColorFormat)
{
QXL_ASSERT_CHK(pDeviceContext != NULL);
2013-12-30 13:02:44 +01:00
DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
2013-12-09 11:55:42 +01:00
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
return pQxl->SystemDisplayEnable(TargetId, Flags, Width, Height, ColorFormat);
}
VOID
APIENTRY
DodSystemDisplayWrite(
_In_ VOID* pDeviceContext,
_In_ VOID* Source,
_In_ UINT SourceWidth,
_In_ UINT SourceHeight,
_In_ UINT SourceStride,
_In_ UINT PositionX,
_In_ UINT PositionY)
{
QXL_ASSERT_CHK(pDeviceContext != NULL);
DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
pQxl->SystemDisplayWrite(Source, SourceWidth, SourceHeight, SourceStride, PositionX, PositionY);
}
#if defined(DBG)
#define RHEL_DEBUG_PORT ((PUCHAR)0x3F8)
#define TEMP_BUFFER_SIZE 256
2013-12-09 11:55:42 +01:00
static void DebugPrintFuncSerial(const char *format, va_list list)
2013-12-09 11:55:42 +01:00
{
char buf[TEMP_BUFFER_SIZE];
NTSTATUS status;
size_t len;
status = RtlStringCbVPrintfA(buf, sizeof(buf), format, list);
if (status == STATUS_SUCCESS)
{
len = strlen(buf);
}
else
{
len = 2;
buf[0] = 'O';
buf[1] = '\n';
}
if (len)
{
2014-01-26 12:28:01 +01:00
WRITE_PORT_BUFFER_UCHAR(RHEL_DEBUG_PORT, (PUCHAR)buf, (ULONG)len);
2013-12-09 11:55:42 +01:00
WRITE_PORT_UCHAR(RHEL_DEBUG_PORT, '\r');
}
}
void DebugPrint(int level, const char *fmt, ...)
{
va_list list;
if (level <= nDebugLevel) {
va_start(list, fmt);
DebugPrintFuncSerial(fmt, list);
va_end(list);
}
static const ULONG xlate[] = { 0, 0, 1, 2, 3 };
if (level <= 0 || level > 5)
return;
va_start(list, fmt);
vDbgPrintEx(DPFLTR_IHVVIDEO_ID, xlate[level - 1], fmt, list);
va_end(list);
}
2013-12-09 11:55:42 +01:00
#endif
#pragma code_seg(pop) // End Non-Paged Code