diff options
Diffstat (limited to 'video/IndirectDisplay/IddSampleDriver')
| -rw-r--r-- | video/IndirectDisplay/IddSampleDriver/Driver.cpp | 686 | ||||
| -rw-r--r-- | video/IndirectDisplay/IddSampleDriver/Driver.h | 103 | ||||
| -rw-r--r-- | video/IndirectDisplay/IddSampleDriver/IddSampleDriver.inf | bin | 0 -> 4580 bytes | |||
| -rw-r--r-- | video/IndirectDisplay/IddSampleDriver/IddSampleDriver.rc | 10 | ||||
| -rw-r--r-- | video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj | 319 | ||||
| -rw-r--r-- | video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj.filters | 39 | ||||
| -rw-r--r-- | video/IndirectDisplay/IddSampleDriver/Trace.h | 63 |
7 files changed, 1220 insertions, 0 deletions
diff --git a/video/IndirectDisplay/IddSampleDriver/Driver.cpp b/video/IndirectDisplay/IddSampleDriver/Driver.cpp new file mode 100644 index 00000000..a9bd6108 --- /dev/null +++ b/video/IndirectDisplay/IddSampleDriver/Driver.cpp @@ -0,0 +1,686 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Abstract: + + This module contains a sample implementation of an indirect display driver. See the included README.md file and the + various TODO blocks throughout this file and all accompanying files for information on building a production driver. + + MSDN documentation on indirect displays can be found at https://msdn.microsoft.com/en-us/library/windows/hardware/mt761968(v=vs.85).aspx. + +Environment: + + User Mode, UMDF + +--*/ + +#include "Driver.h" +#include "Driver.tmh" + +using namespace std; +using namespace Microsoft::IndirectDisp; +using namespace Microsoft::WRL; + +extern "C" DRIVER_INITIALIZE DriverEntry; + +EVT_WDF_DRIVER_DEVICE_ADD IddSampleDeviceAdd; +EVT_WDF_DEVICE_D0_ENTRY IddSampleDeviceD0Entry; + +EVT_IDD_CX_ADAPTER_INIT_FINISHED IddSampleAdapterInitFinished; +EVT_IDD_CX_ADAPTER_COMMIT_MODES IddSampleAdapterCommitModes; + +EVT_IDD_CX_PARSE_MONITOR_DESCRIPTION IddSampleParseMonitorDescription; +EVT_IDD_CX_MONITOR_GET_DEFAULT_DESCRIPTION_MODES IddSampleMonitorGetDefaultModes; +EVT_IDD_CX_MONITOR_QUERY_TARGET_MODES IddSampleMonitorQueryModes; + +EVT_IDD_CX_MONITOR_ASSIGN_SWAPCHAIN IddSampleMonitorAssignSwapChain; +EVT_IDD_CX_MONITOR_UNASSIGN_SWAPCHAIN IddSampleMonitorUnassignSwapChain; + +struct IndirectDeviceContextWrapper +{ + IndirectDeviceContext* pContext; + + void Cleanup() + { + delete pContext; + pContext = nullptr; + } +}; + +// This macro creates the methods for accessing an IndirectDeviceContextWrapper as a context for a WDF object +WDF_DECLARE_CONTEXT_TYPE(IndirectDeviceContextWrapper); + +extern "C" BOOL WINAPI DllMain( + _In_ HINSTANCE hInstance, + _In_ UINT dwReason, + _In_opt_ LPVOID lpReserved) +{ + UNREFERENCED_PARAMETER(hInstance); + UNREFERENCED_PARAMETER(lpReserved); + UNREFERENCED_PARAMETER(dwReason); + + return TRUE; +} + +_Use_decl_annotations_ +extern "C" NTSTATUS DriverEntry( + PDRIVER_OBJECT pDriverObject, + PUNICODE_STRING pRegistryPath +) +{ + WDF_DRIVER_CONFIG Config; + NTSTATUS Status; + + WDF_OBJECT_ATTRIBUTES Attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&Attributes); + + WDF_DRIVER_CONFIG_INIT(&Config, + IddSampleDeviceAdd + ); + + Status = WdfDriverCreate(pDriverObject, pRegistryPath, &Attributes, &Config, WDF_NO_HANDLE); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + return Status; +} + +_Use_decl_annotations_ +NTSTATUS IddSampleDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT pDeviceInit) +{ + NTSTATUS Status = STATUS_SUCCESS; + WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks; + + UNREFERENCED_PARAMETER(Driver); + + // Register for power callbacks - in this sample only power-on is needed + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks); + PnpPowerCallbacks.EvtDeviceD0Entry = IddSampleDeviceD0Entry; + WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &PnpPowerCallbacks); + + IDD_CX_CLIENT_CONFIG IddConfig; + IDD_CX_CLIENT_CONFIG_INIT(&IddConfig); + + // If the driver wishes to handle custom IoDeviceControl requests, it's necessary to use this callback since IddCx + // redirects IoDeviceControl requests to an internal queue. This sample does not need this. + // IddConfig.EvtIddCxDeviceIoControl = IddSampleIoDeviceControl; + + IddConfig.EvtIddCxAdapterInitFinished = IddSampleAdapterInitFinished; + + IddConfig.EvtIddCxParseMonitorDescription = IddSampleParseMonitorDescription; + IddConfig.EvtIddCxMonitorGetDefaultDescriptionModes = IddSampleMonitorGetDefaultModes; + IddConfig.EvtIddCxMonitorQueryTargetModes = IddSampleMonitorQueryModes; + IddConfig.EvtIddCxAdapterCommitModes = IddSampleAdapterCommitModes; + IddConfig.EvtIddCxMonitorAssignSwapChain = IddSampleMonitorAssignSwapChain; + IddConfig.EvtIddCxMonitorUnassignSwapChain = IddSampleMonitorUnassignSwapChain; + + Status = IddCxDeviceInitConfig(pDeviceInit, &IddConfig); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + WDF_OBJECT_ATTRIBUTES Attr; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attr, IndirectDeviceContextWrapper); + Attr.EvtCleanupCallback = [](WDFOBJECT Object) + { + // Automatically cleanup the context when the WDF object is about to be deleted + auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Object); + if (pContext) + { + pContext->Cleanup(); + } + }; + + WDFDEVICE Device = nullptr; + Status = WdfDeviceCreate(&pDeviceInit, &Attr, &Device); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + Status = IddCxDeviceInitialize(Device); + + // Create a new device context object and attach it to the WDF device object + auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Device); + pContext->pContext = new IndirectDeviceContext(Device); + + return Status; +} + +_Use_decl_annotations_ +NTSTATUS IddSampleDeviceD0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState) +{ + UNREFERENCED_PARAMETER(PreviousState); + + // This function is called by WDF to start the device in the fully-on power state. + + auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Device); + pContext->pContext->InitAdapter(); + + return STATUS_SUCCESS; +} + +#pragma region Direct3DDevice + +Direct3DDevice::Direct3DDevice(LUID AdapterLuid) : AdapterLuid(AdapterLuid) +{ + +} + +Direct3DDevice::Direct3DDevice() +{ + AdapterLuid = LUID{}; +} + +HRESULT Direct3DDevice::Init() +{ + // The DXGI factory could be cached, but if a new render adapter appears on the system, a new factory needs to be + // created. If caching is desired, check DxgiFactory->IsCurrent() each time and recreate the factory if !IsCurrent. + HRESULT hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&DxgiFactory)); + if (FAILED(hr)) + { + return hr; + } + + // Find the specified render adapter + hr = DxgiFactory->EnumAdapterByLuid(AdapterLuid, IID_PPV_ARGS(&Adapter)); + if (FAILED(hr)) + { + return hr; + } + + // Create a D3D device using the render adapter. BGRA support is required by the WHQL test suite. + hr = D3D11CreateDevice(Adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, D3D11_SDK_VERSION, &Device, nullptr, &DeviceContext); + if (FAILED(hr)) + { + // If creating the D3D device failed, it's possible the render GPU was lost (e.g. detachable GPU) or else the + // system is in a transient state. + return hr; + } + + return S_OK; +} + +#pragma endregion + +#pragma region SwapChainProcessor + +SwapChainProcessor::SwapChainProcessor(IDDCX_SWAPCHAIN hSwapChain, shared_ptr<Direct3DDevice> Device, HANDLE NewFrameEvent) + : m_hSwapChain(hSwapChain), m_Device(Device), m_hAvailableBufferEvent(NewFrameEvent) +{ + m_hTerminateEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + + // Immediately create and run the swap-chain processing thread, passing 'this' as the thread parameter + m_hThread.Attach(CreateThread(nullptr, 0, RunThread, this, 0, nullptr)); +} + +SwapChainProcessor::~SwapChainProcessor() +{ + // Alert the swap-chain processing thread to terminate + SetEvent(m_hTerminateEvent.Get()); + + if (m_hThread.Get()) + { + // Wait for the thread to terminate + WaitForSingleObject(m_hThread.Get(), INFINITE); + } +} + +DWORD CALLBACK SwapChainProcessor::RunThread(LPVOID Argument) +{ + reinterpret_cast<SwapChainProcessor*>(Argument)->Run(); + return 0; +} + +void SwapChainProcessor::Run() +{ + // For improved performance, make use of the Multimedia Class Scheduler Service, which will intelligently + // prioritize this thread for improved throughput in high CPU-load scenarios. + DWORD AvTask = 0; + HANDLE AvTaskHandle = AvSetMmThreadCharacteristics(L"Distribution", &AvTask); + + RunCore(); + + // Always delete the swap-chain object when swap-chain processing loop terminates in order to kick the system to + // provide a new swap-chain if necessary. + WdfObjectDelete((WDFOBJECT)m_hSwapChain); + m_hSwapChain = nullptr; + + AvRevertMmThreadCharacteristics(AvTaskHandle); +} + +void SwapChainProcessor::RunCore() +{ + // Get the DXGI device interface + ComPtr<IDXGIDevice> DxgiDevice; + HRESULT hr = m_Device->Device.As(&DxgiDevice); + if (FAILED(hr)) + { + return; + } + + IDARG_IN_SWAPCHAINSETDEVICE SetDevice = {}; + SetDevice.pDevice = DxgiDevice.Get(); + + hr = IddCxSwapChainSetDevice(m_hSwapChain, &SetDevice); + if (FAILED(hr)) + { + return; + } + + // Acquire and release buffers in a loop + for (;;) + { + ComPtr<IDXGIResource> AcquiredBuffer; + + // Ask for the next buffer from the producer + IDARG_OUT_RELEASEANDACQUIREBUFFER Buffer = {}; + hr = IddCxSwapChainReleaseAndAcquireBuffer(m_hSwapChain, &Buffer); + + // AcquireBuffer immediately returns STATUS_PENDING if no buffer is yet available + if (hr == E_PENDING) + { + // We must wait for a new buffer + HANDLE WaitHandles [] = + { + m_hAvailableBufferEvent, + m_hTerminateEvent.Get() + }; + DWORD WaitResult = WaitForMultipleObjects(ARRAYSIZE(WaitHandles), WaitHandles, FALSE, 16); + if (WaitResult == WAIT_OBJECT_0 || WaitResult == WAIT_TIMEOUT) + { + // We have a new buffer, so try the AcquireBuffer again + continue; + } + else if (WaitResult == WAIT_OBJECT_0 + 1) + { + // We need to terminate + break; + } + else + { + // The wait was cancelled or something unexpected happened + hr = HRESULT_FROM_WIN32(WaitResult); + break; + } + } + else if (SUCCEEDED(hr)) + { + AcquiredBuffer.Attach(Buffer.MetaData.pSurface); + + // ============================== + // TODO: Process the frame here + // + // This is the most performance-critical section of code in an IddCx driver. It's important that whatever + // is done with the acquired surface be finished as quickly as possible. This operation could be: + // * a GPU copy to another buffer surface for later processing (such as a staging surface for mapping to CPU memory) + // * a GPU encode operation + // * a GPU VPBlt to another surface + // * a GPU custom compute shader encode operation + // ============================== + + AcquiredBuffer.Reset(); + hr = IddCxSwapChainFinishedProcessingFrame(m_hSwapChain); + if (FAILED(hr)) + { + break; + } + + // ============================== + // TODO: Report frame statistics once the asynchronous encode/send work is completed + // + // Drivers should report information about sub-frame timings, like encode time, send time, etc. + // ============================== + // IddCxSwapChainReportFrameStatistics(m_hSwapChain, ...); + } + else + { + // The swap-chain was likely abandoned (e.g. DXGI_ERROR_ACCESS_LOST), so exit the processing loop + break; + } + } +} + +#pragma endregion + +#pragma region IndirectDeviceContext + +const UINT64 MHZ = 1000000; +const UINT64 KHZ = 1000; + +// A list of modes exposed by the sample monitor EDID - FOR SAMPLE PURPOSES ONLY +const DISPLAYCONFIG_VIDEO_SIGNAL_INFO IndirectDeviceContext::s_KnownMonitorModes[] = +{ + // 800 x 600 @ 60Hz + { + 40 * MHZ, // pixel clock rate [Hz] + { 40 * MHZ, 800 + 256 }, // fractional horizontal refresh rate [Hz] + { 40 * MHZ, (800 + 256) * (600 + 28) }, // fractional vertical refresh rate [Hz] + { 800, 600 }, // (horizontal, vertical) active pixel resolution + { 800 + 256, 600 + 28 }, // (horizontal, vertical) total pixel resolution + { { 255, 0 }}, // video standard and vsync divider + DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE + }, + // 640 x 480 @ 60Hz + { + 25175 * KHZ, // pixel clock rate [Hz] + { 25175 * KHZ, 640 + 160 }, // fractional horizontal refresh rate [Hz] + { 25175 * KHZ, (640 + 160) * (480 + 46) }, // fractional vertical refresh rate [Hz] + { 640, 480 }, // (horizontal, vertical) active pixel resolution + { 640 + 160, 480 + 46 }, // (horizontal, vertical) blanking pixel resolution + { { 255, 0 } }, // video standard and vsync divider + DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE + }, +}; + +// This is a sample monitor EDID - FOR SAMPLE PURPOSES ONLY +const BYTE IndirectDeviceContext::s_KnownMonitorEdid[] = +{ + 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x79,0x5E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA6,0x01,0x03,0x80,0x28, + 0x1E,0x78,0x0A,0xEE,0x91,0xA3,0x54,0x4C,0x99,0x26,0x0F,0x50,0x54,0x20,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xA0,0x0F,0x20,0x00,0x31,0x58,0x1C,0x20,0x28,0x80,0x14,0x00, + 0x90,0x2C,0x11,0x00,0x00,0x1E,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E +}; + +IndirectDeviceContext::IndirectDeviceContext(_In_ WDFDEVICE WdfDevice) : + m_WdfDevice(WdfDevice) +{ + m_Adapter = {}; + m_Monitor = {}; +} + +IndirectDeviceContext::~IndirectDeviceContext() +{ + m_ProcessingThread.reset(); +} + +void IndirectDeviceContext::InitAdapter() +{ + // ============================== + // TODO: Update the below diagnostic information in accordance with the target hardware. The strings and version + // numbers are used for telemetry and may be displayed to the user in some situations. + // + // This is also where static per-adapter capabilities are determined. + // ============================== + + IDDCX_ADAPTER_CAPS AdapterCaps = {}; + AdapterCaps.Size = sizeof(AdapterCaps); + + // Declare basic feature support for the adapter (required) + AdapterCaps.MaxMonitorsSupported = 1; + AdapterCaps.EndPointDiagnostics.Size = sizeof(AdapterCaps.EndPointDiagnostics); + AdapterCaps.EndPointDiagnostics.GammaSupport = IDDCX_FEATURE_IMPLEMENTATION_NONE; + AdapterCaps.EndPointDiagnostics.TransmissionType = IDDCX_TRANSMISSION_TYPE_WIRED_OTHER; + + // Declare your device strings for telemetry (required) + AdapterCaps.EndPointDiagnostics.pEndPointFriendlyName = L"IddSample Device"; + AdapterCaps.EndPointDiagnostics.pEndPointManufacturerName = L"Microsoft"; + AdapterCaps.EndPointDiagnostics.pEndPointModelName = L"IddSample Model"; + + // Declare your hardware and firmware versions (required) + IDDCX_ENDPOINT_VERSION Version = {}; + Version.Size = sizeof(Version); + Version.MajorVer = 1; + AdapterCaps.EndPointDiagnostics.pFirmwareVersion = &Version; + AdapterCaps.EndPointDiagnostics.pHardwareVersion = &Version; + + // Initialize a WDF context that can store a pointer to the device context object + WDF_OBJECT_ATTRIBUTES Attr; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attr, IndirectDeviceContextWrapper); + + IDARG_IN_ADAPTER_INIT AdapterInit = {}; + AdapterInit.WdfDevice = m_WdfDevice; + AdapterInit.pCaps = &AdapterCaps; + AdapterInit.ObjectAttributes = &Attr; + + // Start the initialization of the adapter, which will trigger the AdapterFinishInit callback later + IDARG_OUT_ADAPTER_INIT AdapterInitOut; + NTSTATUS Status = IddCxAdapterInitAsync(&AdapterInit, &AdapterInitOut); + + if (NT_SUCCESS(Status)) + { + // Store a reference to the WDF adapter handle + m_Adapter = AdapterInitOut.AdapterObject; + + // Store the device context object into the WDF object context + auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(AdapterInitOut.AdapterObject); + pContext->pContext = this; + } +} + +void IndirectDeviceContext::FinishInit() +{ + // ============================== + // TODO: In a real driver, the EDID should be retrieved dynamically from a connected physical monitor. The EDID + // provided here is purely for demonstration, as it describes only 640x480 @ 60 Hz and 800x600 @ 60 Hz. Monitor + // manufacturers are required to correctly fill in physical monitor attributes in order to allow the OS to optimize + // settings like viewing distance and scale factor. Manufacturers should also use a unique serial number every + // single device to ensure the OS can tell the monitors apart. + // ============================== + + WDF_OBJECT_ATTRIBUTES Attr; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attr, IndirectDeviceContextWrapper); + + IDDCX_MONITOR_INFO MonitorInfo = {}; + MonitorInfo.Size = sizeof(MonitorInfo); + MonitorInfo.MonitorType = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI; + MonitorInfo.ConnectorIndex = 0; + MonitorInfo.MonitorDescription.Size = sizeof(MonitorInfo.MonitorDescription); + MonitorInfo.MonitorDescription.Type = IDDCX_MONITOR_DESCRIPTION_TYPE_EDID; + MonitorInfo.MonitorDescription.DataSize = sizeof(s_KnownMonitorEdid); + MonitorInfo.MonitorDescription.pData = const_cast<BYTE*>(s_KnownMonitorEdid); + + // ============================== + // TODO: The monitor's container ID should be distinct from "this" device's container ID if the monitor is not + // permanently attached to the display adapter device object. The container ID is typically made unique for each + // monitor and can be used to associate the monitor with other devices, like audio or input devices. In this + // sample we generate a random container ID GUID, but it's best practice to choose a stable container ID for a + // unique monitor or to use "this" device's container ID for a permanent/integrated monitor. + // ============================== + + // Create a container ID + CoCreateGuid(&MonitorInfo.MonitorContainerId); + + IDARG_IN_MONITORCREATE MonitorCreate = {}; + MonitorCreate.ObjectAttributes = &Attr; + MonitorCreate.pMonitorInfo = &MonitorInfo; + + // Create a monitor object with the specified monitor descriptor + IDARG_OUT_MONITORCREATE MonitorCreateOut; + NTSTATUS Status = IddCxMonitorCreate(m_Adapter, &MonitorCreate, &MonitorCreateOut); + if (NT_SUCCESS(Status)) + { + m_Monitor = MonitorCreateOut.MonitorObject; + + // Associate the monitor with this device context + auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(MonitorCreateOut.MonitorObject); + pContext->pContext = this; + + // Tell the OS that the monitor has been plugged in + IDARG_OUT_MONITORARRIVAL ArrivalOut; + Status = IddCxMonitorArrival(m_Monitor, &ArrivalOut); + } +} + +void IndirectDeviceContext::AssignSwapChain(IDDCX_SWAPCHAIN SwapChain, LUID RenderAdapter, HANDLE NewFrameEvent) +{ + m_ProcessingThread.reset(); + + auto Device = make_shared<Direct3DDevice>(RenderAdapter); + if (FAILED(Device->Init())) + { + // It's important to delete the swap-chain if D3D initialization fails, so that the OS knows to generate a new + // swap-chain and try again. + WdfObjectDelete(SwapChain); + } + else + { + // Create a new swap-chain processing thread + m_ProcessingThread.reset(new SwapChainProcessor(SwapChain, Device, NewFrameEvent)); + } +} + +void IndirectDeviceContext::UnassignSwapChain() +{ + // Stop processing the last swap-chain + m_ProcessingThread.reset(); +} + +#pragma endregion + +#pragma region DDI Callbacks + +_Use_decl_annotations_ +NTSTATUS IddSampleAdapterInitFinished(IDDCX_ADAPTER AdapterObject, const IDARG_IN_ADAPTER_INIT_FINISHED* pInArgs) +{ + // This is called when the OS has finished setting up the adapter for use by the IddCx driver. It's now possible + // to report attached monitors. + + auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(AdapterObject); + if (NT_SUCCESS(pInArgs->AdapterInitStatus)) + { + pContext->pContext->FinishInit(); + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS IddSampleAdapterCommitModes(IDDCX_ADAPTER AdapterObject, const IDARG_IN_COMMITMODES* pInArgs) +{ + UNREFERENCED_PARAMETER(AdapterObject); + UNREFERENCED_PARAMETER(pInArgs); + + // For the sample, do nothing when modes are picked - the swap-chain is taken care of by IddCx + + // ============================== + // TODO: In a real driver, this function would be used to reconfigure the device to commit the new modes. Loop + // through pInArgs->pPaths and look for IDDCX_PATH_FLAGS_ACTIVE. Any path not active is inactive (e.g. the monitor + // should be turned off). + // ============================== + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS IddSampleParseMonitorDescription(const IDARG_IN_PARSEMONITORDESCRIPTION* pInArgs, IDARG_OUT_PARSEMONITORDESCRIPTION* pOutArgs) +{ + // ============================== + // TODO: In a real driver, this function would be called to generate monitor modes for an EDID by parsing it. In + // this sample driver, we hard-code the EDID, so this function can generate known modes. + // ============================== + + pOutArgs->MonitorModeBufferOutputCount = ARRAYSIZE(IndirectDeviceContext::s_KnownMonitorModes); + + if (pInArgs->MonitorModeBufferInputCount < ARRAYSIZE(IndirectDeviceContext::s_KnownMonitorModes)) + { + // Return success if there was no buffer, since the caller was only asking for a count of modes + return (pInArgs->MonitorModeBufferInputCount > 0) ? STATUS_BUFFER_TOO_SMALL : STATUS_SUCCESS; + } + else + { + // Copy the known modes to the output buffer + for (DWORD ModeIndex = 0; ModeIndex < ARRAYSIZE(IndirectDeviceContext::s_KnownMonitorModes); ModeIndex++) + { + pInArgs->pMonitorModes[ModeIndex].Size = sizeof(IDDCX_MONITOR_MODE); + pInArgs->pMonitorModes[ModeIndex].Origin = IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR; + pInArgs->pMonitorModes[ModeIndex].MonitorVideoSignalInfo = IndirectDeviceContext::s_KnownMonitorModes[ModeIndex]; + } + + // Set the preferred mode as represented in the EDID + pOutArgs->PreferredMonitorModeIdx = 0; + + return STATUS_SUCCESS; + } +} + +_Use_decl_annotations_ +NTSTATUS IddSampleMonitorGetDefaultModes(IDDCX_MONITOR MonitorObject, const IDARG_IN_GETDEFAULTDESCRIPTIONMODES* pInArgs, IDARG_OUT_GETDEFAULTDESCRIPTIONMODES* pOutArgs) +{ + UNREFERENCED_PARAMETER(MonitorObject); + UNREFERENCED_PARAMETER(pInArgs); + UNREFERENCED_PARAMETER(pOutArgs); + + // Should never be called since we create a single monitor with a known EDID in this sample driver. + + // ============================== + // TODO: In a real driver, this function would be called to generate monitor modes for a monitor with no EDID. + // Drivers should report modes that are guaranteed to be supported by the transport protocol and by nearly all + // monitors (such 640x480, 800x600, or 1024x768). If the driver has access to monitor modes from a descriptor other + // than an EDID, those modes would also be reported here. + // ============================== + + return STATUS_NOT_IMPLEMENTED; +} + +/// <summary> +/// Creates a target mode from the fundamental mode attributes. +/// </summary> +void CreateTargetMode(DISPLAYCONFIG_VIDEO_SIGNAL_INFO& Mode, UINT Width, UINT Height, UINT VSync) +{ + Mode.totalSize.cx = Mode.activeSize.cx = Width; + Mode.totalSize.cy = Mode.activeSize.cy = Height; + Mode.AdditionalSignalInfo.vSyncFreqDivider = 1; + Mode.AdditionalSignalInfo.videoStandard = 255; + Mode.vSyncFreq.Numerator = VSync; + Mode.vSyncFreq.Denominator = Mode.hSyncFreq.Denominator = 1; + Mode.hSyncFreq.Numerator = VSync * Height; + Mode.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE; + Mode.pixelRate = ((UINT64) VSync) * ((UINT64) Width) * ((UINT64) Height); +} + +void CreateTargetMode(IDDCX_TARGET_MODE& Mode, UINT Width, UINT Height, UINT VSync) +{ + Mode.Size = sizeof(Mode); + CreateTargetMode(Mode.TargetVideoSignalInfo.targetVideoSignalInfo, Width, Height, VSync); +} + +_Use_decl_annotations_ +NTSTATUS IddSampleMonitorQueryModes(IDDCX_MONITOR MonitorObject, const IDARG_IN_QUERYTARGETMODES* pInArgs, IDARG_OUT_QUERYTARGETMODES* pOutArgs) +{ + UNREFERENCED_PARAMETER(MonitorObject); + + vector<IDDCX_TARGET_MODE> TargetModes(4); + + // Create a set of modes supported for frame processing and scan-out. These are typically not based on the + // monitor's descriptor and instead are based on the static processing capability of the device. The OS will + // report the available set of modes for a given output as the intersection of monitor modes with target modes. + + CreateTargetMode(TargetModes[0], 1920, 1080, 60); + CreateTargetMode(TargetModes[1], 1024, 768, 60); + CreateTargetMode(TargetModes[2], 800, 600, 60); + CreateTargetMode(TargetModes[3], 640, 480, 60); + + pOutArgs->TargetModeBufferOutputCount = (UINT)TargetModes.size(); + + if (pInArgs->TargetModeBufferInputCount >= TargetModes.size()) + { + copy(TargetModes.begin(), TargetModes.end(), pInArgs->pTargetModes); + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS IddSampleMonitorAssignSwapChain(IDDCX_MONITOR MonitorObject, const IDARG_IN_SETSWAPCHAIN* pInArgs) +{ + auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(MonitorObject); + pContext->pContext->AssignSwapChain(pInArgs->hSwapChain, pInArgs->RenderAdapterLuid, pInArgs->hNextSurfaceAvailable); + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS IddSampleMonitorUnassignSwapChain(IDDCX_MONITOR MonitorObject) +{ + auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(MonitorObject); + pContext->pContext->UnassignSwapChain(); + return STATUS_SUCCESS; +} + +#pragma endregion diff --git a/video/IndirectDisplay/IddSampleDriver/Driver.h b/video/IndirectDisplay/IddSampleDriver/Driver.h new file mode 100644 index 00000000..df69b0e4 --- /dev/null +++ b/video/IndirectDisplay/IddSampleDriver/Driver.h @@ -0,0 +1,103 @@ +#pragma once + +#define NOMINMAX +#include <windows.h> +#include <bugcodes.h> +#include <wudfwdm.h> +#include <wdf.h> +#include <iddcx.h> + +#include <dxgi1_5.h> +#include <d3d11_2.h> +#include <avrt.h> +#include <wrl.h> + +#include <memory> +#include <vector> + +#include "Trace.h" + +namespace Microsoft +{ + namespace WRL + { + namespace Wrappers + { + // Adds a wrapper for thread handles to the existing set of WRL handle wrapper classes + typedef HandleT<HandleTraits::HANDLENullTraits> Thread; + } + } +} + +namespace Microsoft +{ + namespace IndirectDisp + { + /// <summary> + /// Manages the creation and lifetime of a Direct3D render device. + /// </summary> + struct Direct3DDevice + { + Direct3DDevice(LUID AdapterLuid); + Direct3DDevice(); + HRESULT Init(); + + LUID AdapterLuid; + Microsoft::WRL::ComPtr<IDXGIFactory5> DxgiFactory; + Microsoft::WRL::ComPtr<IDXGIAdapter1> Adapter; + Microsoft::WRL::ComPtr<ID3D11Device> Device; + Microsoft::WRL::ComPtr<ID3D11DeviceContext> DeviceContext; + }; + + /// <summary> + /// Manages a thread that consumes buffers from an indirect display swap-chain object. + /// </summary> + class SwapChainProcessor + { + public: + SwapChainProcessor(IDDCX_SWAPCHAIN hSwapChain, std::shared_ptr<Direct3DDevice> Device, HANDLE NewFrameEvent); + ~SwapChainProcessor(); + + private: + static DWORD CALLBACK RunThread(LPVOID Argument); + + void Run(); + void RunCore(); + + public: + IDDCX_SWAPCHAIN m_hSwapChain; + std::shared_ptr<Direct3DDevice> m_Device; + HANDLE m_hAvailableBufferEvent; + Microsoft::WRL::Wrappers::Thread m_hThread; + Microsoft::WRL::Wrappers::Event m_hTerminateEvent; + }; + + /// <summary> + /// Provides a sample implementation of an indirect display driver. + /// </summary> + class IndirectDeviceContext + { + public: + IndirectDeviceContext(_In_ WDFDEVICE WdfDevice); + virtual ~IndirectDeviceContext(); + + void InitAdapter(); + void FinishInit(); + + void AssignSwapChain(IDDCX_SWAPCHAIN SwapChain, LUID RenderAdapter, HANDLE NewFrameEvent); + void UnassignSwapChain(); + + protected: + + WDFDEVICE m_WdfDevice; + IDDCX_ADAPTER m_Adapter; + IDDCX_MONITOR m_Monitor; + + std::unique_ptr<SwapChainProcessor> m_ProcessingThread; + + public: + static const DISPLAYCONFIG_VIDEO_SIGNAL_INFO s_KnownMonitorModes[]; + static const BYTE s_KnownMonitorEdid[]; + }; + } +} diff --git a/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.inf b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.inf Binary files differnew file mode 100644 index 00000000..d70c8a87 --- /dev/null +++ b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.inf diff --git a/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.rc b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.rc new file mode 100644 index 00000000..ca2d8226 --- /dev/null +++ b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.rc @@ -0,0 +1,10 @@ +#include <windows.h> +#include <ntverp.h> + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT_UNKNOWN +#define VER_FILEDESCRIPTION_STR "UMDF Indirect Display Driver Sample" +#define VER_INTERNALNAME_STR "IddSampleDriver" +#define VER_ORIGINALFILENAME_STR "IddSampleDriver.dll" + +#include "common.ver" diff --git a/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj new file mode 100644 index 00000000..8a484288 --- /dev/null +++ b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj @@ -0,0 +1,319 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|ARM"> + <Configuration>Debug</Configuration> + <Platform>ARM</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM"> + <Configuration>Release</Configuration> + <Platform>ARM</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|ARM64"> + <Configuration>Debug</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM64"> + <Configuration>Release</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + </ItemGroup> + <ItemGroup> + <ClCompile Include="Driver.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="Driver.h" /> + <ClInclude Include="Trace.h" /> + </ItemGroup> + <ItemGroup> + <Inf Include="IddSampleDriver.inf" /> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{2D54CB75-8B17-4F11-97DC-847B0244CD46}</ProjectGuid> + <TemplateGuid>{32909489-7be5-497b-aafa-db6669d9b44b}</TemplateGuid> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <Configuration>Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <RootNamespace>IddSampleDriver</RootNamespace> + </PropertyGroup> + <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR> + <IndirectDisplayDriver>true</IndirectDisplayDriver> + <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR> + <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR> + <IndirectDisplayDriver>true</IndirectDisplayDriver> + <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR> + <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR> + <IndirectDisplayDriver>true</IndirectDisplayDriver> + <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR> + <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR> + <IndirectDisplayDriver>true</IndirectDisplayDriver> + <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR> + <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR> + <IndirectDisplayDriver>true</IndirectDisplayDriver> + <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR> + <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR> + <IndirectDisplayDriver>true</IndirectDisplayDriver> + <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR> + <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR> + <IndirectDisplayDriver>true</IndirectDisplayDriver> + <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR> + <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR> + <IndirectDisplayDriver>true</IndirectDisplayDriver> + <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR> + <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <RunCodeAnalysis>true</RunCodeAnalysis> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <RunCodeAnalysis>true</RunCodeAnalysis> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <RunCodeAnalysis>true</RunCodeAnalysis> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <RunCodeAnalysis>true</RunCodeAnalysis> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <RunCodeAnalysis>true</RunCodeAnalysis> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <RunCodeAnalysis>true</RunCodeAnalysis> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <RunCodeAnalysis>true</RunCodeAnalysis> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <RunCodeAnalysis>true</RunCodeAnalysis> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData> + <ExceptionHandling>Async</ExceptionHandling> + <EnablePREfast>true</EnablePREfast> + <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData> + <ExceptionHandling>Async</ExceptionHandling> + <EnablePREfast>true</EnablePREfast> + <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData> + <ExceptionHandling>Async</ExceptionHandling> + <EnablePREfast>true</EnablePREfast> + <PreprocessorDefinitions>_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData> + <ExceptionHandling>Async</ExceptionHandling> + <EnablePREfast>true</EnablePREfast> + <PreprocessorDefinitions>_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies> + <AdditionalOptions>%(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData> + <ExceptionHandling>Async</ExceptionHandling> + <EnablePREfast>true</EnablePREfast> + <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData> + <ExceptionHandling>Async</ExceptionHandling> + <EnablePREfast>true</EnablePREfast> + <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData> + <ExceptionHandling>Async</ExceptionHandling> + <EnablePREfast>true</EnablePREfast> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData> + <ExceptionHandling>Async</ExceptionHandling> + <EnablePREfast>true</EnablePREfast> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj.filters b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj.filters new file mode 100644 index 00000000..f47c3804 --- /dev/null +++ b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj.filters @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + <Filter Include="Driver Files"> + <UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <Inf Include="IddSampleDriver.inf"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> + <ItemGroup> + <ClInclude Include="Driver.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="Trace.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="Driver.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/video/IndirectDisplay/IddSampleDriver/Trace.h b/video/IndirectDisplay/IddSampleDriver/Trace.h new file mode 100644 index 00000000..9852bab4 --- /dev/null +++ b/video/IndirectDisplay/IddSampleDriver/Trace.h @@ -0,0 +1,63 @@ +/*++ + +Module Name: + + Internal.h + +Abstract: + + This module contains the local type definitions for the + driver. + +Environment: + + Windows User-Mode Driver Framework 2 + +--*/ + +// +// Define the tracing flags. +// +// Tracing GUID - b254994f-46e6-4718-80a0-0a3aa50d6ce4 +// + +#define WPP_CONTROL_GUIDS \ + WPP_DEFINE_CONTROL_GUID( \ + MyDriver1TraceGuid, (b254994f,46e6,4718,80a0,0a3aa50d6ce4), \ + \ + WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \ + WPP_DEFINE_BIT(TRACE_DRIVER) \ + WPP_DEFINE_BIT(TRACE_DEVICE) \ + WPP_DEFINE_BIT(TRACE_QUEUE) \ + ) + +#define WPP_FLAG_LEVEL_LOGGER(flag, level) \ + WPP_LEVEL_LOGGER(flag) + +#define WPP_FLAG_LEVEL_ENABLED(flag, level) \ + (WPP_LEVEL_ENABLED(flag) && \ + WPP_CONTROL(WPP_BIT_ ## flag).Level >= level) + +#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \ + WPP_LEVEL_LOGGER(flags) + +#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \ + (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) + +// +// This comment block is scanned by the trace preprocessor to define our +// Trace function. +// +// begin_wpp config +// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...); +// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...); +// end_wpp + +// +// +// Driver specific #defines +// + +// TODO: Use a unique driver tracing ID here, +// see https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/adding-wpp-software-tracing-to-a-windows-driver +#define MYDRIVER_TRACING_ID L"Microsoft\\UMDF2.25\\IddSampleDriver v1.0" |
