From 529445dbb99d4c5511644ecc257bfe786045ec78 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 10 Mar 2014 22:49:58 +1100 Subject: add dual interface to support QXL or VGA modes --- qxldod/QxlDod.cpp | 814 ++++++++++++++++++++++++++++++------------------------ qxldod/QxlDod.h | 116 +++++--- 2 files changed, 533 insertions(+), 397 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index a48023f..3e29478 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -55,7 +55,7 @@ QxlDod::QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pP RtlZeroMemory(&m_DeviceInfo, sizeof(m_DeviceInfo)); RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes)); RtlZeroMemory(&m_PointerShape, sizeof(m_PointerShape)); - m_pHWDevice = new(PagedPool) VgaDevice(this); + m_pHWDevice = NULL; DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); } @@ -66,9 +66,46 @@ QxlDod::~QxlDod(void) DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); CleanUp(); delete m_pHWDevice; + m_pHWDevice = NULL; DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } +NTSTATUS QxlDod::CheckHardware() +{ + PAGED_CODE(); + + NTSTATUS Status; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + + // Get the Vendor & Device IDs on PCI system + PCI_COMMON_HEADER Header = {0}; + ULONG BytesRead; + + Status = m_DxgkInterface.DxgkCbReadDeviceSpace(m_DxgkInterface.DeviceHandle, + DXGK_WHICHSPACE_CONFIG, + &Header, + 0, + sizeof(Header), + &BytesRead); + + if (!NT_SUCCESS(Status)) + { + DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbReadDeviceSpace failed with status 0x%X\n", Status)); + return Status; + } + + Status = STATUS_GRAPHICS_DRIVER_MISMATCH; + if (Header.VendorID == 0x1B36 && + Header.DeviceID == 0x0100 && + Header.RevisionID == 4) + { + Status = STATUS_SUCCESS; + } + + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s returned with status 0x%X\n", __FUNCTION__, Status)); + return Status; +} NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, _In_ DXGKRNL_INTERFACE* pDxgkInterface, @@ -103,13 +140,6 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, return Status; } -// TODO: Uncomment the line below after updating the TODOs in the function CheckHardware -// Status = CheckHardware(); -// if (!NT_SUCCESS(Status)) -// { -// return Status; -// } - // This sample driver only uses the frame buffer of the POST device. DxgkCbAcquirePostDisplayOwnership // gives you the frame buffer address and ensures that no one else is drawing to it. Be sure to give it back! Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &(m_CurrentModes[0].DispInfo)); @@ -117,14 +147,25 @@ NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo, { // The most likely cause of failure is that the driver is simply not running on a POST device, or we are running // after a pre-WDDM 1.2 driver. Since we can't draw anything, we should fail to start. + DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbAcquirePostDisplayOwnership failed with status 0x%X Width = %d\n", + Status, m_CurrentModes[0].DispInfo.Width)); return STATUS_UNSUCCESSFUL; } + Status = CheckHardware(); + if (NT_SUCCESS(Status)) + { + m_pHWDevice = new(PagedPool) QxlDevice(this); + } + else + { + m_pHWDevice = new(PagedPool) VgaDevice(this); + } + Status = m_pHWDevice->HWInit(m_DeviceInfo.TranslatedResourceList, &m_CurrentModes[0].DispInfo); if (!NT_SUCCESS(Status)) { - QXL_LOG_ASSERTION1("HWInit failed with status 0x%X\n", - Status); + DbgPrint(TRACE_LEVEL_ERROR, ("HWInit failed with status 0x%X\n", Status)); return Status; } @@ -456,7 +497,7 @@ NTSTATUS QxlDod::PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPre m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].SrcModeWidth)*DstBitPerPixel/8; pDst += (int)CenterShift/2; } - Status = ExecutePresentDisplayOnly( + Status = m_pHWDevice->ExecutePresentDisplayOnly( pDst, DstBitPerPixel, (BYTE*)pPresentDisplayOnly->pSource, @@ -466,7 +507,8 @@ NTSTATUS QxlDod::PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPre pPresentDisplayOnly->pMoves, pPresentDisplayOnly->NumDirtyRects, pPresentDisplayOnly->pDirtyRect, - RotationNeededByFb); + RotationNeededByFb, + &m_CurrentModes[0]); } DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return Status; @@ -499,62 +541,13 @@ NTSTATUS QxlDod::StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRE } // The driver has to black out the display and ensure it is visible when releasing ownership - BlackOutScreen(SourceId); + m_pHWDevice->BlackOutScreen(&m_CurrentModes[SourceId]); *pDisplayInfo = m_CurrentModes[SourceId].DispInfo; return StopDevice(); } -VOID QxlDod::BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId) -{ - PAGED_CODE(); - - UINT ScreenHeight = m_CurrentModes[SourceId].DispInfo.Height; - UINT ScreenPitch = m_CurrentModes[SourceId].DispInfo.Pitch; - - PHYSICAL_ADDRESS NewPhysAddrStart = m_CurrentModes[SourceId].DispInfo.PhysicAddress; - PHYSICAL_ADDRESS NewPhysAddrEnd; - NewPhysAddrEnd.QuadPart = NewPhysAddrStart.QuadPart + (ScreenHeight * ScreenPitch); - - if (m_CurrentModes[SourceId].Flags.FrameBufferIsActive) - { - BYTE* MappedAddr = reinterpret_cast(m_CurrentModes[SourceId].FrameBuffer.Ptr); - - // Zero any memory at the start that hasn't been zeroed recently - if (NewPhysAddrStart.QuadPart < m_CurrentModes[SourceId].ZeroedOutStart.QuadPart) - { - if (NewPhysAddrEnd.QuadPart < m_CurrentModes[SourceId].ZeroedOutStart.QuadPart) - { - // No overlap - RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch); - } - else - { - RtlZeroMemory(MappedAddr, (UINT)(m_CurrentModes[SourceId].ZeroedOutStart.QuadPart - NewPhysAddrStart.QuadPart)); - } - } - - // Zero any memory at the end that hasn't been zeroed recently - if (NewPhysAddrEnd.QuadPart > m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart) - { - if (NewPhysAddrStart.QuadPart > m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart) - { - // No overlap - // NOTE: When actual pixels were the most recent thing drawn, ZeroedOutStart & ZeroedOutEnd will both be 0 - // and this is the path that will be used to black out the current screen. - RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch); - } - else - { - RtlZeroMemory(MappedAddr, (UINT)(NewPhysAddrEnd.QuadPart - m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart)); - } - } - } - - m_CurrentModes[SourceId].ZeroedOutStart.QuadPart = NewPhysAddrStart.QuadPart; - m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart = NewPhysAddrEnd.QuadPart; -} NTSTATUS QxlDod::QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps) { @@ -1275,7 +1268,7 @@ NTSTATUS QxlDod::SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIB } else { - BlackOutScreen(SourceId); + m_pHWDevice->BlackOutScreen(&m_CurrentModes[SourceId]); } // Store current visibility so it can be dealt with during Present call @@ -1481,7 +1474,7 @@ NTSTATUS QxlDod::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMo CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) { PAGED_CODE(); - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s SourceId = %d\n", __FUNCTION__, pPath->VidPnSourceId)); NTSTATUS Status = STATUS_SUCCESS; @@ -1510,13 +1503,15 @@ NTSTATUS QxlDod::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMo { pCurrentBddMode->Flags.FrameBufferIsActive = TRUE; - BlackOutScreen(pPath->VidPnSourceId); + m_pHWDevice->BlackOutScreen(&m_CurrentModes[pPath->VidPnSourceId]); // Mark that the next present should be fullscreen so the screen doesn't go from black to actual pixels one dirty rect at a time. pCurrentBddMode->Flags.FullscreenPresent = TRUE; for (USHORT ModeIndex = 0; ModeIndex < m_pHWDevice->GetModeCount(); ++ModeIndex) { - PVIDEO_MODE_INFORMATION pModeInfo = m_pHWDevice->GetModeInfo(m_pHWDevice->GetCurrentModeIndex()); + PVIDEO_MODE_INFORMATION pModeInfo = m_pHWDevice->GetModeInfo(ModeIndex); + DbgPrint(TRACE_LEVEL_INFORMATION, ("%d\t%d x %d\t%d x %d\n", ModeIndex, pCurrentBddMode->DispInfo.Width, pCurrentBddMode->DispInfo.Height, + pModeInfo->VisScreenWidth, pModeInfo->VisScreenHeight)); if (pCurrentBddMode->DispInfo.Width == pModeInfo->VisScreenWidth && pCurrentBddMode->DispInfo.Height == pModeInfo->VisScreenHeight ) { @@ -1530,7 +1525,7 @@ NTSTATUS QxlDod::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMo } } - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); return Status; } @@ -1877,214 +1872,107 @@ NTSTATUS QxlDod::RegisterHWInfo() } -NTSTATUS -QxlDod::ExecutePresentDisplayOnly( - _In_ BYTE* DstAddr, - _In_ UINT DstBitPerPixel, - _In_ BYTE* SrcAddr, - _In_ UINT SrcBytesPerPixel, - _In_ LONG SrcPitch, - _In_ ULONG NumMoves, - _In_ D3DKMT_MOVE_RECT* Moves, - _In_ ULONG NumDirtyRects, - _In_ RECT* DirtyRect, - _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation) -/*++ - - Routine Description: - - The method creates present worker thread and provides context - for it filled with present commands - - Arguments: +// +// Non-Paged Code +// +#pragma code_seg(push) +#pragma code_seg() +D3DDDI_VIDEO_PRESENT_SOURCE_ID QxlDod::FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero) +{ + UNREFERENCED_PARAMETER(TargetId); + for (UINT SourceId = 0; SourceId < MAX_VIEWS; ++SourceId) + { + if (m_CurrentModes[SourceId].FrameBuffer.Ptr != NULL) + { + return SourceId; + } + } - DstAddr - address of destination surface - DstBitPerPixel - color depth of destination surface - SrcAddr - address of source surface - SrcBytesPerPixel - bytes per pixel of source surface - SrcPitch - source surface pitch (bytes in a row) - NumMoves - number of moves to be copied - Moves - moves' data - NumDirtyRects - number of rectangles to be copied - DirtyRect - rectangles' data - Rotation - roatation to be performed when executing copy - CallBack - callback for present worker thread to report execution status + return DefaultToZero ? 0 : D3DDDI_ID_UNINITIALIZED; +} - Return Value: +#pragma code_seg(pop) // End Non-Paged Code - Status +// +// Frame buffer map/unmap +// ---*/ +NTSTATUS +MapFrameBuffer( + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ ULONG Length, + _Outptr_result_bytebuffer_(Length) VOID** VirtualAddress) { - PAGED_CODE(); - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); - - NTSTATUS Status = STATUS_SUCCESS; - - SIZE_T sizeMoves = NumMoves*sizeof(D3DKMT_MOVE_RECT); - SIZE_T sizeRects = NumDirtyRects*sizeof(RECT); - SIZE_T size = sizeof(DoPresentMemory) + sizeMoves + sizeRects; - - DoPresentMemory* ctx = reinterpret_cast - (new (NonPagedPoolNx) BYTE[size]); - if (!ctx) + // + // Check for parameters + // + if ((PhysicalAddress.QuadPart == (ULONGLONG)0) || + (Length == 0) || + (VirtualAddress == NULL)) { - return STATUS_NO_MEMORY; + DbgPrint(TRACE_LEVEL_ERROR, ("One of PhysicalAddress.QuadPart (0x%I64x), Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0", + PhysicalAddress.QuadPart, Length, VirtualAddress)); + return STATUS_INVALID_PARAMETER; } - RtlZeroMemory(ctx,size); - - const CURRENT_BDD_MODE* pModeCur = &m_CurrentModes[0]; - ctx->DstAddr = DstAddr; - ctx->DstBitPerPixel = DstBitPerPixel; - ctx->DstStride = pModeCur->DispInfo.Pitch; - ctx->SrcWidth = pModeCur->SrcModeWidth; - ctx->SrcHeight = pModeCur->SrcModeHeight; - ctx->SrcAddr = NULL; - ctx->SrcPitch = SrcPitch; - ctx->Rotation = Rotation; - ctx->NumMoves = NumMoves; - ctx->Moves = Moves; - ctx->NumDirtyRects = NumDirtyRects; - ctx->DirtyRect = DirtyRect; -// ctx->SourceID = m_SourceId; -// ctx->hAdapter = m_DevExt; - ctx->Mdl = NULL; - ctx->DisplaySource = this; - - // Alternate between synch and asynch execution, for demonstrating - // that a real hardware implementation can do either - + *VirtualAddress = MmMapIoSpace(PhysicalAddress, + Length, + MmWriteCombined); + if (*VirtualAddress == NULL) { - // Map Source into kernel space, as Blt will be executed by system worker thread - UINT sizeToMap = SrcBytesPerPixel * ctx->SrcWidth * ctx->SrcHeight; - - PMDL mdl = IoAllocateMdl((PVOID)SrcAddr, sizeToMap, FALSE, FALSE, NULL); - if(!mdl) - { - return STATUS_INSUFFICIENT_RESOURCES; - } + // The underlying call to MmMapIoSpace failed. This may be because, MmWriteCombined + // isn't supported, so try again with MmNonCached - KPROCESSOR_MODE AccessMode = static_cast(( SrcAddr <= - (BYTE* const) MM_USER_PROBE_ADDRESS)?UserMode:KernelMode); - __try - { - // Probe and lock the pages of this buffer in physical memory. - // We need only IoReadAccess. - MmProbeAndLockPages(mdl, AccessMode, IoReadAccess); - } - #pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try/except is only able to protect against user-mode errors and these are the only errors we try to catch here"); - __except(EXCEPTION_EXECUTE_HANDLER) + *VirtualAddress = MmMapIoSpace(PhysicalAddress, + Length, + MmNonCached); + if (*VirtualAddress == NULL) { - Status = GetExceptionCode(); - IoFreeMdl(mdl); - return Status; + DbgPrint(TRACE_LEVEL_ERROR, ("MmMapIoSpace returned a NULL buffer when trying to allocate 0x%I64x bytes", Length)); + return STATUS_NO_MEMORY; } + } - // Map the physical pages described by the MDL into system space. - // Note: double mapping the buffer this way causes lot of system - // overhead for large size buffers. - ctx->SrcAddr = reinterpret_cast - (MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority )); - - if(!ctx->SrcAddr) { - Status = STATUS_INSUFFICIENT_RESOURCES; - MmUnlockPages(mdl); - IoFreeMdl(mdl); - return Status; - } + return STATUS_SUCCESS; +} - // Save Mdl to unmap and unlock the pages in worker thread - ctx->Mdl = mdl; - } +NTSTATUS +UnmapFrameBuffer( + _In_reads_bytes_(Length) VOID* VirtualAddress, + _In_ ULONG Length) +{ + PAGED_CODE(); - BYTE* rects = reinterpret_cast(ctx+1); - // copy moves and update pointer - if (Moves) + // + // Check for parameters + // + if ((VirtualAddress == NULL) && (Length == 0)) { - memcpy(rects,Moves,sizeMoves); - ctx->Moves = reinterpret_cast(rects); - rects += sizeMoves; + // Allow this function to be called when there's no work to do, and treat as successful + return STATUS_SUCCESS; } - - // copy dirty rects and update pointer - if (DirtyRect) + else if ((VirtualAddress == NULL) || (Length == 0)) { - memcpy(rects,DirtyRect,sizeRects); - ctx->DirtyRect = reinterpret_cast(rects); + DbgPrint(TRACE_LEVEL_ERROR, ("Only one of Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0", + Length, VirtualAddress)); + return STATUS_INVALID_PARAMETER; } + MmUnmapIoSpace(VirtualAddress, + Length); -// HwExecutePresentDisplayOnly((PVOID)ctx); + return STATUS_SUCCESS; +} - // Set up destination blt info - BLT_INFO DstBltInfo; - DstBltInfo.pBits = ctx->DstAddr; - DstBltInfo.Pitch = ctx->DstStride; - DstBltInfo.BitsPerPel = ctx->DstBitPerPixel; - DstBltInfo.Offset.x = 0; - DstBltInfo.Offset.y = 0; - DstBltInfo.Rotation = ctx->Rotation; - DstBltInfo.Width = ctx->SrcWidth; - DstBltInfo.Height = ctx->SrcHeight; - - // Set up source blt info - BLT_INFO SrcBltInfo; - SrcBltInfo.pBits = ctx->SrcAddr; - SrcBltInfo.Pitch = ctx->SrcPitch; - SrcBltInfo.BitsPerPel = 32; - SrcBltInfo.Offset.x = 0; - SrcBltInfo.Offset.y = 0; - SrcBltInfo.Rotation = D3DKMDT_VPPR_IDENTITY; - if (ctx->Rotation == D3DKMDT_VPPR_ROTATE90 || - ctx->Rotation == D3DKMDT_VPPR_ROTATE270) - { - SrcBltInfo.Width = DstBltInfo.Height; - SrcBltInfo.Height = DstBltInfo.Width; - } - else - { - SrcBltInfo.Width = DstBltInfo.Width; - SrcBltInfo.Height = DstBltInfo.Height; - } - - // Copy all the scroll rects from source image to video frame buffer. - for (UINT i = 0; i < ctx->NumMoves; i++) - { - BltBits(&DstBltInfo, - &SrcBltInfo, - 1, // NumRects - &ctx->Moves[i].DestRect); - } - - // Copy all the dirty rects from source image to video frame buffer. - for (UINT i = 0; i < ctx->NumDirtyRects; i++) - { - - BltBits(&DstBltInfo, - &SrcBltInfo, - 1, // NumRects - &ctx->DirtyRect[i]); - } - - // Unmap unmap and unlock the pages. - if (ctx->Mdl) - { - MmUnlockPages(ctx->Mdl); - IoFreeMdl(ctx->Mdl); - } - delete [] reinterpret_cast(ctx); - - return STATUS_SUCCESS; -} +// HW specific code -VOID QxlDod::GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch) +VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch) { switch (pBltInfo->Rotation) { @@ -2122,7 +2010,7 @@ VOID QxlDod::GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, } } -BYTE* QxlDod::GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect) +BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect) { BYTE* pRet = NULL; LONG OffLeft = pRect->left + pBltInfo->Offset.x; @@ -2185,7 +2073,7 @@ BYTE* QxlDod::GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect) * \**************************************************************************/ -VOID QxlDod::CopyBitsGeneric( +VOID CopyBitsGeneric( BLT_INFO* pDst, CONST BLT_INFO* pSrc, UINT NumRects, @@ -2279,7 +2167,7 @@ VOID QxlDod::CopyBitsGeneric( } -VOID QxlDod::CopyBits32_32( +VOID CopyBits32_32( BLT_INFO* pDst, CONST BLT_INFO* pSrc, UINT NumRects, @@ -2320,7 +2208,7 @@ VOID QxlDod::CopyBits32_32( } -VOID QxlDod::BltBits ( +VOID BltBits ( BLT_INFO* pDst, CONST BLT_INFO* pSrc, UINT NumRects, @@ -2352,103 +2240,6 @@ VOID QxlDod::BltBits ( } } -// -// Non-Paged Code -// -#pragma code_seg(push) -#pragma code_seg() -D3DDDI_VIDEO_PRESENT_SOURCE_ID QxlDod::FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero) -{ - UNREFERENCED_PARAMETER(TargetId); - for (UINT SourceId = 0; SourceId < MAX_VIEWS; ++SourceId) - { - if (m_CurrentModes[SourceId].FrameBuffer.Ptr != NULL) - { - return SourceId; - } - } - - return DefaultToZero ? 0 : D3DDDI_ID_UNINITIALIZED; -} - -#pragma code_seg(pop) // End Non-Paged Code - -// -// Frame buffer map/unmap -// - -NTSTATUS -MapFrameBuffer( - _In_ PHYSICAL_ADDRESS PhysicalAddress, - _In_ ULONG Length, - _Outptr_result_bytebuffer_(Length) VOID** VirtualAddress) -{ - PAGED_CODE(); - - // - // Check for parameters - // - if ((PhysicalAddress.QuadPart == (ULONGLONG)0) || - (Length == 0) || - (VirtualAddress == NULL)) - { - DbgPrint(TRACE_LEVEL_ERROR, ("One of PhysicalAddress.QuadPart (0x%I64x), Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0", - PhysicalAddress.QuadPart, Length, VirtualAddress)); - return STATUS_INVALID_PARAMETER; - } - - *VirtualAddress = MmMapIoSpace(PhysicalAddress, - Length, - MmWriteCombined); - if (*VirtualAddress == NULL) - { - // The underlying call to MmMapIoSpace failed. This may be because, MmWriteCombined - // isn't supported, so try again with MmNonCached - - *VirtualAddress = MmMapIoSpace(PhysicalAddress, - Length, - MmNonCached); - if (*VirtualAddress == NULL) - { - DbgPrint(TRACE_LEVEL_ERROR, ("MmMapIoSpace returned a NULL buffer when trying to allocate 0x%I64x bytes", Length)); - return STATUS_NO_MEMORY; - } - } - - return STATUS_SUCCESS; -} - -NTSTATUS -UnmapFrameBuffer( - _In_reads_bytes_(Length) VOID* VirtualAddress, - _In_ ULONG Length) -{ - PAGED_CODE(); - - - // - // Check for parameters - // - if ((VirtualAddress == NULL) && (Length == 0)) - { - // Allow this function to be called when there's no work to do, and treat as successful - return STATUS_SUCCESS; - } - else if ((VirtualAddress == NULL) || (Length == 0)) - { - DbgPrint(TRACE_LEVEL_ERROR, ("Only one of Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0", - Length, VirtualAddress)); - return STATUS_INVALID_PARAMETER; - } - - MmUnmapIoSpace(VirtualAddress, - Length); - - return STATUS_SUCCESS; -} - -// HW specific code - VgaDevice::VgaDevice(_In_ QxlDod* pQxlDod) { m_pQxlDod = pQxlDod; @@ -2692,7 +2483,7 @@ NTSTATUS VgaDevice::SetCurrentMode(ULONG Mode) DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n")); return STATUS_UNSUCCESSFUL; } - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); return Status; } @@ -2729,7 +2520,7 @@ NTSTATUS VgaDevice::HWClose(void) NTSTATUS VgaDevice::SetPowerState(POWER_ACTION ActionType) { - DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); X86BIOS_REGISTERS regs = {0}; regs.Eax = 0x4F10; @@ -2748,10 +2539,268 @@ NTSTATUS VgaDevice::SetPowerState(POWER_ACTION ActionType) DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n")); return STATUS_UNSUCCESSFUL; } - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); + DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); return STATUS_SUCCESS; } + +NTSTATUS +VgaDevice::ExecutePresentDisplayOnly( + _In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* Moves, + _In_ ULONG NumDirtyRects, + _In_ RECT* DirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, + _In_ const CURRENT_BDD_MODE* pModeCur) +/*++ + + Routine Description: + + The method creates present worker thread and provides context + for it filled with present commands + + Arguments: + + DstAddr - address of destination surface + DstBitPerPixel - color depth of destination surface + SrcAddr - address of source surface + SrcBytesPerPixel - bytes per pixel of source surface + SrcPitch - source surface pitch (bytes in a row) + NumMoves - number of moves to be copied + Moves - moves' data + NumDirtyRects - number of rectangles to be copied + DirtyRect - rectangles' data + Rotation - roatation to be performed when executing copy + CallBack - callback for present worker thread to report execution status + + Return Value: + + Status + +--*/ +{ + + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + NTSTATUS Status = STATUS_SUCCESS; + + SIZE_T sizeMoves = NumMoves*sizeof(D3DKMT_MOVE_RECT); + SIZE_T sizeRects = NumDirtyRects*sizeof(RECT); + SIZE_T size = sizeof(DoPresentMemory) + sizeMoves + sizeRects; + + DoPresentMemory* ctx = reinterpret_cast + (new (NonPagedPoolNx) BYTE[size]); + + if (!ctx) + { + return STATUS_NO_MEMORY; + } + + RtlZeroMemory(ctx,size); + +// const CURRENT_BDD_MODE* pModeCur = &m_CurrentModes[0]; + ctx->DstAddr = DstAddr; + ctx->DstBitPerPixel = DstBitPerPixel; + ctx->DstStride = pModeCur->DispInfo.Pitch; + ctx->SrcWidth = pModeCur->SrcModeWidth; + ctx->SrcHeight = pModeCur->SrcModeHeight; + ctx->SrcAddr = NULL; + ctx->SrcPitch = SrcPitch; + ctx->Rotation = Rotation; + ctx->NumMoves = NumMoves; + ctx->Moves = Moves; + ctx->NumDirtyRects = NumDirtyRects; + ctx->DirtyRect = DirtyRect; +// ctx->SourceID = m_SourceId; +// ctx->hAdapter = m_DevExt; + ctx->Mdl = NULL; + ctx->DisplaySource = this; + + // Alternate between synch and asynch execution, for demonstrating + // that a real hardware implementation can do either + + { + // Map Source into kernel space, as Blt will be executed by system worker thread + UINT sizeToMap = SrcBytesPerPixel * ctx->SrcWidth * ctx->SrcHeight; + + PMDL mdl = IoAllocateMdl((PVOID)SrcAddr, sizeToMap, FALSE, FALSE, NULL); + if(!mdl) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + KPROCESSOR_MODE AccessMode = static_cast(( SrcAddr <= + (BYTE* const) MM_USER_PROBE_ADDRESS)?UserMode:KernelMode); + __try + { + // Probe and lock the pages of this buffer in physical memory. + // We need only IoReadAccess. + MmProbeAndLockPages(mdl, AccessMode, IoReadAccess); + } + #pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try/except is only able to protect against user-mode errors and these are the only errors we try to catch here"); + __except(EXCEPTION_EXECUTE_HANDLER) + { + Status = GetExceptionCode(); + IoFreeMdl(mdl); + return Status; + } + + // Map the physical pages described by the MDL into system space. + // Note: double mapping the buffer this way causes lot of system + // overhead for large size buffers. + ctx->SrcAddr = reinterpret_cast + (MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority )); + + if(!ctx->SrcAddr) { + Status = STATUS_INSUFFICIENT_RESOURCES; + MmUnlockPages(mdl); + IoFreeMdl(mdl); + return Status; + } + + // Save Mdl to unmap and unlock the pages in worker thread + ctx->Mdl = mdl; + } + + BYTE* rects = reinterpret_cast(ctx+1); + + // copy moves and update pointer + if (Moves) + { + memcpy(rects,Moves,sizeMoves); + ctx->Moves = reinterpret_cast(rects); + rects += sizeMoves; + } + + // copy dirty rects and update pointer + if (DirtyRect) + { + memcpy(rects,DirtyRect,sizeRects); + ctx->DirtyRect = reinterpret_cast(rects); + } + + +// HwExecutePresentDisplayOnly((PVOID)ctx); + + + // Set up destination blt info + BLT_INFO DstBltInfo; + DstBltInfo.pBits = ctx->DstAddr; + DstBltInfo.Pitch = ctx->DstStride; + DstBltInfo.BitsPerPel = ctx->DstBitPerPixel; + DstBltInfo.Offset.x = 0; + DstBltInfo.Offset.y = 0; + DstBltInfo.Rotation = ctx->Rotation; + DstBltInfo.Width = ctx->SrcWidth; + DstBltInfo.Height = ctx->SrcHeight; + + // Set up source blt info + BLT_INFO SrcBltInfo; + SrcBltInfo.pBits = ctx->SrcAddr; + SrcBltInfo.Pitch = ctx->SrcPitch; + SrcBltInfo.BitsPerPel = 32; + SrcBltInfo.Offset.x = 0; + SrcBltInfo.Offset.y = 0; + SrcBltInfo.Rotation = D3DKMDT_VPPR_IDENTITY; + if (ctx->Rotation == D3DKMDT_VPPR_ROTATE90 || + ctx->Rotation == D3DKMDT_VPPR_ROTATE270) + { + SrcBltInfo.Width = DstBltInfo.Height; + SrcBltInfo.Height = DstBltInfo.Width; + } + else + { + SrcBltInfo.Width = DstBltInfo.Width; + SrcBltInfo.Height = DstBltInfo.Height; + } + + + // Copy all the scroll rects from source image to video frame buffer. + for (UINT i = 0; i < ctx->NumMoves; i++) + { + BltBits(&DstBltInfo, + &SrcBltInfo, + 1, // NumRects + &ctx->Moves[i].DestRect); + } + + // Copy all the dirty rects from source image to video frame buffer. + for (UINT i = 0; i < ctx->NumDirtyRects; i++) + { + + BltBits(&DstBltInfo, + &SrcBltInfo, + 1, // NumRects + &ctx->DirtyRect[i]); + } + + // Unmap unmap and unlock the pages. + if (ctx->Mdl) + { + MmUnlockPages(ctx->Mdl); + IoFreeMdl(ctx->Mdl); + } + delete [] reinterpret_cast(ctx); + + return STATUS_SUCCESS; +} + +VOID VgaDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) +{ + PAGED_CODE(); + + UINT ScreenHeight = pCurrentBddMod->DispInfo.Height; + UINT ScreenPitch = pCurrentBddMod->DispInfo.Pitch; + + PHYSICAL_ADDRESS NewPhysAddrStart = pCurrentBddMod->DispInfo.PhysicAddress; + PHYSICAL_ADDRESS NewPhysAddrEnd; + NewPhysAddrEnd.QuadPart = NewPhysAddrStart.QuadPart + (ScreenHeight * ScreenPitch); + + if (pCurrentBddMod->Flags.FrameBufferIsActive) + { + BYTE* MappedAddr = reinterpret_cast(pCurrentBddMod->FrameBuffer.Ptr); + + // Zero any memory at the start that hasn't been zeroed recently + if (NewPhysAddrStart.QuadPart < pCurrentBddMod->ZeroedOutStart.QuadPart) + { + if (NewPhysAddrEnd.QuadPart < pCurrentBddMod->ZeroedOutStart.QuadPart) + { + // No overlap + RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch); + } + else + { + RtlZeroMemory(MappedAddr, (UINT)(pCurrentBddMod->ZeroedOutStart.QuadPart - NewPhysAddrStart.QuadPart)); + } + } + + // Zero any memory at the end that hasn't been zeroed recently + if (NewPhysAddrEnd.QuadPart > pCurrentBddMod->ZeroedOutEnd.QuadPart) + { + if (NewPhysAddrStart.QuadPart > pCurrentBddMod->ZeroedOutEnd.QuadPart) + { + // No overlap + // NOTE: When actual pixels were the most recent thing drawn, ZeroedOutStart & ZeroedOutEnd will both be 0 + // and this is the path that will be used to black out the current screen. + RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch); + } + else + { + RtlZeroMemory(MappedAddr, (UINT)(NewPhysAddrEnd.QuadPart - pCurrentBddMod->ZeroedOutEnd.QuadPart)); + } + } + } + + pCurrentBddMod->ZeroedOutStart.QuadPart = NewPhysAddrStart.QuadPart; + pCurrentBddMod->ZeroedOutEnd.QuadPart = NewPhysAddrEnd.QuadPart; +} + QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod) { m_pQxlDod = pQxlDod; @@ -2822,32 +2871,36 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) return STATUS_UNSUCCESSFUL; } + DbgPrint(TRACE_LEVEL_ERROR, ("%s: ModeCount = %d\n", __FUNCTION__, ModeCount)); + ModeCount += 2; m_ModeInfo = reinterpret_cast (new (PagedPool) BYTE[sizeof (VIDEO_MODE_INFORMATION) * ModeCount]); m_ModeNumbers = reinterpret_cast (new (PagedPool) BYTE [sizeof (USHORT) * ModeCount]); m_CurrentMode = 0; + UINT Height = pDispInfo->Height; + UINT Width = pDispInfo->Width; +// UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); for (CurrentMode = 0, SuitableModeCount = 0; CurrentMode < ModeCount; CurrentMode++) { - UINT Height = pDispInfo->Height; - UINT Width = pDispInfo->Width; - UINT BitsPerPixel = BPPFromPixelFormat(pDispInfo->ColorFormat); QXLMode* tmpModeInfo = &modes->modes[CurrentMode]; + DbgPrint(TRACE_LEVEL_ERROR, ("%s: modes[%d] x_res = %d, y_res = %d, bits = %d\n", __FUNCTION__, CurrentMode, tmpModeInfo->x_res, tmpModeInfo->y_res, tmpModeInfo->bits)); + if (tmpModeInfo->x_res >= Width && - tmpModeInfo->y_res >= Height && - tmpModeInfo->bits == BitsPerPixel) + tmpModeInfo->y_res >= Height/* && + tmpModeInfo->bits == BitsPerPixel*/) { - m_ModeNumbers[SuitableModeCount] = (USHORT)SuitableModeCount; + m_ModeNumbers[SuitableModeCount] = CurrentMode; SetVideoModeInfo(SuitableModeCount, tmpModeInfo); - if (tmpModeInfo->x_res == 1024 && - tmpModeInfo->y_res == 768) - { - m_CurrentMode = (USHORT)SuitableModeCount; - } +// if (tmpModeInfo->x_res == 1024 && +// tmpModeInfo->y_res == 768) +// { +// m_CurrentMode = (USHORT)SuitableModeCount; +// } SuitableModeCount++; } } @@ -2858,6 +2911,7 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) Status = STATUS_UNSUCCESSFUL; } + m_CurrentMode = m_ModeNumbers[0]; m_ModeCount = SuitableModeCount; DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount)); for (ULONG idx = 0; idx < m_ModeCount; idx++) @@ -3044,8 +3098,8 @@ NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* Status = GetModeList(pDispInfo); if (!NT_SUCCESS(Status)) { - QXL_LOG_ASSERTION1("GetModeList failed with status 0x%X\n", - Status); + DbgPrint(TRACE_LEVEL_ERROR, ("GetModeList failed with status 0x%X\n", + Status)); return Status; } @@ -3170,6 +3224,40 @@ void QxlDevice::ResetDevice(void) WRITE_PORT_UCHAR(m_IoBase + QXL_IO_MEMSLOT_ADD, 0); } + +NTSTATUS +QxlDevice::ExecutePresentDisplayOnly( + _In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* Moves, + _In_ ULONG NumDirtyRects, + _In_ RECT* DirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, + _In_ const CURRENT_BDD_MODE* pModeCur) +{ + + PAGED_CODE(); + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + NTSTATUS Status = STATUS_SUCCESS; + return Status; +} + +VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) +{ + PAGED_CODE(); + + UINT ScreenHeight = pCurrentBddMod->DispInfo.Height; + UINT ScreenPitch = pCurrentBddMod->DispInfo.Pitch; + + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + +} + NTSTATUS QxlDevice::HWClose(void) { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 36c8aa1..ee24f9e 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -210,7 +210,7 @@ class HwDeviceIntrface : public BaseObject { public: -// HwDeviceIntrface(_In_ QxlDod* pQxlDod); +// HwDeviceIntrface(_In_ QxlDod* pQxlDod) {m_pQxlDod = pQxlDod;} // virtual ~HwDeviceIntrface(void); virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0; virtual NTSTATUS SetCurrentMode(ULONG Mode) = 0; @@ -223,7 +223,41 @@ public: USHORT GetModeNumber(USHORT idx) {return m_ModeNumbers[idx];} USHORT GetCurrentModeIndex(void) {return m_CurrentMode;} VOID SetCurrentModeIndex(USHORT idx) {m_CurrentMode = idx;} + virtual NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* pMoves, + _In_ ULONG NumDirtyRects, + _In_ RECT* pDirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, + _In_ const CURRENT_BDD_MODE* pModeCur) = 0; + + virtual VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) = 0; protected: +/* + BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect); + VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch); + + VOID CopyBitsGeneric( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + + VOID CopyBits32_32( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + VOID BltBits ( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); +*/ virtual NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; protected: QxlDod* m_pQxlDod; @@ -245,6 +279,18 @@ public: NTSTATUS SetPowerState(POWER_ACTION ActionType); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); + NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* pMoves, + _In_ ULONG NumDirtyRects, + _In_ RECT* pDirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, + _In_ const CURRENT_BDD_MODE* pModeCur); + VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); private: @@ -272,6 +318,18 @@ public: NTSTATUS SetPowerState(POWER_ACTION ActionType); NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo); NTSTATUS HWClose(void); + NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, + _In_ UINT DstBitPerPixel, + _In_ BYTE* SrcAddr, + _In_ UINT SrcBytesPerPixel, + _In_ LONG SrcPitch, + _In_ ULONG NumMoves, + _In_ D3DKMT_MOVE_RECT* pMoves, + _In_ ULONG NumDirtyRects, + _In_ RECT* pDirtyRect, + _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation, + _In_ const CURRENT_BDD_MODE* pModeCur); + VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); private: @@ -434,6 +492,7 @@ public: PDXGKRNL_INTERFACE GetDxgkInterrface(void) { return &m_DxgkInterface;} private: VOID CleanUp(VOID); + NTSTATUS CheckHardware(); NTSTATUS WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue); // Set the given source mode on the given path NTSTATUS SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode, @@ -458,42 +517,12 @@ private: NTSTATUS RegisterHWInfo(); - - NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr, - _In_ UINT DstBitPerPixel, - _In_ BYTE* SrcAddr, - _In_ UINT SrcBytesPerPixel, - _In_ LONG SrcPitch, - _In_ ULONG NumMoves, - _In_ D3DKMT_MOVE_RECT* pMoves, - _In_ ULONG NumDirtyRects, - _In_ RECT* pDirtyRect, - _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation); - BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect); - VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch); - VOID CopyBitsGeneric( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); - - VOID CopyBits32_32( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); - VOID BltBits ( - BLT_INFO* pDst, - CONST BLT_INFO* pSrc, - UINT NumRects, - _In_reads_(NumRects) CONST RECT *pRects); - VOID BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId); }; NTSTATUS MapFrameBuffer( - _In_ PHYSICAL_ADDRESS PhysicalAddress, - _In_ ULONG Length, + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ ULONG Length, _Outptr_result_bytebuffer_(Length) VOID** VirtualAddress); NTSTATUS @@ -501,6 +530,25 @@ UnmapFrameBuffer( _In_reads_bytes_(Length) VOID* VirtualAddress, _In_ ULONG Length); - UINT BPPFromPixelFormat(D3DDDIFORMAT Format); D3DDDIFORMAT PixelFormatFromBPP(UINT BPP); + +VOID CopyBitsGeneric( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + +VOID CopyBits32_32( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); +VOID BltBits ( + BLT_INFO* pDst, + CONST BLT_INFO* pSrc, + UINT NumRects, + _In_reads_(NumRects) CONST RECT *pRects); + +BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect); +VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch); -- cgit v1.2.3