VirtualBox

source: vbox/trunk/src/VBox/Additions/3D/win/VBoxGL/VBoxGL.c

Last change on this file was 103999, checked in by vboxsync, 5 weeks ago

Addition/3D,Additions/WINNT/Graphics: Updates for mesa-24.0.2 (not enabled yet). bugref:10606

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.9 KB
Line 
1/* $Id: VBoxGL.c 103999 2024-03-22 12:38:39Z vboxsync $ */
2/** @file
3 * VirtualBox Windows Guest Mesa3D - OpenGL driver.
4 */
5
6/*
7 * Copyright (C) 2018-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 "GaDrvEnvKMT.h"
29
30#include "stw_winsys.h"
31#include "stw_device.h"
32#include "stw_context.h"
33
34#include "pipe/p_state.h"
35#if VBOX_MESA_V_MAJOR >= 24
36#include "state_tracker/st_context.h"
37#endif
38#include "svga3d_reg.h"
39
40#include <iprt/asm.h>
41#include <iprt/initterm.h>
42
43#include <common/wddm/VBoxMPIf.h>
44
45#include <Psapi.h>
46
47#if VBOX_MESA_V_MAJOR < 24
48static const char *g_pszSvgaDll =
49#ifdef VBOX_WOW64
50 "VBoxSVGA-x86.dll"
51#else
52 "VBoxSVGA.dll"
53#endif
54;
55#endif
56
57static struct GaDrvFunctions
58{
59 PFNGaDrvScreenCreate pfnGaDrvScreenCreate;
60 PFNGaDrvScreenDestroy pfnGaDrvScreenDestroy;
61 PFNGaDrvGetWDDMEnv pfnGaDrvGetWDDMEnv;
62 PFNGaDrvGetContextId pfnGaDrvGetContextId;
63 PFNGaDrvGetSurfaceId pfnGaDrvGetSurfaceId;
64 PFNGaDrvContextFlush pfnGaDrvContextFlush;
65} g_drvfuncs;
66
67
68#if VBOX_MESA_V_MAJOR < 24
69static HMODULE gaDrvLoadSVGA(struct GaDrvFunctions *pDrvFuncs)
70{
71 struct VBOXWDDMDLLPROC aDrvProcs[] =
72 {
73 { "GaDrvScreenCreate", (FARPROC *)&pDrvFuncs->pfnGaDrvScreenCreate },
74 { "GaDrvScreenDestroy", (FARPROC *)&pDrvFuncs->pfnGaDrvScreenDestroy },
75 { "GaDrvGetWDDMEnv", (FARPROC *)&pDrvFuncs->pfnGaDrvGetWDDMEnv },
76 { "GaDrvGetContextId", (FARPROC *)&pDrvFuncs->pfnGaDrvGetContextId },
77 { "GaDrvGetSurfaceId", (FARPROC *)&pDrvFuncs->pfnGaDrvGetSurfaceId },
78 { "GaDrvContextFlush", (FARPROC *)&pDrvFuncs->pfnGaDrvContextFlush },
79 { NULL, NULL }
80 };
81
82 HMODULE hmod = VBoxWddmLoadSystemDll(g_pszSvgaDll);
83 if (hmod)
84 {
85 VBoxWddmLoadAdresses(hmod, aDrvProcs);
86 }
87 return hmod;
88}
89#else
90struct pipe_screen * WINAPI GaDrvScreenCreate(const WDDMGalliumDriverEnv *pEnv);
91void WINAPI GaDrvScreenDestroy(struct pipe_screen *s);
92uint32_t WINAPI GaDrvGetSurfaceId(struct pipe_screen *pScreen, struct pipe_resource *pResource);
93const WDDMGalliumDriverEnv *WINAPI GaDrvGetWDDMEnv(struct pipe_screen *pScreen);
94uint32_t WINAPI GaDrvGetContextId(struct pipe_context *pPipeContext);
95void WINAPI GaDrvContextFlush(struct pipe_context *pPipeContext);
96
97static void initDrvFuncs(void)
98{
99 g_drvfuncs.pfnGaDrvScreenCreate = GaDrvScreenCreate;
100 g_drvfuncs.pfnGaDrvScreenDestroy = GaDrvScreenDestroy;
101 g_drvfuncs.pfnGaDrvGetWDDMEnv = GaDrvGetWDDMEnv;
102 g_drvfuncs.pfnGaDrvGetContextId = GaDrvGetContextId;
103 g_drvfuncs.pfnGaDrvGetSurfaceId = GaDrvGetSurfaceId;
104 g_drvfuncs.pfnGaDrvContextFlush = GaDrvContextFlush;
105}
106#endif
107
108struct stw_shared_surface
109{
110 D3DKMT_HANDLE hResource;
111 D3DKMT_HANDLE hSurface;
112 uint32_t u32Sid;
113};
114
115static NTSTATUS vboxKmtPresent(D3DKMT_HANDLE hContext, HWND hwnd, D3DKMT_HANDLE hSource, LONG lWidth, LONG lHeight)
116{
117 RECT r;
118 r.left = 0;
119 r.top = 0;
120 r.right = lWidth;
121 r.bottom = lHeight;
122
123 D3DKMT_PRESENT PresentData;
124 memset(&PresentData, 0, sizeof(PresentData));
125 PresentData.hContext = hContext;
126 PresentData.hWindow = hwnd;
127 PresentData.hSource = hSource;
128 PresentData.hDestination = 0;
129 PresentData.Flags.Blt = 1;
130 PresentData.Flags.SrcRectValid = 1;
131 PresentData.Flags.DstRectValid = 1;
132 PresentData.SrcRect = r;
133 PresentData.SubRectCnt = 1;
134 PresentData.pSrcSubRects = &r;
135 PresentData.DstRect = r;
136
137 D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
138 NTSTATUS Status = d3dkmt->pfnD3DKMTPresent(&PresentData);
139 return Status;
140}
141
142NTSTATUS vboxKmtOpenSharedSurface(D3DKMT_HANDLE hAdapter, D3DKMT_HANDLE hDevice, D3DKMT_HANDLE hSharedSurface, struct stw_shared_surface *pSurf)
143{
144 D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
145
146 D3DKMT_QUERYRESOURCEINFO QueryResourceInfoData;
147 memset(&QueryResourceInfoData, 0, sizeof(QueryResourceInfoData));
148 QueryResourceInfoData.hDevice = hDevice;
149 QueryResourceInfoData.hGlobalShare = hSharedSurface;
150
151 NTSTATUS Status = d3dkmt->pfnD3DKMTQueryResourceInfo(&QueryResourceInfoData);
152 if (Status == STATUS_SUCCESS)
153 {
154 D3DDDI_OPENALLOCATIONINFO OpenAllocationInfoData;
155 memset(&OpenAllocationInfoData, 0, sizeof(OpenAllocationInfoData));
156
157 D3DKMT_OPENRESOURCE OpenResourceData;
158 memset(&OpenResourceData, 0, sizeof(OpenResourceData));
159 OpenResourceData.hDevice = hDevice;
160 OpenResourceData.hGlobalShare = hSharedSurface;
161 OpenResourceData.NumAllocations = 1;
162 OpenResourceData.pOpenAllocationInfo = &OpenAllocationInfoData;
163 if (QueryResourceInfoData.PrivateRuntimeDataSize)
164 {
165 OpenResourceData.pPrivateRuntimeData = malloc(QueryResourceInfoData.PrivateRuntimeDataSize);
166 if (OpenResourceData.pPrivateRuntimeData == NULL)
167 {
168 Status = STATUS_NOT_SUPPORTED;
169 }
170 OpenResourceData.PrivateRuntimeDataSize = QueryResourceInfoData.PrivateRuntimeDataSize;
171 }
172 if (QueryResourceInfoData.ResourcePrivateDriverDataSize)
173 {
174 OpenResourceData.pResourcePrivateDriverData = malloc(QueryResourceInfoData.ResourcePrivateDriverDataSize);
175 if (OpenResourceData.pResourcePrivateDriverData == NULL)
176 {
177 Status = STATUS_NOT_SUPPORTED;
178 }
179 OpenResourceData.ResourcePrivateDriverDataSize = QueryResourceInfoData.ResourcePrivateDriverDataSize;
180 }
181 if (QueryResourceInfoData.TotalPrivateDriverDataSize)
182 {
183 OpenResourceData.pTotalPrivateDriverDataBuffer = malloc(QueryResourceInfoData.TotalPrivateDriverDataSize);
184 if (OpenResourceData.pTotalPrivateDriverDataBuffer == NULL)
185 {
186 Status = STATUS_NOT_SUPPORTED;
187 }
188 OpenResourceData.TotalPrivateDriverDataBufferSize = QueryResourceInfoData.TotalPrivateDriverDataSize;
189 }
190
191 if (Status == STATUS_SUCCESS)
192 {
193 Status = d3dkmt->pfnD3DKMTOpenResource(&OpenResourceData);
194 if (Status == STATUS_SUCCESS)
195 {
196 if (OpenAllocationInfoData.PrivateDriverDataSize == sizeof(VBOXWDDM_ALLOCINFO))
197 {
198 VBOXWDDM_ALLOCINFO *pVBoxAllocInfo = (VBOXWDDM_ALLOCINFO *)OpenAllocationInfoData.pPrivateDriverData;
199 pSurf->hResource = OpenResourceData.hResource;
200 pSurf->hSurface = OpenAllocationInfoData.hAllocation;
201 pSurf->u32Sid = pVBoxAllocInfo->hostID;
202 }
203 else if (OpenAllocationInfoData.PrivateDriverDataSize == sizeof(VBOXDXALLOCATIONDESC))
204 {
205 //VBOXDXALLOCATIONDESC *pAllocDesc = (VBOXDXALLOCATIONDESC *)OpenAllocationInfoData.PrivateDriverDataSize;
206 pSurf->hResource = OpenResourceData.hResource;
207 pSurf->hSurface = OpenAllocationInfoData.hAllocation;
208
209 VBOXDISPIFESCAPE_SVGAGETSID data;
210 memset(&data, 0, sizeof(data));
211 data.EscapeHdr.escapeCode = VBOXESC_SVGAGETSID;
212 data.hAllocation = OpenAllocationInfoData.hAllocation;
213 // data.u32Sid = 0;
214
215 D3DKMT_ESCAPE EscapeData;
216 memset(&EscapeData, 0, sizeof(EscapeData));
217 EscapeData.hAdapter = hAdapter;
218 EscapeData.hDevice = hDevice;
219 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
220 // EscapeData.Flags.HardwareAccess = 0;
221 EscapeData.pPrivateDriverData = &data;
222 EscapeData.PrivateDriverDataSize = sizeof(data);
223 // EscapeData.hContext = 0;
224 Status = d3dkmt->pfnD3DKMTEscape(&EscapeData);
225 if (Status == STATUS_SUCCESS)
226 pSurf->u32Sid = data.u32Sid;
227 else
228 Assert(0);
229 }
230 else
231 Assert(0);
232 }
233 }
234
235 if (OpenResourceData.pPrivateRuntimeData != NULL)
236 {
237 free(OpenResourceData.pPrivateRuntimeData);
238 }
239 if (OpenResourceData.pResourcePrivateDriverData != NULL)
240 {
241 free(OpenResourceData.pResourcePrivateDriverData);
242 }
243 if (OpenResourceData.pTotalPrivateDriverDataBuffer != NULL)
244 {
245 free(OpenResourceData.pTotalPrivateDriverDataBuffer);
246 }
247 }
248
249 return Status;
250}
251
252NTSTATUS vboxKmtCloseSharedSurface(D3DKMT_HANDLE hDevice, struct stw_shared_surface *pSurf)
253{
254 D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
255
256 D3DKMT_DESTROYALLOCATION DestroyAllocationData;
257 memset(&DestroyAllocationData, 0, sizeof(DestroyAllocationData));
258 DestroyAllocationData.hDevice = hDevice;
259 DestroyAllocationData.hResource = pSurf->hResource;
260 /* "If the OpenGL ICD sets the handle in the hResource member to a non-NULL value,
261 * the ICD must set phAllocationList to NULL." and
262 * "the AllocationCount member is ignored by the OpenGL runtime."
263 */
264 // DestroyAllocationData.phAllocationList = NULL;
265 // DestroyAllocationData.AllocationCount = 0;
266
267 NTSTATUS Status = d3dkmt->pfnD3DKMTDestroyAllocation(&DestroyAllocationData);
268 Assert(Status == STATUS_SUCCESS);
269 return Status;
270}
271
272
273static struct pipe_screen *
274wddm_screen_create(HDC hDC)
275{
276 RT_NOREF(hDC); /** @todo Use it? */
277 struct pipe_screen *screen = NULL;
278
279#if VBOX_MESA_V_MAJOR < 24
280 if (gaDrvLoadSVGA(&g_drvfuncs))
281#else
282 initDrvFuncs();
283#endif
284 {
285 WDDMGalliumDriverEnv const *pEnv = GaDrvEnvKmtCreate();
286 if (pEnv)
287 {
288 /// @todo pEnv to include destructor callback, to be called from winsys screen destructor?
289 screen = g_drvfuncs.pfnGaDrvScreenCreate(pEnv);
290 }
291 }
292
293 return screen;
294}
295
296static void
297wddm_present(struct pipe_screen *screen,
298 struct pipe_context *context,
299 struct pipe_resource *res,
300 HDC hDC)
301{
302 RT_NOREF(context);
303 struct stw_context *ctx = stw_current_context();
304 struct pipe_context *pipe = ctx->st->pipe;
305
306 const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
307 if (pEnv)
308 {
309 /* Get context and kernel-mode handle of the resource. */
310 uint32_t u32Cid = g_drvfuncs.pfnGaDrvGetContextId(pipe);
311 D3DKMT_HANDLE hContext = GaDrvEnvKmtContextHandle(pEnv, u32Cid);
312
313 uint32_t u32SourceSid = g_drvfuncs.pfnGaDrvGetSurfaceId(screen, res);
314 D3DKMT_HANDLE hSource = GaDrvEnvKmtSurfaceHandle(pEnv, u32SourceSid);
315
316 HWND hwnd = WindowFromDC(hDC);
317
318 vboxKmtPresent(hContext, hwnd, hSource, res->width0, res->height0);
319 }
320}
321
322#if VBOX_MESA_V_MAJOR < 24
323static boolean
324#else
325static bool
326#endif
327wddm_get_adapter_luid(struct pipe_screen *screen,
328 HDC hDC,
329 LUID *pAdapterLuid)
330{
331 RT_NOREF(hDC); /** @todo Use it? */
332 const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
333 if (pEnv)
334 {
335 GaDrvEnvKmtAdapterLUID(pEnv, pAdapterLuid);
336 return true;
337 }
338
339 return false;
340}
341
342static struct stw_shared_surface *
343wddm_shared_surface_open(struct pipe_screen *screen,
344 HANDLE hSharedSurface)
345{
346 struct stw_shared_surface *surface = NULL;
347
348 const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
349 if (pEnv)
350 {
351 surface = (struct stw_shared_surface *)malloc(sizeof(struct stw_shared_surface));
352 if (surface)
353 {
354 D3DKMT_HANDLE hAdapter = GaDrvEnvKmtAdapterHandle(pEnv);
355 D3DKMT_HANDLE hDevice = GaDrvEnvKmtDeviceHandle(pEnv);
356 NTSTATUS Status = vboxKmtOpenSharedSurface(hAdapter, hDevice, (D3DKMT_HANDLE)(uintptr_t)hSharedSurface, surface);
357 if (Status != STATUS_SUCCESS)
358 {
359 free(surface);
360 surface = NULL;
361 }
362 }
363 }
364 return surface;
365}
366
367static void
368wddm_shared_surface_close(struct pipe_screen *screen,
369 struct stw_shared_surface *surface)
370{
371 const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
372 if (pEnv)
373 {
374 D3DKMT_HANDLE hDevice = GaDrvEnvKmtDeviceHandle(pEnv);
375 vboxKmtCloseSharedSurface(hDevice, surface);
376 }
377 free(surface);
378}
379
380static void
381wddm_compose(struct pipe_screen *screen,
382 struct pipe_resource *res,
383 struct stw_shared_surface *dest,
384 LPCRECT pRect,
385 ULONGLONG PresentHistoryToken)
386{
387 struct stw_context *ctx = stw_current_context();
388 struct pipe_context *pipe = ctx->st->pipe;
389
390 /* The ICD asked to present something, make sure that any outstanding commends are submitted. */
391 g_drvfuncs.pfnGaDrvContextFlush(pipe);
392
393 uint32_t u32SourceSid = g_drvfuncs.pfnGaDrvGetSurfaceId(screen, res);
394
395 /* Generate SVGA_3D_CMD_SURFACE_COPY command for these resources. */
396 struct
397 {
398 SVGA3dCmdHeader header;
399 SVGA3dCmdSurfaceCopy surfaceCopy;
400 SVGA3dCopyBox box;
401 } command;
402
403 command.header.id = SVGA_3D_CMD_SURFACE_COPY;
404 command.header.size = sizeof(command) - sizeof(SVGA3dCmdHeader);
405
406 command.surfaceCopy.src.sid = u32SourceSid;
407 command.surfaceCopy.src.face = 0;
408 command.surfaceCopy.src.mipmap = 0;
409 command.surfaceCopy.dest.sid = dest->u32Sid;
410 command.surfaceCopy.dest.face = 0;
411 command.surfaceCopy.dest.mipmap = 0;
412
413 command.box.x = pRect->left;
414 command.box.y = pRect->top;
415 command.box.z = 0;
416 command.box.w = pRect->right - pRect->left;
417 command.box.h = pRect->bottom - pRect->top;
418 command.box.d = 1;
419 command.box.srcx = 0;
420 command.box.srcy = 0;
421 command.box.srcz = 0;
422
423 const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
424 if (pEnv)
425 {
426 uint32_t u32Cid = g_drvfuncs.pfnGaDrvGetContextId(pipe);
427 GaDrvEnvKmtRenderCompose(pEnv, u32Cid, &command, sizeof(command), PresentHistoryToken);
428 }
429}
430
431static unsigned
432wddm_get_pfd_flags(struct pipe_screen *screen)
433{
434 (void)screen;
435 return stw_pfd_gdi_support | stw_pfd_double_buffer;
436}
437
438static const char *
439wddm_get_name(void)
440{
441 return "VBoxGL";
442}
443
444static const struct stw_winsys stw_winsys = {
445 wddm_screen_create,
446 wddm_present,
447 wddm_get_adapter_luid,
448 wddm_shared_surface_open,
449 wddm_shared_surface_close,
450 wddm_compose,
451 wddm_get_pfd_flags,
452 NULL, /* create_framebuffer */
453 wddm_get_name,
454};
455
456#ifdef DEBUG
457typedef BOOL WINAPI FNGetModuleInformation(HANDLE hProcess, HMODULE hModule, LPMODULEINFO lpmodinfo, DWORD cb);
458typedef FNGetModuleInformation *PFNGetModuleInformation;
459
460static PFNGetModuleInformation g_pfnGetModuleInformation = NULL;
461static HMODULE g_hModPsapi = NULL;
462static PVOID g_VBoxWDbgVEHandler = NULL;
463
464static bool vboxVDbgIsAddressInModule(PVOID pv, const char *pszModuleName)
465{
466 HMODULE hMod = GetModuleHandleA(pszModuleName);
467 if (!hMod)
468 return false;
469
470 if (!g_pfnGetModuleInformation)
471 return false;
472
473 HANDLE hProcess = GetCurrentProcess();
474 MODULEINFO ModuleInfo = {0};
475 if (!g_pfnGetModuleInformation(hProcess, hMod, &ModuleInfo, sizeof(ModuleInfo)))
476 return false;
477
478 return (uintptr_t)ModuleInfo.lpBaseOfDll <= (uintptr_t)pv
479 && (uintptr_t)pv < (uintptr_t)ModuleInfo.lpBaseOfDll + ModuleInfo.SizeOfImage;
480}
481
482static bool vboxVDbgIsExceptionIgnored(PEXCEPTION_RECORD pExceptionRecord)
483{
484 /* Module (dll) names for GetModuleHandle.
485 * Exceptions originated from these modules will be ignored.
486 */
487 static const char *apszIgnoredModuleNames[] =
488 {
489 NULL
490 };
491
492 int i = 0;
493 while (apszIgnoredModuleNames[i])
494 {
495 if (vboxVDbgIsAddressInModule(pExceptionRecord->ExceptionAddress, apszIgnoredModuleNames[i]))
496 return true;
497
498 ++i;
499 }
500
501 return false;
502}
503
504static LONG WINAPI vboxVDbgVectoredHandler(struct _EXCEPTION_POINTERS *pExceptionInfo) RT_NOTHROW_DEF
505{
506 static volatile bool g_fAllowIgnore = true; /* Might be changed in kernel debugger. */
507
508 PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
509 /* PCONTEXT pContextRecord = pExceptionInfo->ContextRecord; */
510
511 switch (pExceptionRecord->ExceptionCode)
512 {
513 default:
514 break;
515 case EXCEPTION_BREAKPOINT:
516 case EXCEPTION_ACCESS_VIOLATION:
517 case EXCEPTION_STACK_OVERFLOW:
518 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
519 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
520 case EXCEPTION_FLT_INVALID_OPERATION:
521 case EXCEPTION_INT_DIVIDE_BY_ZERO:
522 case EXCEPTION_ILLEGAL_INSTRUCTION:
523 if (g_fAllowIgnore && vboxVDbgIsExceptionIgnored(pExceptionRecord))
524 break;
525 ASMBreakpoint();
526 break;
527 case 0x40010006: /* OutputDebugStringA? */
528 case 0x4001000a: /* OutputDebugStringW? */
529 break;
530 }
531 return EXCEPTION_CONTINUE_SEARCH;
532}
533
534static void vboxVDbgVEHandlerRegister(void)
535{
536 Assert(!g_VBoxWDbgVEHandler);
537 g_VBoxWDbgVEHandler = AddVectoredExceptionHandler(1, vboxVDbgVectoredHandler);
538 Assert(g_VBoxWDbgVEHandler);
539
540 g_hModPsapi = GetModuleHandleA("Psapi.dll"); /* Usually already loaded. */
541 if (g_hModPsapi)
542 g_pfnGetModuleInformation = (PFNGetModuleInformation)GetProcAddress(g_hModPsapi, "GetModuleInformation");
543}
544
545static void vboxVDbgVEHandlerUnregister(void)
546{
547 Assert(g_VBoxWDbgVEHandler);
548 ULONG uResult = RemoveVectoredExceptionHandler(g_VBoxWDbgVEHandler);
549 Assert(uResult); RT_NOREF(uResult);
550 g_VBoxWDbgVEHandler = NULL;
551
552 g_hModPsapi = NULL;
553 g_pfnGetModuleInformation = NULL;
554}
555#endif /* DEBUG */
556
557BOOL WINAPI DllMain(HINSTANCE hDLLInst,
558 DWORD fdwReason,
559 LPVOID lpvReserved)
560{
561 RT_NOREF2(hDLLInst, lpvReserved);
562
563 switch (fdwReason)
564 {
565 case DLL_PROCESS_ATTACH:
566#ifdef DEBUG
567 vboxVDbgVEHandlerRegister();
568#endif
569 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
570 D3DKMTLoad();
571 stw_init(&stw_winsys);
572 stw_init_thread();
573 break;
574
575 case DLL_PROCESS_DETACH:
576#ifdef DEBUG
577 vboxVDbgVEHandlerUnregister();
578#endif
579 break;
580
581 case DLL_THREAD_ATTACH:
582 stw_init_thread();
583 break;
584
585 case DLL_THREAD_DETACH:
586 stw_cleanup_thread();
587 break;
588
589 default:
590 if (lpvReserved == NULL)
591 {
592 // We're being unloaded from the process.
593 stw_cleanup_thread();
594 stw_cleanup();
595 }
596 else
597 {
598 // Process itself is terminating, and all threads and modules are
599 // being detached.
600 //
601 // The order threads (including llvmpipe rasterizer threads) are
602 // destroyed can not be relied up, so it's not safe to cleanup.
603 //
604 // However global destructors (e.g., LLVM's) will still be called, and
605 // if Microsoft OPENGL32.DLL's DllMain is called after us, it will
606 // still try to invoke DrvDeleteContext to destroys all outstanding,
607 // so set stw_dev to NULL to return immediately if that happens.
608 stw_dev = NULL;
609 }
610 break;
611 }
612
613 return TRUE;
614}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use