VirtualBox

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

Last change on this file since 39602 was 39602, checked in by vboxsync, 13 years ago

wine/XPDM: 1. Additional swapchain creation fixes 2. De-libwine'ize wined3d 3. Single context per swapchain 4. wine & crOgl current context sync fixes 5. Proper Get/ReleaseDC handling

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 38.8 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 int 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 crWindowDestroy((GLint)pWindow->hWnd);
193#else
194 crWindowDestroy((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 crHashtableWalk(stub.contextTable, hsWalkStubDestroyContexts, NULL);
343
344 /* shutdown, now trap any calls to a NULL dispatcher */
345 crSPUCopyDispatchTable(&glim, &stubNULLDispatch);
346
347 crSPUUnloadChain(stub.spu);
348 stub.spu = NULL;
349
350#ifndef Linux
351 crUnloadOpenGL();
352#endif
353
354#ifndef WINDOWS
355 crNetTearDown();
356#endif
357
358#ifdef GLX
359 if (stub.xshmSI.shmid>=0)
360 {
361 shmctl(stub.xshmSI.shmid, IPC_RMID, 0);
362 shmdt(stub.xshmSI.shmaddr);
363 }
364 crFreeHashtable(stub.pGLXPixmapsHash, crFree);
365#endif
366
367 crFreeHashtable(stub.windowTable, crFree);
368 crFreeHashtable(stub.contextTable, NULL);
369
370 crMemset(&stub, 0, sizeof(stub));
371
372}
373
374/**
375 * This is called when we exit.
376 * We call all the SPU's cleanup functions.
377 */
378static void stubSPUTearDown(void)
379{
380 STUB_INIT_LOCK();
381 if (stub_initialized)
382 {
383 stubSPUTearDownLocked();
384 stub_initialized = 0;
385 }
386 STUB_INIT_UNLOCK();
387}
388
389static void stubSPUSafeTearDown(void)
390{
391#ifdef CHROMIUM_THREADSAFE
392 CRmutex *mutex;
393#endif
394
395 if (!stub_initialized) return;
396 stub_initialized = 0;
397
398#ifdef CHROMIUM_THREADSAFE
399 mutex = &stub.mutex;
400 crLockMutex(mutex);
401#endif
402 crDebug("stubSPUSafeTearDown");
403
404#ifdef WINDOWS
405# ifndef CR_NEWWINTRACK
406 stubUninstallWindowMessageHook();
407# endif
408#endif
409
410#if defined(CR_NEWWINTRACK)
411 crUnlockMutex(mutex);
412# if defined(WINDOWS)
413 if (RTThreadGetState(stub.hSyncThread)!=RTTHREADSTATE_TERMINATED)
414 {
415 HANDLE hNative;
416 DWORD ec=0;
417
418 hNative = OpenThread(SYNCHRONIZE|THREAD_QUERY_INFORMATION|THREAD_TERMINATE,
419 false, RTThreadGetNative(stub.hSyncThread));
420 if (!hNative)
421 {
422 crWarning("Failed to get handle for sync thread(%#x)", GetLastError());
423 }
424 else
425 {
426 crDebug("Got handle %p for thread %#x", hNative, RTThreadGetNative(stub.hSyncThread));
427 }
428
429 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
430
431 if (PostThreadMessage(RTThreadGetNative(stub.hSyncThread), WM_QUIT, 0, 0))
432 {
433 RTThreadWait(stub.hSyncThread, 1000, NULL);
434
435 /*Same issue as on linux, RTThreadWait exits before system thread is terminated, which leads
436 * to issues as our dll goes to be unloaded.
437 *@todo
438 *We usually call this function from DllMain which seems to be holding some lock and thus we have to
439 * kill thread via TerminateThread.
440 */
441 if (WaitForSingleObject(hNative, 100)==WAIT_TIMEOUT)
442 {
443 crDebug("Wait failed, terminating");
444 if (!TerminateThread(hNative, 1))
445 {
446 crDebug("TerminateThread failed");
447 }
448 }
449 if (GetExitCodeThread(hNative, &ec))
450 {
451 crDebug("Thread %p exited with ec=%i", hNative, ec);
452 }
453 else
454 {
455 crDebug("GetExitCodeThread failed(%#x)", GetLastError());
456 }
457 }
458 else
459 {
460 crDebug("Sync thread killed before DLL_PROCESS_DETACH");
461 }
462
463 if (hNative)
464 {
465 CloseHandle(hNative);
466 }
467 }
468#else
469 if (stub.hSyncThread!=NIL_RTTHREAD)
470 {
471 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
472 {
473 /*RTThreadWait might return too early, which cause our code being unloaded while RT thread wrapper is still running*/
474 int rc = pthread_join(RTThreadGetNative(stub.hSyncThread), NULL);
475 if (!rc)
476 {
477 crDebug("pthread_join failed %i", rc);
478 }
479 }
480 }
481#endif
482 crLockMutex(mutex);
483#endif
484
485#ifndef WINDOWS
486 crNetTearDown();
487#endif
488
489#ifdef CHROMIUM_THREADSAFE
490 crUnlockMutex(mutex);
491 crFreeMutex(mutex);
492#endif
493 crMemset(&stub, 0, sizeof(stub));
494}
495
496
497static void stubExitHandler(void)
498{
499 stubSPUSafeTearDown();
500}
501
502/**
503 * Called when we receive a SIGTERM signal.
504 */
505static void stubSignalHandler(int signo)
506{
507 stubSPUSafeTearDown();
508 exit(0); /* this causes stubExitHandler() to be called */
509}
510
511#ifndef RT_OS_WINDOWS
512# ifdef CHROMIUM_THREADSAFE
513static DECLCALLBACK(void) stubThreadTlsDtor(void *pvValue)
514{
515 ContextInfo *pCtx = (ContextInfo*)pvValue;
516 VBoxTlsRefRelease(pCtx);
517}
518# endif
519#endif
520
521
522/**
523 * Init variables in the stub structure, install signal handler.
524 */
525static void stubInitVars(void)
526{
527 WindowInfo *defaultWin;
528
529#ifdef CHROMIUM_THREADSAFE
530 crInitMutex(&stub.mutex);
531#endif
532
533 /* At the very least we want CR_RGB_BIT. */
534 stub.haveNativeOpenGL = GL_FALSE;
535 stub.spu = NULL;
536 stub.appDrawCursor = 0;
537 stub.minChromiumWindowWidth = 0;
538 stub.minChromiumWindowHeight = 0;
539 stub.maxChromiumWindowWidth = 0;
540 stub.maxChromiumWindowHeight = 0;
541 stub.matchChromiumWindowCount = 0;
542 stub.matchChromiumWindowID = NULL;
543 stub.matchWindowTitle = NULL;
544 stub.ignoreFreeglutMenus = 0;
545 stub.threadSafe = GL_FALSE;
546 stub.trackWindowSize = 0;
547 stub.trackWindowPos = 0;
548 stub.trackWindowVisibility = 0;
549 stub.trackWindowVisibleRgn = 0;
550 stub.mothershipPID = 0;
551 stub.spu_dir = NULL;
552
553 stub.freeContextNumber = MAGIC_CONTEXT_BASE;
554 stub.contextTable = crAllocHashtable();
555#ifndef RT_OS_WINDOWS
556# ifdef CHROMIUM_THREADSAFE
557 if (!g_stubIsCurrentContextTSDInited)
558 {
559 crInitTSDF(&g_stubCurrentContextTSD, stubThreadTlsDtor);
560 g_stubIsCurrentContextTSDInited = true;
561 }
562# endif
563#endif
564 stubSetCurrentContext(NULL);
565
566 stub.windowTable = crAllocHashtable();
567
568#ifdef CR_NEWWINTRACK
569 stub.bShutdownSyncThread = false;
570 stub.hSyncThread = NIL_RTTHREAD;
571#endif
572
573 defaultWin = (WindowInfo *) crCalloc(sizeof(WindowInfo));
574 defaultWin->type = CHROMIUM;
575 defaultWin->spuWindow = 0; /* window 0 always exists */
576#ifdef WINDOWS
577 defaultWin->hVisibleRegion = INVALID_HANDLE_VALUE;
578#elif defined(GLX)
579 defaultWin->pVisibleRegions = NULL;
580 defaultWin->cVisibleRegions = 0;
581#endif
582 crHashtableAdd(stub.windowTable, 0, defaultWin);
583
584#if 1
585 atexit(stubExitHandler);
586 signal(SIGTERM, stubSignalHandler);
587 signal(SIGINT, stubSignalHandler);
588#ifndef WINDOWS
589 signal(SIGPIPE, SIG_IGN); /* the networking code should catch this */
590#endif
591#else
592 (void) stubExitHandler;
593 (void) stubSignalHandler;
594#endif
595}
596
597
598/**
599 * Return a free port number for the mothership to use, or -1 if we
600 * can't find one.
601 */
602static int
603GenerateMothershipPort(void)
604{
605 const int MAX_PORT = 10100;
606 unsigned short port;
607
608 /* generate initial port number randomly */
609 crRandAutoSeed();
610 port = (unsigned short) crRandInt(10001, MAX_PORT);
611
612#ifdef WINDOWS
613 /* XXX should implement a free port check here */
614 return port;
615#else
616 /*
617 * See if this port number really is free, try another if needed.
618 */
619 {
620 struct sockaddr_in servaddr;
621 int so_reuseaddr = 1;
622 int sock, k;
623
624 /* create socket */
625 sock = socket(AF_INET, SOCK_STREAM, 0);
626 CRASSERT(sock > 2);
627
628 /* deallocate socket/port when we exit */
629 k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
630 (char *) &so_reuseaddr, sizeof(so_reuseaddr));
631 CRASSERT(k == 0);
632
633 /* initialize the servaddr struct */
634 crMemset(&servaddr, 0, sizeof(servaddr) );
635 servaddr.sin_family = AF_INET;
636 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
637
638 while (port < MAX_PORT) {
639 /* Bind to the given port number, return -1 if we fail */
640 servaddr.sin_port = htons((unsigned short) port);
641 k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
642 if (k) {
643 /* failed to create port. try next one. */
644 port++;
645 }
646 else {
647 /* free the socket/port now so mothership can make it */
648 close(sock);
649 return port;
650 }
651 }
652 }
653#endif /* WINDOWS */
654 return -1;
655}
656
657
658/**
659 * Try to determine which mothership configuration to use for this program.
660 */
661static char **
662LookupMothershipConfig(const char *procName)
663{
664 const int procNameLen = crStrlen(procName);
665 FILE *f;
666 const char *home;
667 char configPath[1000];
668
669 /* first, check if the CR_CONFIG env var is set */
670 {
671 const char *conf = crGetenv("CR_CONFIG");
672 if (conf && crStrlen(conf) > 0)
673 return crStrSplit(conf, " ");
674 }
675
676 /* second, look up config name from config file */
677 home = crGetenv("HOME");
678 if (home)
679 sprintf(configPath, "%s/%s", home, CONFIG_LOOKUP_FILE);
680 else
681 crStrcpy(configPath, CONFIG_LOOKUP_FILE); /* from current dir */
682 /* Check if the CR_CONFIG_PATH env var is set. */
683 {
684 const char *conf = crGetenv("CR_CONFIG_PATH");
685 if (conf)
686 crStrcpy(configPath, conf); /* from env var */
687 }
688
689 f = fopen(configPath, "r");
690 if (!f) {
691 return NULL;
692 }
693
694 while (!feof(f)) {
695 char line[1000];
696 char **args;
697 fgets(line, 999, f);
698 line[crStrlen(line) - 1] = 0; /* remove trailing newline */
699 if (crStrncmp(line, procName, procNameLen) == 0 &&
700 (line[procNameLen] == ' ' || line[procNameLen] == '\t'))
701 {
702 crWarning("Using Chromium configuration for %s from %s",
703 procName, configPath);
704 args = crStrSplit(line + procNameLen + 1, " ");
705 return args;
706 }
707 }
708 fclose(f);
709 return NULL;
710}
711
712
713static int Mothership_Awake = 0;
714
715
716/**
717 * Signal handler to determine when mothership is ready.
718 */
719static void
720MothershipPhoneHome(int signo)
721{
722 crDebug("Got signal %d: mothership is awake!", signo);
723 Mothership_Awake = 1;
724}
725
726void stubSetDefaultConfigurationOptions(void)
727{
728 unsigned char key[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
729
730 stub.appDrawCursor = 0;
731 stub.minChromiumWindowWidth = 0;
732 stub.minChromiumWindowHeight = 0;
733 stub.maxChromiumWindowWidth = 0;
734 stub.maxChromiumWindowHeight = 0;
735 stub.matchChromiumWindowID = NULL;
736 stub.numIgnoreWindowID = 0;
737 stub.matchWindowTitle = NULL;
738 stub.ignoreFreeglutMenus = 0;
739 stub.trackWindowSize = 1;
740 stub.trackWindowPos = 1;
741 stub.trackWindowVisibility = 1;
742 stub.trackWindowVisibleRgn = 1;
743 stub.matchChromiumWindowCount = 0;
744 stub.spu_dir = NULL;
745 crNetSetRank(0);
746 crNetSetContextRange(32, 35);
747 crNetSetNodeRange("iam0", "iamvis20");
748 crNetSetKey(key,sizeof(key));
749 stub.force_pbuffers = 0;
750 stub.viewportHack = 0;
751
752#ifdef WINDOWS
753 {
754 char name[1000];
755 int i;
756
757# ifdef VBOX_WITH_WDDM
758 stub.bRunningUnderWDDM = false;
759# endif
760 /* Apply viewport hack only if we're running under wine */
761 if (NULL!=GetModuleHandle("wined3d.dll") || NULL != GetModuleHandle("wined3dwddm.dll"))
762 {
763 crGetProcName(name, 1000);
764 for (i=0; gsViewportHackApps[i]; ++i)
765 {
766 if (!stricmp(name, gsViewportHackApps[i]))
767 {
768 stub.viewportHack = 1;
769 break;
770 }
771 }
772 }
773 }
774#endif
775}
776
777#ifdef CR_NEWWINTRACK
778# ifdef VBOX_WITH_WDDM
779static stubDispatchVisibleRegions(WindowInfo *pWindow)
780{
781 DWORD dwCount;
782 LPRGNDATA lpRgnData;
783
784 dwCount = GetRegionData(pWindow->hVisibleRegion, 0, NULL);
785 lpRgnData = crAlloc(dwCount);
786
787 if (lpRgnData)
788 {
789 GetRegionData(pWindow->hVisibleRegion, dwCount, lpRgnData);
790 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, lpRgnData->rdh.nCount);
791 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, lpRgnData->rdh.nCount, (GLint*) lpRgnData->Buffer);
792 crFree(lpRgnData);
793 }
794 else crWarning("GetRegionData failed, VisibleRegions update failed");
795}
796
797static HRGN stubMakeRegionFromRects(PVBOXVIDEOCM_CMD_RECTS pRegions, uint32_t start)
798{
799 HRGN hRgn, hTmpRgn;
800 uint32_t i;
801
802 if (pRegions->RectsInfo.cRects<=start)
803 {
804 return INVALID_HANDLE_VALUE;
805 }
806
807 hRgn = CreateRectRgn(0, 0, 0, 0);
808 for (i=start; i<pRegions->RectsInfo.cRects; ++i)
809 {
810 hTmpRgn = CreateRectRgnIndirect(&pRegions->RectsInfo.aRects[i]);
811 CombineRgn(hRgn, hRgn, hTmpRgn, RGN_OR);
812 DeleteObject(hTmpRgn);
813 }
814 return hRgn;
815}
816
817typedef struct VBOXCR_UPDATEWNDCB
818{
819 VBOXDISPMP_REGIONS Regions;
820 bool fSendUpdateMsg;
821} VBOXCR_UPDATEWNDCB, *PVBOXCR_UPDATEWNDCB;
822
823static void stubSyncTrUpdateWindowCB(unsigned long key, void *data1, void *data2)
824{
825 WindowInfo *pWindow = (WindowInfo *) data1;
826 PVBOXCR_UPDATEWNDCB pCbData = (PVBOXCR_UPDATEWNDCB) data2;
827 VBOXDISPMP_REGIONS *pRegions = &pCbData->Regions;
828 bool bChanged = false;
829 HRGN hNewRgn = INVALID_HANDLE_VALUE;
830
831 if (pRegions->hWnd != pWindow->hWnd)
832 {
833 return;
834 }
835
836 stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID);
837
838 if (!stubSystemWindowExist(pWindow))
839 {
840 crWindowDestroy((GLint)pWindow->hWnd);
841 return;
842 }
843
844 if (!pWindow->mapped)
845 {
846 pWindow->mapped = GL_TRUE;
847 bChanged = true;
848 crDebug("Dispatched: WindowShow(%i, %i)", pWindow->spuWindow, pWindow->mapped);
849 stub.spu->dispatch_table.WindowShow(pWindow->spuWindow, pWindow->mapped);
850 }
851
852 if (pRegions->pRegions->fFlags.bSetVisibleRects || pRegions->pRegions->fFlags.bSetViewRect)
853 {
854 /* ensure data integrity */
855 Assert(!pRegions->pRegions->fFlags.bAddHiddenRects);
856
857 if (pRegions->pRegions->fFlags.bSetViewRect)
858 {
859 int winX, winY;
860 unsigned int winW, winH;
861 BOOL bRc;
862
863 winX = pRegions->pRegions->RectsInfo.aRects[0].left;
864 winY = pRegions->pRegions->RectsInfo.aRects[0].top;
865 winW = pRegions->pRegions->RectsInfo.aRects[0].right - winX;
866 winH = pRegions->pRegions->RectsInfo.aRects[0].bottom - winY;
867
868 if (stub.trackWindowPos && (winX!=pWindow->x || winY!=pWindow->y))
869 {
870 crDebug("Dispatched WindowPosition (%i)", pWindow->spuWindow);
871 stub.spuDispatch.WindowPosition(pWindow->spuWindow, winX, winY);
872 pWindow->x = winX;
873 pWindow->y = winY;
874 bChanged = true;
875 }
876
877 if (stub.trackWindowSize && (winW!=pWindow->width || winH!=pWindow->height))
878 {
879 crDebug("Dispatched WindowSize (%i)", pWindow->spuWindow);
880 stub.spuDispatch.WindowSize(pWindow->spuWindow, winW, winH);
881 pWindow->width = winW;
882 pWindow->height = winH;
883 bChanged = true;
884 }
885
886 bRc = MoveWindow(pRegions->hWnd, winX, winY, winW, winH, FALSE /*BOOL bRepaint*/);
887 if (!bRc)
888 {
889 DWORD winEr = GetLastError();
890 crWarning("stubSyncTrUpdateWindowCB: MoveWindow failed winEr(%d)", winEr);
891 }
892 }
893
894 if (pRegions->pRegions->fFlags.bSetVisibleRects)
895 {
896 hNewRgn = stubMakeRegionFromRects(pRegions->pRegions, pRegions->pRegions->fFlags.bSetViewRect ? 1 : 0);
897 }
898 }
899 else if (!pRegions->pRegions->fFlags.bHide)
900 {
901 Assert(pRegions->pRegions->fFlags.bAddHiddenRects);
902 hNewRgn = stubMakeRegionFromRects(pRegions->pRegions, 0);
903 }
904 else
905 {
906 Assert(pRegions->pRegions->fFlags.bAddHiddenRects);
907 hNewRgn = CreateRectRgn(pWindow->x, pWindow->y, pWindow->x + pWindow->width, pWindow->y + pWindow->height);
908 }
909
910 if (hNewRgn!=INVALID_HANDLE_VALUE)
911 {
912 if (pRegions->pRegions->fFlags.bSetVisibleRects)
913 {
914 HRGN hEmptyRgn = CreateRectRgn(0, 0, 0, 0);
915
916 if (hEmptyRgn!=INVALID_HANDLE_VALUE)
917 {
918 if (pWindow->hVisibleRegion==INVALID_HANDLE_VALUE || EqualRgn(pWindow->hVisibleRegion, hEmptyRgn))
919 {
920 pCbData->fSendUpdateMsg = true;
921 }
922
923 DeleteObject(hEmptyRgn);
924 }
925 else
926 {
927 crWarning("Failed to created empty region!");
928 }
929 }
930
931 OffsetRgn(hNewRgn, -pWindow->x, -pWindow->y);
932
933 if (pWindow->hVisibleRegion!=INVALID_HANDLE_VALUE)
934 {
935 CombineRgn(hNewRgn, pWindow->hVisibleRegion, hNewRgn,
936 pRegions->pRegions->fFlags.bAddHiddenRects ? RGN_DIFF:RGN_OR);
937
938 if (!EqualRgn(pWindow->hVisibleRegion, hNewRgn))
939 {
940 DeleteObject(pWindow->hVisibleRegion);
941 pWindow->hVisibleRegion = hNewRgn;
942 stubDispatchVisibleRegions(pWindow);
943 bChanged = true;
944 }
945 else
946 {
947 DeleteObject(hNewRgn);
948 }
949 }
950 else
951 {
952 if (pRegions->pRegions->fFlags.bSetVisibleRects)
953 {
954 pWindow->hVisibleRegion = hNewRgn;
955 stubDispatchVisibleRegions(pWindow);
956 bChanged = true;
957 }
958 }
959 }
960
961 if (bChanged)
962 {
963 stub.spu->dispatch_table.Flush();
964 }
965}
966# endif
967
968static void stubSyncTrCheckWindowsCB(unsigned long key, void *data1, void *data2)
969{
970 WindowInfo *pWindow = (WindowInfo *) data1;
971 (void) data2;
972
973 if (pWindow->type!=CHROMIUM || pWindow->spuWindow==0)
974 {
975 return;
976 }
977
978 stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID);
979
980 if (!stubSystemWindowExist(pWindow))
981 {
982#ifdef WINDOWS
983 crWindowDestroy((GLint)pWindow->hWnd);
984#else
985 crWindowDestroy((GLint)pWindow->drawable);
986#endif
987 /*No need to flush here as crWindowDestroy does it*/
988 return;
989 }
990
991#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
992 if (stub.bRunningUnderWDDM)
993 return;
994#endif
995 stubCheckWindowState(pWindow, GL_TRUE);
996}
997
998static DECLCALLBACK(int) stubSyncThreadProc(RTTHREAD ThreadSelf, void *pvUser)
999{
1000#ifdef WINDOWS
1001 MSG msg;
1002# ifdef VBOX_WITH_WDDM
1003 static VBOXDISPMP_CALLBACKS VBoxDispMpTstCallbacks = {NULL, NULL, NULL};
1004 HMODULE hVBoxD3D = NULL;
1005 VBOXCR_UPDATEWNDCB RegionsData;
1006 HRESULT hr;
1007# endif
1008#endif
1009
1010 (void) pvUser;
1011
1012 crDebug("Sync thread started");
1013#ifdef WINDOWS
1014 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
1015# ifdef VBOX_WITH_WDDM
1016 hVBoxD3D = GetModuleHandle("VBoxDispD3D");
1017 if (hVBoxD3D)
1018 {
1019 hVBoxD3D = LoadLibrary("VBoxDispD3D");
1020 }
1021
1022 if (hVBoxD3D)
1023 {
1024 PFNVBOXDISPMP_GETCALLBACKS pfnVBoxDispMpGetCallbacks;
1025 pfnVBoxDispMpGetCallbacks = (PFNVBOXDISPMP_GETCALLBACKS)GetProcAddress(hVBoxD3D, TEXT("VBoxDispMpGetCallbacks"));
1026 if (pfnVBoxDispMpGetCallbacks)
1027 {
1028 hr = pfnVBoxDispMpGetCallbacks(VBOXDISPMP_VERSION, &VBoxDispMpTstCallbacks);
1029 if (S_OK==hr)
1030 {
1031 CRASSERT(VBoxDispMpTstCallbacks.pfnEnableEvents);
1032 CRASSERT(VBoxDispMpTstCallbacks.pfnDisableEvents);
1033 CRASSERT(VBoxDispMpTstCallbacks.pfnGetRegions);
1034
1035 hr = VBoxDispMpTstCallbacks.pfnEnableEvents();
1036 if (hr != S_OK)
1037 {
1038 crWarning("VBoxDispMpTstCallbacks.pfnEnableEvents failed");
1039 }
1040 else
1041 {
1042 crDebug("running with VBoxDispD3D");
1043 stub.trackWindowVisibleRgn = 0;
1044 stub.bRunningUnderWDDM = true;
1045 }
1046 }
1047 else
1048 {
1049 crWarning("VBoxDispMpGetCallbacks failed");
1050 }
1051 }
1052 }
1053# endif
1054#endif
1055
1056 crLockMutex(&stub.mutex);
1057 stub.spu->dispatch_table.VBoxPackSetInjectThread();
1058 crUnlockMutex(&stub.mutex);
1059
1060 RTThreadUserSignal(ThreadSelf);
1061
1062 while(!stub.bShutdownSyncThread)
1063 {
1064#ifdef WINDOWS
1065 if (!PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
1066 {
1067# ifdef VBOX_WITH_WDDM
1068 if (VBoxDispMpTstCallbacks.pfnGetRegions)
1069 {
1070 hr = VBoxDispMpTstCallbacks.pfnGetRegions(&RegionsData.Regions, 50);
1071 if (S_OK==hr)
1072 {
1073 RegionsData.fSendUpdateMsg = false;
1074# if 0
1075 uint32_t i;
1076 crDebug(">>>Regions for HWND(0x%x)>>>", RegionsData.Regions.hWnd);
1077 crDebug("Flags(0x%x)", RegionsData.Regions.pRegions->fFlags.Value);
1078 for (i = 0; i < RegionsData.Regions.pRegions->RectsInfo.cRects; ++i)
1079 {
1080 RECT *pRect = &RegionsData.Regions.pRegions->RectsInfo.aRects[i];
1081 crDebug("Rect(%d): left(%d), top(%d), right(%d), bottom(%d)", i, pRect->left, pRect->top, pRect->right, pRect->bottom);
1082 }
1083 crDebug("<<<<<");
1084# endif
1085 /*hacky way to make sure window wouldn't be deleted in another thread as we hold hashtable lock here*/
1086 crHashtableWalk(stub.windowTable, stubSyncTrUpdateWindowCB, &RegionsData);
1087 if (RegionsData.fSendUpdateMsg)
1088 {
1089 SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, SMTO_NORMAL, 1000, NULL);
1090 }
1091 }
1092 else
1093 {
1094 if (WAIT_TIMEOUT!=hr)
1095 {
1096 crWarning("VBoxDispMpTstCallbacks.pfnGetRegions failed with 0x%x", hr);
1097 }
1098 crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
1099 }
1100 }
1101 else
1102# endif
1103 {
1104 crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
1105 RTThreadSleep(50);
1106 }
1107 }
1108 else
1109 {
1110 if (WM_QUIT==msg.message)
1111 {
1112 crDebug("Sync thread got WM_QUIT");
1113 break;
1114 }
1115 else
1116 {
1117 TranslateMessage(&msg);
1118 DispatchMessage(&msg);
1119 }
1120 }
1121#else
1122 crLockMutex(&stub.mutex);
1123 crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
1124 crUnlockMutex(&stub.mutex);
1125 RTThreadSleep(50);
1126#endif
1127 }
1128
1129#ifdef VBOX_WITH_WDDM
1130 if (VBoxDispMpTstCallbacks.pfnDisableEvents)
1131 {
1132 VBoxDispMpTstCallbacks.pfnDisableEvents();
1133 }
1134 if (hVBoxD3D)
1135 {
1136 FreeLibrary(hVBoxD3D);
1137 }
1138#endif
1139 crDebug("Sync thread stopped");
1140 return 0;
1141}
1142#endif
1143
1144/**
1145 * Do one-time initializations for the faker.
1146 * Returns TRUE on success, FALSE otherwise.
1147 */
1148static bool
1149stubInitLocked(void)
1150{
1151 /* Here is where we contact the mothership to find out what we're supposed
1152 * to be doing. Networking code in a DLL initializer. I sure hope this
1153 * works :)
1154 *
1155 * HOW can I pass the mothership address to this if I already know it?
1156 */
1157
1158 CRConnection *conn = NULL;
1159 char response[1024];
1160 char **spuchain;
1161 int num_spus;
1162 int *spu_ids;
1163 char **spu_names;
1164 const char *app_id;
1165 int i;
1166 int disable_sync = 0;
1167
1168 stubInitVars();
1169
1170 crGetProcName(response, 1024);
1171 crDebug("Stub launched for %s", response);
1172
1173#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
1174 /*@todo when vm boots with compiz turned on, new code causes hang in xcb_wait_for_reply in the sync thread
1175 * as at the start compiz runs our code under XGrabServer.
1176 */
1177 if (!crStrcmp(response, "compiz") || !crStrcmp(response, "compiz_real") || !crStrcmp(response, "compiz.real")
1178 || !crStrcmp(response, "compiz-bin"))
1179 {
1180 disable_sync = 1;
1181 }
1182#endif
1183
1184 /* @todo check if it'd be of any use on other than guests, no use for windows */
1185 app_id = crGetenv( "CR_APPLICATION_ID_NUMBER" );
1186
1187 crNetInit( NULL, NULL );
1188
1189#ifndef WINDOWS
1190 {
1191 CRNetServer ns;
1192
1193 ns.name = "vboxhgcm://host:0";
1194 ns.buffer_size = 1024;
1195 crNetServerConnect(&ns);
1196 if (!ns.conn)
1197 {
1198 crWarning("Failed to connect to host. Make sure 3D acceleration is enabled for this VM.");
1199 return false;
1200 }
1201 else
1202 {
1203 crNetFreeConnection(ns.conn);
1204 }
1205#if 0 && defined(CR_NEWWINTRACK)
1206 {
1207 Status st = XInitThreads();
1208 if (st==0)
1209 {
1210 crWarning("XInitThreads returned %i", (int)st);
1211 }
1212 }
1213#endif
1214 }
1215#endif
1216
1217 strcpy(response, "2 0 feedback 1 pack");
1218 spuchain = crStrSplit( response, " " );
1219 num_spus = crStrToInt( spuchain[0] );
1220 spu_ids = (int *) crAlloc( num_spus * sizeof( *spu_ids ) );
1221 spu_names = (char **) crAlloc( num_spus * sizeof( *spu_names ) );
1222 for (i = 0 ; i < num_spus ; i++)
1223 {
1224 spu_ids[i] = crStrToInt( spuchain[2*i+1] );
1225 spu_names[i] = crStrdup( spuchain[2*i+2] );
1226 crDebug( "SPU %d/%d: (%d) \"%s\"", i+1, num_spus, spu_ids[i], spu_names[i] );
1227 }
1228
1229 stubSetDefaultConfigurationOptions();
1230
1231 stub.spu = crSPULoadChain( num_spus, spu_ids, spu_names, stub.spu_dir, NULL );
1232
1233 crFree( spuchain );
1234 crFree( spu_ids );
1235 for (i = 0; i < num_spus; ++i)
1236 crFree(spu_names[i]);
1237 crFree( spu_names );
1238
1239 // spu chain load failed somewhere
1240 if (!stub.spu) {
1241 return false;
1242 }
1243
1244 crSPUInitDispatchTable( &glim );
1245
1246 /* This is unlikely to change -- We still want to initialize our dispatch
1247 * table with the functions of the first SPU in the chain. */
1248 stubInitSPUDispatch( stub.spu );
1249
1250 /* we need to plug one special stub function into the dispatch table */
1251 glim.GetChromiumParametervCR = stub_GetChromiumParametervCR;
1252
1253#if !defined(VBOX_NO_NATIVEGL)
1254 /* Load pointers to native OpenGL functions into stub.nativeDispatch */
1255 stubInitNativeDispatch();
1256#endif
1257
1258/*crDebug("stub init");
1259raise(SIGINT);*/
1260
1261#ifdef WINDOWS
1262# ifndef CR_NEWWINTRACK
1263 stubInstallWindowMessageHook();
1264# endif
1265#endif
1266
1267#ifdef CR_NEWWINTRACK
1268 {
1269 int rc;
1270
1271 RTR3InitDll(0);
1272
1273 if (!disable_sync)
1274 {
1275 crDebug("Starting sync thread");
1276
1277 rc = RTThreadCreate(&stub.hSyncThread, stubSyncThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Sync");
1278 if (RT_FAILURE(rc))
1279 {
1280 crError("Failed to start sync thread! (%x)", rc);
1281 }
1282 RTThreadUserWait(stub.hSyncThread, 60 * 1000);
1283 RTThreadUserReset(stub.hSyncThread);
1284
1285 crDebug("Going on");
1286 }
1287 }
1288#endif
1289
1290#ifdef GLX
1291 stub.xshmSI.shmid = -1;
1292 stub.bShmInitFailed = GL_FALSE;
1293 stub.pGLXPixmapsHash = crAllocHashtable();
1294
1295 stub.bXExtensionsChecked = GL_FALSE;
1296 stub.bHaveXComposite = GL_FALSE;
1297 stub.bHaveXFixes = GL_FALSE;
1298#endif
1299
1300 return true;
1301}
1302
1303/**
1304 * Do one-time initializations for the faker.
1305 * Returns TRUE on success, FALSE otherwise.
1306 */
1307bool
1308stubInit(void)
1309{
1310 bool bRc = true;
1311 /* we need to serialize the initialization, otherwise racing is possible
1312 * for XPDM-based d3d when a d3d switcher is testing the gl lib in two or more threads
1313 * NOTE: the STUB_INIT_LOCK/UNLOCK is a NOP for non-win currently */
1314 STUB_INIT_LOCK();
1315 if (!stub_initialized)
1316 bRc = stub_initialized = stubInitLocked();
1317 STUB_INIT_UNLOCK();
1318 return bRc;
1319}
1320
1321/* Sigh -- we can't do initialization at load time, since Windows forbids
1322 * the loading of other libraries from DLLMain. */
1323
1324#ifdef LINUX
1325/* GCC crap
1326 *void (*stub_init_ptr)(void) __attribute__((section(".ctors"))) = __stubInit; */
1327#endif
1328
1329#ifdef WINDOWS
1330#define WIN32_LEAN_AND_MEAN
1331#include <windows.h>
1332
1333#ifdef DEBUG_misha
1334 /* debugging: this is to be able to catch first-chance notifications
1335 * for exceptions other than EXCEPTION_BREAKPOINT in kernel debugger */
1336# define VDBG_VEHANDLER
1337#endif
1338
1339#ifdef VDBG_VEHANDLER
1340static PVOID g_VBoxWDbgVEHandler = NULL;
1341LONG WINAPI vboxVDbgVectoredHandler(struct _EXCEPTION_POINTERS *pExceptionInfo)
1342{
1343 PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
1344 PCONTEXT pContextRecord = pExceptionInfo->ContextRecord;
1345 switch (pExceptionRecord->ExceptionCode)
1346 {
1347 case EXCEPTION_BREAKPOINT:
1348 case EXCEPTION_ACCESS_VIOLATION:
1349 case EXCEPTION_STACK_OVERFLOW:
1350 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1351 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1352 case EXCEPTION_FLT_INVALID_OPERATION:
1353 case EXCEPTION_INT_DIVIDE_BY_ZERO:
1354 case EXCEPTION_ILLEGAL_INSTRUCTION:
1355 CRASSERT(0);
1356 break;
1357 default:
1358 break;
1359 }
1360 return EXCEPTION_CONTINUE_SEARCH;
1361}
1362
1363void vboxVDbgVEHandlerRegister()
1364{
1365 CRASSERT(!g_VBoxWDbgVEHandler);
1366 g_VBoxWDbgVEHandler = AddVectoredExceptionHandler(1,vboxVDbgVectoredHandler);
1367 CRASSERT(g_VBoxWDbgVEHandler);
1368}
1369
1370void vboxVDbgVEHandlerUnregister()
1371{
1372 ULONG uResult;
1373 if (g_VBoxWDbgVEHandler)
1374 {
1375 uResult = RemoveVectoredExceptionHandler(g_VBoxWDbgVEHandler);
1376 CRASSERT(uResult);
1377 g_VBoxWDbgVEHandler = NULL;
1378 }
1379}
1380#endif
1381
1382/* Windows crap */
1383BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
1384{
1385 (void) lpvReserved;
1386
1387 switch (fdwReason)
1388 {
1389 case DLL_PROCESS_ATTACH:
1390 {
1391 CRNetServer ns;
1392
1393#ifdef CHROMIUM_THREADSAFE
1394 crInitTSD(&g_stubCurrentContextTSD);
1395#endif
1396
1397 crInitMutex(&stub_init_mutex);
1398
1399#ifdef VDBG_VEHANDLER
1400 vboxVDbgVEHandlerRegister();
1401#endif
1402
1403 crNetInit(NULL, NULL);
1404 ns.name = "vboxhgcm://host:0";
1405 ns.buffer_size = 1024;
1406 crNetServerConnect(&ns);
1407 if (!ns.conn)
1408 {
1409 crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load.");
1410#ifdef VDBG_VEHANDLER
1411 vboxVDbgVEHandlerUnregister();
1412#endif
1413 return FALSE;
1414 }
1415 else
1416 crNetFreeConnection(ns.conn);
1417
1418 break;
1419 }
1420
1421 case DLL_PROCESS_DETACH:
1422 {
1423 stubSPUSafeTearDown();
1424
1425#ifdef CHROMIUM_THREADSAFE
1426 crFreeTSD(&g_stubCurrentContextTSD);
1427#endif
1428
1429#ifdef VDBG_VEHANDLER
1430 vboxVDbgVEHandlerUnregister();
1431#endif
1432 break;
1433 }
1434
1435 case DLL_THREAD_ATTACH:
1436 {
1437#if 0
1438 if (stub_initialized)
1439 {
1440 CRASSERT(stub.spu);
1441 stub.spu->dispatch_table.VBoxPackAttachThread();
1442 }
1443#endif
1444 break;
1445 }
1446
1447 case DLL_THREAD_DETACH:
1448 {
1449 stubSetCurrentContext(NULL);
1450#if 0
1451 if (stub_initialized)
1452 {
1453 CRASSERT(stub.spu);
1454 stub.spu->dispatch_table.VBoxPackDetachThread();
1455 }
1456#endif
1457 break;
1458 }
1459
1460 default:
1461 break;
1462 }
1463
1464 return TRUE;
1465}
1466#endif
Note: See TracBrowser for help on using the repository browser.

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