VirtualBox

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

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

bugref:8087: Additions/x11: support non-root X server: when we load the system OpenGL library into a process (the X server process) to replac ours, we want to load the system EGL library too, to make sure that the process does not use our EGL library, which depends on an underlying GLX implementation, in combination with the system OpenGL library, which can also be used without GLX.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 42.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# ifdef VBOXOGL_FAKEDRI
989 return false;
990# else
991 exit(1);
992# endif
993 }
994 else
995 {
996 crNetFreeConnection(ns.conn);
997 }
998 }
999#endif
1000
1001 strcpy(response, "2 0 feedback 1 pack");
1002 spuchain = crStrSplit( response, " " );
1003 num_spus = crStrToInt( spuchain[0] );
1004 spu_ids = (int *) crAlloc( num_spus * sizeof( *spu_ids ) );
1005 spu_names = (char **) crAlloc( num_spus * sizeof( *spu_names ) );
1006 for (i = 0 ; i < num_spus ; i++)
1007 {
1008 spu_ids[i] = crStrToInt( spuchain[2*i+1] );
1009 spu_names[i] = crStrdup( spuchain[2*i+2] );
1010 crDebug( "SPU %d/%d: (%d) \"%s\"", i+1, num_spus, spu_ids[i], spu_names[i] );
1011 }
1012
1013 stubSetDefaultConfigurationOptions();
1014
1015#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
1016 hVBoxD3D = NULL;
1017 if (!GetModuleHandleEx(0, VBOX_MODNAME_DISPD3D, &hVBoxD3D))
1018 {
1019 crDebug("GetModuleHandleEx failed err %d", GetLastError());
1020 hVBoxD3D = NULL;
1021 }
1022
1023 if (hVBoxD3D)
1024 {
1025 disable_sync = 1;
1026 crDebug("running with %s", VBOX_MODNAME_DISPD3D);
1027 stub.trackWindowVisibleRgn = 0;
1028 /* @todo: should we enable that? */
1029 stub.trackWindowSize = 0;
1030 stub.trackWindowPos = 0;
1031 stub.trackWindowVisibility = 0;
1032 stub.bRunningUnderWDDM = true;
1033 }
1034#endif
1035
1036 stub.spu = crSPULoadChain( num_spus, spu_ids, spu_names, stub.spu_dir, NULL );
1037
1038 crFree( spuchain );
1039 crFree( spu_ids );
1040 for (i = 0; i < num_spus; ++i)
1041 crFree(spu_names[i]);
1042 crFree( spu_names );
1043
1044 // spu chain load failed somewhere
1045 if (!stub.spu) {
1046 return false;
1047 }
1048
1049 crSPUInitDispatchTable( &glim );
1050
1051 /* This is unlikely to change -- We still want to initialize our dispatch
1052 * table with the functions of the first SPU in the chain. */
1053 stubInitSPUDispatch( stub.spu );
1054
1055 /* we need to plug one special stub function into the dispatch table */
1056 glim.GetChromiumParametervCR = stub_GetChromiumParametervCR;
1057
1058#if !defined(VBOX_NO_NATIVEGL)
1059 /* Load pointers to native OpenGL functions into stub.nativeDispatch */
1060 stubInitNativeDispatch();
1061#endif
1062
1063/*crDebug("stub init");
1064raise(SIGINT);*/
1065
1066#ifdef WINDOWS
1067# ifndef CR_NEWWINTRACK
1068 stubInstallWindowMessageHook();
1069# endif
1070#endif
1071
1072#ifdef CR_NEWWINTRACK
1073 {
1074 int rc;
1075
1076 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
1077
1078 if (!disable_sync)
1079 {
1080 crDebug("Starting sync thread");
1081
1082 rc = RTThreadCreate(&stub.hSyncThread, stubSyncThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Sync");
1083 if (RT_FAILURE(rc))
1084 {
1085 crError("Failed to start sync thread! (%x)", rc);
1086 }
1087 RTThreadUserWait(stub.hSyncThread, 60 * 1000);
1088 RTThreadUserReset(stub.hSyncThread);
1089
1090 crDebug("Going on");
1091 }
1092 }
1093#endif
1094
1095#ifdef GLX
1096 stub.xshmSI.shmid = -1;
1097 stub.bShmInitFailed = GL_FALSE;
1098 stub.pGLXPixmapsHash = crAllocHashtable();
1099
1100 stub.bXExtensionsChecked = GL_FALSE;
1101 stub.bHaveXComposite = GL_FALSE;
1102 stub.bHaveXFixes = GL_FALSE;
1103#endif
1104
1105 return true;
1106}
1107
1108/**
1109 * Do one-time initializations for the faker.
1110 * Returns TRUE on success, FALSE otherwise.
1111 */
1112bool
1113stubInit(void)
1114{
1115 bool bRc = true;
1116 /* we need to serialize the initialization, otherwise racing is possible
1117 * for XPDM-based d3d when a d3d switcher is testing the gl lib in two or more threads
1118 * NOTE: the STUB_INIT_LOCK/UNLOCK is a NOP for non-win currently */
1119 STUB_INIT_LOCK();
1120 if (!stub_initialized)
1121 bRc = stub_initialized = stubInitLocked();
1122 STUB_INIT_UNLOCK();
1123 return bRc;
1124}
1125
1126#if defined(Linux) && !defined(VBOXOGL_FAKEDRI)
1127# include <dlfcn.h>
1128/* We only support being used by GLX clients. If the X server GLX extension
1129 * tries to use our OpenGL library it will fail, as it is written specifically
1130 * against Mesa. So we detect this with the assumption that the server will
1131 * not have the DISPLAY variable set, and a client will do or we can't do much
1132 * with it anyway. This is only needed on Linux, as Solaris lets us replace
1133 * the client library only. To avoid complications with iprt initialisation
1134 * we use native system/C library APIs.
1135 * We do this in a very naive way, not even checking for failure (not much we
1136 * can do, better for GLX to fail than the whole X server). To keep things as
1137 * simple and fail-safe as possible, we use a fixed path to the system GL
1138 * library. */
1139#ifndef RTLD_DEEPBIND
1140# define RTLD_DEEPBIND 0x8
1141#endif
1142
1143void __attribute__ ((constructor)) checkServerGLX(void)
1144{
1145 char *pszDisplay = getenv("DISPLAY");
1146
1147 if (!pszDisplay || !*pszDisplay)
1148 {
1149 dlopen("/tmp/VBoxOGL/system/libGL.so.1", RTLD_LAZY | RTLD_GLOBAL | RTLD_DEEPBIND);
1150 dlopen("/tmp/VBoxOGL/system/libEGL.so.1", RTLD_LAZY | RTLD_GLOBAL | RTLD_DEEPBIND);
1151 }
1152}
1153#endif
1154
1155/* Sigh -- we can't do initialization at load time, since Windows forbids
1156 * the loading of other libraries from DLLMain. */
1157
1158#ifdef WINDOWS
1159#define WIN32_LEAN_AND_MEAN
1160#include <windows.h>
1161
1162#if 1//def DEBUG_misha
1163 /* debugging: this is to be able to catch first-chance notifications
1164 * for exceptions other than EXCEPTION_BREAKPOINT in kernel debugger */
1165# define VDBG_VEHANDLER
1166#endif
1167
1168#ifdef VDBG_VEHANDLER
1169# include <dbghelp.h>
1170# include <cr_string.h>
1171static PVOID g_VBoxVehHandler = NULL;
1172static DWORD g_VBoxVehEnable = 0;
1173
1174/* generate a crash dump on exception */
1175#define VBOXVEH_F_DUMP 0x00000001
1176/* generate a debugger breakpoint exception */
1177#define VBOXVEH_F_BREAK 0x00000002
1178/* exit on exception */
1179#define VBOXVEH_F_EXIT 0x00000004
1180
1181static DWORD g_VBoxVehFlags = 0;
1182
1183typedef BOOL WINAPI FNVBOXDBG_MINIDUMPWRITEDUMP(HANDLE hProcess,
1184 DWORD ProcessId,
1185 HANDLE hFile,
1186 MINIDUMP_TYPE DumpType,
1187 PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
1188 PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
1189 PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
1190typedef FNVBOXDBG_MINIDUMPWRITEDUMP *PFNVBOXDBG_MINIDUMPWRITEDUMP;
1191
1192static HMODULE g_hVBoxMdDbgHelp = NULL;
1193static PFNVBOXDBG_MINIDUMPWRITEDUMP g_pfnVBoxMdMiniDumpWriteDump = NULL;
1194static size_t g_cVBoxMdFilePrefixLen = 0;
1195static WCHAR g_aszwVBoxMdFilePrefix[MAX_PATH];
1196static WCHAR g_aszwVBoxMdDumpCount = 0;
1197static MINIDUMP_TYPE g_enmVBoxMdDumpType = MiniDumpNormal
1198 | MiniDumpWithDataSegs
1199 | MiniDumpWithFullMemory
1200 | MiniDumpWithHandleData
1201//// | MiniDumpFilterMemory
1202//// | MiniDumpScanMemory
1203// | MiniDumpWithUnloadedModules
1204//// | MiniDumpWithIndirectlyReferencedMemory
1205//// | MiniDumpFilterModulePaths
1206// | MiniDumpWithProcessThreadData
1207// | MiniDumpWithPrivateReadWriteMemory
1208//// | MiniDumpWithoutOptionalData
1209// | MiniDumpWithFullMemoryInfo
1210// | MiniDumpWithThreadInfo
1211// | MiniDumpWithCodeSegs
1212// | MiniDumpWithFullAuxiliaryState
1213// | MiniDumpWithPrivateWriteCopyMemory
1214// | MiniDumpIgnoreInaccessibleMemory
1215// | MiniDumpWithTokenInformation
1216//// | MiniDumpWithModuleHeaders
1217//// | MiniDumpFilterTriage
1218 ;
1219
1220
1221
1222#define VBOXMD_DUMP_DIR_DEFAULT "C:\\dumps"
1223#define VBOXMD_DUMP_NAME_PREFIX_W L"VBoxDmp_"
1224
1225static HMODULE loadSystemDll(const char *pszName)
1226{
1227 char szPath[MAX_PATH];
1228 UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
1229 size_t cbName = strlen(pszName) + 1;
1230 if (cchPath + 1 + cbName > sizeof(szPath))
1231 {
1232 SetLastError(ERROR_FILENAME_EXCED_RANGE);
1233 return NULL;
1234 }
1235 szPath[cchPath] = '\\';
1236 memcpy(&szPath[cchPath + 1], pszName, cbName);
1237 return LoadLibraryA(szPath);
1238}
1239
1240static DWORD vboxMdMinidumpCreate(struct _EXCEPTION_POINTERS *pExceptionInfo)
1241{
1242 WCHAR aszwMdFileName[MAX_PATH];
1243 HANDLE hProcess = GetCurrentProcess();
1244 DWORD ProcessId = GetCurrentProcessId();
1245 MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo;
1246 HANDLE hFile;
1247 DWORD winErr = ERROR_SUCCESS;
1248
1249 if (!g_pfnVBoxMdMiniDumpWriteDump)
1250 {
1251 if (!g_hVBoxMdDbgHelp)
1252 {
1253 g_hVBoxMdDbgHelp = loadSystemDll("DbgHelp.dll");
1254 if (!g_hVBoxMdDbgHelp)
1255 return GetLastError();
1256 }
1257
1258 g_pfnVBoxMdMiniDumpWriteDump = (PFNVBOXDBG_MINIDUMPWRITEDUMP)GetProcAddress(g_hVBoxMdDbgHelp, "MiniDumpWriteDump");
1259 if (!g_pfnVBoxMdMiniDumpWriteDump)
1260 return GetLastError();
1261 }
1262
1263 ++g_aszwVBoxMdDumpCount;
1264
1265 memcpy(aszwMdFileName, g_aszwVBoxMdFilePrefix, g_cVBoxMdFilePrefixLen * sizeof (g_aszwVBoxMdFilePrefix[0]));
1266 swprintf(aszwMdFileName + g_cVBoxMdFilePrefixLen, RT_ELEMENTS(aszwMdFileName) - g_cVBoxMdFilePrefixLen, L"%d_%d.dmp", ProcessId, g_aszwVBoxMdDumpCount);
1267
1268 hFile = CreateFileW(aszwMdFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1269 if (hFile == INVALID_HANDLE_VALUE)
1270 return GetLastError();
1271
1272 ExceptionInfo.ThreadId = GetCurrentThreadId();
1273 ExceptionInfo.ExceptionPointers = pExceptionInfo;
1274 ExceptionInfo.ClientPointers = FALSE;
1275
1276 if (!g_pfnVBoxMdMiniDumpWriteDump(hProcess, ProcessId, hFile, g_enmVBoxMdDumpType, &ExceptionInfo, NULL, NULL))
1277 winErr = GetLastError();
1278
1279 CloseHandle(hFile);
1280 return winErr;
1281}
1282
1283LONG WINAPI vboxVDbgVectoredHandler(struct _EXCEPTION_POINTERS *pExceptionInfo)
1284{
1285 PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
1286 PCONTEXT pContextRecord = pExceptionInfo->ContextRecord;
1287 switch (pExceptionRecord->ExceptionCode)
1288 {
1289 case EXCEPTION_BREAKPOINT:
1290 case EXCEPTION_ACCESS_VIOLATION:
1291 case EXCEPTION_STACK_OVERFLOW:
1292 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1293 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1294 case EXCEPTION_FLT_INVALID_OPERATION:
1295 case EXCEPTION_INT_DIVIDE_BY_ZERO:
1296 case EXCEPTION_ILLEGAL_INSTRUCTION:
1297 if (g_VBoxVehFlags & VBOXVEH_F_BREAK)
1298 {
1299 BOOL fBreak = TRUE;
1300#ifndef DEBUG_misha
1301 if (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
1302 {
1303 HANDLE hProcess = GetCurrentProcess();
1304 BOOL fDebuggerPresent = FALSE;
1305 /* we do not want to generate breakpoint exceptions recursively, so do it only when running under debugger */
1306 if (CheckRemoteDebuggerPresent(hProcess, &fDebuggerPresent))
1307 fBreak = !!fDebuggerPresent;
1308 else
1309 fBreak = FALSE; /* <- the function has failed, don't break for sanity */
1310 }
1311#endif
1312
1313 if (fBreak)
1314 {
1315 RT_BREAKPOINT();
1316 }
1317 }
1318
1319 if (g_VBoxVehFlags & VBOXVEH_F_DUMP)
1320 vboxMdMinidumpCreate(pExceptionInfo);
1321
1322 if (g_VBoxVehFlags & VBOXVEH_F_EXIT)
1323 exit(1);
1324 break;
1325 default:
1326 break;
1327 }
1328 return EXCEPTION_CONTINUE_SEARCH;
1329}
1330
1331void vboxVDbgVEHandlerRegister()
1332{
1333 CRASSERT(!g_VBoxVehHandler);
1334 g_VBoxVehHandler = AddVectoredExceptionHandler(1,vboxVDbgVectoredHandler);
1335 CRASSERT(g_VBoxVehHandler);
1336}
1337
1338void vboxVDbgVEHandlerUnregister()
1339{
1340 ULONG uResult;
1341 if (g_VBoxVehHandler)
1342 {
1343 uResult = RemoveVectoredExceptionHandler(g_VBoxVehHandler);
1344 CRASSERT(uResult);
1345 g_VBoxVehHandler = NULL;
1346 }
1347}
1348#endif
1349
1350/* Windows crap */
1351BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
1352{
1353 (void) lpvReserved;
1354
1355 switch (fdwReason)
1356 {
1357 case DLL_PROCESS_ATTACH:
1358 {
1359 CRNetServer ns;
1360 const char * env;
1361#if defined(DEBUG_misha)
1362 HMODULE hCrUtil;
1363 char aName[MAX_PATH];
1364
1365 GetModuleFileNameA(hDLLInst, aName, RT_ELEMENTS(aName));
1366 crDbgCmdSymLoadPrint(aName, hDLLInst);
1367
1368 hCrUtil = GetModuleHandleA("VBoxOGLcrutil.dll");
1369 Assert(hCrUtil);
1370 crDbgCmdSymLoadPrint("VBoxOGLcrutil.dll", hCrUtil);
1371#endif
1372#ifdef CHROMIUM_THREADSAFE
1373 crInitTSD(&g_stubCurrentContextTSD);
1374#endif
1375
1376 crInitMutex(&stub_init_mutex);
1377
1378#ifdef VDBG_VEHANDLER
1379 env = crGetenv("CR_DBG_VEH_ENABLE");
1380 g_VBoxVehEnable = crStrParseI32(env,
1381# ifdef DEBUG_misha
1382 1
1383# else
1384 0
1385# endif
1386 );
1387
1388 if (g_VBoxVehEnable)
1389 {
1390 char procName[1024];
1391 size_t cProcName;
1392 size_t cChars;
1393
1394 env = crGetenv("CR_DBG_VEH_FLAGS");
1395 g_VBoxVehFlags = crStrParseI32(env,
1396 0
1397# ifdef DEBUG_misha
1398 | VBOXVEH_F_BREAK
1399# else
1400 | VBOXVEH_F_DUMP
1401# endif
1402 );
1403
1404 env = crGetenv("CR_DBG_VEH_DUMP_DIR");
1405 if (!env)
1406 env = VBOXMD_DUMP_DIR_DEFAULT;
1407
1408 g_cVBoxMdFilePrefixLen = strlen(env);
1409
1410 if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) <= g_cVBoxMdFilePrefixLen + 26 + (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR))
1411 {
1412 g_cVBoxMdFilePrefixLen = 0;
1413 env = "";
1414 }
1415
1416 mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix, g_cVBoxMdFilePrefixLen + 1, env, _TRUNCATE);
1417
1418 Assert(cChars == g_cVBoxMdFilePrefixLen + 1);
1419
1420 g_cVBoxMdFilePrefixLen = cChars - 1;
1421
1422 if (g_cVBoxMdFilePrefixLen && g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen - 1] != L'\\')
1423 g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'\\';
1424
1425 memcpy(g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, VBOXMD_DUMP_NAME_PREFIX_W, sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR));
1426 g_cVBoxMdFilePrefixLen += (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR);
1427
1428 crGetProcName(procName, RT_ELEMENTS(procName));
1429 cProcName = strlen(procName);
1430
1431 if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) > g_cVBoxMdFilePrefixLen + cProcName + 1 + 26)
1432 {
1433 mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, cProcName + 1, procName, _TRUNCATE);
1434 Assert(cChars == cProcName + 1);
1435 g_cVBoxMdFilePrefixLen += cChars - 1;
1436 g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'_';
1437 }
1438
1439 /* sanity */
1440 g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen] = L'\0';
1441
1442 env = crGetenv("CR_DBG_VEH_DUMP_TYPE");
1443
1444 g_enmVBoxMdDumpType = crStrParseI32(env,
1445 MiniDumpNormal
1446 | MiniDumpWithDataSegs
1447 | MiniDumpWithFullMemory
1448 | MiniDumpWithHandleData
1449 //// | MiniDumpFilterMemory
1450 //// | MiniDumpScanMemory
1451 // | MiniDumpWithUnloadedModules
1452 //// | MiniDumpWithIndirectlyReferencedMemory
1453 //// | MiniDumpFilterModulePaths
1454 // | MiniDumpWithProcessThreadData
1455 // | MiniDumpWithPrivateReadWriteMemory
1456 //// | MiniDumpWithoutOptionalData
1457 // | MiniDumpWithFullMemoryInfo
1458 // | MiniDumpWithThreadInfo
1459 // | MiniDumpWithCodeSegs
1460 // | MiniDumpWithFullAuxiliaryState
1461 // | MiniDumpWithPrivateWriteCopyMemory
1462 // | MiniDumpIgnoreInaccessibleMemory
1463 // | MiniDumpWithTokenInformation
1464 //// | MiniDumpWithModuleHeaders
1465 //// | MiniDumpFilterTriage
1466 );
1467
1468 vboxVDbgVEHandlerRegister();
1469 }
1470#endif
1471
1472 crNetInit(NULL, NULL);
1473 ns.name = "vboxhgcm://host:0";
1474 ns.buffer_size = 1024;
1475 crNetServerConnect(&ns
1476#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
1477 , NULL
1478#endif
1479);
1480 if (!ns.conn)
1481 {
1482 crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load.");
1483#ifdef VDBG_VEHANDLER
1484 if (g_VBoxVehEnable)
1485 vboxVDbgVEHandlerUnregister();
1486#endif
1487 return FALSE;
1488 }
1489 else
1490 {
1491 crNetFreeConnection(ns.conn);
1492 }
1493
1494#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
1495 VBoxCrHgsmiInit();
1496#endif
1497 break;
1498 }
1499
1500 case DLL_PROCESS_DETACH:
1501 {
1502 /* do exactly the same thing as for DLL_THREAD_DETACH since
1503 * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */
1504 stubSetCurrentContext(NULL);
1505 if (stub_initialized)
1506 {
1507 CRASSERT(stub.spu);
1508 stub.spu->dispatch_table.VBoxDetachThread();
1509 }
1510
1511
1512#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
1513 VBoxCrHgsmiTerm();
1514#endif
1515
1516 stubSPUSafeTearDown();
1517
1518#ifdef CHROMIUM_THREADSAFE
1519 crFreeTSD(&g_stubCurrentContextTSD);
1520#endif
1521
1522#ifdef VDBG_VEHANDLER
1523 if (g_VBoxVehEnable)
1524 vboxVDbgVEHandlerUnregister();
1525#endif
1526 break;
1527 }
1528
1529 case DLL_THREAD_ATTACH:
1530 {
1531 if (stub_initialized)
1532 {
1533 CRASSERT(stub.spu);
1534 stub.spu->dispatch_table.VBoxAttachThread();
1535 }
1536 break;
1537 }
1538
1539 case DLL_THREAD_DETACH:
1540 {
1541 stubSetCurrentContext(NULL);
1542 if (stub_initialized)
1543 {
1544 CRASSERT(stub.spu);
1545 stub.spu->dispatch_table.VBoxDetachThread();
1546 }
1547 break;
1548 }
1549
1550 default:
1551 break;
1552 }
1553
1554 return TRUE;
1555}
1556#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