VirtualBox

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

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

crOpenGL: 1.don't unload rt-dependant libs 2.wait for sync thread termination properly

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 37.9 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#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}
488
489/**
490 * Called when we receive a SIGTERM signal.
491 */
492static void stubSignalHandler(int signo)
493{
494 stubSPUSafeTearDown();
495 exit(0); /* this causes stubExitHandler() to be called */
496}
497
498#ifndef RT_OS_WINDOWS
499# ifdef CHROMIUM_THREADSAFE
500static DECLCALLBACK(void) stubThreadTlsDtor(void *pvValue)
501{
502 ContextInfo *pCtx = (ContextInfo*)pvValue;
503 VBoxTlsRefRelease(pCtx);
504}
505# endif
506#endif
507
508
509/**
510 * Init variables in the stub structure, install signal handler.
511 */
512static void stubInitVars(void)
513{
514 WindowInfo *defaultWin;
515
516#ifdef CHROMIUM_THREADSAFE
517 crInitMutex(&stub.mutex);
518#endif
519
520 /* At the very least we want CR_RGB_BIT. */
521 stub.haveNativeOpenGL = GL_FALSE;
522 stub.spu = NULL;
523 stub.appDrawCursor = 0;
524 stub.minChromiumWindowWidth = 0;
525 stub.minChromiumWindowHeight = 0;
526 stub.maxChromiumWindowWidth = 0;
527 stub.maxChromiumWindowHeight = 0;
528 stub.matchChromiumWindowCount = 0;
529 stub.matchChromiumWindowID = NULL;
530 stub.matchWindowTitle = NULL;
531 stub.ignoreFreeglutMenus = 0;
532 stub.threadSafe = GL_FALSE;
533 stub.trackWindowSize = 0;
534 stub.trackWindowPos = 0;
535 stub.trackWindowVisibility = 0;
536 stub.trackWindowVisibleRgn = 0;
537 stub.mothershipPID = 0;
538 stub.spu_dir = NULL;
539
540 stub.freeContextNumber = MAGIC_CONTEXT_BASE;
541 stub.contextTable = crAllocHashtable();
542#ifndef RT_OS_WINDOWS
543# ifdef CHROMIUM_THREADSAFE
544 if (!g_stubIsCurrentContextTSDInited)
545 {
546 crInitTSDF(&g_stubCurrentContextTSD, stubThreadTlsDtor);
547 g_stubIsCurrentContextTSDInited = true;
548 }
549# endif
550#endif
551 stubSetCurrentContext(NULL);
552
553 stub.windowTable = crAllocHashtable();
554
555#ifdef CR_NEWWINTRACK
556 stub.bShutdownSyncThread = false;
557 stub.hSyncThread = NIL_RTTHREAD;
558#endif
559
560 defaultWin = (WindowInfo *) crCalloc(sizeof(WindowInfo));
561 defaultWin->type = CHROMIUM;
562 defaultWin->spuWindow = 0; /* window 0 always exists */
563#ifdef WINDOWS
564 defaultWin->hVisibleRegion = INVALID_HANDLE_VALUE;
565#elif defined(GLX)
566 defaultWin->pVisibleRegions = NULL;
567 defaultWin->cVisibleRegions = 0;
568#endif
569 crHashtableAdd(stub.windowTable, 0, defaultWin);
570
571#if 1
572 atexit(stubExitHandler);
573 signal(SIGTERM, stubSignalHandler);
574 signal(SIGINT, stubSignalHandler);
575#ifndef WINDOWS
576 signal(SIGPIPE, SIG_IGN); /* the networking code should catch this */
577#endif
578#else
579 (void) stubExitHandler;
580 (void) stubSignalHandler;
581#endif
582}
583
584
585/**
586 * Return a free port number for the mothership to use, or -1 if we
587 * can't find one.
588 */
589static int
590GenerateMothershipPort(void)
591{
592 const int MAX_PORT = 10100;
593 unsigned short port;
594
595 /* generate initial port number randomly */
596 crRandAutoSeed();
597 port = (unsigned short) crRandInt(10001, MAX_PORT);
598
599#ifdef WINDOWS
600 /* XXX should implement a free port check here */
601 return port;
602#else
603 /*
604 * See if this port number really is free, try another if needed.
605 */
606 {
607 struct sockaddr_in servaddr;
608 int so_reuseaddr = 1;
609 int sock, k;
610
611 /* create socket */
612 sock = socket(AF_INET, SOCK_STREAM, 0);
613 CRASSERT(sock > 2);
614
615 /* deallocate socket/port when we exit */
616 k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
617 (char *) &so_reuseaddr, sizeof(so_reuseaddr));
618 CRASSERT(k == 0);
619
620 /* initialize the servaddr struct */
621 crMemset(&servaddr, 0, sizeof(servaddr) );
622 servaddr.sin_family = AF_INET;
623 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
624
625 while (port < MAX_PORT) {
626 /* Bind to the given port number, return -1 if we fail */
627 servaddr.sin_port = htons((unsigned short) port);
628 k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
629 if (k) {
630 /* failed to create port. try next one. */
631 port++;
632 }
633 else {
634 /* free the socket/port now so mothership can make it */
635 close(sock);
636 return port;
637 }
638 }
639 }
640#endif /* WINDOWS */
641 return -1;
642}
643
644
645/**
646 * Try to determine which mothership configuration to use for this program.
647 */
648static char **
649LookupMothershipConfig(const char *procName)
650{
651 const int procNameLen = crStrlen(procName);
652 FILE *f;
653 const char *home;
654 char configPath[1000];
655
656 /* first, check if the CR_CONFIG env var is set */
657 {
658 const char *conf = crGetenv("CR_CONFIG");
659 if (conf && crStrlen(conf) > 0)
660 return crStrSplit(conf, " ");
661 }
662
663 /* second, look up config name from config file */
664 home = crGetenv("HOME");
665 if (home)
666 sprintf(configPath, "%s/%s", home, CONFIG_LOOKUP_FILE);
667 else
668 crStrcpy(configPath, CONFIG_LOOKUP_FILE); /* from current dir */
669 /* Check if the CR_CONFIG_PATH env var is set. */
670 {
671 const char *conf = crGetenv("CR_CONFIG_PATH");
672 if (conf)
673 crStrcpy(configPath, conf); /* from env var */
674 }
675
676 f = fopen(configPath, "r");
677 if (!f) {
678 return NULL;
679 }
680
681 while (!feof(f)) {
682 char line[1000];
683 char **args;
684 fgets(line, 999, f);
685 line[crStrlen(line) - 1] = 0; /* remove trailing newline */
686 if (crStrncmp(line, procName, procNameLen) == 0 &&
687 (line[procNameLen] == ' ' || line[procNameLen] == '\t'))
688 {
689 crWarning("Using Chromium configuration for %s from %s",
690 procName, configPath);
691 args = crStrSplit(line + procNameLen + 1, " ");
692 return args;
693 }
694 }
695 fclose(f);
696 return NULL;
697}
698
699
700static int Mothership_Awake = 0;
701
702
703/**
704 * Signal handler to determine when mothership is ready.
705 */
706static void
707MothershipPhoneHome(int signo)
708{
709 crDebug("Got signal %d: mothership is awake!", signo);
710 Mothership_Awake = 1;
711}
712
713void stubSetDefaultConfigurationOptions(void)
714{
715 unsigned char key[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
716
717 stub.appDrawCursor = 0;
718 stub.minChromiumWindowWidth = 0;
719 stub.minChromiumWindowHeight = 0;
720 stub.maxChromiumWindowWidth = 0;
721 stub.maxChromiumWindowHeight = 0;
722 stub.matchChromiumWindowID = NULL;
723 stub.numIgnoreWindowID = 0;
724 stub.matchWindowTitle = NULL;
725 stub.ignoreFreeglutMenus = 0;
726 stub.trackWindowSize = 1;
727 stub.trackWindowPos = 1;
728 stub.trackWindowVisibility = 1;
729 stub.trackWindowVisibleRgn = 1;
730 stub.matchChromiumWindowCount = 0;
731 stub.spu_dir = NULL;
732 crNetSetRank(0);
733 crNetSetContextRange(32, 35);
734 crNetSetNodeRange("iam0", "iamvis20");
735 crNetSetKey(key,sizeof(key));
736 stub.force_pbuffers = 0;
737
738#ifdef WINDOWS
739# ifdef VBOX_WITH_WDDM
740 stub.bRunningUnderWDDM = false;
741# endif
742#endif
743}
744
745#ifdef CR_NEWWINTRACK
746# ifdef VBOX_WITH_WDDM
747static stubDispatchVisibleRegions(WindowInfo *pWindow)
748{
749 DWORD dwCount;
750 LPRGNDATA lpRgnData;
751
752 dwCount = GetRegionData(pWindow->hVisibleRegion, 0, NULL);
753 lpRgnData = crAlloc(dwCount);
754
755 if (lpRgnData)
756 {
757 GetRegionData(pWindow->hVisibleRegion, dwCount, lpRgnData);
758 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, lpRgnData->rdh.nCount);
759 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, lpRgnData->rdh.nCount, (GLint*) lpRgnData->Buffer);
760 crFree(lpRgnData);
761 }
762 else crWarning("GetRegionData failed, VisibleRegions update failed");
763}
764
765static HRGN stubMakeRegionFromRects(PVBOXVIDEOCM_CMD_RECTS pRegions, uint32_t start)
766{
767 HRGN hRgn, hTmpRgn;
768 uint32_t i;
769
770 if (pRegions->RectsInfo.cRects<=start)
771 {
772 return INVALID_HANDLE_VALUE;
773 }
774
775 hRgn = CreateRectRgn(0, 0, 0, 0);
776 for (i=start; i<pRegions->RectsInfo.cRects; ++i)
777 {
778 hTmpRgn = CreateRectRgnIndirect(&pRegions->RectsInfo.aRects[i]);
779 CombineRgn(hRgn, hRgn, hTmpRgn, RGN_OR);
780 DeleteObject(hTmpRgn);
781 }
782 return hRgn;
783}
784
785# endif /* VBOX_WITH_WDDM */
786
787static void stubSyncTrCheckWindowsCB(unsigned long key, void *data1, void *data2)
788{
789 WindowInfo *pWindow = (WindowInfo *) data1;
790 (void) data2;
791
792 if (pWindow->type!=CHROMIUM || pWindow->spuWindow==0)
793 {
794 return;
795 }
796
797 stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID);
798
799 if (!stubSystemWindowExist(pWindow))
800 {
801#ifdef WINDOWS
802 stubDestroyWindow(0, (GLint)pWindow->hWnd);
803#else
804 stubDestroyWindow(0, (GLint)pWindow->drawable);
805#endif
806 /*No need to flush here as crWindowDestroy does it*/
807 return;
808 }
809
810#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
811 if (stub.bRunningUnderWDDM)
812 return;
813#endif
814 stubCheckWindowState(pWindow, GL_TRUE);
815}
816
817static DECLCALLBACK(int) stubSyncThreadProc(RTTHREAD ThreadSelf, void *pvUser)
818{
819#ifdef WINDOWS
820 MSG msg;
821# ifdef VBOX_WITH_WDDM
822 HMODULE hVBoxD3D = NULL;
823 GLint spuConnection = 0;
824# endif
825#endif
826
827 (void) pvUser;
828
829 crDebug("Sync thread started");
830#ifdef WINDOWS
831 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
832# ifdef VBOX_WITH_WDDM
833 hVBoxD3D = NULL;
834 if (!GetModuleHandleEx(0, VBOX_MODNAME_DISPD3D, &hVBoxD3D))
835 {
836 crDebug("GetModuleHandleEx failed err %d", GetLastError());
837 hVBoxD3D = NULL;
838 }
839
840 if (hVBoxD3D)
841 {
842 crDebug("running with " VBOX_MODNAME_DISPD3D);
843 stub.trackWindowVisibleRgn = 0;
844 stub.bRunningUnderWDDM = true;
845 }
846# endif /* VBOX_WITH_WDDM */
847#endif /* WINDOWS */
848
849 crLockMutex(&stub.mutex);
850#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
851 spuConnection =
852#endif
853 stub.spu->dispatch_table.VBoxPackSetInjectThread(NULL);
854#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
855 if (stub.bRunningUnderWDDM && !spuConnection)
856 {
857 crError("VBoxPackSetInjectThread failed!");
858 }
859#endif
860 crUnlockMutex(&stub.mutex);
861
862 RTThreadUserSignal(ThreadSelf);
863
864 while(!stub.bShutdownSyncThread)
865 {
866#ifdef WINDOWS
867 if (!PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
868 {
869# ifdef VBOX_WITH_WDDM
870 if (stub.bRunningUnderWDDM)
871 {
872
873 }
874 else
875# endif
876 {
877 crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
878 RTThreadSleep(50);
879 }
880 }
881 else
882 {
883 if (WM_QUIT==msg.message)
884 {
885 crDebug("Sync thread got WM_QUIT");
886 break;
887 }
888 else
889 {
890 TranslateMessage(&msg);
891 DispatchMessage(&msg);
892 }
893 }
894#else
895 /* Try to keep a consistent locking order. */
896 crHashtableLock(stub.windowTable);
897 crLockMutex(&stub.mutex);
898 crHashtableWalkUnlocked(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
899 crUnlockMutex(&stub.mutex);
900 crHashtableUnlock(stub.windowTable);
901 RTThreadSleep(50);
902#endif
903 }
904
905#ifdef VBOX_WITH_WDDM
906 if (spuConnection)
907 {
908 stub.spu->dispatch_table.VBoxConDestroy(spuConnection);
909 }
910 if (hVBoxD3D)
911 {
912 FreeLibrary(hVBoxD3D);
913 }
914#endif
915 crDebug("Sync thread stopped");
916 return 0;
917}
918#endif /* CR_NEWWINTRACK */
919
920/**
921 * Do one-time initializations for the faker.
922 * Returns TRUE on success, FALSE otherwise.
923 */
924static bool
925stubInitLocked(void)
926{
927 /* Here is where we contact the mothership to find out what we're supposed
928 * to be doing. Networking code in a DLL initializer. I sure hope this
929 * works :)
930 *
931 * HOW can I pass the mothership address to this if I already know it?
932 */
933
934 CRConnection *conn = NULL;
935 char response[1024];
936 char **spuchain;
937 int num_spus;
938 int *spu_ids;
939 char **spu_names;
940 const char *app_id;
941 int i;
942 int disable_sync = 0;
943#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
944 HMODULE hVBoxD3D = NULL;
945#endif
946
947 stubInitVars();
948
949 crGetProcName(response, 1024);
950 crDebug("Stub launched for %s", response);
951
952#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
953 /*@todo when vm boots with compiz turned on, new code causes hang in xcb_wait_for_reply in the sync thread
954 * as at the start compiz runs our code under XGrabServer.
955 */
956 if (!crStrcmp(response, "compiz") || !crStrcmp(response, "compiz_real") || !crStrcmp(response, "compiz.real")
957 || !crStrcmp(response, "compiz-bin"))
958 {
959 disable_sync = 1;
960 }
961#endif
962
963 /* @todo check if it'd be of any use on other than guests, no use for windows */
964 app_id = crGetenv( "CR_APPLICATION_ID_NUMBER" );
965
966 crNetInit( NULL, NULL );
967
968#ifndef WINDOWS
969 {
970 CRNetServer ns;
971
972 ns.name = "vboxhgcm://host:0";
973 ns.buffer_size = 1024;
974 crNetServerConnect(&ns
975#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
976 , NULL
977#endif
978 );
979 if (!ns.conn)
980 {
981 crWarning("Failed to connect to host. Make sure 3D acceleration is enabled for this VM.");
982 return false;
983 }
984 else
985 {
986 crNetFreeConnection(ns.conn);
987 }
988 }
989#endif
990
991 strcpy(response, "2 0 feedback 1 pack");
992 spuchain = crStrSplit( response, " " );
993 num_spus = crStrToInt( spuchain[0] );
994 spu_ids = (int *) crAlloc( num_spus * sizeof( *spu_ids ) );
995 spu_names = (char **) crAlloc( num_spus * sizeof( *spu_names ) );
996 for (i = 0 ; i < num_spus ; i++)
997 {
998 spu_ids[i] = crStrToInt( spuchain[2*i+1] );
999 spu_names[i] = crStrdup( spuchain[2*i+2] );
1000 crDebug( "SPU %d/%d: (%d) \"%s\"", i+1, num_spus, spu_ids[i], spu_names[i] );
1001 }
1002
1003 stubSetDefaultConfigurationOptions();
1004
1005#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
1006 hVBoxD3D = NULL;
1007 if (!GetModuleHandleEx(0, VBOX_MODNAME_DISPD3D, &hVBoxD3D))
1008 {
1009 crDebug("GetModuleHandleEx failed err %d", GetLastError());
1010 hVBoxD3D = NULL;
1011 }
1012
1013 if (hVBoxD3D)
1014 {
1015 disable_sync = 1;
1016 crDebug("running with %s", VBOX_MODNAME_DISPD3D);
1017 stub.trackWindowVisibleRgn = 0;
1018 /* @todo: should we enable that? */
1019 stub.trackWindowSize = 0;
1020 stub.trackWindowPos = 0;
1021 stub.trackWindowVisibility = 0;
1022 stub.bRunningUnderWDDM = true;
1023 }
1024#endif
1025
1026 stub.spu = crSPULoadChain( num_spus, spu_ids, spu_names, stub.spu_dir, NULL );
1027
1028 crFree( spuchain );
1029 crFree( spu_ids );
1030 for (i = 0; i < num_spus; ++i)
1031 crFree(spu_names[i]);
1032 crFree( spu_names );
1033
1034 // spu chain load failed somewhere
1035 if (!stub.spu) {
1036 return false;
1037 }
1038
1039 crSPUInitDispatchTable( &glim );
1040
1041 /* This is unlikely to change -- We still want to initialize our dispatch
1042 * table with the functions of the first SPU in the chain. */
1043 stubInitSPUDispatch( stub.spu );
1044
1045 /* we need to plug one special stub function into the dispatch table */
1046 glim.GetChromiumParametervCR = stub_GetChromiumParametervCR;
1047
1048#if !defined(VBOX_NO_NATIVEGL)
1049 /* Load pointers to native OpenGL functions into stub.nativeDispatch */
1050 stubInitNativeDispatch();
1051#endif
1052
1053/*crDebug("stub init");
1054raise(SIGINT);*/
1055
1056#ifdef WINDOWS
1057# ifndef CR_NEWWINTRACK
1058 stubInstallWindowMessageHook();
1059# endif
1060#endif
1061
1062#ifdef CR_NEWWINTRACK
1063 {
1064 int rc;
1065
1066 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
1067
1068 if (!disable_sync)
1069 {
1070 crDebug("Starting sync thread");
1071
1072 rc = RTThreadCreate(&stub.hSyncThread, stubSyncThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Sync");
1073 if (RT_FAILURE(rc))
1074 {
1075 crError("Failed to start sync thread! (%x)", rc);
1076 }
1077 RTThreadUserWait(stub.hSyncThread, 60 * 1000);
1078 RTThreadUserReset(stub.hSyncThread);
1079
1080 crDebug("Going on");
1081 }
1082 }
1083#endif
1084
1085#ifdef GLX
1086 stub.xshmSI.shmid = -1;
1087 stub.bShmInitFailed = GL_FALSE;
1088 stub.pGLXPixmapsHash = crAllocHashtable();
1089
1090 stub.bXExtensionsChecked = GL_FALSE;
1091 stub.bHaveXComposite = GL_FALSE;
1092 stub.bHaveXFixes = GL_FALSE;
1093#endif
1094
1095 return true;
1096}
1097
1098/**
1099 * Do one-time initializations for the faker.
1100 * Returns TRUE on success, FALSE otherwise.
1101 */
1102bool
1103stubInit(void)
1104{
1105 bool bRc = true;
1106 /* we need to serialize the initialization, otherwise racing is possible
1107 * for XPDM-based d3d when a d3d switcher is testing the gl lib in two or more threads
1108 * NOTE: the STUB_INIT_LOCK/UNLOCK is a NOP for non-win currently */
1109 STUB_INIT_LOCK();
1110 if (!stub_initialized)
1111 bRc = stub_initialized = stubInitLocked();
1112 STUB_INIT_UNLOCK();
1113 return bRc;
1114}
1115
1116/* Sigh -- we can't do initialization at load time, since Windows forbids
1117 * the loading of other libraries from DLLMain. */
1118
1119#ifdef LINUX
1120/* GCC crap
1121 *void (*stub_init_ptr)(void) __attribute__((section(".ctors"))) = __stubInit; */
1122#endif
1123
1124#ifdef WINDOWS
1125#define WIN32_LEAN_AND_MEAN
1126#include <windows.h>
1127
1128#if 1//def DEBUG_misha
1129 /* debugging: this is to be able to catch first-chance notifications
1130 * for exceptions other than EXCEPTION_BREAKPOINT in kernel debugger */
1131# define VDBG_VEHANDLER
1132#endif
1133
1134#ifdef VDBG_VEHANDLER
1135# include <dbghelp.h>
1136static PVOID g_VBoxVehHandler = NULL;
1137static DWORD g_VBoxVehEnable = 0;
1138
1139/* generate a crash dump on exception */
1140#define VBOXVEH_F_DUMP 0x00000001
1141/* generate a debugger breakpoint exception */
1142#define VBOXVEH_F_BREAK 0x00000002
1143/* exit on exception */
1144#define VBOXVEH_F_EXIT 0x00000004
1145
1146static DWORD g_VBoxVehFlags = 0
1147#ifdef DEBUG_misha
1148 | VBOXVEH_F_BREAK
1149#else
1150 | VBOXVEH_F_DUMP
1151#endif
1152 ;
1153
1154typedef BOOL WINAPI FNVBOXDBG_MINIDUMPWRITEDUMP(HANDLE hProcess,
1155 DWORD ProcessId,
1156 HANDLE hFile,
1157 MINIDUMP_TYPE DumpType,
1158 PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
1159 PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
1160 PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
1161typedef FNVBOXDBG_MINIDUMPWRITEDUMP *PFNVBOXDBG_MINIDUMPWRITEDUMP;
1162
1163static HMODULE g_hVBoxMdDbgHelp = NULL;
1164static PFNVBOXDBG_MINIDUMPWRITEDUMP g_pfnVBoxMdMiniDumpWriteDump = NULL;
1165static uint32_t g_cVBoxMdFilePrefixLen = 0;
1166static WCHAR g_aszwVBoxMdFilePrefix[MAX_PATH];
1167static WCHAR g_aszwVBoxMdDumpCount = 0;
1168static MINIDUMP_TYPE g_enmVBoxMdDumpType = MiniDumpNormal
1169 | MiniDumpWithDataSegs
1170 | MiniDumpWithFullMemory
1171 | MiniDumpWithHandleData
1172//// | MiniDumpFilterMemory
1173//// | MiniDumpScanMemory
1174// | MiniDumpWithUnloadedModules
1175//// | MiniDumpWithIndirectlyReferencedMemory
1176//// | MiniDumpFilterModulePaths
1177// | MiniDumpWithProcessThreadData
1178// | MiniDumpWithPrivateReadWriteMemory
1179//// | MiniDumpWithoutOptionalData
1180// | MiniDumpWithFullMemoryInfo
1181// | MiniDumpWithThreadInfo
1182// | MiniDumpWithCodeSegs
1183// | MiniDumpWithFullAuxiliaryState
1184// | MiniDumpWithPrivateWriteCopyMemory
1185// | MiniDumpIgnoreInaccessibleMemory
1186// | MiniDumpWithTokenInformation
1187//// | MiniDumpWithModuleHeaders
1188//// | MiniDumpFilterTriage
1189 ;
1190
1191
1192
1193#define VBOXMD_DUMP_DIR_PREFIX_DEFAULT L"C:\\dumps\\vboxdmp"
1194
1195static HMODULE loadSystemDll(const char *pszName)
1196{
1197 char szPath[MAX_PATH];
1198 UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
1199 size_t cbName = strlen(pszName) + 1;
1200 if (cchPath + 1 + cbName > sizeof(szPath))
1201 {
1202 SetLastError(ERROR_FILENAME_EXCED_RANGE);
1203 return NULL;
1204 }
1205 szPath[cchPath] = '\\';
1206 memcpy(&szPath[cchPath + 1], pszName, cbName);
1207 return LoadLibraryA(szPath);
1208}
1209
1210static DWORD vboxMdMinidumpCreate(struct _EXCEPTION_POINTERS *pExceptionInfo)
1211{
1212 WCHAR aszwMdFileName[MAX_PATH];
1213 HANDLE hProcess = GetCurrentProcess();
1214 DWORD ProcessId = GetCurrentProcessId();
1215 MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo;
1216 HANDLE hFile;
1217 DWORD winErr = ERROR_SUCCESS;
1218
1219 if (!g_pfnVBoxMdMiniDumpWriteDump)
1220 {
1221 if (!g_hVBoxMdDbgHelp)
1222 {
1223 g_hVBoxMdDbgHelp = loadSystemDll("DbgHelp.dll");
1224 if (!g_hVBoxMdDbgHelp)
1225 return GetLastError();
1226 }
1227
1228 g_pfnVBoxMdMiniDumpWriteDump = (PFNVBOXDBG_MINIDUMPWRITEDUMP)GetProcAddress(g_hVBoxMdDbgHelp, "MiniDumpWriteDump");
1229 if (!g_pfnVBoxMdMiniDumpWriteDump)
1230 return GetLastError();
1231 }
1232
1233 /* @todo: this is a tmp stuff until we get that info from the settings properly */
1234 if (!g_cVBoxMdFilePrefixLen)
1235 {
1236 g_cVBoxMdFilePrefixLen = sizeof (VBOXMD_DUMP_DIR_PREFIX_DEFAULT)/sizeof (g_aszwVBoxMdFilePrefix[0]) - 1 /* <- don't include nul terminator */;
1237 memcpy(g_aszwVBoxMdFilePrefix, VBOXMD_DUMP_DIR_PREFIX_DEFAULT, sizeof (VBOXMD_DUMP_DIR_PREFIX_DEFAULT));
1238 }
1239
1240
1241 if (RT_ELEMENTS(aszwMdFileName) <= g_cVBoxMdFilePrefixLen)
1242 {
1243 return ERROR_INVALID_STATE;
1244 }
1245
1246 ++g_aszwVBoxMdDumpCount;
1247
1248 memcpy(aszwMdFileName, g_aszwVBoxMdFilePrefix, g_cVBoxMdFilePrefixLen * sizeof (g_aszwVBoxMdFilePrefix[0]));
1249 swprintf(aszwMdFileName + g_cVBoxMdFilePrefixLen, RT_ELEMENTS(aszwMdFileName) - g_cVBoxMdFilePrefixLen, L"%d_%d.dmp", ProcessId, g_aszwVBoxMdDumpCount);
1250
1251 hFile = CreateFileW(aszwMdFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1252 if (hFile == INVALID_HANDLE_VALUE)
1253 return GetLastError();
1254
1255 ExceptionInfo.ThreadId = GetCurrentThreadId();
1256 ExceptionInfo.ExceptionPointers = pExceptionInfo;
1257 ExceptionInfo.ClientPointers = FALSE;
1258
1259 if (!g_pfnVBoxMdMiniDumpWriteDump(hProcess, ProcessId, hFile, g_enmVBoxMdDumpType, &ExceptionInfo, NULL, NULL))
1260 winErr = GetLastError();
1261
1262 CloseHandle(hFile);
1263 return winErr;
1264}
1265
1266LONG WINAPI vboxVDbgVectoredHandler(struct _EXCEPTION_POINTERS *pExceptionInfo)
1267{
1268 PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
1269 PCONTEXT pContextRecord = pExceptionInfo->ContextRecord;
1270 switch (pExceptionRecord->ExceptionCode)
1271 {
1272 case EXCEPTION_BREAKPOINT:
1273 case EXCEPTION_ACCESS_VIOLATION:
1274 case EXCEPTION_STACK_OVERFLOW:
1275 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1276 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1277 case EXCEPTION_FLT_INVALID_OPERATION:
1278 case EXCEPTION_INT_DIVIDE_BY_ZERO:
1279 case EXCEPTION_ILLEGAL_INSTRUCTION:
1280 if (g_VBoxVehFlags & VBOXVEH_F_BREAK)
1281 {
1282 BOOL fBreak = TRUE;
1283#ifndef DEBUG_misha
1284 if (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
1285 {
1286 HANDLE hProcess = GetCurrentProcess();
1287 BOOL fDebuggerPresent = FALSE;
1288 /* we do not want to generate breakpoint exceptions recursively, so do it only when running under debugger */
1289 if (CheckRemoteDebuggerPresent(hProcess, &fDebuggerPresent))
1290 fBreak = !!fDebuggerPresent;
1291 else
1292 fBreak = FALSE; /* <- the function has failed, don't break for sanity */
1293 }
1294#endif
1295
1296 if (fBreak)
1297 {
1298 RT_BREAKPOINT();
1299 }
1300 }
1301
1302 if (g_VBoxVehFlags & VBOXVEH_F_DUMP)
1303 vboxMdMinidumpCreate(pExceptionInfo);
1304
1305 if (g_VBoxVehFlags & VBOXVEH_F_EXIT)
1306 exit(1);
1307 break;
1308 default:
1309 break;
1310 }
1311 return EXCEPTION_CONTINUE_SEARCH;
1312}
1313
1314void vboxVDbgVEHandlerRegister()
1315{
1316 CRASSERT(!g_VBoxVehHandler);
1317 g_VBoxVehHandler = AddVectoredExceptionHandler(1,vboxVDbgVectoredHandler);
1318 CRASSERT(g_VBoxVehHandler);
1319}
1320
1321void vboxVDbgVEHandlerUnregister()
1322{
1323 ULONG uResult;
1324 if (g_VBoxVehHandler)
1325 {
1326 uResult = RemoveVectoredExceptionHandler(g_VBoxVehHandler);
1327 CRASSERT(uResult);
1328 g_VBoxVehHandler = NULL;
1329 }
1330}
1331#endif
1332
1333/* Windows crap */
1334BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
1335{
1336 (void) lpvReserved;
1337
1338 switch (fdwReason)
1339 {
1340 case DLL_PROCESS_ATTACH:
1341 {
1342 CRNetServer ns;
1343
1344#ifdef CHROMIUM_THREADSAFE
1345 crInitTSD(&g_stubCurrentContextTSD);
1346#endif
1347
1348 crInitMutex(&stub_init_mutex);
1349
1350#ifdef VDBG_VEHANDLER
1351 g_VBoxVehEnable = !!crGetenv("CR_DBG_VEH_ENABLE");
1352# ifdef DEBUG_misha
1353 g_VBoxVehEnable = 1;
1354# endif
1355 if (g_VBoxVehEnable)
1356 vboxVDbgVEHandlerRegister();
1357#endif
1358
1359 crNetInit(NULL, NULL);
1360 ns.name = "vboxhgcm://host:0";
1361 ns.buffer_size = 1024;
1362 crNetServerConnect(&ns
1363#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
1364 , NULL
1365#endif
1366);
1367 if (!ns.conn)
1368 {
1369 crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load.");
1370#ifdef VDBG_VEHANDLER
1371 if (g_VBoxVehEnable)
1372 vboxVDbgVEHandlerUnregister();
1373#endif
1374 return FALSE;
1375 }
1376 else
1377 {
1378 crNetFreeConnection(ns.conn);
1379 }
1380
1381 break;
1382 }
1383
1384 case DLL_PROCESS_DETACH:
1385 {
1386 /* do exactly the same thing as for DLL_THREAD_DETACH since
1387 * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */
1388 stubSetCurrentContext(NULL);
1389 if (stub_initialized)
1390 {
1391 CRASSERT(stub.spu);
1392 stub.spu->dispatch_table.VBoxDetachThread();
1393 }
1394
1395 stubSPUSafeTearDown();
1396
1397#ifdef CHROMIUM_THREADSAFE
1398 crFreeTSD(&g_stubCurrentContextTSD);
1399#endif
1400
1401#ifdef VDBG_VEHANDLER
1402 if (g_VBoxVehEnable)
1403 vboxVDbgVEHandlerUnregister();
1404#endif
1405 break;
1406 }
1407
1408 case DLL_THREAD_ATTACH:
1409 {
1410 if (stub_initialized)
1411 {
1412 CRASSERT(stub.spu);
1413 stub.spu->dispatch_table.VBoxAttachThread();
1414 }
1415 break;
1416 }
1417
1418 case DLL_THREAD_DETACH:
1419 {
1420 stubSetCurrentContext(NULL);
1421 if (stub_initialized)
1422 {
1423 CRASSERT(stub.spu);
1424 stub.spu->dispatch_table.VBoxDetachThread();
1425 }
1426 break;
1427 }
1428
1429 default:
1430 break;
1431 }
1432
1433 return TRUE;
1434}
1435#endif
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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