VirtualBox

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

Last change on this file since 68643 was 68248, checked in by vboxsync, 7 years ago

Additions/common/crOpenGL: remove unused code and dependency on VBoxMPIf.h

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