VirtualBox

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

Last change on this file since 58575 was 58575, checked in by vboxsync, 9 years ago

bugref:8087: Additions/x11: support non-root X server: when our OpenGL library is loaded directly on Linux, rather than by hijacking the DRI interface, the constructor needs to be called. For whatever reason it was disabled up until now.

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