VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispDbg.cpp

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.4 KB
RevLine 
[36867]1/* $Id: VBoxDispDbg.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxVideo Display D3D User mode dll
4 */
5
6/*
[98103]7 * Copyright (C) 2011-2023 Oracle and/or its affiliates.
[36867]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
[36867]26 */
27
28#include "VBoxDispD3DCmn.h"
29
[69872]30#ifdef VBOXWDDMDISP_DEBUG_VEHANDLER
[95955]31# include <Psapi.h>
[69872]32#endif
33
[36867]34#include <iprt/asm.h>
[41472]35#include <iprt/assert.h>
[95955]36#include <iprt/process.h>
37#include <iprt/string.h>
[36867]38
[95955]39#ifndef IPRT_NO_CRT
40# include <stdio.h>
41#endif
[41637]42
[95955]43
44#if defined(VBOXWDDMDISP_DEBUG) || defined(LOG_TO_BACKDOOR_DRV)
45static const char *vboxVDbgDoGetExeName(void)
[41637]46{
[95955]47# ifdef IPRT_NO_CRT
48 /** @todo use RTProcShortName instead? */
49 return RTProcExecutablePath(); /* should've been initialized by nocrt-startup-dll-win.cpp already */
50# else
51 static bool volatile s_fInitialized = false;
52 static char s_szExePath[MAX_PATH];
53 if (!s_fInitialized)
[41637]54 {
[95955]55 DWORD cName = GetModuleFileNameA(NULL, s_szExePath, RT_ELEMENTS(s_szExePath));
[41637]56 if (!cName)
57 {
[95955]58# ifdef LOG_ENABLED
[41637]59 DWORD winEr = GetLastError();
[95955]60# endif
[41637]61 WARN(("GetModuleFileNameA failed, winEr %d", winEr));
62 return NULL;
63 }
[95955]64 s_fInitialized = TRUE;
[41637]65 }
[95955]66 return s_szExePath;
67#endif /* !IPRT_NO_CRT */
[41637]68}
69
[95955]70static void vboxDispLogDbgFormatStringV(char *pszBuffer, uint32_t cbBuffer, const char *pszFormat, va_list va)
[41475]71{
[95955]72# ifdef IPRT_NO_CRT
73 va_list vaCopy;
74 va_copy(vaCopy, va); /* The &va for a %N must not be taken from an parameter list, so copy it onto the stack. */
75 RTStrPrintf(pszBuffer, cbBuffer, "['%s' 0x%lx.0x%lx] Disp: %N",
76 vboxVDbgDoGetExeName(), GetCurrentProcessId(), GetCurrentThreadId(), pszFormat, &vaCopy);
77 va_end(vaCopy);
78# else
[95957]79 int cch = _snprintf(pszBuffer, cbBuffer, "['%s' 0x%lx.0x%lx] Disp: ",
[95955]80 vboxVDbgDoGetExeName(), GetCurrentProcessId(), GetCurrentThreadId());
81 AssertReturnVoid(cch > 0);
82 AssertReturnVoid((unsigned)cch + 2 <= cbBuffer);
83 cbBuffer -= (unsigned)cch;
84 pszBuffer += (unsigned)cch;
[41475]85
[95955]86 cch = _vsnprintf(pszBuffer, cbBuffer, pszFormat, va);
87 pszBuffer[cbBuffer - 1] = '\0'; /* Don't trust _vsnprintf to terminate the output. */
88# endif
[41475]89}
90
[95955]91#endif /* VBOXWDDMDISP_DEBUG || LOG_TO_BACKDOOR_DRV */
[80372]92#if defined(VBOXWDDMDISP_DEBUG)
[42027]93LONG g_VBoxVDbgFIsDwm = -1;
94
95DWORD g_VBoxVDbgPid = 0;
96
[43236]97DWORD g_VBoxVDbgFLogRel = 1;
[49263]98# if !defined(VBOXWDDMDISP_DEBUG)
99DWORD g_VBoxVDbgFLog = 0;
100# else
[43236]101DWORD g_VBoxVDbgFLog = 1;
[49263]102# endif
[43236]103DWORD g_VBoxVDbgFLogFlow = 0;
104
[49263]105#endif
106
107#ifdef VBOXWDDMDISP_DEBUG
108
[38238]109#define VBOXWDDMDISP_DEBUG_DUMP_DEFAULT 0
[38112]110DWORD g_VBoxVDbgFDumpSetTexture = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
111DWORD g_VBoxVDbgFDumpDrawPrim = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
112DWORD g_VBoxVDbgFDumpTexBlt = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
113DWORD g_VBoxVDbgFDumpBlt = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
114DWORD g_VBoxVDbgFDumpRtSynch = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
115DWORD g_VBoxVDbgFDumpFlush = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
116DWORD g_VBoxVDbgFDumpShared = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
117DWORD g_VBoxVDbgFDumpLock = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
118DWORD g_VBoxVDbgFDumpUnlock = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
[39819]119DWORD g_VBoxVDbgFDumpPresentEnter = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
120DWORD g_VBoxVDbgFDumpPresentLeave = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
121DWORD g_VBoxVDbgFDumpScSync = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
[36867]122
[38112]123DWORD g_VBoxVDbgFBreakShared = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
[38930]124DWORD g_VBoxVDbgFBreakDdi = 0;
[38112]125
[38982]126DWORD g_VBoxVDbgFCheckSysMemSync = 0;
[39130]127DWORD g_VBoxVDbgFCheckBlt = 0;
128DWORD g_VBoxVDbgFCheckTexBlt = 0;
[39819]129DWORD g_VBoxVDbgFCheckScSync = 0;
[38982]130
[39130]131DWORD g_VBoxVDbgFSkipCheckTexBltDwmWndUpdate = 1;
132
[42683]133DWORD g_VBoxVDbgCfgMaxDirectRts = 3;
[39819]134DWORD g_VBoxVDbgCfgForceDummyDevCreate = 0;
135
136PVBOXWDDMDISP_DEVICE g_VBoxVDbgInternalDevice = NULL;
137PVBOXWDDMDISP_RESOURCE g_VBoxVDbgInternalRc = NULL;
138
[95955]139VOID vboxVDbgDoPrintDmlCmd(const char *pszDesc, const char *pszCmd)
[38112]140{
[95955]141#ifdef IPRT_NO_CRT
142 /* DML isn't exactly following XML rules, docs + examples are not consistent
143 about escaping sequences even. But assume it groks the typical XML
144 escape sequences for now. */
145 vboxVDbgPrint(("<?dml?><exec cmd=\"%RMas\">%RMes</exec>, ( %s )\n", pszCmd, pszDesc, pszCmd)); /** @todo escape the last pszCmd too? */
146#else
[39130]147 vboxVDbgPrint(("<?dml?><exec cmd=\"%s\">%s</exec>, ( %s )\n", pszCmd, pszDesc, pszCmd));
[95955]148#endif
[38112]149}
150
[39130]151VOID vboxVDbgDoPrintDumpCmd(const char* pszDesc, const void *pvData, uint32_t width, uint32_t height, uint32_t bpp, uint32_t pitch)
152{
[95955]153 char szCmd[1024];
154#ifdef IPRT_NO_CRT
155 RTStrPrintf(szCmd, sizeof(szCmd), "!vbvdbg.ms 0x%p 0n%d 0n%d 0n%d 0n%d", pvData, width, height, bpp, pitch);
156#else
157 _snprintf(szCmd, sizeof(szCmd), "!vbvdbg.ms 0x%p 0n%d 0n%d 0n%d 0n%d", pvData, width, height, bpp, pitch);
158 szCmd[sizeof(szCmd) - 1] = '\0';
159#endif
160 vboxVDbgDoPrintDmlCmd(pszDesc, szCmd);
[39130]161}
162
163VOID vboxVDbgDoPrintLopLastCmd(const char* pszDesc)
164{
165 vboxVDbgDoPrintDmlCmd(pszDesc, "ed @@(&vboxVDbgLoop) 0");
166}
167
[41472]168typedef struct VBOXVDBG_DUMP_INFO
[36867]169{
[41472]170 DWORD fFlags;
[45132]171 const VBOXWDDMDISP_ALLOCATION *pAlloc;
[41472]172 IDirect3DResource9 *pD3DRc;
[45132]173 const RECT *pRect;
[41472]174} VBOXVDBG_DUMP_INFO, *PVBOXVDBG_DUMP_INFO;
175
[85121]176typedef DECLCALLBACKTYPE(void, FNVBOXVDBG_CONTENTS_DUMPER,(PVBOXVDBG_DUMP_INFO pInfo, BOOLEAN fBreak, void *pvDumper));
[41472]177typedef FNVBOXVDBG_CONTENTS_DUMPER *PFNVBOXVDBG_CONTENTS_DUMPER;
178
179static VOID vboxVDbgDoDumpSummary(const char * pPrefix, PVBOXVDBG_DUMP_INFO pInfo, const char * pSuffix)
180{
[45132]181 const VBOXWDDMDISP_ALLOCATION *pAlloc = pInfo->pAlloc;
[41472]182 IDirect3DResource9 *pD3DRc = pInfo->pD3DRc;
[95955]183 const RECT * const pRect = pInfo->pRect;
184 char szRectBuf[24];
185 if (pRect)
186#ifdef IPRT_NO_CRT
187 RTStrPrintf(szRectBuf, sizeof(szRectBuf), "(%ld:%ld);(%ld:%ld)", pRect->left, pRect->top, pRect->right, pRect->bottom);
188#else
189 _snprintf(szRectBuf, sizeof(szRectBuf), "(%ld:%ld);(%ld:%ld)", pRect->left, pRect->top, pRect->right, pRect->bottom);
190#endif
[41472]191 else
[95955]192 strcpy(szRectBuf, "n/a");
[41472]193
194 vboxVDbgPrint(("%s Sh(0x%p), Rc(0x%p), pAlloc(0x%x), pD3DIf(0x%p), Type(%s), Rect(%s), Locks(%d) %s",
195 pPrefix ? pPrefix : "",
196 pAlloc ? pAlloc->pRc->aAllocations[0].hSharedHandle : NULL,
197 pAlloc ? pAlloc->pRc : NULL,
198 pAlloc,
199 pD3DRc,
200 pD3DRc ? vboxDispLogD3DRcType(pD3DRc->GetType()) : "n/a",
[95955]201 szRectBuf,
[41472]202 pAlloc ? pAlloc->LockInfo.cLocks : 0,
203 pSuffix ? pSuffix : ""));
204}
205
206VOID vboxVDbgDoDumpPerform(const char * pPrefix, PVBOXVDBG_DUMP_INFO pInfo, const char * pSuffix,
207 PFNVBOXVDBG_CONTENTS_DUMPER pfnCd, void *pvCd)
208{
209 DWORD fFlags = pInfo->fFlags;
210
[41475]211 if (!VBOXVDBG_DUMP_TYPE_ENABLED_FOR_INFO(pInfo, fFlags))
[41472]212 return;
213
214 if (!pInfo->pD3DRc && pInfo->pAlloc)
215 pInfo->pD3DRc = (IDirect3DResource9*)pInfo->pAlloc->pD3DIf;
216
217 BOOLEAN bLogOnly = VBOXVDBG_DUMP_TYPE_FLOW_ONLY(fFlags);
218 if (bLogOnly || !pfnCd)
[36867]219 {
[41472]220 vboxVDbgDoDumpSummary(pPrefix, pInfo, pSuffix);
221 if (VBOXVDBG_DUMP_FLAGS_IS_SET(fFlags, VBOXVDBG_DUMP_TYPEF_BREAK_ON_FLOW)
222 || (!bLogOnly && VBOXVDBG_DUMP_FLAGS_IS_CLEARED(fFlags, VBOXVDBG_DUMP_TYPEF_DONT_BREAK_ON_CONTENTS)))
223 Assert(0);
224 return;
[36867]225 }
226
[41472]227 vboxVDbgDoDumpSummary(pPrefix, pInfo, NULL);
[36867]228
[41472]229 pfnCd(pInfo, VBOXVDBG_DUMP_FLAGS_IS_CLEARED(fFlags, VBOXVDBG_DUMP_TYPEF_DONT_BREAK_ON_CONTENTS), pvCd);
[37870]230
[41472]231 if (pSuffix && pSuffix[0] != '\0')
232 vboxVDbgPrint(("%s", pSuffix));
233}
[37870]234
[41472]235static DECLCALLBACK(void) vboxVDbgAllocRectContentsDumperCb(PVBOXVDBG_DUMP_INFO pInfo, BOOLEAN fBreak, void *pvDumper)
236{
[63033]237 RT_NOREF(fBreak, pvDumper);
[45132]238 const VBOXWDDMDISP_ALLOCATION *pAlloc = pInfo->pAlloc;
[41472]239 const RECT *pRect = pInfo->pRect;
240
241 Assert(pAlloc->hAllocation);
242
[36867]243 D3DDDICB_LOCK LockData;
244 LockData.hAllocation = pAlloc->hAllocation;
245 LockData.PrivateDriverData = 0;
246 LockData.NumPages = 0;
247 LockData.pPages = NULL;
248 LockData.pData = NULL; /* out */
249 LockData.Flags.Value = 0;
250 LockData.Flags.LockEntire =1;
251 LockData.Flags.ReadOnly = 1;
252
253 PVBOXWDDMDISP_DEVICE pDevice = pAlloc->pRc->pDevice;
254
255 HRESULT hr = pDevice->RtCallbacks.pfnLockCb(pDevice->hDevice, &LockData);
256 Assert(hr == S_OK);
257 if (hr == S_OK)
258 {
259 UINT bpp = vboxWddmCalcBitsPerPixel(pAlloc->SurfDesc.format);
[43607]260 vboxVDbgDoPrintDumpCmd("Surf Info", LockData.pData, pAlloc->SurfDesc.d3dWidth, pAlloc->SurfDesc.height, bpp, pAlloc->SurfDesc.pitch);
[36867]261 if (pRect)
262 {
263 Assert(pRect->right > pRect->left);
264 Assert(pRect->bottom > pRect->top);
265 vboxVDbgDoPrintRect("rect: ", pRect, "\n");
[39130]266 vboxVDbgDoPrintDumpCmd("Rect Info", ((uint8_t*)LockData.pData) + (pRect->top * pAlloc->SurfDesc.pitch) + ((pRect->left * bpp) >> 3),
[38112]267 pRect->right - pRect->left, pRect->bottom - pRect->top, bpp, pAlloc->SurfDesc.pitch);
[36867]268 }
269 Assert(0);
270
271 D3DDDICB_UNLOCK DdiUnlock;
272
273 DdiUnlock.NumAllocations = 1;
274 DdiUnlock.phAllocations = &pAlloc->hAllocation;
275
276 hr = pDevice->RtCallbacks.pfnUnlockCb(pDevice->hDevice, &DdiUnlock);
277 Assert(hr == S_OK);
278 }
279}
280
[41472]281VOID vboxVDbgDoDumpAllocRect(const char * pPrefix, PVBOXWDDMDISP_ALLOCATION pAlloc, RECT *pRect, const char* pSuffix, DWORD fFlags)
[36867]282{
[41472]283 VBOXVDBG_DUMP_INFO Info;
284 Info.fFlags = fFlags;
285 Info.pAlloc = pAlloc;
286 Info.pD3DRc = NULL;
287 Info.pRect = pRect;
288 vboxVDbgDoDumpPerform(pPrefix, &Info, pSuffix, vboxVDbgAllocRectContentsDumperCb, NULL);
[36867]289}
290
[41472]291static DECLCALLBACK(void) vboxVDbgRcRectContentsDumperCb(PVBOXVDBG_DUMP_INFO pInfo, BOOLEAN fBreak, void *pvDumper)
[36867]292{
[63033]293 RT_NOREF(pvDumper);
[45132]294 const VBOXWDDMDISP_ALLOCATION *pAlloc = pInfo->pAlloc;
[41472]295 const RECT *pRect = pInfo->pRect;
296 IDirect3DSurface9 *pSurf;
[43236]297 HRESULT hr = VBoxD3DIfSurfGet(pAlloc->pRc, pAlloc->iAlloc, &pSurf);
[41472]298 if (hr != S_OK)
[36867]299 {
[43236]300 WARN(("VBoxD3DIfSurfGet failed, hr 0x%x", hr));
[41472]301 return;
[36867]302 }
303
304 D3DSURFACE_DESC Desc;
[41472]305 hr = pSurf->GetDesc(&Desc);
[36867]306 Assert(hr == S_OK);
307 if (hr == S_OK)
308 {
309 D3DLOCKED_RECT Lr;
310 hr = pSurf->LockRect(&Lr, NULL, D3DLOCK_READONLY);
311 Assert(hr == S_OK);
312 if (hr == S_OK)
313 {
314 UINT bpp = vboxWddmCalcBitsPerPixel((D3DDDIFORMAT)Desc.Format);
[39130]315 vboxVDbgDoPrintDumpCmd("Surf Info", Lr.pBits, Desc.Width, Desc.Height, bpp, Lr.Pitch);
[36867]316 if (pRect)
317 {
318 Assert(pRect->right > pRect->left);
319 Assert(pRect->bottom > pRect->top);
320 vboxVDbgDoPrintRect("rect: ", pRect, "\n");
[39130]321 vboxVDbgDoPrintDumpCmd("Rect Info", ((uint8_t*)Lr.pBits) + (pRect->top * Lr.Pitch) + ((pRect->left * bpp) >> 3),
[38112]322 pRect->right - pRect->left, pRect->bottom - pRect->top, bpp, Lr.Pitch);
[36867]323 }
324
[41472]325 if (fBreak)
[36867]326 {
327 Assert(0);
328 }
[41472]329 hr = pSurf->UnlockRect();
330 Assert(hr == S_OK);
[36867]331 }
332 }
[49449]333
334 pSurf->Release();
[36867]335}
336
[41472]337VOID vboxVDbgDoDumpRcRect(const char * pPrefix, PVBOXWDDMDISP_ALLOCATION pAlloc,
338 IDirect3DResource9 *pD3DRc, RECT *pRect, const char * pSuffix, DWORD fFlags)
[36867]339{
[41472]340 VBOXVDBG_DUMP_INFO Info;
341 Info.fFlags = fFlags;
342 Info.pAlloc = pAlloc;
343 Info.pD3DRc = pD3DRc;
344 Info.pRect = pRect;
345 vboxVDbgDoDumpPerform(pPrefix, &Info, pSuffix, vboxVDbgRcRectContentsDumperCb, NULL);
[36867]346}
347
[39819]348
[36867]349#define VBOXVDBG_STRCASE(_t) \
350 case _t: return #_t;
351#define VBOXVDBG_STRCASE_UNKNOWN() \
352 default: Assert(0); return "Unknown";
353
354const char* vboxVDbgStrCubeFaceType(D3DCUBEMAP_FACES enmFace)
355{
356 switch (enmFace)
357 {
358 VBOXVDBG_STRCASE(D3DCUBEMAP_FACE_POSITIVE_X);
359 VBOXVDBG_STRCASE(D3DCUBEMAP_FACE_NEGATIVE_X);
360 VBOXVDBG_STRCASE(D3DCUBEMAP_FACE_POSITIVE_Y);
361 VBOXVDBG_STRCASE(D3DCUBEMAP_FACE_NEGATIVE_Y);
362 VBOXVDBG_STRCASE(D3DCUBEMAP_FACE_POSITIVE_Z);
363 VBOXVDBG_STRCASE(D3DCUBEMAP_FACE_NEGATIVE_Z);
364 VBOXVDBG_STRCASE_UNKNOWN();
365 }
366}
367
[41472]368VOID vboxVDbgDoDumpRt(const char * pPrefix, PVBOXWDDMDISP_DEVICE pDevice, const char * pSuffix, DWORD fFlags)
[36867]369{
[38112]370 for (UINT i = 0; i < pDevice->cRTs; ++i)
[36867]371 {
[38112]372 IDirect3DSurface9 *pRt;
373 PVBOXWDDMDISP_ALLOCATION pAlloc = pDevice->apRTs[i];
[57633]374 if (!pAlloc) continue;
[38112]375 IDirect3DDevice9 *pDeviceIf = pDevice->pDevice9If;
376 HRESULT hr = pDeviceIf->GetRenderTarget(i, &pRt);
377 Assert(hr == S_OK);
378 if (hr == S_OK)
379 {
380// Assert(pAlloc->pD3DIf == pRt);
[41472]381 vboxVDbgDoDumpRcRect(pPrefix, pAlloc, NULL, NULL, pSuffix, fFlags);
[38112]382 pRt->Release();
383 }
384 else
385 {
386 vboxVDbgPrint((__FUNCTION__": ERROR getting rt: 0x%x", hr));
387 }
[36867]388 }
[38112]389}
390
[41475]391VOID vboxVDbgDoDumpSamplers(const char * pPrefix, PVBOXWDDMDISP_DEVICE pDevice, const char * pSuffix, DWORD fFlags)
392{
393 for (UINT i = 0, iSampler = 0; iSampler < pDevice->cSamplerTextures; ++i)
394 {
395 Assert(i < RT_ELEMENTS(pDevice->aSamplerTextures));
396 if (!pDevice->aSamplerTextures[i]) continue;
397 PVBOXWDDMDISP_RESOURCE pRc = pDevice->aSamplerTextures[i];
398 for (UINT j = 0; j < pRc->cAllocations; ++j)
399 {
400 PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[j];
401 vboxVDbgDoDumpRcRect(pPrefix, pAlloc, NULL, NULL, pSuffix, fFlags);
402 }
403 ++iSampler;
404 }
405}
406
[41472]407static DECLCALLBACK(void) vboxVDbgLockUnlockSurfTexContentsDumperCb(PVBOXVDBG_DUMP_INFO pInfo, BOOLEAN fBreak, void *pvDumper)
[38112]408{
[63033]409 RT_NOREF(pvDumper);
[45132]410 const VBOXWDDMDISP_ALLOCATION *pAlloc = pInfo->pAlloc;
411 const RECT *pRect = pInfo->pRect;
[38112]412 UINT bpp = vboxWddmCalcBitsPerPixel(pAlloc->SurfDesc.format);
[56279]413 uint32_t width, height, pitch = 0;
[38112]414 void *pvData;
415 if (pAlloc->LockInfo.fFlags.AreaValid)
416 {
417 width = pAlloc->LockInfo.Area.left - pAlloc->LockInfo.Area.right;
418 height = pAlloc->LockInfo.Area.bottom - pAlloc->LockInfo.Area.top;
419 }
[36867]420 else
421 {
[38112]422 width = pAlloc->SurfDesc.width;
423 height = pAlloc->SurfDesc.height;
[36867]424 }
[38112]425
426 if (pAlloc->LockInfo.fFlags.NotifyOnly)
427 {
428 pitch = pAlloc->SurfDesc.pitch;
429 pvData = ((uint8_t*)pAlloc->pvMem) + pitch*pRect->top + ((bpp*pRect->left) >> 3);
430 }
431 else
432 {
433 pvData = pAlloc->LockInfo.pvData;
434 }
435
[39130]436 vboxVDbgDoPrintDumpCmd("Surf Info", pvData, width, height, bpp, pitch);
[38112]437
438 if (fBreak)
439 {
440 Assert(0);
441 }
[41472]442}
[38112]443
[45132]444VOID vboxVDbgDoDumpLockUnlockSurfTex(const char * pPrefix, const VBOXWDDMDISP_ALLOCATION *pAlloc, const char * pSuffix, DWORD fFlags)
[41472]445{
446 Assert(!pAlloc->hSharedHandle);
447
[45132]448 RECT Rect;
449 const RECT *pRect;
[41472]450 Assert(!pAlloc->LockInfo.fFlags.RangeValid);
451 Assert(!pAlloc->LockInfo.fFlags.BoxValid);
452 if (pAlloc->LockInfo.fFlags.AreaValid)
[38112]453 {
[41472]454 pRect = &pAlloc->LockInfo.Area;
[38112]455 }
[41472]456 else
457 {
458 Rect.top = 0;
459 Rect.bottom = pAlloc->SurfDesc.height;
460 Rect.left = 0;
461 Rect.right = pAlloc->SurfDesc.width;
462 pRect = &Rect;
463 }
[38112]464
[41472]465 VBOXVDBG_DUMP_INFO Info;
466 Info.fFlags = fFlags;
467 Info.pAlloc = pAlloc;
468 Info.pD3DRc = NULL;
469 Info.pRect = pRect;
470 vboxVDbgDoDumpPerform(pPrefix, &Info, pSuffix, vboxVDbgLockUnlockSurfTexContentsDumperCb, NULL);
[36867]471}
472
[41472]473VOID vboxVDbgDoDumpLockSurfTex(const char * pPrefix, const D3DDDIARG_LOCK* pData, const char * pSuffix, DWORD fFlags)
[38112]474{
[45132]475 const VBOXWDDMDISP_RESOURCE *pRc = (const VBOXWDDMDISP_RESOURCE*)pData->hResource;
476 const VBOXWDDMDISP_ALLOCATION *pAlloc = &pRc->aAllocations[pData->SubResourceIndex];
477#ifdef VBOXWDDMDISP_DEBUG
478 VBOXWDDMDISP_ALLOCATION *pUnconstpAlloc = (VBOXWDDMDISP_ALLOCATION *)pAlloc;
479 pUnconstpAlloc->LockInfo.pvData = pData->pSurfData;
480#endif
[41472]481 vboxVDbgDoDumpLockUnlockSurfTex(pPrefix, pAlloc, pSuffix, fFlags);
[38112]482}
483
[41472]484VOID vboxVDbgDoDumpUnlockSurfTex(const char * pPrefix, const D3DDDIARG_UNLOCK* pData, const char * pSuffix, DWORD fFlags)
[38112]485{
[45132]486 const VBOXWDDMDISP_RESOURCE *pRc = (const VBOXWDDMDISP_RESOURCE*)pData->hResource;
487 const VBOXWDDMDISP_ALLOCATION *pAlloc = &pRc->aAllocations[pData->SubResourceIndex];
[41472]488 vboxVDbgDoDumpLockUnlockSurfTex(pPrefix, pAlloc, pSuffix, fFlags);
[38112]489}
490
[39130]491BOOL vboxVDbgDoCheckLRects(D3DLOCKED_RECT *pDstLRect, const RECT *pDstRect, D3DLOCKED_RECT *pSrcLRect, const RECT *pSrcRect, DWORD bpp, BOOL fBreakOnMismatch)
492{
493 LONG DstH, DstW, SrcH, SrcW, DstWBytes;
494 BOOL fMatch = FALSE;
495 DstH = pDstRect->bottom - pDstRect->top;
496 DstW = pDstRect->right - pDstRect->left;
497 SrcH = pSrcRect->bottom - pSrcRect->top;
498 SrcW = pSrcRect->right - pSrcRect->left;
499
500 DstWBytes = ((DstW * bpp + 7) >> 3);
501
502 if(DstW != SrcW && DstH != SrcH)
503 {
504 WARN(("stretched comparison not supported!!"));
505 return FALSE;
506 }
507
508 uint8_t *pDst = (uint8_t*)pDstLRect->pBits;
509 uint8_t *pSrc = (uint8_t*)pSrcLRect->pBits;
510 for (LONG i = 0; i < DstH; ++i)
511 {
512 if (!(fMatch = !memcmp(pDst, pSrc, DstWBytes)))
513 {
514 vboxVDbgPrint(("not match!\n"));
515 if (fBreakOnMismatch)
516 Assert(0);
517 break;
518 }
519 pDst += pDstLRect->Pitch;
520 pSrc += pSrcLRect->Pitch;
521 }
522 return fMatch;
523}
524
[45132]525BOOL vboxVDbgDoCheckRectsMatch(const VBOXWDDMDISP_RESOURCE *pDstRc, uint32_t iDstAlloc,
526 const VBOXWDDMDISP_RESOURCE *pSrcRc, uint32_t iSrcAlloc,
[39130]527 const RECT *pDstRect,
528 const RECT *pSrcRect,
529 BOOL fBreakOnMismatch)
530{
531 BOOL fMatch = FALSE;
532 RECT DstRect = {0}, SrcRect = {0};
533 if (!pDstRect)
534 {
535 DstRect.left = 0;
536 DstRect.right = pDstRc->aAllocations[iDstAlloc].SurfDesc.width;
537 DstRect.top = 0;
538 DstRect.bottom = pDstRc->aAllocations[iDstAlloc].SurfDesc.height;
539 pDstRect = &DstRect;
540 }
541
542 if (!pSrcRect)
543 {
544 SrcRect.left = 0;
545 SrcRect.right = pSrcRc->aAllocations[iSrcAlloc].SurfDesc.width;
546 SrcRect.top = 0;
547 SrcRect.bottom = pSrcRc->aAllocations[iSrcAlloc].SurfDesc.height;
548 pSrcRect = &SrcRect;
549 }
550
551 if (pDstRc == pSrcRc
552 && iDstAlloc == iSrcAlloc)
553 {
554 if (!memcmp(pDstRect, pSrcRect, sizeof (*pDstRect)))
555 {
556 vboxVDbgPrint(("matching same rect of one allocation, skipping..\n"));
557 return TRUE;
558 }
559 WARN(("matching different rects of the same allocation, unsupported!"));
560 return FALSE;
561 }
562
563 if (pDstRc->RcDesc.enmFormat != pSrcRc->RcDesc.enmFormat)
564 {
565 WARN(("matching different formats, unsupported!"));
566 return FALSE;
567 }
568
569 DWORD bpp = pDstRc->aAllocations[iDstAlloc].SurfDesc.bpp;
570 if (!bpp)
571 {
572 WARN(("uninited bpp! unsupported!"));
573 return FALSE;
574 }
575
576 LONG DstH, DstW, SrcH, SrcW;
577 DstH = pDstRect->bottom - pDstRect->top;
578 DstW = pDstRect->right - pDstRect->left;
579 SrcH = pSrcRect->bottom - pSrcRect->top;
580 SrcW = pSrcRect->right - pSrcRect->left;
581
582 if(DstW != SrcW && DstH != SrcH)
583 {
584 WARN(("stretched comparison not supported!!"));
585 return FALSE;
586 }
587
588 D3DLOCKED_RECT SrcLRect, DstLRect;
[45132]589 HRESULT hr = VBoxD3DIfLockRect((VBOXWDDMDISP_RESOURCE *)pDstRc, iDstAlloc, &DstLRect, pDstRect, D3DLOCK_READONLY);
[39130]590 if (FAILED(hr))
591 {
[43236]592 WARN(("VBoxD3DIfLockRect failed, hr(0x%x)", hr));
[39130]593 return FALSE;
594 }
595
[45132]596 hr = VBoxD3DIfLockRect((VBOXWDDMDISP_RESOURCE *)pSrcRc, iSrcAlloc, &SrcLRect, pSrcRect, D3DLOCK_READONLY);
[39130]597 if (FAILED(hr))
598 {
[43236]599 WARN(("VBoxD3DIfLockRect failed, hr(0x%x)", hr));
[45132]600 hr = VBoxD3DIfUnlockRect((VBOXWDDMDISP_RESOURCE *)pDstRc, iDstAlloc);
[39130]601 return FALSE;
602 }
603
604 fMatch = vboxVDbgDoCheckLRects(&DstLRect, pDstRect, &SrcLRect, pSrcRect, bpp, fBreakOnMismatch);
605
[45132]606 hr = VBoxD3DIfUnlockRect((VBOXWDDMDISP_RESOURCE *)pDstRc, iDstAlloc);
[39130]607 Assert(hr == S_OK);
608
[45132]609 hr = VBoxD3DIfUnlockRect((VBOXWDDMDISP_RESOURCE *)pSrcRc, iSrcAlloc);
[39130]610 Assert(hr == S_OK);
611
612 return fMatch;
613}
614
[45132]615void vboxVDbgDoPrintAlloc(const char * pPrefix, const VBOXWDDMDISP_RESOURCE *pRc, uint32_t iAlloc, const char * pSuffix)
[36867]616{
617 Assert(pRc->cAllocations > iAlloc);
[45132]618 const VBOXWDDMDISP_ALLOCATION *pAlloc = &pRc->aAllocations[iAlloc];
[36867]619 BOOL bPrimary = pRc->RcDesc.fFlags.Primary;
620 BOOL bFrontBuf = FALSE;
[43607]621 vboxVDbgPrint(("%s d3dWidth(%d), width(%d), height(%d), format(%d), usage(%s), %s", pPrefix,
622 pAlloc->SurfDesc.d3dWidth, pAlloc->SurfDesc.width, pAlloc->SurfDesc.height, pAlloc->SurfDesc.format,
[36867]623 bPrimary ?
624 (bFrontBuf ? "Front Buffer" : "Back Buffer")
625 : "?Everage? Alloc",
626 pSuffix));
627}
628
629void vboxVDbgDoPrintRect(const char * pPrefix, const RECT *pRect, const char * pSuffix)
630{
631 vboxVDbgPrint(("%s left(%d), top(%d), right(%d), bottom(%d) %s", pPrefix, pRect->left, pRect->top, pRect->right, pRect->bottom, pSuffix));
632}
[39130]633
[85121]634static VOID CALLBACK vboxVDbgTimerCb(__in PVOID lpParameter, __in BOOLEAN TimerOrWaitFired) RT_NOTHROW_DEF
[41637]635{
[63033]636 RT_NOREF(lpParameter, TimerOrWaitFired);
[41637]637 Assert(0);
638}
639
640HRESULT vboxVDbgTimerStart(HANDLE hTimerQueue, HANDLE *phTimer, DWORD msTimeout)
641{
642 if (!CreateTimerQueueTimer(phTimer, hTimerQueue,
643 vboxVDbgTimerCb,
644 NULL,
645 msTimeout, /* ms*/
646 0,
647 WT_EXECUTEONLYONCE))
648 {
649 DWORD winEr = GetLastError();
650 AssertMsgFailed(("CreateTimerQueueTimer failed, winEr (%d)\n", winEr));
651 return E_FAIL;
652 }
653 return S_OK;
654}
655
656HRESULT vboxVDbgTimerStop(HANDLE hTimerQueue, HANDLE hTimer)
657{
658 if (!DeleteTimerQueueTimer(hTimerQueue, hTimer, NULL))
659 {
660 DWORD winEr = GetLastError();
661 AssertMsg(winEr == ERROR_IO_PENDING, ("DeleteTimerQueueTimer failed, winEr (%d)\n", winEr));
662 }
663 return S_OK;
664}
[36867]665#endif
666
[80372]667#if defined(VBOXWDDMDISP_DEBUG)
[42027]668BOOL vboxVDbgDoCheckExe(const char * pszName)
669{
[95955]670 char const *pszModule = vboxVDbgDoGetExeName();
[42027]671 if (!pszModule)
672 return FALSE;
[95955]673 size_t cchModule = strlen(pszModule);
674 size_t cchName = strlen(pszName);
675 if (cchName > cchModule)
[42027]676 return FALSE;
[95955]677# ifdef IPRT_NO_CRT
678 if (RTStrICmp(pszName, &pszModule[cchModule - cchName]))
679# else
680 if (_stricmp(pszName, &pszModule[cchModule - cchName]))
681# endif
[42027]682 return FALSE;
683 return TRUE;
684}
685#endif
686
[36867]687#ifdef VBOXWDDMDISP_DEBUG_VEHANDLER
688
[69872]689typedef BOOL WINAPI FNGetModuleInformation(HANDLE hProcess, HMODULE hModule, LPMODULEINFO lpmodinfo, DWORD cb);
690typedef FNGetModuleInformation *PFNGetModuleInformation;
691
692static PFNGetModuleInformation g_pfnGetModuleInformation = NULL;
693static HMODULE g_hModPsapi = NULL;
[36867]694static PVOID g_VBoxWDbgVEHandler = NULL;
[69872]695
696static bool vboxVDbgIsAddressInModule(PVOID pv, const char *pszModuleName)
697{
698 HMODULE hMod = GetModuleHandleA(pszModuleName);
699 if (!hMod)
700 return false;
701
702 HANDLE hProcess = GetCurrentProcess();
703
704 if (!g_pfnGetModuleInformation)
705 return false;
706
707 MODULEINFO ModuleInfo = {0};
708 if (!g_pfnGetModuleInformation(hProcess, hMod, &ModuleInfo, sizeof(ModuleInfo)))
709 return false;
710
711 return (uintptr_t)ModuleInfo.lpBaseOfDll <= (uintptr_t)pv
712 && (uintptr_t)pv < (uintptr_t)ModuleInfo.lpBaseOfDll + ModuleInfo.SizeOfImage;
713}
714
715static bool vboxVDbgIsExceptionIgnored(PEXCEPTION_RECORD pExceptionRecord)
716{
717 /* Module (dll) names for GetModuleHandle.
718 * Exceptions originated from these modules will be ignored.
719 */
720 static const char *apszIgnoredModuleNames[] =
721 {
722 NULL
723 };
724
725 int i = 0;
726 while (apszIgnoredModuleNames[i])
727 {
728 if (vboxVDbgIsAddressInModule(pExceptionRecord->ExceptionAddress, apszIgnoredModuleNames[i]))
729 return true;
730
731 ++i;
732 }
733
734 return false;
735}
736
[85121]737static LONG WINAPI vboxVDbgVectoredHandler(struct _EXCEPTION_POINTERS *pExceptionInfo) RT_NOTHROW_DEF
[36867]738{
[69872]739 static volatile bool g_fAllowIgnore = true; /* Might be changed in kernel debugger. */
740
[36867]741 PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
[69872]742 /* PCONTEXT pContextRecord = pExceptionInfo->ContextRecord; */
743
[36867]744 switch (pExceptionRecord->ExceptionCode)
745 {
[69872]746 default:
747 break;
[38982]748 case EXCEPTION_BREAKPOINT:
749 case EXCEPTION_ACCESS_VIOLATION:
750 case EXCEPTION_STACK_OVERFLOW:
751 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
752 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
753 case EXCEPTION_FLT_INVALID_OPERATION:
754 case EXCEPTION_INT_DIVIDE_BY_ZERO:
755 case EXCEPTION_ILLEGAL_INSTRUCTION:
[69872]756 if (g_fAllowIgnore && vboxVDbgIsExceptionIgnored(pExceptionRecord))
757 break;
758 ASMBreakpoint();
[36867]759 break;
[69872]760 case 0x40010006: /* OutputDebugStringA? */
761 case 0x4001000a: /* OutputDebugStringW? */
[36867]762 break;
763 }
764 return EXCEPTION_CONTINUE_SEARCH;
765}
766
767void vboxVDbgVEHandlerRegister()
768{
769 Assert(!g_VBoxWDbgVEHandler);
[85121]770 g_VBoxWDbgVEHandler = AddVectoredExceptionHandler(1, vboxVDbgVectoredHandler);
[36867]771 Assert(g_VBoxWDbgVEHandler);
[69872]772
773 g_hModPsapi = GetModuleHandleA("Psapi.dll"); /* Usually already loaded. */
774 if (g_hModPsapi)
775 g_pfnGetModuleInformation = (PFNGetModuleInformation)GetProcAddress(g_hModPsapi, "GetModuleInformation");
[36867]776}
777
778void vboxVDbgVEHandlerUnregister()
779{
780 Assert(g_VBoxWDbgVEHandler);
781 ULONG uResult = RemoveVectoredExceptionHandler(g_VBoxWDbgVEHandler);
[69872]782 Assert(uResult); RT_NOREF(uResult);
[36867]783 g_VBoxWDbgVEHandler = NULL;
[69872]784
785 g_hModPsapi = NULL;
786 g_pfnGetModuleInformation = NULL;
[36867]787}
788
[69872]789#endif /* VBOXWDDMDISP_DEBUG_VEHANDLER */
[95955]790#if defined(VBOXWDDMDISP_DEBUG) || defined(LOG_TO_BACKDOOR_DRV)
[39160]791
[95955]792void vboxDispLogDrvF(char const *pszFormat, ...)
[41472]793{
[95955]794 char szBuffer[4096];
795 va_list va;
796 va_start(va, pszFormat);
797 vboxDispLogDbgFormatStringV(szBuffer, sizeof(szBuffer), pszFormat, va);
798 va_end(va);
[39160]799
[41472]800 VBoxDispMpLoggerLog(szBuffer);
801}
[79938]802
[95955]803void vboxDispLogDbgPrintF(const char *pszFormat, ...)
[79938]804{
[95955]805 char szBuffer[4096];
806 va_list va;
807 va_start(va, pszFormat);
808 vboxDispLogDbgFormatStringV(szBuffer, sizeof(szBuffer), pszFormat, va);
809 va_end(va);
[79938]810
811 OutputDebugStringA(szBuffer);
812}
[95955]813
[39160]814#endif
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use