VirtualBox

source: vbox/trunk/src/VBox/Additions/common/crOpenGL/load.c@ 68080

Last change on this file since 68080 was 65381, checked in by vboxsync, 8 years ago

bugref:8282: Additions/linux: submit DRM driver to the Linux kernel: move all graphics device-related header files to a separate sub-directory and add that to the include path where they are needed. The intention is too be able to remove the VBox/ include folder in the DRM driver package.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 41.5 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "cr_spu.h"
8#include "cr_net.h"
9#include "cr_error.h"
10#include "cr_mem.h"
11#include "cr_string.h"
12#include "cr_net.h"
13#include "cr_environment.h"
14#include "cr_process.h"
15#include "cr_rand.h"
16#include "cr_netserver.h"
17#include "stub.h"
18#include <stdlib.h>
19#include <string.h>
20#include <signal.h>
21#include <iprt/initterm.h>
22#include <iprt/thread.h>
23#include <iprt/err.h>
24#include <iprt/asm.h>
25#ifndef WINDOWS
26# include <sys/types.h>
27# include <unistd.h>
28#endif
29
30#ifdef VBOX_WITH_WDDM
31#include <d3d9types.h>
32#include <D3dumddi.h>
33#include "../../WINNT/Graphics/Video/common/wddm/VBoxMPIf.h"
34#endif
35
36#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
37# include <VBoxCrHgsmi.h>
38#endif
39
40/**
41 * If you change this, see the comments in tilesortspu_context.c
42 */
43#define MAGIC_CONTEXT_BASE 500
44
45#define CONFIG_LOOKUP_FILE ".crconfigs"
46
47#ifdef WINDOWS
48#define PYTHON_EXE "python.exe"
49#else
50#define PYTHON_EXE "python"
51#endif
52
53static bool stub_initialized = 0;
54#ifdef WINDOWS
55static CRmutex stub_init_mutex;
56#define STUB_INIT_LOCK() do { crLockMutex(&stub_init_mutex); } while (0)
57#define STUB_INIT_UNLOCK() do { crUnlockMutex(&stub_init_mutex); } while (0)
58#else
59#define STUB_INIT_LOCK() do { } while (0)
60#define STUB_INIT_UNLOCK() do { } while (0)
61#endif
62
63/* NOTE: 'SPUDispatchTable glim' is declared in NULLfuncs.py now */
64/* NOTE: 'SPUDispatchTable stubThreadsafeDispatch' is declared in tsfuncs.c */
65Stub stub;
66#ifdef CHROMIUM_THREADSAFE
67static bool g_stubIsCurrentContextTSDInited;
68CRtsd g_stubCurrentContextTSD;
69#endif
70
71
72#ifndef VBOX_NO_NATIVEGL
73static void stubInitNativeDispatch( void )
74{
75# define MAX_FUNCS 1000
76 SPUNamedFunctionTable gl_funcs[MAX_FUNCS];
77 int numFuncs;
78
79 numFuncs = crLoadOpenGL( &stub.wsInterface, gl_funcs );
80
81 stub.haveNativeOpenGL = (numFuncs > 0);
82
83 /* XXX call this after context binding */
84 numFuncs += crLoadOpenGLExtensions( &stub.wsInterface, gl_funcs + numFuncs );
85
86 CRASSERT(numFuncs < MAX_FUNCS);
87
88 crSPUInitDispatchTable( &stub.nativeDispatch );
89 crSPUInitDispatch( &stub.nativeDispatch, gl_funcs );
90 crSPUInitDispatchNops( &stub.nativeDispatch );
91# undef MAX_FUNCS
92}
93#endif /* !VBOX_NO_NATIVEGL */
94
95
96/** Pointer to the SPU's real glClear and glViewport functions */
97static ClearFunc_t origClear;
98static ViewportFunc_t origViewport;
99static SwapBuffersFunc_t origSwapBuffers;
100static DrawBufferFunc_t origDrawBuffer;
101static ScissorFunc_t origScissor;
102
103static void stubCheckWindowState(WindowInfo *window, GLboolean bFlushOnChange)
104{
105 bool bForceUpdate = false;
106 bool bChanged = false;
107
108#ifdef WINDOWS
109 /* @todo install hook and track for WM_DISPLAYCHANGE */
110 {
111 DEVMODE devMode;
112
113 devMode.dmSize = sizeof(DEVMODE);
114 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);
115
116 if (devMode.dmPelsWidth!=window->dmPelsWidth || devMode.dmPelsHeight!=window->dmPelsHeight)
117 {
118 crDebug("Resolution changed(%d,%d), forcing window Pos/Size update", devMode.dmPelsWidth, devMode.dmPelsHeight);
119 window->dmPelsWidth = devMode.dmPelsWidth;
120 window->dmPelsHeight = devMode.dmPelsHeight;
121 bForceUpdate = true;
122 }
123 }
124#endif
125
126 bChanged = stubUpdateWindowGeometry(window, bForceUpdate) || bForceUpdate;
127
128#if defined(GLX) || defined (WINDOWS)
129 if (stub.trackWindowVisibleRgn)
130 {
131 bChanged = stubUpdateWindowVisibileRegions(window) || bChanged;
132 }
133#endif
134
135 if (stub.trackWindowVisibility && window->type == CHROMIUM && window->drawable) {
136 const int mapped = stubIsWindowVisible(window);
137 if (mapped != window->mapped) {
138 crDebug("Dispatched: WindowShow(%i, %i)", window->spuWindow, mapped);
139 stub.spu->dispatch_table.WindowShow(window->spuWindow, mapped);
140 window->mapped = mapped;
141 bChanged = true;
142 }
143 }
144
145 if (bFlushOnChange && bChanged)
146 {
147 stub.spu->dispatch_table.Flush();
148 }
149}
150
151static bool stubSystemWindowExist(WindowInfo *pWindow)
152{
153#ifdef WINDOWS
154 if (pWindow->hWnd!=WindowFromDC(pWindow->drawable))
155 {
156 return false;
157 }
158#else
159 Window root;
160 int x, y;
161 unsigned int border, depth, w, h;
162 Display *dpy;
163
164 dpy = stubGetWindowDisplay(pWindow);
165
166 XLOCK(dpy);
167 if (!XGetGeometry(dpy, pWindow->drawable, &root, &x, &y, &w, &h, &border, &depth))
168 {
169 XUNLOCK(dpy);
170 return false;
171 }
172 XUNLOCK(dpy);
173#endif
174
175 return true;
176}
177
178static void stubCheckWindowsCB(unsigned long key, void *data1, void *data2)
179{
180 WindowInfo *pWindow = (WindowInfo *) data1;
181 ContextInfo *pCtx = (ContextInfo *) data2;
182 (void)key;
183
184 if (pWindow == pCtx->currentDrawable
185 || pWindow->type!=CHROMIUM
186 || pWindow->pOwner!=pCtx)
187 {
188 return;
189 }
190
191 if (!stubSystemWindowExist(pWindow))
192 {
193#ifdef WINDOWS
194 stubDestroyWindow(CR_CTX_CON(pCtx), (GLint)pWindow->hWnd);
195#else
196 stubDestroyWindow(CR_CTX_CON(pCtx), (GLint)pWindow->drawable);
197#endif
198 return;
199 }
200
201 stubCheckWindowState(pWindow, GL_FALSE);
202}
203
204static void stubCheckWindowsState(void)
205{
206 ContextInfo *context = stubGetCurrentContext();
207
208 CRASSERT(stub.trackWindowSize || stub.trackWindowPos);
209
210 if (!context)
211 return;
212
213#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
214 if (stub.bRunningUnderWDDM)
215 return;
216#endif
217
218 /* Try to keep a consistent locking order. */
219 crHashtableLock(stub.windowTable);
220#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
221 crLockMutex(&stub.mutex);
222#endif
223
224 stubCheckWindowState(context->currentDrawable, GL_TRUE);
225 crHashtableWalkUnlocked(stub.windowTable, stubCheckWindowsCB, context);
226
227#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
228 crUnlockMutex(&stub.mutex);
229#endif
230 crHashtableUnlock(stub.windowTable);
231}
232
233
234/**
235 * Override the head SPU's glClear function.
236 * We're basically trapping this function so that we can poll the
237 * application window size at a regular interval.
238 */
239static void SPU_APIENTRY trapClear(GLbitfield mask)
240{
241 stubCheckWindowsState();
242 /* call the original SPU glClear function */
243 origClear(mask);
244}
245
246/**
247 * As above, but for glViewport. Most apps call glViewport before
248 * glClear when a window is resized.
249 */
250static void SPU_APIENTRY trapViewport(GLint x, GLint y, GLsizei w, GLsizei h)
251{
252 stubCheckWindowsState();
253 /* call the original SPU glViewport function */
254 origViewport(x, y, w, h);
255}
256
257/*static void SPU_APIENTRY trapSwapBuffers(GLint window, GLint flags)
258{
259 stubCheckWindowsState();
260 origSwapBuffers(window, flags);
261}
262
263static void SPU_APIENTRY trapDrawBuffer(GLenum buf)
264{
265 stubCheckWindowsState();
266 origDrawBuffer(buf);
267}*/
268
269#if 0 /* unused */
270static void SPU_APIENTRY trapScissor(GLint x, GLint y, GLsizei w, GLsizei h)
271{
272 int winX, winY;
273 unsigned int winW, winH;
274 WindowInfo *pWindow;
275 ContextInfo *context = stubGetCurrentContext();
276 (void)x; (void)y; (void)w; (void)h;
277
278 pWindow = context->currentDrawable;
279 stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
280 origScissor(0, 0, winW, winH);
281}
282#endif /* unused */
283
284/**
285 * Use the GL function pointers in \<spu\> to initialize the static glim
286 * dispatch table.
287 */
288static void stubInitSPUDispatch(SPU *spu)
289{
290 crSPUInitDispatchTable( &stub.spuDispatch );
291 crSPUCopyDispatchTable( &stub.spuDispatch, &(spu->dispatch_table) );
292
293 if (stub.trackWindowSize || stub.trackWindowPos || stub.trackWindowVisibleRgn) {
294 /* patch-in special glClear/Viewport function to track window sizing */
295 origClear = stub.spuDispatch.Clear;
296 origViewport = stub.spuDispatch.Viewport;
297 origSwapBuffers = stub.spuDispatch.SwapBuffers;
298 origDrawBuffer = stub.spuDispatch.DrawBuffer;
299 origScissor = stub.spuDispatch.Scissor;
300 stub.spuDispatch.Clear = trapClear;
301 stub.spuDispatch.Viewport = trapViewport;
302
303 /*stub.spuDispatch.SwapBuffers = trapSwapBuffers;
304 stub.spuDispatch.DrawBuffer = trapDrawBuffer;*/
305 }
306
307 crSPUCopyDispatchTable( &glim, &stub.spuDispatch );
308}
309
310#if 0 /** @todo stubSPUTearDown & stubSPUTearDownLocked are not referenced */
311
312// Callback function, used to destroy all created contexts
313static void hsWalkStubDestroyContexts(unsigned long key, void *data1, void *data2)
314{
315 (void)data1; (void)data2;
316 stubDestroyContext(key);
317}
318
319/**
320 * This is called when we exit.
321 * We call all the SPU's cleanup functions.
322 */
323static void stubSPUTearDownLocked(void)
324{
325 crDebug("stubSPUTearDownLocked");
326
327#ifdef WINDOWS
328# ifndef CR_NEWWINTRACK
329 stubUninstallWindowMessageHook();
330# endif
331#endif
332
333#ifdef CR_NEWWINTRACK
334 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
335#endif
336
337 //delete all created contexts
338 stubMakeCurrent( NULL, NULL);
339
340 /* the lock order is windowTable->contextTable (see wglMakeCurrent_prox, glXMakeCurrent)
341 * this is why we need to take a windowTable lock since we will later do stub.windowTable access & locking */
342 crHashtableLock(stub.windowTable);
343 crHashtableWalk(stub.contextTable, hsWalkStubDestroyContexts, NULL);
344 crHashtableUnlock(stub.windowTable);
345
346 /* shutdown, now trap any calls to a NULL dispatcher */
347 crSPUCopyDispatchTable(&glim, &stubNULLDispatch);
348
349 crSPUUnloadChain(stub.spu);
350 stub.spu = NULL;
351
352#ifndef Linux
353 crUnloadOpenGL();
354#endif
355
356#ifndef WINDOWS
357 crNetTearDown();
358#endif
359
360#ifdef GLX
361 if (stub.xshmSI.shmid>=0)
362 {
363 shmctl(stub.xshmSI.shmid, IPC_RMID, 0);
364 shmdt(stub.xshmSI.shmaddr);
365 }
366 crFreeHashtable(stub.pGLXPixmapsHash, crFree);
367#endif
368
369 crFreeHashtable(stub.windowTable, crFree);
370 crFreeHashtable(stub.contextTable, NULL);
371
372 crMemset(&stub, 0, sizeof(stub));
373
374}
375
376/**
377 * This is called when we exit.
378 * We call all the SPU's cleanup functions.
379 */
380static void stubSPUTearDown(void)
381{
382 STUB_INIT_LOCK();
383 if (stub_initialized)
384 {
385 stubSPUTearDownLocked();
386 stub_initialized = 0;
387 }
388 STUB_INIT_UNLOCK();
389}
390
391#endif /** @todo stubSPUTearDown & stubSPUTearDownLocked are not referenced */
392
393static void stubSPUSafeTearDown(void)
394{
395#ifdef CHROMIUM_THREADSAFE
396 CRmutex *mutex;
397#endif
398
399 if (!stub_initialized) return;
400 stub_initialized = 0;
401
402#ifdef CHROMIUM_THREADSAFE
403 mutex = &stub.mutex;
404 crLockMutex(mutex);
405#endif
406 crDebug("stubSPUSafeTearDown");
407
408#ifdef WINDOWS
409# ifndef CR_NEWWINTRACK
410 stubUninstallWindowMessageHook();
411# endif
412#endif
413
414#if defined(CR_NEWWINTRACK)
415 crUnlockMutex(mutex);
416# if defined(WINDOWS)
417 if (stub.hSyncThread && RTThreadGetState(stub.hSyncThread)!=RTTHREADSTATE_TERMINATED)
418 {
419 HANDLE hNative;
420 DWORD ec=0;
421
422 hNative = OpenThread(SYNCHRONIZE|THREAD_QUERY_INFORMATION|THREAD_TERMINATE,
423 false, RTThreadGetNative(stub.hSyncThread));
424 if (!hNative)
425 {
426 crWarning("Failed to get handle for sync thread(%#x)", GetLastError());
427 }
428 else
429 {
430 crDebug("Got handle %p for thread %#x", hNative, RTThreadGetNative(stub.hSyncThread));
431 }
432
433 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
434
435 if (PostThreadMessage(RTThreadGetNative(stub.hSyncThread), WM_QUIT, 0, 0))
436 {
437 RTThreadWait(stub.hSyncThread, 1000, NULL);
438
439 /*Same issue as on linux, RTThreadWait exits before system thread is terminated, which leads
440 * to issues as our dll goes to be unloaded.
441 *@todo
442 *We usually call this function from DllMain which seems to be holding some lock and thus we have to
443 * kill thread via TerminateThread.
444 */
445 if (WaitForSingleObject(hNative, 100)==WAIT_TIMEOUT)
446 {
447 crDebug("Wait failed, terminating");
448 if (!TerminateThread(hNative, 1))
449 {
450 crDebug("TerminateThread failed");
451 }
452 }
453 if (GetExitCodeThread(hNative, &ec))
454 {
455 crDebug("Thread %p exited with ec=%i", hNative, ec);
456 }
457 else
458 {
459 crDebug("GetExitCodeThread failed(%#x)", GetLastError());
460 }
461 }
462 else
463 {
464 crDebug("Sync thread killed before DLL_PROCESS_DETACH");
465 }
466
467 if (hNative)
468 {
469 CloseHandle(hNative);
470 }
471 }
472#else
473 if (stub.hSyncThread!=NIL_RTTHREAD)
474 {
475 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
476 {
477 int rc = RTThreadWait(stub.hSyncThread, RT_INDEFINITE_WAIT, NULL);
478 if (RT_FAILURE(rc))
479 {
480 WARN(("RTThreadWait_join failed %i", rc));
481 }
482 }
483 }
484#endif
485 crLockMutex(mutex);
486#endif
487
488#ifndef WINDOWS
489 crNetTearDown();
490#endif
491
492#ifdef CHROMIUM_THREADSAFE
493 crUnlockMutex(mutex);
494 crFreeMutex(mutex);
495#endif
496 crMemset(&stub, 0, sizeof(stub));
497}
498
499
500static void stubExitHandler(void)
501{
502 stubSPUSafeTearDown();
503 signal(SIGTERM, SIG_DFL);
504 signal(SIGINT, SIG_DFL);
505}
506
507/**
508 * Called when we receive a SIGTERM signal.
509 */
510static void stubSignalHandler(int signo)
511{
512 (void)signo;
513 stubSPUSafeTearDown();
514 exit(0); /* this causes stubExitHandler() to be called */
515}
516
517#ifndef RT_OS_WINDOWS
518# ifdef CHROMIUM_THREADSAFE
519static void stubThreadTlsDtor(void *pvValue)
520{
521 ContextInfo *pCtx = (ContextInfo*)pvValue;
522 VBoxTlsRefRelease(pCtx);
523}
524# endif
525#endif
526
527
528/**
529 * Init variables in the stub structure, install signal handler.
530 */
531static void stubInitVars(void)
532{
533 WindowInfo *defaultWin;
534
535#ifdef CHROMIUM_THREADSAFE
536 crInitMutex(&stub.mutex);
537#endif
538
539 /* At the very least we want CR_RGB_BIT. */
540 stub.haveNativeOpenGL = GL_FALSE;
541 stub.spu = NULL;
542 stub.appDrawCursor = 0;
543 stub.minChromiumWindowWidth = 0;
544 stub.minChromiumWindowHeight = 0;
545 stub.maxChromiumWindowWidth = 0;
546 stub.maxChromiumWindowHeight = 0;
547 stub.matchChromiumWindowCount = 0;
548 stub.matchChromiumWindowID = NULL;
549 stub.matchWindowTitle = NULL;
550 stub.ignoreFreeglutMenus = 0;
551 stub.threadSafe = GL_FALSE;
552 stub.trackWindowSize = 0;
553 stub.trackWindowPos = 0;
554 stub.trackWindowVisibility = 0;
555 stub.trackWindowVisibleRgn = 0;
556 stub.mothershipPID = 0;
557 stub.spu_dir = NULL;
558
559 stub.freeContextNumber = MAGIC_CONTEXT_BASE;
560 stub.contextTable = crAllocHashtable();
561#ifndef RT_OS_WINDOWS
562# ifdef CHROMIUM_THREADSAFE
563 if (!g_stubIsCurrentContextTSDInited)
564 {
565 crInitTSDF(&g_stubCurrentContextTSD, stubThreadTlsDtor);
566 g_stubIsCurrentContextTSDInited = true;
567 }
568# endif
569#endif
570 stubSetCurrentContext(NULL);
571
572 stub.windowTable = crAllocHashtable();
573
574#ifdef CR_NEWWINTRACK
575 stub.bShutdownSyncThread = false;
576 stub.hSyncThread = NIL_RTTHREAD;
577#endif
578
579 defaultWin = (WindowInfo *) crCalloc(sizeof(WindowInfo));
580 defaultWin->type = CHROMIUM;
581 defaultWin->spuWindow = 0; /* window 0 always exists */
582#ifdef WINDOWS
583 defaultWin->hVisibleRegion = INVALID_HANDLE_VALUE;
584#elif defined(GLX)
585 defaultWin->pVisibleRegions = NULL;
586 defaultWin->cVisibleRegions = 0;
587#endif
588 crHashtableAdd(stub.windowTable, 0, defaultWin);
589
590#if 1
591 atexit(stubExitHandler);
592 signal(SIGTERM, stubSignalHandler);
593 signal(SIGINT, stubSignalHandler);
594#ifndef WINDOWS
595 signal(SIGPIPE, SIG_IGN); /* the networking code should catch this */
596#endif
597#else
598 (void) stubExitHandler;
599 (void) stubSignalHandler;
600#endif
601}
602
603
604#if 0 /* unused */
605
606/**
607 * Return a free port number for the mothership to use, or -1 if we
608 * can't find one.
609 */
610static int
611GenerateMothershipPort(void)
612{
613 const int MAX_PORT = 10100;
614 unsigned short port;
615
616 /* generate initial port number randomly */
617 crRandAutoSeed();
618 port = (unsigned short) crRandInt(10001, MAX_PORT);
619
620#ifdef WINDOWS
621 /* XXX should implement a free port check here */
622 return port;
623#else
624 /*
625 * See if this port number really is free, try another if needed.
626 */
627 {
628 struct sockaddr_in servaddr;
629 int so_reuseaddr = 1;
630 int sock, k;
631
632 /* create socket */
633 sock = socket(AF_INET, SOCK_STREAM, 0);
634 CRASSERT(sock > 2);
635
636 /* deallocate socket/port when we exit */
637 k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
638 (char *) &so_reuseaddr, sizeof(so_reuseaddr));
639 CRASSERT(k == 0);
640
641 /* initialize the servaddr struct */
642 crMemset(&servaddr, 0, sizeof(servaddr) );
643 servaddr.sin_family = AF_INET;
644 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
645
646 while (port < MAX_PORT) {
647 /* Bind to the given port number, return -1 if we fail */
648 servaddr.sin_port = htons((unsigned short) port);
649 k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
650 if (k) {
651 /* failed to create port. try next one. */
652 port++;
653 }
654 else {
655 /* free the socket/port now so mothership can make it */
656 close(sock);
657 return port;
658 }
659 }
660 }
661#endif /* WINDOWS */
662 return -1;
663}
664
665
666/**
667 * Try to determine which mothership configuration to use for this program.
668 */
669static char **
670LookupMothershipConfig(const char *procName)
671{
672 const int procNameLen = crStrlen(procName);
673 FILE *f;
674 const char *home;
675 char configPath[1000];
676
677 /* first, check if the CR_CONFIG env var is set */
678 {
679 const char *conf = crGetenv("CR_CONFIG");
680 if (conf && crStrlen(conf) > 0)
681 return crStrSplit(conf, " ");
682 }
683
684 /* second, look up config name from config file */
685 home = crGetenv("HOME");
686 if (home)
687 sprintf(configPath, "%s/%s", home, CONFIG_LOOKUP_FILE);
688 else
689 crStrcpy(configPath, CONFIG_LOOKUP_FILE); /* from current dir */
690 /* Check if the CR_CONFIG_PATH env var is set. */
691 {
692 const char *conf = crGetenv("CR_CONFIG_PATH");
693 if (conf)
694 crStrcpy(configPath, conf); /* from env var */
695 }
696
697 f = fopen(configPath, "r");
698 if (!f) {
699 return NULL;
700 }
701
702 while (!feof(f)) {
703 char line[1000];
704 char **args;
705 fgets(line, 999, f);
706 line[crStrlen(line) - 1] = 0; /* remove trailing newline */
707 if (crStrncmp(line, procName, procNameLen) == 0 &&
708 (line[procNameLen] == ' ' || line[procNameLen] == '\t'))
709 {
710 crWarning("Using Chromium configuration for %s from %s",
711 procName, configPath);
712 args = crStrSplit(line + procNameLen + 1, " ");
713 return args;
714 }
715 }
716 fclose(f);
717 return NULL;
718}
719
720
721static int Mothership_Awake = 0;
722
723
724/**
725 * Signal handler to determine when mothership is ready.
726 */
727static void
728MothershipPhoneHome(int signo)
729{
730 crDebug("Got signal %d: mothership is awake!", signo);
731 Mothership_Awake = 1;
732}
733
734#endif /* 0 */
735
736static void stubSetDefaultConfigurationOptions(void)
737{
738 unsigned char key[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
739
740 stub.appDrawCursor = 0;
741 stub.minChromiumWindowWidth = 0;
742 stub.minChromiumWindowHeight = 0;
743 stub.maxChromiumWindowWidth = 0;
744 stub.maxChromiumWindowHeight = 0;
745 stub.matchChromiumWindowID = NULL;
746 stub.numIgnoreWindowID = 0;
747 stub.matchWindowTitle = NULL;
748 stub.ignoreFreeglutMenus = 0;
749 stub.trackWindowSize = 1;
750 stub.trackWindowPos = 1;
751 stub.trackWindowVisibility = 1;
752 stub.trackWindowVisibleRgn = 1;
753 stub.matchChromiumWindowCount = 0;
754 stub.spu_dir = NULL;
755 crNetSetRank(0);
756 crNetSetContextRange(32, 35);
757 crNetSetNodeRange("iam0", "iamvis20");
758 crNetSetKey(key,sizeof(key));
759 stub.force_pbuffers = 0;
760
761#ifdef WINDOWS
762# ifdef VBOX_WITH_WDDM
763 stub.bRunningUnderWDDM = false;
764# endif
765#endif
766}
767
768#ifdef CR_NEWWINTRACK
769# ifdef VBOX_WITH_WDDM
770static void stubDispatchVisibleRegions(WindowInfo *pWindow)
771{
772 DWORD dwCount;
773 LPRGNDATA lpRgnData;
774
775 dwCount = GetRegionData(pWindow->hVisibleRegion, 0, NULL);
776 lpRgnData = crAlloc(dwCount);
777
778 if (lpRgnData)
779 {
780 GetRegionData(pWindow->hVisibleRegion, dwCount, lpRgnData);
781 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, lpRgnData->rdh.nCount);
782 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, lpRgnData->rdh.nCount, (GLint*) lpRgnData->Buffer);
783 crFree(lpRgnData);
784 }
785 else crWarning("GetRegionData failed, VisibleRegions update failed");
786}
787
788static HRGN stubMakeRegionFromRects(PVBOXVIDEOCM_CMD_RECTS pRegions, uint32_t start)
789{
790 HRGN hRgn, hTmpRgn;
791 uint32_t i;
792
793 if (pRegions->RectsInfo.cRects<=start)
794 {
795 return INVALID_HANDLE_VALUE;
796 }
797
798 hRgn = CreateRectRgn(0, 0, 0, 0);
799 for (i=start; i<pRegions->RectsInfo.cRects; ++i)
800 {
801 hTmpRgn = CreateRectRgnIndirect(&pRegions->RectsInfo.aRects[i]);
802 CombineRgn(hRgn, hRgn, hTmpRgn, RGN_OR);
803 DeleteObject(hTmpRgn);
804 }
805 return hRgn;
806}
807
808# endif /* VBOX_WITH_WDDM */
809
810static void stubSyncTrCheckWindowsCB(unsigned long key, void *data1, void *data2)
811{
812 WindowInfo *pWindow = (WindowInfo *) data1;
813 (void)key; (void) data2;
814
815 if (pWindow->type!=CHROMIUM || pWindow->spuWindow==0)
816 {
817 return;
818 }
819
820 stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID);
821
822 if (!stubSystemWindowExist(pWindow))
823 {
824#ifdef WINDOWS
825 stubDestroyWindow(0, (GLint)pWindow->hWnd);
826#else
827 stubDestroyWindow(0, (GLint)pWindow->drawable);
828#endif
829 /*No need to flush here as crWindowDestroy does it*/
830 return;
831 }
832
833#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
834 if (stub.bRunningUnderWDDM)
835 return;
836#endif
837 stubCheckWindowState(pWindow, GL_TRUE);
838}
839
840static DECLCALLBACK(int) stubSyncThreadProc(RTTHREAD ThreadSelf, void *pvUser)
841{
842#ifdef WINDOWS
843 MSG msg;
844# ifdef VBOX_WITH_WDDM
845 HMODULE hVBoxD3D = NULL;
846 GLint spuConnection = 0;
847# endif
848#endif
849
850 (void) pvUser;
851
852 crDebug("Sync thread started");
853#ifdef WINDOWS
854 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
855# ifdef VBOX_WITH_WDDM
856 hVBoxD3D = NULL;
857 if (!GetModuleHandleEx(0, VBOX_MODNAME_DISPD3D, &hVBoxD3D))
858 {
859 crDebug("GetModuleHandleEx failed err %d", GetLastError());
860 hVBoxD3D = NULL;
861 }
862
863 if (hVBoxD3D)
864 {
865 crDebug("running with " VBOX_MODNAME_DISPD3D);
866 stub.trackWindowVisibleRgn = 0;
867 stub.bRunningUnderWDDM = true;
868 }
869# endif /* VBOX_WITH_WDDM */
870#endif /* WINDOWS */
871
872 crLockMutex(&stub.mutex);
873#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
874 spuConnection =
875#endif
876 stub.spu->dispatch_table.VBoxPackSetInjectThread(NULL);
877#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
878 if (stub.bRunningUnderWDDM && !spuConnection)
879 {
880 crError("VBoxPackSetInjectThread failed!");
881 }
882#endif
883 crUnlockMutex(&stub.mutex);
884
885 RTThreadUserSignal(ThreadSelf);
886
887 while(!stub.bShutdownSyncThread)
888 {
889#ifdef WINDOWS
890 if (!PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
891 {
892# ifdef VBOX_WITH_WDDM
893 if (stub.bRunningUnderWDDM)
894 {
895
896 }
897 else
898# endif
899 {
900 crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
901 RTThreadSleep(50);
902 }
903 }
904 else
905 {
906 if (WM_QUIT==msg.message)
907 {
908 crDebug("Sync thread got WM_QUIT");
909 break;
910 }
911 else
912 {
913 TranslateMessage(&msg);
914 DispatchMessage(&msg);
915 }
916 }
917#else
918 /* Try to keep a consistent locking order. */
919 crHashtableLock(stub.windowTable);
920 crLockMutex(&stub.mutex);
921 crHashtableWalkUnlocked(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
922 crUnlockMutex(&stub.mutex);
923 crHashtableUnlock(stub.windowTable);
924 RTThreadSleep(50);
925#endif
926 }
927
928#ifdef VBOX_WITH_WDDM
929 if (spuConnection)
930 {
931 stub.spu->dispatch_table.VBoxConDestroy(spuConnection);
932 }
933 if (hVBoxD3D)
934 {
935 FreeLibrary(hVBoxD3D);
936 }
937#endif
938 crDebug("Sync thread stopped");
939 return 0;
940}
941#endif /* CR_NEWWINTRACK */
942
943/**
944 * Do one-time initializations for the faker.
945 * Returns TRUE on success, FALSE otherwise.
946 */
947static bool
948stubInitLocked(void)
949{
950 /* Here is where we contact the mothership to find out what we're supposed
951 * to be doing. Networking code in a DLL initializer. I sure hope this
952 * works :)
953 *
954 * HOW can I pass the mothership address to this if I already know it?
955 */
956
957 char response[1024];
958 char **spuchain;
959 int num_spus;
960 int *spu_ids;
961 char **spu_names;
962 const char *app_id;
963 int i;
964 int disable_sync = 0;
965#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
966 HMODULE hVBoxD3D = NULL;
967#endif
968
969 stubInitVars();
970
971 crGetProcName(response, 1024);
972 crDebug("Stub launched for %s", response);
973
974#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
975 /*@todo when vm boots with compiz turned on, new code causes hang in xcb_wait_for_reply in the sync thread
976 * as at the start compiz runs our code under XGrabServer.
977 */
978 if (!crStrcmp(response, "compiz") || !crStrcmp(response, "compiz_real") || !crStrcmp(response, "compiz.real")
979 || !crStrcmp(response, "compiz-bin"))
980 {
981 disable_sync = 1;
982 }
983#endif
984
985 /* @todo check if it'd be of any use on other than guests, no use for windows */
986 app_id = crGetenv( "CR_APPLICATION_ID_NUMBER" );
987
988 crNetInit( NULL, NULL );
989
990#ifndef WINDOWS
991 {
992 CRNetServer ns;
993
994 ns.name = "vboxhgcm://host:0";
995 ns.buffer_size = 1024;
996 crNetServerConnect(&ns
997#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
998 , NULL
999#endif
1000 );
1001 if (!ns.conn)
1002 {
1003 crWarning("Failed to connect to host. Make sure 3D acceleration is enabled for this VM.");
1004# ifdef VBOXOGL_FAKEDRI
1005 return false;
1006# else
1007 exit(1);
1008# endif
1009 }
1010 else
1011 {
1012 crNetFreeConnection(ns.conn);
1013 }
1014 }
1015#endif
1016
1017 strcpy(response, "2 0 feedback 1 pack");
1018 spuchain = crStrSplit( response, " " );
1019 num_spus = crStrToInt( spuchain[0] );
1020 spu_ids = (int *) crAlloc( num_spus * sizeof( *spu_ids ) );
1021 spu_names = (char **) crAlloc( num_spus * sizeof( *spu_names ) );
1022 for (i = 0 ; i < num_spus ; i++)
1023 {
1024 spu_ids[i] = crStrToInt( spuchain[2*i+1] );
1025 spu_names[i] = crStrdup( spuchain[2*i+2] );
1026 crDebug( "SPU %d/%d: (%d) \"%s\"", i+1, num_spus, spu_ids[i], spu_names[i] );
1027 }
1028
1029 stubSetDefaultConfigurationOptions();
1030
1031#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
1032 hVBoxD3D = NULL;
1033 if (!GetModuleHandleEx(0, VBOX_MODNAME_DISPD3D, &hVBoxD3D))
1034 {
1035 crDebug("GetModuleHandleEx failed err %d", GetLastError());
1036 hVBoxD3D = NULL;
1037 }
1038
1039 if (hVBoxD3D)
1040 {
1041 disable_sync = 1;
1042 crDebug("running with %s", VBOX_MODNAME_DISPD3D);
1043 stub.trackWindowVisibleRgn = 0;
1044 /* @todo: should we enable that? */
1045 stub.trackWindowSize = 0;
1046 stub.trackWindowPos = 0;
1047 stub.trackWindowVisibility = 0;
1048 stub.bRunningUnderWDDM = true;
1049 }
1050#endif
1051
1052 stub.spu = crSPULoadChain( num_spus, spu_ids, spu_names, stub.spu_dir, NULL );
1053
1054 crFree( spuchain );
1055 crFree( spu_ids );
1056 for (i = 0; i < num_spus; ++i)
1057 crFree(spu_names[i]);
1058 crFree( spu_names );
1059
1060 // spu chain load failed somewhere
1061 if (!stub.spu) {
1062 return false;
1063 }
1064
1065 crSPUInitDispatchTable( &glim );
1066
1067 /* This is unlikely to change -- We still want to initialize our dispatch
1068 * table with the functions of the first SPU in the chain. */
1069 stubInitSPUDispatch( stub.spu );
1070
1071 /* we need to plug one special stub function into the dispatch table */
1072 glim.GetChromiumParametervCR = stub_GetChromiumParametervCR;
1073
1074#if !defined(VBOX_NO_NATIVEGL)
1075 /* Load pointers to native OpenGL functions into stub.nativeDispatch */
1076 stubInitNativeDispatch();
1077#endif
1078
1079/*crDebug("stub init");
1080raise(SIGINT);*/
1081
1082#ifdef WINDOWS
1083# ifndef CR_NEWWINTRACK
1084 stubInstallWindowMessageHook();
1085# endif
1086#endif
1087
1088#ifdef CR_NEWWINTRACK
1089 {
1090 int rc;
1091
1092 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
1093
1094 if (!disable_sync)
1095 {
1096 crDebug("Starting sync thread");
1097
1098 rc = RTThreadCreate(&stub.hSyncThread, stubSyncThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Sync");
1099 if (RT_FAILURE(rc))
1100 {
1101 crError("Failed to start sync thread! (%x)", rc);
1102 }
1103 RTThreadUserWait(stub.hSyncThread, 60 * 1000);
1104 RTThreadUserReset(stub.hSyncThread);
1105
1106 crDebug("Going on");
1107 }
1108 }
1109#endif
1110
1111#ifdef GLX
1112 stub.xshmSI.shmid = -1;
1113 stub.bShmInitFailed = GL_FALSE;
1114 stub.pGLXPixmapsHash = crAllocHashtable();
1115
1116 stub.bXExtensionsChecked = GL_FALSE;
1117 stub.bHaveXComposite = GL_FALSE;
1118 stub.bHaveXFixes = GL_FALSE;
1119#endif
1120
1121 return true;
1122}
1123
1124/**
1125 * Do one-time initializations for the faker.
1126 * Returns TRUE on success, FALSE otherwise.
1127 */
1128bool
1129stubInit(void)
1130{
1131 bool bRc = true;
1132 /* we need to serialize the initialization, otherwise racing is possible
1133 * for XPDM-based d3d when a d3d switcher is testing the gl lib in two or more threads
1134 * NOTE: the STUB_INIT_LOCK/UNLOCK is a NOP for non-win currently */
1135 STUB_INIT_LOCK();
1136 if (!stub_initialized)
1137 bRc = stub_initialized = stubInitLocked();
1138 STUB_INIT_UNLOCK();
1139 return bRc;
1140}
1141
1142/* Sigh -- we can't do initialization at load time, since Windows forbids
1143 * the loading of other libraries from DLLMain. */
1144
1145#ifdef WINDOWS
1146#define WIN32_LEAN_AND_MEAN
1147#include <windows.h>
1148
1149#if 1//def DEBUG_misha
1150 /* debugging: this is to be able to catch first-chance notifications
1151 * for exceptions other than EXCEPTION_BREAKPOINT in kernel debugger */
1152# define VDBG_VEHANDLER
1153#endif
1154
1155#ifdef VDBG_VEHANDLER
1156# include <dbghelp.h>
1157# include <cr_string.h>
1158static PVOID g_VBoxVehHandler = NULL;
1159static DWORD g_VBoxVehEnable = 0;
1160
1161/* generate a crash dump on exception */
1162#define VBOXVEH_F_DUMP 0x00000001
1163/* generate a debugger breakpoint exception */
1164#define VBOXVEH_F_BREAK 0x00000002
1165/* exit on exception */
1166#define VBOXVEH_F_EXIT 0x00000004
1167
1168static DWORD g_VBoxVehFlags = 0;
1169
1170typedef BOOL WINAPI FNVBOXDBG_MINIDUMPWRITEDUMP(HANDLE hProcess,
1171 DWORD ProcessId,
1172 HANDLE hFile,
1173 MINIDUMP_TYPE DumpType,
1174 PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
1175 PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
1176 PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
1177typedef FNVBOXDBG_MINIDUMPWRITEDUMP *PFNVBOXDBG_MINIDUMPWRITEDUMP;
1178
1179static HMODULE g_hVBoxMdDbgHelp = NULL;
1180static PFNVBOXDBG_MINIDUMPWRITEDUMP g_pfnVBoxMdMiniDumpWriteDump = NULL;
1181static size_t g_cVBoxMdFilePrefixLen = 0;
1182static WCHAR g_aszwVBoxMdFilePrefix[MAX_PATH];
1183static WCHAR g_aszwVBoxMdDumpCount = 0;
1184static MINIDUMP_TYPE g_enmVBoxMdDumpType = MiniDumpNormal
1185 | MiniDumpWithDataSegs
1186 | MiniDumpWithFullMemory
1187 | MiniDumpWithHandleData
1188//// | MiniDumpFilterMemory
1189//// | MiniDumpScanMemory
1190// | MiniDumpWithUnloadedModules
1191//// | MiniDumpWithIndirectlyReferencedMemory
1192//// | MiniDumpFilterModulePaths
1193// | MiniDumpWithProcessThreadData
1194// | MiniDumpWithPrivateReadWriteMemory
1195//// | MiniDumpWithoutOptionalData
1196// | MiniDumpWithFullMemoryInfo
1197// | MiniDumpWithThreadInfo
1198// | MiniDumpWithCodeSegs
1199// | MiniDumpWithFullAuxiliaryState
1200// | MiniDumpWithPrivateWriteCopyMemory
1201// | MiniDumpIgnoreInaccessibleMemory
1202// | MiniDumpWithTokenInformation
1203//// | MiniDumpWithModuleHeaders
1204//// | MiniDumpFilterTriage
1205 ;
1206
1207
1208
1209#define VBOXMD_DUMP_DIR_DEFAULT "C:\\dumps"
1210#define VBOXMD_DUMP_NAME_PREFIX_W L"VBoxDmp_"
1211
1212static HMODULE loadSystemDll(const char *pszName)
1213{
1214 char szPath[MAX_PATH];
1215 UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
1216 size_t cbName = strlen(pszName) + 1;
1217 if (cchPath + 1 + cbName > sizeof(szPath))
1218 {
1219 SetLastError(ERROR_FILENAME_EXCED_RANGE);
1220 return NULL;
1221 }
1222 szPath[cchPath] = '\\';
1223 memcpy(&szPath[cchPath + 1], pszName, cbName);
1224 return LoadLibraryA(szPath);
1225}
1226
1227static DWORD vboxMdMinidumpCreate(struct _EXCEPTION_POINTERS *pExceptionInfo)
1228{
1229 WCHAR aszwMdFileName[MAX_PATH];
1230 HANDLE hProcess = GetCurrentProcess();
1231 DWORD ProcessId = GetCurrentProcessId();
1232 MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo;
1233 HANDLE hFile;
1234 DWORD winErr = ERROR_SUCCESS;
1235
1236 if (!g_pfnVBoxMdMiniDumpWriteDump)
1237 {
1238 if (!g_hVBoxMdDbgHelp)
1239 {
1240 g_hVBoxMdDbgHelp = loadSystemDll("DbgHelp.dll");
1241 if (!g_hVBoxMdDbgHelp)
1242 return GetLastError();
1243 }
1244
1245 g_pfnVBoxMdMiniDumpWriteDump = (PFNVBOXDBG_MINIDUMPWRITEDUMP)GetProcAddress(g_hVBoxMdDbgHelp, "MiniDumpWriteDump");
1246 if (!g_pfnVBoxMdMiniDumpWriteDump)
1247 return GetLastError();
1248 }
1249
1250 ++g_aszwVBoxMdDumpCount;
1251
1252 memcpy(aszwMdFileName, g_aszwVBoxMdFilePrefix, g_cVBoxMdFilePrefixLen * sizeof (g_aszwVBoxMdFilePrefix[0]));
1253 swprintf(aszwMdFileName + g_cVBoxMdFilePrefixLen, RT_ELEMENTS(aszwMdFileName) - g_cVBoxMdFilePrefixLen, L"%d_%d.dmp", ProcessId, g_aszwVBoxMdDumpCount);
1254
1255 hFile = CreateFileW(aszwMdFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1256 if (hFile == INVALID_HANDLE_VALUE)
1257 return GetLastError();
1258
1259 ExceptionInfo.ThreadId = GetCurrentThreadId();
1260 ExceptionInfo.ExceptionPointers = pExceptionInfo;
1261 ExceptionInfo.ClientPointers = FALSE;
1262
1263 if (!g_pfnVBoxMdMiniDumpWriteDump(hProcess, ProcessId, hFile, g_enmVBoxMdDumpType, &ExceptionInfo, NULL, NULL))
1264 winErr = GetLastError();
1265
1266 CloseHandle(hFile);
1267 return winErr;
1268}
1269
1270LONG WINAPI vboxVDbgVectoredHandler(struct _EXCEPTION_POINTERS *pExceptionInfo)
1271{
1272 PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
1273 PCONTEXT pContextRecord = pExceptionInfo->ContextRecord;
1274 switch (pExceptionRecord->ExceptionCode)
1275 {
1276 case EXCEPTION_BREAKPOINT:
1277 case EXCEPTION_ACCESS_VIOLATION:
1278 case EXCEPTION_STACK_OVERFLOW:
1279 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1280 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1281 case EXCEPTION_FLT_INVALID_OPERATION:
1282 case EXCEPTION_INT_DIVIDE_BY_ZERO:
1283 case EXCEPTION_ILLEGAL_INSTRUCTION:
1284 if (g_VBoxVehFlags & VBOXVEH_F_BREAK)
1285 {
1286 BOOL fBreak = TRUE;
1287#ifndef DEBUG_misha
1288 if (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
1289 {
1290 HANDLE hProcess = GetCurrentProcess();
1291 BOOL fDebuggerPresent = FALSE;
1292 /* we do not want to generate breakpoint exceptions recursively, so do it only when running under debugger */
1293 if (CheckRemoteDebuggerPresent(hProcess, &fDebuggerPresent))
1294 fBreak = !!fDebuggerPresent;
1295 else
1296 fBreak = FALSE; /* <- the function has failed, don't break for sanity */
1297 }
1298#endif
1299
1300 if (fBreak)
1301 {
1302 RT_BREAKPOINT();
1303 }
1304 }
1305
1306 if (g_VBoxVehFlags & VBOXVEH_F_DUMP)
1307 vboxMdMinidumpCreate(pExceptionInfo);
1308
1309 if (g_VBoxVehFlags & VBOXVEH_F_EXIT)
1310 exit(1);
1311 break;
1312 default:
1313 break;
1314 }
1315 return EXCEPTION_CONTINUE_SEARCH;
1316}
1317
1318void vboxVDbgVEHandlerRegister()
1319{
1320 CRASSERT(!g_VBoxVehHandler);
1321 g_VBoxVehHandler = AddVectoredExceptionHandler(1,vboxVDbgVectoredHandler);
1322 CRASSERT(g_VBoxVehHandler);
1323}
1324
1325void vboxVDbgVEHandlerUnregister()
1326{
1327 ULONG uResult;
1328 if (g_VBoxVehHandler)
1329 {
1330 uResult = RemoveVectoredExceptionHandler(g_VBoxVehHandler);
1331 CRASSERT(uResult);
1332 g_VBoxVehHandler = NULL;
1333 }
1334}
1335#endif
1336
1337/* Windows crap */
1338BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
1339{
1340 (void) lpvReserved;
1341
1342 switch (fdwReason)
1343 {
1344 case DLL_PROCESS_ATTACH:
1345 {
1346 CRNetServer ns;
1347 const char * env;
1348#if defined(DEBUG_misha)
1349 HMODULE hCrUtil;
1350 char aName[MAX_PATH];
1351
1352 GetModuleFileNameA(hDLLInst, aName, RT_ELEMENTS(aName));
1353 crDbgCmdSymLoadPrint(aName, hDLLInst);
1354
1355 hCrUtil = GetModuleHandleA("VBoxOGLcrutil.dll");
1356 Assert(hCrUtil);
1357 crDbgCmdSymLoadPrint("VBoxOGLcrutil.dll", hCrUtil);
1358#endif
1359#ifdef CHROMIUM_THREADSAFE
1360 crInitTSD(&g_stubCurrentContextTSD);
1361#endif
1362
1363 crInitMutex(&stub_init_mutex);
1364
1365#ifdef VDBG_VEHANDLER
1366 env = crGetenv("CR_DBG_VEH_ENABLE");
1367 g_VBoxVehEnable = crStrParseI32(env,
1368# ifdef DEBUG_misha
1369 1
1370# else
1371 0
1372# endif
1373 );
1374
1375 if (g_VBoxVehEnable)
1376 {
1377 char procName[1024];
1378 size_t cProcName;
1379 size_t cChars;
1380
1381 env = crGetenv("CR_DBG_VEH_FLAGS");
1382 g_VBoxVehFlags = crStrParseI32(env,
1383 0
1384# ifdef DEBUG_misha
1385 | VBOXVEH_F_BREAK
1386# else
1387 | VBOXVEH_F_DUMP
1388# endif
1389 );
1390
1391 env = crGetenv("CR_DBG_VEH_DUMP_DIR");
1392 if (!env)
1393 env = VBOXMD_DUMP_DIR_DEFAULT;
1394
1395 g_cVBoxMdFilePrefixLen = strlen(env);
1396
1397 if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) <= g_cVBoxMdFilePrefixLen + 26 + (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR))
1398 {
1399 g_cVBoxMdFilePrefixLen = 0;
1400 env = "";
1401 }
1402
1403 mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix, g_cVBoxMdFilePrefixLen + 1, env, _TRUNCATE);
1404
1405 Assert(cChars == g_cVBoxMdFilePrefixLen + 1);
1406
1407 g_cVBoxMdFilePrefixLen = cChars - 1;
1408
1409 if (g_cVBoxMdFilePrefixLen && g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen - 1] != L'\\')
1410 g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'\\';
1411
1412 memcpy(g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, VBOXMD_DUMP_NAME_PREFIX_W, sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR));
1413 g_cVBoxMdFilePrefixLen += (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR);
1414
1415 crGetProcName(procName, RT_ELEMENTS(procName));
1416 cProcName = strlen(procName);
1417
1418 if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) > g_cVBoxMdFilePrefixLen + cProcName + 1 + 26)
1419 {
1420 mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, cProcName + 1, procName, _TRUNCATE);
1421 Assert(cChars == cProcName + 1);
1422 g_cVBoxMdFilePrefixLen += cChars - 1;
1423 g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'_';
1424 }
1425
1426 /* sanity */
1427 g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen] = L'\0';
1428
1429 env = crGetenv("CR_DBG_VEH_DUMP_TYPE");
1430
1431 g_enmVBoxMdDumpType = crStrParseI32(env,
1432 MiniDumpNormal
1433 | MiniDumpWithDataSegs
1434 | MiniDumpWithFullMemory
1435 | MiniDumpWithHandleData
1436 //// | MiniDumpFilterMemory
1437 //// | MiniDumpScanMemory
1438 // | MiniDumpWithUnloadedModules
1439 //// | MiniDumpWithIndirectlyReferencedMemory
1440 //// | MiniDumpFilterModulePaths
1441 // | MiniDumpWithProcessThreadData
1442 // | MiniDumpWithPrivateReadWriteMemory
1443 //// | MiniDumpWithoutOptionalData
1444 // | MiniDumpWithFullMemoryInfo
1445 // | MiniDumpWithThreadInfo
1446 // | MiniDumpWithCodeSegs
1447 // | MiniDumpWithFullAuxiliaryState
1448 // | MiniDumpWithPrivateWriteCopyMemory
1449 // | MiniDumpIgnoreInaccessibleMemory
1450 // | MiniDumpWithTokenInformation
1451 //// | MiniDumpWithModuleHeaders
1452 //// | MiniDumpFilterTriage
1453 );
1454
1455 vboxVDbgVEHandlerRegister();
1456 }
1457#endif
1458
1459 crNetInit(NULL, NULL);
1460 ns.name = "vboxhgcm://host:0";
1461 ns.buffer_size = 1024;
1462 crNetServerConnect(&ns
1463#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
1464 , NULL
1465#endif
1466);
1467 if (!ns.conn)
1468 {
1469 crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load.");
1470#ifdef VDBG_VEHANDLER
1471 if (g_VBoxVehEnable)
1472 vboxVDbgVEHandlerUnregister();
1473#endif
1474 return FALSE;
1475 }
1476 else
1477 {
1478 crNetFreeConnection(ns.conn);
1479 }
1480
1481#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
1482 VBoxCrHgsmiInit();
1483#endif
1484 break;
1485 }
1486
1487 case DLL_PROCESS_DETACH:
1488 {
1489 /* do exactly the same thing as for DLL_THREAD_DETACH since
1490 * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */
1491 stubSetCurrentContext(NULL);
1492 if (stub_initialized)
1493 {
1494 CRASSERT(stub.spu);
1495 stub.spu->dispatch_table.VBoxDetachThread();
1496 }
1497
1498
1499#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
1500 VBoxCrHgsmiTerm();
1501#endif
1502
1503 stubSPUSafeTearDown();
1504
1505#ifdef CHROMIUM_THREADSAFE
1506 crFreeTSD(&g_stubCurrentContextTSD);
1507#endif
1508
1509#ifdef VDBG_VEHANDLER
1510 if (g_VBoxVehEnable)
1511 vboxVDbgVEHandlerUnregister();
1512#endif
1513 break;
1514 }
1515
1516 case DLL_THREAD_ATTACH:
1517 {
1518 if (stub_initialized)
1519 {
1520 CRASSERT(stub.spu);
1521 stub.spu->dispatch_table.VBoxAttachThread();
1522 }
1523 break;
1524 }
1525
1526 case DLL_THREAD_DETACH:
1527 {
1528 stubSetCurrentContext(NULL);
1529 if (stub_initialized)
1530 {
1531 CRASSERT(stub.spu);
1532 stub.spu->dispatch_table.VBoxDetachThread();
1533 }
1534 break;
1535 }
1536
1537 default:
1538 break;
1539 }
1540
1541 return TRUE;
1542}
1543#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette