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, 16 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
Line 
1/* $Id: VBoxDispDbg.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxVideo Display D3D User mode dll
4 */
5
6/*
7 * Copyright (C) 2011-2023 Oracle and/or its affiliates.
8 *
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
26 */
27
28#include "VBoxDispD3DCmn.h"
29
30#ifdef VBOXWDDMDISP_DEBUG_VEHANDLER
31# include <Psapi.h>
32#endif
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/process.h>
37#include <iprt/string.h>
38
39#ifndef IPRT_NO_CRT
40# include <stdio.h>
41#endif
42
43
44#if defined(VBOXWDDMDISP_DEBUG) || defined(LOG_TO_BACKDOOR_DRV)
45static const char *vboxVDbgDoGetExeName(void)
46{
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)
54 {
55 DWORD cName = GetModuleFileNameA(NULL, s_szExePath, RT_ELEMENTS(s_szExePath));
56 if (!cName)
57 {
58# ifdef LOG_ENABLED
59 DWORD winEr = GetLastError();
60# endif
61 WARN(("GetModuleFileNameA failed, winEr %d", winEr));
62 return NULL;
63 }
64 s_fInitialized = TRUE;
65 }
66 return s_szExePath;
67#endif /* !IPRT_NO_CRT */
68}
69
70static void vboxDispLogDbgFormatStringV(char *pszBuffer, uint32_t cbBuffer, const char *pszFormat, va_list va)
71{
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
79 int cch = _snprintf(pszBuffer, cbBuffer, "['%s' 0x%lx.0x%lx] Disp: ",
80 vboxVDbgDoGetExeName(), GetCurrentProcessId(), GetCurrentThreadId());
81 AssertReturnVoid(cch > 0);
82 AssertReturnVoid((unsigned)cch + 2 <= cbBuffer);
83 cbBuffer -= (unsigned)cch;
84 pszBuffer += (unsigned)cch;
85
86 cch = _vsnprintf(pszBuffer, cbBuffer, pszFormat, va);
87 pszBuffer[cbBuffer - 1] = '\0'; /* Don't trust _vsnprintf to terminate the output. */
88# endif
89}
90
91#endif /* VBOXWDDMDISP_DEBUG || LOG_TO_BACKDOOR_DRV */
92#if defined(VBOXWDDMDISP_DEBUG)
93LONG g_VBoxVDbgFIsDwm = -1;
94
95DWORD g_VBoxVDbgPid = 0;
96
97DWORD g_VBoxVDbgFLogRel = 1;
98# if !defined(VBOXWDDMDISP_DEBUG)
99DWORD g_VBoxVDbgFLog = 0;
100# else
101DWORD g_VBoxVDbgFLog = 1;
102# endif
103DWORD g_VBoxVDbgFLogFlow = 0;
104
105#endif
106
107#ifdef VBOXWDDMDISP_DEBUG
108
109#define VBOXWDDMDISP_DEBUG_DUMP_DEFAULT 0
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;
119DWORD g_VBoxVDbgFDumpPresentEnter = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
120DWORD g_VBoxVDbgFDumpPresentLeave = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
121DWORD g_VBoxVDbgFDumpScSync = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
122
123DWORD g_VBoxVDbgFBreakShared = VBOXWDDMDISP_DEBUG_DUMP_DEFAULT;
124DWORD g_VBoxVDbgFBreakDdi = 0;
125
126DWORD g_VBoxVDbgFCheckSysMemSync = 0;
127DWORD g_VBoxVDbgFCheckBlt = 0;
128DWORD g_VBoxVDbgFCheckTexBlt = 0;
129DWORD g_VBoxVDbgFCheckScSync = 0;
130
131DWORD g_VBoxVDbgFSkipCheckTexBltDwmWndUpdate = 1;
132
133DWORD g_VBoxVDbgCfgMaxDirectRts = 3;
134DWORD g_VBoxVDbgCfgForceDummyDevCreate = 0;
135
136PVBOXWDDMDISP_DEVICE g_VBoxVDbgInternalDevice = NULL;
137PVBOXWDDMDISP_RESOURCE g_VBoxVDbgInternalRc = NULL;
138
139VOID vboxVDbgDoPrintDmlCmd(const char *pszDesc, const char *pszCmd)
140{
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
147 vboxVDbgPrint(("<?dml?><exec cmd=\"%s\">%s</exec>, ( %s )\n", pszCmd, pszDesc, pszCmd));
148#endif
149}
150
151VOID vboxVDbgDoPrintDumpCmd(const char* pszDesc, const void *pvData, uint32_t width, uint32_t height, uint32_t bpp, uint32_t pitch)
152{
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);
161}
162
163VOID vboxVDbgDoPrintLopLastCmd(const char* pszDesc)
164{
165 vboxVDbgDoPrintDmlCmd(pszDesc, "ed @@(&vboxVDbgLoop) 0");
166}
167
168typedef struct VBOXVDBG_DUMP_INFO
169{
170 DWORD fFlags;
171 const VBOXWDDMDISP_ALLOCATION *pAlloc;
172 IDirect3DResource9 *pD3DRc;
173 const RECT *pRect;
174} VBOXVDBG_DUMP_INFO, *PVBOXVDBG_DUMP_INFO;
175
176typedef DECLCALLBACKTYPE(void, FNVBOXVDBG_CONTENTS_DUMPER,(PVBOXVDBG_DUMP_INFO pInfo, BOOLEAN fBreak, void *pvDumper));
177typedef FNVBOXVDBG_CONTENTS_DUMPER *PFNVBOXVDBG_CONTENTS_DUMPER;
178
179static VOID vboxVDbgDoDumpSummary(const char * pPrefix, PVBOXVDBG_DUMP_INFO pInfo, const char * pSuffix)
180{
181 const VBOXWDDMDISP_ALLOCATION *pAlloc = pInfo->pAlloc;
182 IDirect3DResource9 *pD3DRc = pInfo->pD3DRc;
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
191 else
192 strcpy(szRectBuf, "n/a");
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",
201 szRectBuf,
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
211 if (!VBOXVDBG_DUMP_TYPE_ENABLED_FOR_INFO(pInfo, fFlags))
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)
219 {
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;
225 }
226
227 vboxVDbgDoDumpSummary(pPrefix, pInfo, NULL);
228
229 pfnCd(pInfo, VBOXVDBG_DUMP_FLAGS_IS_CLEARED(fFlags, VBOXVDBG_DUMP_TYPEF_DONT_BREAK_ON_CONTENTS), pvCd);
230
231 if (pSuffix && pSuffix[0] != '\0')
232 vboxVDbgPrint(("%s", pSuffix));
233}
234
235static DECLCALLBACK(void) vboxVDbgAllocRectContentsDumperCb(PVBOXVDBG_DUMP_INFO pInfo, BOOLEAN fBreak, void *pvDumper)
236{
237 RT_NOREF(fBreak, pvDumper);
238 const VBOXWDDMDISP_ALLOCATION *pAlloc = pInfo->pAlloc;
239 const RECT *pRect = pInfo->pRect;
240
241 Assert(pAlloc->hAllocation);
242
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);
260 vboxVDbgDoPrintDumpCmd("Surf Info", LockData.pData, pAlloc->SurfDesc.d3dWidth, pAlloc->SurfDesc.height, bpp, pAlloc->SurfDesc.pitch);
261 if (pRect)
262 {
263 Assert(pRect->right > pRect->left);
264 Assert(pRect->bottom > pRect->top);
265 vboxVDbgDoPrintRect("rect: ", pRect, "\n");
266 vboxVDbgDoPrintDumpCmd("Rect Info", ((uint8_t*)LockData.pData) + (pRect->top * pAlloc->SurfDesc.pitch) + ((pRect->left * bpp) >> 3),
267 pRect->right - pRect->left, pRect->bottom - pRect->top, bpp, pAlloc->SurfDesc.pitch);
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
281VOID vboxVDbgDoDumpAllocRect(const char * pPrefix, PVBOXWDDMDISP_ALLOCATION pAlloc, RECT *pRect, const char* pSuffix, DWORD fFlags)
282{
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);
289}
290
291static DECLCALLBACK(void) vboxVDbgRcRectContentsDumperCb(PVBOXVDBG_DUMP_INFO pInfo, BOOLEAN fBreak, void *pvDumper)
292{
293 RT_NOREF(pvDumper);
294 const VBOXWDDMDISP_ALLOCATION *pAlloc = pInfo->pAlloc;
295 const RECT *pRect = pInfo->pRect;
296 IDirect3DSurface9 *pSurf;
297 HRESULT hr = VBoxD3DIfSurfGet(pAlloc->pRc, pAlloc->iAlloc, &pSurf);
298 if (hr != S_OK)
299 {
300 WARN(("VBoxD3DIfSurfGet failed, hr 0x%x", hr));
301 return;
302 }
303
304 D3DSURFACE_DESC Desc;
305 hr = pSurf->GetDesc(&Desc);
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);
315 vboxVDbgDoPrintDumpCmd("Surf Info", Lr.pBits, Desc.Width, Desc.Height, bpp, Lr.Pitch);
316 if (pRect)
317 {
318 Assert(pRect->right > pRect->left);
319 Assert(pRect->bottom > pRect->top);
320 vboxVDbgDoPrintRect("rect: ", pRect, "\n");
321 vboxVDbgDoPrintDumpCmd("Rect Info", ((uint8_t*)Lr.pBits) + (pRect->top * Lr.Pitch) + ((pRect->left * bpp) >> 3),
322 pRect->right - pRect->left, pRect->bottom - pRect->top, bpp, Lr.Pitch);
323 }
324
325 if (fBreak)
326 {
327 Assert(0);
328 }
329 hr = pSurf->UnlockRect();
330 Assert(hr == S_OK);
331 }
332 }
333
334 pSurf->Release();
335}
336
337VOID vboxVDbgDoDumpRcRect(const char * pPrefix, PVBOXWDDMDISP_ALLOCATION pAlloc,
338 IDirect3DResource9 *pD3DRc, RECT *pRect, const char * pSuffix, DWORD fFlags)
339{
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);
346}
347
348
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
368VOID vboxVDbgDoDumpRt(const char * pPrefix, PVBOXWDDMDISP_DEVICE pDevice, const char * pSuffix, DWORD fFlags)
369{
370 for (UINT i = 0; i < pDevice->cRTs; ++i)
371 {
372 IDirect3DSurface9 *pRt;
373 PVBOXWDDMDISP_ALLOCATION pAlloc = pDevice->apRTs[i];
374 if (!pAlloc) continue;
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);
381 vboxVDbgDoDumpRcRect(pPrefix, pAlloc, NULL, NULL, pSuffix, fFlags);
382 pRt->Release();
383 }
384 else
385 {
386 vboxVDbgPrint((__FUNCTION__": ERROR getting rt: 0x%x", hr));
387 }
388 }
389}
390
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
407static DECLCALLBACK(void) vboxVDbgLockUnlockSurfTexContentsDumperCb(PVBOXVDBG_DUMP_INFO pInfo, BOOLEAN fBreak, void *pvDumper)
408{
409 RT_NOREF(pvDumper);
410 const VBOXWDDMDISP_ALLOCATION *pAlloc = pInfo->pAlloc;
411 const RECT *pRect = pInfo->pRect;
412 UINT bpp = vboxWddmCalcBitsPerPixel(pAlloc->SurfDesc.format);
413 uint32_t width, height, pitch = 0;
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 }
420 else
421 {
422 width = pAlloc->SurfDesc.width;
423 height = pAlloc->SurfDesc.height;
424 }
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
436 vboxVDbgDoPrintDumpCmd("Surf Info", pvData, width, height, bpp, pitch);
437
438 if (fBreak)
439 {
440 Assert(0);
441 }
442}
443
444VOID vboxVDbgDoDumpLockUnlockSurfTex(const char * pPrefix, const VBOXWDDMDISP_ALLOCATION *pAlloc, const char * pSuffix, DWORD fFlags)
445{
446 Assert(!pAlloc->hSharedHandle);
447
448 RECT Rect;
449 const RECT *pRect;
450 Assert(!pAlloc->LockInfo.fFlags.RangeValid);
451 Assert(!pAlloc->LockInfo.fFlags.BoxValid);
452 if (pAlloc->LockInfo.fFlags.AreaValid)
453 {
454 pRect = &pAlloc->LockInfo.Area;
455 }
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 }
464
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);
471}
472
473VOID vboxVDbgDoDumpLockSurfTex(const char * pPrefix, const D3DDDIARG_LOCK* pData, const char * pSuffix, DWORD fFlags)
474{
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
481 vboxVDbgDoDumpLockUnlockSurfTex(pPrefix, pAlloc, pSuffix, fFlags);
482}
483
484VOID vboxVDbgDoDumpUnlockSurfTex(const char * pPrefix, const D3DDDIARG_UNLOCK* pData, const char * pSuffix, DWORD fFlags)
485{
486 const VBOXWDDMDISP_RESOURCE *pRc = (const VBOXWDDMDISP_RESOURCE*)pData->hResource;
487 const VBOXWDDMDISP_ALLOCATION *pAlloc = &pRc->aAllocations[pData->SubResourceIndex];
488 vboxVDbgDoDumpLockUnlockSurfTex(pPrefix, pAlloc, pSuffix, fFlags);
489}
490
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
525BOOL vboxVDbgDoCheckRectsMatch(const VBOXWDDMDISP_RESOURCE *pDstRc, uint32_t iDstAlloc,
526 const VBOXWDDMDISP_RESOURCE *pSrcRc, uint32_t iSrcAlloc,
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;
589 HRESULT hr = VBoxD3DIfLockRect((VBOXWDDMDISP_RESOURCE *)pDstRc, iDstAlloc, &DstLRect, pDstRect, D3DLOCK_READONLY);
590 if (FAILED(hr))
591 {
592 WARN(("VBoxD3DIfLockRect failed, hr(0x%x)", hr));
593 return FALSE;
594 }
595
596 hr = VBoxD3DIfLockRect((VBOXWDDMDISP_RESOURCE *)pSrcRc, iSrcAlloc, &SrcLRect, pSrcRect, D3DLOCK_READONLY);
597 if (FAILED(hr))
598 {
599 WARN(("VBoxD3DIfLockRect failed, hr(0x%x)", hr));
600 hr = VBoxD3DIfUnlockRect((VBOXWDDMDISP_RESOURCE *)pDstRc, iDstAlloc);
601 return FALSE;
602 }
603
604 fMatch = vboxVDbgDoCheckLRects(&DstLRect, pDstRect, &SrcLRect, pSrcRect, bpp, fBreakOnMismatch);
605
606 hr = VBoxD3DIfUnlockRect((VBOXWDDMDISP_RESOURCE *)pDstRc, iDstAlloc);
607 Assert(hr == S_OK);
608
609 hr = VBoxD3DIfUnlockRect((VBOXWDDMDISP_RESOURCE *)pSrcRc, iSrcAlloc);
610 Assert(hr == S_OK);
611
612 return fMatch;
613}
614
615void vboxVDbgDoPrintAlloc(const char * pPrefix, const VBOXWDDMDISP_RESOURCE *pRc, uint32_t iAlloc, const char * pSuffix)
616{
617 Assert(pRc->cAllocations > iAlloc);
618 const VBOXWDDMDISP_ALLOCATION *pAlloc = &pRc->aAllocations[iAlloc];
619 BOOL bPrimary = pRc->RcDesc.fFlags.Primary;
620 BOOL bFrontBuf = FALSE;
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,
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}
633
634static VOID CALLBACK vboxVDbgTimerCb(__in PVOID lpParameter, __in BOOLEAN TimerOrWaitFired) RT_NOTHROW_DEF
635{
636 RT_NOREF(lpParameter, TimerOrWaitFired);
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}
665#endif
666
667#if defined(VBOXWDDMDISP_DEBUG)
668BOOL vboxVDbgDoCheckExe(const char * pszName)
669{
670 char const *pszModule = vboxVDbgDoGetExeName();
671 if (!pszModule)
672 return FALSE;
673 size_t cchModule = strlen(pszModule);
674 size_t cchName = strlen(pszName);
675 if (cchName > cchModule)
676 return FALSE;
677# ifdef IPRT_NO_CRT
678 if (RTStrICmp(pszName, &pszModule[cchModule - cchName]))
679# else
680 if (_stricmp(pszName, &pszModule[cchModule - cchName]))
681# endif
682 return FALSE;
683 return TRUE;
684}
685#endif
686
687#ifdef VBOXWDDMDISP_DEBUG_VEHANDLER
688
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;
694static PVOID g_VBoxWDbgVEHandler = NULL;
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
737static LONG WINAPI vboxVDbgVectoredHandler(struct _EXCEPTION_POINTERS *pExceptionInfo) RT_NOTHROW_DEF
738{
739 static volatile bool g_fAllowIgnore = true; /* Might be changed in kernel debugger. */
740
741 PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
742 /* PCONTEXT pContextRecord = pExceptionInfo->ContextRecord; */
743
744 switch (pExceptionRecord->ExceptionCode)
745 {
746 default:
747 break;
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:
756 if (g_fAllowIgnore && vboxVDbgIsExceptionIgnored(pExceptionRecord))
757 break;
758 ASMBreakpoint();
759 break;
760 case 0x40010006: /* OutputDebugStringA? */
761 case 0x4001000a: /* OutputDebugStringW? */
762 break;
763 }
764 return EXCEPTION_CONTINUE_SEARCH;
765}
766
767void vboxVDbgVEHandlerRegister()
768{
769 Assert(!g_VBoxWDbgVEHandler);
770 g_VBoxWDbgVEHandler = AddVectoredExceptionHandler(1, vboxVDbgVectoredHandler);
771 Assert(g_VBoxWDbgVEHandler);
772
773 g_hModPsapi = GetModuleHandleA("Psapi.dll"); /* Usually already loaded. */
774 if (g_hModPsapi)
775 g_pfnGetModuleInformation = (PFNGetModuleInformation)GetProcAddress(g_hModPsapi, "GetModuleInformation");
776}
777
778void vboxVDbgVEHandlerUnregister()
779{
780 Assert(g_VBoxWDbgVEHandler);
781 ULONG uResult = RemoveVectoredExceptionHandler(g_VBoxWDbgVEHandler);
782 Assert(uResult); RT_NOREF(uResult);
783 g_VBoxWDbgVEHandler = NULL;
784
785 g_hModPsapi = NULL;
786 g_pfnGetModuleInformation = NULL;
787}
788
789#endif /* VBOXWDDMDISP_DEBUG_VEHANDLER */
790#if defined(VBOXWDDMDISP_DEBUG) || defined(LOG_TO_BACKDOOR_DRV)
791
792void vboxDispLogDrvF(char const *pszFormat, ...)
793{
794 char szBuffer[4096];
795 va_list va;
796 va_start(va, pszFormat);
797 vboxDispLogDbgFormatStringV(szBuffer, sizeof(szBuffer), pszFormat, va);
798 va_end(va);
799
800 VBoxDispMpLoggerLog(szBuffer);
801}
802
803void vboxDispLogDbgPrintF(const char *pszFormat, ...)
804{
805 char szBuffer[4096];
806 va_list va;
807 va_start(va, pszFormat);
808 vboxDispLogDbgFormatStringV(szBuffer, sizeof(szBuffer), pszFormat, va);
809 va_end(va);
810
811 OutputDebugStringA(szBuffer);
812}
813
814#endif
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use