VirtualBox

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

最後變更 在這個檔案從49891是 49470,由 vboxsync 提交於 11 年 前

Additions/3D: prevent an OpenGL dead-lock.

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

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