/* * 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 */ #pragma once #include "baseobject.h" #include "qxl_dev.h" #include "qxl_windows.h" #include "mspace.h" #define MAX_CHILDREN 1 #define MAX_VIEWS 1 #define BITS_PER_BYTE 8 #define POINTER_SIZE 64 #define MIN_WIDTH_SIZE 1024 #define MIN_HEIGHT_SIZE 768 #define QXL_BPP 32 #define VGA_BPP 24 #define QXL_NON_PAGED __declspec(code_seg(".text")) typedef struct _QXL_FLAGS { UINT DriverStarted : 1; // ( 1) 1 after StartDevice and 0 after StopDevice UINT Unused : 31; } QXL_FLAGS; // 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]) #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 { CHAR Signature[4]; USHORT Version; ULONG OemStringPtr; LONG Capabilities; ULONG VideoModePtr; USHORT TotalMemory; USHORT OemSoftwareRevision; ULONG OemVendorNamePtr; ULONG OemProductNamePtr; ULONG OemProductRevPtr; CHAR Reserved[222]; } VBE_INFO, *PVBE_INFO; typedef struct { /* Mandatory information for all VBE revisions */ USHORT ModeAttributes; UCHAR WinAAttributes; UCHAR WinBAttributes; USHORT WinGranularity; USHORT WinSize; USHORT WinASegment; USHORT WinBSegment; ULONG WinFuncPtr; USHORT BytesPerScanLine; /* Mandatory information for VBE 1.2 and above */ USHORT XResolution; USHORT YResolution; UCHAR XCharSize; UCHAR YCharSize; UCHAR NumberOfPlanes; UCHAR BitsPerPixel; UCHAR NumberOfBanks; UCHAR MemoryModel; UCHAR BankSize; UCHAR NumberOfImagePages; UCHAR Reserved1; /* Direct Color fields (required for Direct/6 and YUV/7 memory models) */ UCHAR RedMaskSize; UCHAR RedFieldPosition; UCHAR GreenMaskSize; UCHAR GreenFieldPosition; UCHAR BlueMaskSize; UCHAR BlueFieldPosition; UCHAR ReservedMaskSize; UCHAR ReservedFieldPosition; UCHAR DirectColorModeInfo; /* Mandatory information for VBE 2.0 and above */ ULONG PhysBasePtr; ULONG Reserved2; USHORT Reserved3; /* Mandatory information for VBE 3.0 and above */ USHORT LinBytesPerScanLine; UCHAR BnkNumberOfImagePages; UCHAR LinNumberOfImagePages; UCHAR LinRedMaskSize; UCHAR LinRedFieldPosition; UCHAR LinGreenMaskSize; UCHAR LinGreenFieldPosition; UCHAR LinBlueMaskSize; UCHAR LinBlueFieldPosition; UCHAR LinReservedMaskSize; UCHAR LinReservedFieldPosition; ULONG MaxPixelClock; CHAR Reserved4[189]; } VBE_MODEINFO, *PVBE_MODEINFO; #pragma pack(pop) typedef struct _X86BIOS_REGISTERS // invented names { ULONG Eax; ULONG Ecx; ULONG Edx; ULONG Ebx; ULONG Ebp; ULONG Esi; ULONG Edi; USHORT SegDs; USHORT SegEs; } X86BIOS_REGISTERS, *PX86BIOS_REGISTERS; /* Undocumented imports from the HAL */ #ifdef __cplusplus extern "C" { #endif NTHALAPI BOOLEAN x86BiosCall (ULONG, PX86BIOS_REGISTERS); NTHALAPI NTSTATUS x86BiosAllocateBuffer (ULONG *, USHORT *, USHORT *); NTHALAPI NTSTATUS x86BiosFreeBuffer (USHORT, USHORT); NTHALAPI NTSTATUS x86BiosReadMemory (USHORT, USHORT, PVOID, ULONG); NTHALAPI NTSTATUS x86BiosWriteMemory (USHORT, USHORT, PVOID, ULONG); #ifdef __cplusplus } #endif 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; class HwDeviceInterface { public: virtual ~HwDeviceInterface() {;} virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0; virtual NTSTATUS SetCurrentMode(ULONG Mode) = 0; virtual NTSTATUS GetCurrentMode(ULONG* Mode) = 0; virtual NTSTATUS SetPowerState(DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; virtual NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; virtual NTSTATUS HWClose(void) = 0; QXL_NON_PAGED virtual BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber) = 0; QXL_NON_PAGED virtual VOID DpcRoutine(PVOID) = 0; QXL_NON_PAGED virtual VOID ResetDevice(void) = 0; virtual NTSTATUS AcquireFrameBuffer(CURRENT_BDD_MODE* pCurrentBddMode) { return STATUS_SUCCESS; } virtual NTSTATUS ReleaseFrameBuffer(CURRENT_BDD_MODE* pCurrentBddMode) { return STATUS_SUCCESS; } virtual ULONG GetModeCount(void) = 0; PVIDEO_MODE_INFORMATION GetModeInfo(UINT idx) {return &m_ModeInfo[idx];} USHORT GetModeNumber(USHORT idx) {return m_ModeNumbers[idx];} USHORT GetCurrentModeIndex(void) {return m_CurrentMode;} VOID SetCurrentModeIndex(USHORT idx) {m_CurrentMode = idx;} virtual NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, _In_ UINT DstBitPerPixel, _In_ BYTE* SrcAddr, _In_ UINT SrcBytesPerPixel, _In_ LONG SrcPitch, _In_ ULONG NumMoves, _In_ D3DKMT_MOVE_RECT* pMoves, _In_ ULONG NumDirtyRects, _In_ RECT* pDirtyRect, _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, _In_ const CURRENT_BDD_MODE* pModeCur) = 0; virtual VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) = 0; virtual NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) = 0; virtual NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) = 0; virtual NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscap) = 0; NTSTATUS AcquireDisplayInfo(DXGK_DISPLAY_INFORMATION& DispInfo); ULONG GetId(void) { return m_Id; } protected: virtual NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; protected: QxlDod* m_pQxlDod; PVIDEO_MODE_INFORMATION m_ModeInfo; ULONG m_ModeCount; PUSHORT m_ModeNumbers; USHORT m_CurrentMode; USHORT m_CustomMode; ULONG m_Id; }; class VgaDevice : public HwDeviceInterface { public: VgaDevice(_In_ QxlDod* pQxlDod); ~VgaDevice(void); NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); NTSTATUS SetCurrentMode(ULONG Mode); NTSTATUS GetCurrentMode(ULONG* Mode); ULONG GetModeCount(void) {return m_ModeCount;} NTSTATUS SetPowerState(DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, _In_ UINT DstBitPerPixel, _In_ BYTE* SrcAddr, _In_ UINT SrcBytesPerPixel, _In_ LONG SrcPitch, _In_ ULONG NumMoves, _In_ D3DKMT_MOVE_RECT* pMoves, _In_ ULONG NumDirtyRects, _In_ RECT* pDirtyRect, _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, _In_ const CURRENT_BDD_MODE* pModeCur); VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod); QXL_NON_PAGED BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber); QXL_NON_PAGED VOID DpcRoutine(PVOID); QXL_NON_PAGED VOID ResetDevice(VOID); NTSTATUS AcquireFrameBuffer(CURRENT_BDD_MODE* pCurrentBddMode); NTSTATUS ReleaseFrameBuffer(CURRENT_BDD_MODE* pCurrentBddMode); NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape); NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition); NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscap); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); private: BOOL SetVideoModeInfo(UINT Idx, PVBE_MODEINFO pModeInfo); }; typedef struct _MemSlot { UINT8 generation; UINT64 start_phys_addr; UINT64 end_phys_addr; UINT64 start_virt_addr; UINT64 end_virt_addr; QXLPHYSICAL high_bits; } MemSlot; typedef struct MspaceInfo { mspace _mspace; UINT8 *mspace_start; UINT8 *mspace_end; } MspaceInfo; enum { MSPACE_TYPE_DEVRAM, MSPACE_TYPE_VRAM, NUM_MSPACES, }; #define RELEASE_RES(res) if (!--(res)->refs) (res)->free(res); #define GET_RES(res) (++(res)->refs) /* Debug helpers - tag each resource with this enum */ enum { RESOURCE_TYPE_DRAWABLE = 1, RESOURCE_TYPE_SURFACE, RESOURCE_TYPE_PATH, RESOURCE_TYPE_CLIP_RECTS, RESOURCE_TYPE_QUIC_IMAGE, RESOURCE_TYPE_BITMAP_IMAGE, RESOURCE_TYPE_SURFACE_IMAGE, RESOURCE_TYPE_SRING, RESOURCE_TYPE_CURSOR, RESOURCE_TYPE_BUF, RESOURCE_TYPE_UPDATE, }; #ifdef DBG #define RESOURCE_TYPE(res, val) do { res->type = val; } while (0) #else #define RESOURCE_TYPE(res, val) #endif typedef struct Resource Resource; struct Resource { UINT32 refs; void* ptr; #ifdef DBG UINT32 type; #endif void (*free)(Resource *res); UINT8 res[0]; }; #define TIMEOUT_TO_MS ((LONGLONG) 1 * 10 * 1000) BOOLEAN FORCEINLINE WaitForObject( PVOID Object, PLARGE_INTEGER Timeout) { NTSTATUS status; status = KeWaitForSingleObject ( Object, Executive, KernelMode, FALSE, Timeout); ASSERT(NT_SUCCESS(status)); return (status == STATUS_SUCCESS); } VOID FORCEINLINE ReleaseMutex( PKMUTEX Mutex, BOOLEAN locked) { if (locked) { KeReleaseMutex(Mutex, FALSE); } } #define QXL_SLEEP(msec) do { \ LARGE_INTEGER timeout; \ timeout.QuadPart = -msec * TIMEOUT_TO_MS; \ KeDelayExecutionThread (KernelMode, FALSE, &timeout);\ } while (0); #define IMAGE_HASH_INIT_VAL(width, height, format) \ ((UINT32)((width) & 0x1FFF) | ((UINT32)((height) & 0x1FFF) << 13) |\ ((UINT32)(format) << 26)) #define MAX_OUTPUT_RES 6 typedef struct QXLOutput { UINT32 num_res; #ifdef DBG UINT32 type; #endif Resource *resources[MAX_OUTPUT_RES]; UINT8 data[0]; } QXLOutput; typedef struct Ring RingItem; typedef struct Ring { RingItem *prev; RingItem *next; } Ring; typedef struct InternalImage { QXLImage image; } InternalImage; typedef struct InternalCursor { QXLCursor cursor; } InternalCursor; #define CURSOR_ALLOC_SIZE (PAGE_SIZE << 1) typedef struct DpcCbContext { void* ptr; UINT32 data; } DPC_CB_CONTEXT,* PDPC_CB_CONTEXT; #define BITMAP_ALLOC_BASE (sizeof(Resource) + sizeof(InternalImage) + sizeof(QXLDataChunk)) #define BITS_BUF_MAX (64 * 1024) #define MIN(x, y) (((x) <= (y)) ? (x) : (y)) #define MAX(x, y) (((x) >= (y)) ? (x) : (y)) #define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1)) class QxlDevice : public HwDeviceInterface { public: QxlDevice(_In_ QxlDod* pQxlDod); ~QxlDevice(void); NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode); NTSTATUS SetCurrentMode(ULONG Mode); NTSTATUS GetCurrentMode(ULONG* Mode); ULONG GetModeCount(void) {return m_ModeCount;} NTSTATUS SetPowerState(DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, _In_ UINT DstBitPerPixel, _In_ BYTE* SrcAddr, _In_ UINT SrcBytesPerPixel, _In_ LONG SrcPitch, _In_ ULONG NumMoves, _In_ D3DKMT_MOVE_RECT* pMoves, _In_ ULONG NumDirtyRects, _In_ RECT* pDirtyRect, _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, _In_ const CURRENT_BDD_MODE* pModeCur); VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod); QXL_NON_PAGED BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber); QXL_NON_PAGED VOID DpcRoutine(PVOID); QXL_NON_PAGED VOID ResetDevice(VOID); NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape); NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition); NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscap); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); VOID BltBits (BLT_INFO* pDst, CONST BLT_INFO* pSrc, UINT NumRects, _In_reads_(NumRects) CONST RECT *pRects, POINT* pSourcePoint); QXLDrawable *Drawable(UINT8 type, CONST RECT *area, CONST RECT *clip, UINT32 surface_id); void PushDrawable(QXLDrawable *drawable); void PushCursorCmd(QXLCursorCmd *cursor_cmd); QXLDrawable *GetDrawable(); QXLCursorCmd *CursorCmd(); void *AllocMem(UINT32 mspace_type, size_t size, BOOL force); VOID UpdateArea(CONST RECT* area, UINT32 surface_id); VOID SetImageId(InternalImage *internal, BOOL cache_me, LONG width, LONG height, UINT8 format, UINT32 key); private: NTSTATUS QxlInit(DXGK_DISPLAY_INFORMATION* pDispInfo); void QxlClose(void); void UnmapMemory(void); BOOL SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo); void UpdateVideoModeInfo(UINT Idx, UINT xres, UINT yres, UINT bpp); BOOL InitMemSlots(void); BOOL CreateMemSlots(void); void DestroyMemSlots(void); void CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo); void DestroyPrimarySurface(void); void SetupHWSlot(UINT8 Idx, MemSlot *pSlot); UINT8 SetupMemSlot(UINT8 Idx, UINT64 pastart, UINT64 paend, UINT64 vastart, UINT64 vaend); BOOL CreateEvents(void); BOOL CreateRings(void); UINT64 VA(QXLPHYSICAL paddr, UINT8 slot_id); QXLPHYSICAL PA(PVOID virt, UINT8 slot_id); void InitDeviceMemoryResources(void); void InitMonitorConfig(); void InitMspace(UINT32 mspace_type, UINT8 *start, size_t capacity); void FlushReleaseRing(); void FreeMem(UINT32 mspace_type, void *ptr); UINT64 ReleaseOutput(UINT64 output_id); void WaitForReleaseRing(void); void EmptyReleaseRing(void); BOOL SetClip(const RECT *clip, QXLDrawable *drawable); void AddRes(QXLOutput *output, Resource *res); void DrawableAddRes(QXLDrawable *drawable, Resource *res); void CursorCmdAddRes(QXLCursorCmd *cmd, Resource *res); void FreeClipRects(Resource *res); void static FreeClipRectsEx(Resource *res); void FreeBitmapImage(Resource *res); void static FreeBitmapImageEx(Resource *res); void static FreeCursorEx(Resource *res); void FreeCursor(Resource *res); void WaitForCmdRing(void); void PushCmd(void); void WaitForCursorRing(void); void PushCursor(void); void PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, UINT8 **end_ptr, UINT8 *src, int size, size_t alloc_size, uint32_t alignment); QXL_NON_PAGED BOOLEAN static DpcCallbackEx(PVOID); QXL_NON_PAGED void DpcCallback(PDPC_CB_CONTEXT); void AsyncIo(UCHAR Port, UCHAR Value); void SyncIo(UCHAR Port, UCHAR Value); NTSTATUS UpdateChildStatus(BOOLEAN connect); NTSTATUS SetCustomDisplay(QXLEscapeSetCustomDisplay* custom_display); void SetMonitorConfig(QXLHead* monitor_config); static LONG GetMaxSourceMappingHeight(D3DKMT_MOVE_RECT* Moves, ULONG NumMoves, RECT* DirtyRects, ULONG NumDirtyRects); private: PUCHAR m_IoBase; BOOLEAN m_IoMapped; ULONG m_IoSize; PHYSICAL_ADDRESS m_RamPA; UINT8 *m_RamStart; QXLRam *m_RamHdr; ULONG m_RamSize; PHYSICAL_ADDRESS m_VRamPA; UINT8 *m_VRamStart; ULONG m_VRamSize; QXLRom *m_RomHdr; ULONG m_RomSize; MemSlot *m_MemSlots; UINT8 m_NumMemSlots; UINT8 m_MainMemSlot; UINT8 m_SurfaceMemSlot; UINT8 m_SlotIdBits; UINT8 m_SlotGenBits; QXLPHYSICAL m_VaSlotMask; QXLCommandRing *m_CommandRing; QXLCursorRing *m_CursorRing; QXLReleaseRing *m_ReleaseRing; KEVENT m_DisplayEvent; KEVENT m_CursorEvent; KEVENT m_IoCmdEvent; PUCHAR m_LogPort; PUCHAR m_LogBuf; KMUTEX m_MemLock; KMUTEX m_CmdLock; KMUTEX m_IoLock; KMUTEX m_CrsLock; MspaceInfo m_MSInfo[NUM_MSPACES]; UINT64 m_FreeOutputs; UINT32 m_Pending; QXLMonitorsConfig* m_monitor_config; QXLPHYSICAL* m_monitor_config_pa; }; class QxlDod { private: DEVICE_OBJECT* m_pPhysicalDevice; DXGKRNL_INTERFACE m_DxgkInterface; DXGK_DEVICE_INFO m_DeviceInfo; DEVICE_POWER_STATE m_MonitorPowerState; DEVICE_POWER_STATE m_AdapterPowerState; QXL_FLAGS m_Flags; CURRENT_BDD_MODE m_CurrentModes[MAX_VIEWS]; D3DDDI_VIDEO_PRESENT_SOURCE_ID m_SystemDisplaySourceId; DXGKARG_SETPOINTERSHAPE m_PointerShape; HwDeviceInterface* m_pHWDevice; DWORD m_VgaCompatible; DWORD m_PointerCaps; public: QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject); ~QxlDod(void); #pragma code_seg(push) #pragma code_seg() BOOLEAN IsDriverActive() const { return m_Flags.DriverStarted; } #pragma code_seg(pop) NTSTATUS StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, _In_ DXGKRNL_INTERFACE* pDxgkInterface, _Out_ ULONG* pNumberOfViews, _Out_ ULONG* pNumberOfChildren); NTSTATUS StopDevice(VOID); // Must be Non-Paged QXL_NON_PAGED VOID ResetDevice(VOID); NTSTATUS DispatchIoRequest(_In_ ULONG VidPnSourceId, _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket); NTSTATUS SetPowerState(_In_ ULONG HardwareUid, _In_ DEVICE_POWER_STATE DevicePowerState, _In_ POWER_ACTION ActionType); // Report back child capabilities NTSTATUS QueryChildRelations(_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations, _In_ ULONG ChildRelationsSize); NTSTATUS QueryChildStatus(_Inout_ DXGK_CHILD_STATUS* pChildStatus, _In_ BOOLEAN NonDestructiveOnly); // Return EDID if previously retrieved NTSTATUS QueryDeviceDescriptor(_In_ ULONG ChildUid, _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor); // Must be Non-Paged // BDD doesn't have interrupts, so just returns false QXL_NON_PAGED BOOLEAN InterruptRoutine(_In_ ULONG MessageNumber); QXL_NON_PAGED VOID DpcRoutine(VOID); // Return DriverCaps, doesn't support other queries though NTSTATUS QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo); NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition); NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape); NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscape); NTSTATUS PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly); NTSTATUS QueryInterface(_In_ CONST PQUERY_INTERFACE QueryInterface); NTSTATUS IsSupportedVidPn(_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn); NTSTATUS RecommendFunctionalVidPn(_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn); NTSTATUS RecommendVidPnTopology(_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology); NTSTATUS RecommendMonitorModes(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes); NTSTATUS EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality); NTSTATUS SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility); NTSTATUS CommitVidPn(_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn); NTSTATUS UpdateActiveVidPnPresentPath(_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath); NTSTATUS QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps); // Part of PnPStop (PnP instance only), returns current mode information (which will be passed to fallback instance by dxgkrnl) NTSTATUS StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, _Out_ DXGK_DISPLAY_INFORMATION* pDisplayInfo); // Must be Non-Paged // Call to initialize as part of bugcheck QXL_NON_PAGED NTSTATUS SystemDisplayEnable(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags, _Out_ UINT* pWidth, _Out_ UINT* pHeight, _Out_ D3DDDIFORMAT* pColorFormat); // Must be Non-Paged // Write out pixels as part of bugcheck QXL_NON_PAGED VOID SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VOID* pSource, _In_ UINT SourceWidth, _In_ UINT SourceHeight, _In_ UINT SourceStride, _In_ INT PositionX, _In_ INT PositionY); PDXGKRNL_INTERFACE GetDxgkInterface(void) { return &m_DxgkInterface;} NTSTATUS AcquireDisplayInfo(DXGK_DISPLAY_INFORMATION& DispInfo) { return m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &DispInfo); } private: VOID CleanUp(VOID); NTSTATUS CheckHardware(); NTSTATUS WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue); // Set the given source mode on the given path NTSTATUS SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode, 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); QXL_NON_PAGED 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(_In_ ULONG Id); NTSTATUS ReadConfiguration(); }; 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); QXL_NON_PAGED UINT BPPFromPixelFormat(D3DDDIFORMAT Format); QXL_NON_PAGED D3DDDIFORMAT PixelFormatFromBPP(UINT BPP); UINT SpiceFromPixelFormat(D3DDDIFORMAT Format); QXL_NON_PAGED VOID CopyBitsGeneric( BLT_INFO* pDst, CONST BLT_INFO* pSrc, UINT NumRects, _In_reads_(NumRects) CONST RECT *pRects); QXL_NON_PAGED VOID CopyBits32_32( BLT_INFO* pDst, CONST BLT_INFO* pSrc, UINT NumRects, _In_reads_(NumRects) CONST RECT *pRects); QXL_NON_PAGED VOID BltBits ( BLT_INFO* pDst, CONST BLT_INFO* pSrc, UINT NumRects, _In_reads_(NumRects) CONST RECT *pRects); QXL_NON_PAGED BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect); QXL_NON_PAGED VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch);