VirtualBox

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

Last change on this file since 43409 was 42536, checked in by vboxsync, 12 years ago

crOpenGL/wddm: WOW64 fix

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