From bcff8a6d4ee5616a2e253da32ec069d4eeee197a Mon Sep 17 00:00:00 2001 From: Sameeh Jubran Date: Wed, 28 Sep 2016 14:09:28 +0300 Subject: [PATCH] Fix source buffer mapping in PresentDisplayOnly Part of source image mapped by PresentDisplayOnly should be big enough to cover all rectangles being transferred. Signed-off-by: Sameeh Jubran Signed-off-by: Dmitry Fleytman Acked-by: Frediano Ziglio --- qxldod/QxlDod.cpp | 28 +++++++++++++++++++++++----- qxldod/QxlDod.h | 2 ++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index f5a2bc8..f70ed25 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -3666,12 +3666,11 @@ QxlDevice::ExecutePresentDisplayOnly( ctx->Mdl = NULL; ctx->DisplaySource = this; - // Alternate between synch and asynch execution, for demonstrating - // that a real hardware implementation can do either - + // Source bitmap is in user mode, must be locked under __try/__except + // and mapped to kernel space before use. { - // Map Source into kernel space, as Blt will be executed by system worker thread - UINT sizeToMap = ctx->SrcPitch * ctx->SrcHeight; + LONG maxHeight = GetMaxSourceMappingHeight(ctx->Moves, ctx->NumMoves, ctx->DirtyRect, ctx->NumDirtyRects); + UINT sizeToMap = ctx->SrcPitch * maxHeight; PMDL mdl = IoAllocateMdl((PVOID)SrcAddr, sizeToMap, FALSE, FALSE, NULL); if(!mdl) @@ -4523,6 +4522,25 @@ void QxlDevice::SetMonitorConfig(QXLHead * monitor_config) AsyncIo(QXL_IO_MONITORS_CONFIG_ASYNC, 0); } +LONG QxlDevice::GetMaxSourceMappingHeight(D3DKMT_MOVE_RECT* Moves, ULONG NumMoves, RECT* DirtyRects, ULONG NumDirtyRects) +{ + LONG maxHeight = 0; + if (Moves != NULL) { + for (UINT i = 0; i < NumMoves; i++) { + const POINT& pSourcePoint = Moves[i].SourcePoint; + const RECT& pDestRect = Moves[i].DestRect; + maxHeight = MAX(maxHeight, pDestRect.bottom - pDestRect.top + pSourcePoint.y); + } + } + if (DirtyRects != NULL) { + for (UINT i = 0; i < NumDirtyRects; i++) { + const RECT& pDirtyRect = DirtyRects[i]; + maxHeight = MAX(maxHeight, pDirtyRect.bottom); + } + } + return maxHeight; +} + NTSTATUS QxlDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscape) { size_t data_size(sizeof(uint32_t)); diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index c808eb1..bf16724 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -542,6 +542,8 @@ private: 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;