VirtualBox

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

Last change on this file since 47151 was 47151, checked in by vboxsync, 11 years ago

crOpenGL & wddm: auto dump file generation, fixes and cleanup

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