VirtualBox

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

Last change on this file since 30440 was 30440, checked in by vboxsync, 15 years ago

crOpenGL: wddm friendly windows info tracking + more consistent updates (disabled except windows yet)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 22.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#ifdef CHROMIUM_THREADSAFE
30#include "cr_threads.h"
31#endif
32
33/**
34 * If you change this, see the comments in tilesortspu_context.c
35 */
36#define MAGIC_CONTEXT_BASE 500
37
38#define CONFIG_LOOKUP_FILE ".crconfigs"
39
40#ifdef WINDOWS
41#define PYTHON_EXE "python.exe"
42#else
43#define PYTHON_EXE "python"
44#endif
45
46#ifdef WINDOWS
47static char* gsViewportHackApps[] = {"googleearth.exe", NULL};
48#endif
49
50static int stub_initialized = 0;
51
52/* NOTE: 'SPUDispatchTable glim' is declared in NULLfuncs.py now */
53/* NOTE: 'SPUDispatchTable stubThreadsafeDispatch' is declared in tsfuncs.c */
54Stub stub;
55
56
57static void stubInitNativeDispatch( void )
58{
59#define MAX_FUNCS 1000
60 SPUNamedFunctionTable gl_funcs[MAX_FUNCS];
61 int numFuncs;
62
63 numFuncs = crLoadOpenGL( &stub.wsInterface, gl_funcs );
64
65 stub.haveNativeOpenGL = (numFuncs > 0);
66
67 /* XXX call this after context binding */
68 numFuncs += crLoadOpenGLExtensions( &stub.wsInterface, gl_funcs + numFuncs );
69
70 CRASSERT(numFuncs < MAX_FUNCS);
71
72 crSPUInitDispatchTable( &stub.nativeDispatch );
73 crSPUInitDispatch( &stub.nativeDispatch, gl_funcs );
74 crSPUInitDispatchNops( &stub.nativeDispatch );
75#undef MAX_FUNCS
76}
77
78
79/** Pointer to the SPU's real glClear and glViewport functions */
80static ClearFunc_t origClear;
81static ViewportFunc_t origViewport;
82static SwapBuffersFunc_t origSwapBuffers;
83static DrawBufferFunc_t origDrawBuffer;
84static ScissorFunc_t origScissor;
85
86static void stubCheckWindowState(WindowInfo *window, GLboolean bFlushOnChange)
87{
88 bool bForceUpdate = false;
89 bool bChanged = false;
90
91#ifdef WINDOWS
92 /* @todo install hook and track for WM_DISPLAYCHANGE */
93 {
94 DEVMODE devMode;
95
96 devMode.dmSize = sizeof(DEVMODE);
97 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);
98
99 if (devMode.dmPelsWidth!=window->dmPelsWidth || devMode.dmPelsHeight!=window->dmPelsHeight)
100 {
101 crDebug("Resolution changed(%d,%d), forcing window Pos/Size update", devMode.dmPelsWidth, devMode.dmPelsHeight);
102 window->dmPelsWidth = devMode.dmPelsWidth;
103 window->dmPelsHeight = devMode.dmPelsHeight;
104 bForceUpdate = true;
105 }
106 }
107#endif
108
109 bChanged = stubUpdateWindowGeometry(window, bForceUpdate) || bForceUpdate;
110
111#if defined(GLX) || defined (WINDOWS)
112 if (stub.trackWindowVisibleRgn)
113 {
114 bChanged = stubUpdateWindowVisibileRegions(window) || bChanged;
115 }
116#endif
117
118 if (stub.trackWindowVisibility && window->type == CHROMIUM && window->drawable) {
119 const int mapped = stubIsWindowVisible(window);
120 if (mapped != window->mapped) {
121 crDebug("Dispatched: WindowShow(%i, %i)", window->spuWindow, mapped);
122 stub.spu->dispatch_table.WindowShow(window->spuWindow, mapped);
123 window->mapped = mapped;
124 bChanged = true;
125 }
126 }
127
128 if (bFlushOnChange && bChanged)
129 {
130 stub.spu->dispatch_table.Flush();
131 }
132}
133
134static bool stubSystemWindowExist(WindowInfo *pWindow)
135{
136#ifdef WINDOWS
137 if (!WindowFromDC(pWindow->drawable))
138 {
139 return false;
140 }
141#else
142 Window root;
143 int x, y;
144 unsigned int border, depth, w, h;
145
146 XLOCK(pWindow->dpy);
147 if (!XGetGeometry(pWindow->dpy, pWindow->drawable, &root, &x, &y, &w, &h, &border, &depth))
148 {
149 XUNLOCK(pWindow->dpy);
150 return false;
151 }
152 XUNLOCK(pWindow->dpy);
153#endif
154
155 return true;
156}
157
158static void stubCheckWindowsCB(unsigned long key, void *data1, void *data2)
159{
160 WindowInfo *pWindow = (WindowInfo *) data1;
161 ContextInfo *pCtx = (ContextInfo *) data2;
162
163 if (pWindow == pCtx->currentDrawable
164 || pWindow->type!=CHROMIUM
165 || pWindow->pOwner!=pCtx)
166 {
167 return;
168 }
169
170 if (!stubSystemWindowExist(pWindow))
171 {
172#ifdef WINDOWS
173 crWindowDestroy((GLint)pWindow->hWnd);
174#else
175 crWindowDestroy((GLint)pWindow->drawable);
176#endif
177 return;
178 }
179
180 stubCheckWindowState(pWindow, GL_FALSE);
181}
182
183static void stubCheckWindowsState(void)
184{
185 CRASSERT(stub.trackWindowSize || stub.trackWindowPos);
186
187 if (!stub.currentContext)
188 return;
189
190#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
191 crLockMutex(&stub.mutex);
192#endif
193
194 stubCheckWindowState(stub.currentContext->currentDrawable, GL_TRUE);
195 crHashtableWalk(stub.windowTable, stubCheckWindowsCB, stub.currentContext);
196
197#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
198 crUnlockMutex(&stub.mutex);
199#endif
200}
201
202
203/**
204 * Override the head SPU's glClear function.
205 * We're basically trapping this function so that we can poll the
206 * application window size at a regular interval.
207 */
208static void SPU_APIENTRY trapClear(GLbitfield mask)
209{
210 stubCheckWindowsState();
211 /* call the original SPU glClear function */
212 origClear(mask);
213}
214
215/**
216 * As above, but for glViewport. Most apps call glViewport before
217 * glClear when a window is resized.
218 */
219static void SPU_APIENTRY trapViewport(GLint x, GLint y, GLsizei w, GLsizei h)
220{
221 stubCheckWindowsState();
222 /* call the original SPU glViewport function */
223 if (!stub.viewportHack)
224 {
225 origViewport(x, y, w, h);
226 }
227 else
228 {
229 int winX, winY;
230 unsigned int winW, winH;
231 WindowInfo *pWindow;
232 pWindow = stub.currentContext->currentDrawable;
233 stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
234 origViewport(0, 0, winW, winH);
235 }
236}
237
238static void SPU_APIENTRY trapSwapBuffers(GLint window, GLint flags)
239{
240 stubCheckWindowsState();
241 origSwapBuffers(window, flags);
242}
243
244static void SPU_APIENTRY trapDrawBuffer(GLenum buf)
245{
246 stubCheckWindowsState();
247 origDrawBuffer(buf);
248}
249
250static void SPU_APIENTRY trapScissor(GLint x, GLint y, GLsizei w, GLsizei h)
251{
252 int winX, winY;
253 unsigned int winW, winH;
254 WindowInfo *pWindow;
255 pWindow = stub.currentContext->currentDrawable;
256 stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
257 origScissor(0, 0, winW, winH);
258}
259
260/**
261 * Use the GL function pointers in <spu> to initialize the static glim
262 * dispatch table.
263 */
264static void stubInitSPUDispatch(SPU *spu)
265{
266 crSPUInitDispatchTable( &stub.spuDispatch );
267 crSPUCopyDispatchTable( &stub.spuDispatch, &(spu->dispatch_table) );
268
269 if (stub.trackWindowSize || stub.trackWindowPos || stub.trackWindowVisibleRgn) {
270 /* patch-in special glClear/Viewport function to track window sizing */
271 origClear = stub.spuDispatch.Clear;
272 origViewport = stub.spuDispatch.Viewport;
273 origSwapBuffers = stub.spuDispatch.SwapBuffers;
274 origDrawBuffer = stub.spuDispatch.DrawBuffer;
275 origScissor = stub.spuDispatch.Scissor;
276#ifndef CR_NEWWINTRACK
277 stub.spuDispatch.Clear = trapClear;
278 stub.spuDispatch.Viewport = trapViewport;
279#endif
280 if (stub.viewportHack)
281 stub.spuDispatch.Scissor = trapScissor;
282 /*stub.spuDispatch.SwapBuffers = trapSwapBuffers;
283 stub.spuDispatch.DrawBuffer = trapDrawBuffer;*/
284 }
285
286 crSPUCopyDispatchTable( &glim, &stub.spuDispatch );
287}
288
289// Callback function, used to destroy all created contexts
290static void hsWalkStubDestroyContexts(unsigned long key, void *data1, void *data2)
291{
292 stubDestroyContext(key);
293}
294
295/**
296 * This is called when we exit.
297 * We call all the SPU's cleanup functions.
298 */
299static void stubSPUTearDown(void)
300{
301 crDebug("stubSPUTearDown");
302 if (!stub_initialized) return;
303
304 stub_initialized = 0;
305
306#ifdef WINDOWS
307# ifndef CR_NEWWINTRACK
308 stubUninstallWindowMessageHook();
309# endif
310#endif
311
312#ifdef CR_NEWWINTRACK
313 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
314#endif
315
316 //delete all created contexts
317 stubMakeCurrent( NULL, NULL);
318 crHashtableWalk(stub.contextTable, hsWalkStubDestroyContexts, NULL);
319
320 /* shutdown, now trap any calls to a NULL dispatcher */
321 crSPUCopyDispatchTable(&glim, &stubNULLDispatch);
322
323 crSPUUnloadChain(stub.spu);
324 stub.spu = NULL;
325
326#ifndef Linux
327 crUnloadOpenGL();
328#endif
329
330 crNetTearDown();
331
332#ifdef GLX
333 if (stub.xshmSI.shmid>=0)
334 {
335 shmctl(stub.xshmSI.shmid, IPC_RMID, 0);
336 shmdt(stub.xshmSI.shmaddr);
337 }
338 crFreeHashtable(stub.pGLXPixmapsHash, crFree);
339#endif
340
341 crFreeHashtable(stub.windowTable, crFree);
342 crFreeHashtable(stub.contextTable, NULL);
343
344 crMemset(&stub, 0, sizeof(stub) );
345}
346
347static void stubSPUSafeTearDown(void)
348{
349#ifdef CHROMIUM_THREADSAFE
350 CRmutex *mutex;
351#endif
352
353 if (!stub_initialized) return;
354 stub_initialized = 0;
355
356#ifdef CHROMIUM_THREADSAFE
357 mutex = &stub.mutex;
358 crLockMutex(mutex);
359#endif
360 crDebug("stubSPUSafeTearDown");
361
362#ifdef WINDOWS
363# ifndef CR_NEWWINTRACK
364 stubUninstallWindowMessageHook();
365# endif
366#endif
367
368#if defined(WINDOWS) && defined(CR_NEWWINTRACK)
369 crUnlockMutex(mutex);
370 if (RTThreadGetState(stub.hSyncThread)!=RTTHREADSTATE_TERMINATED)
371 {
372 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
373 if (PostThreadMessage(RTThreadGetNative(stub.hSyncThread), WM_QUIT, 0, 0))
374 {
375 RTThreadWait(stub.hSyncThread, 1000, NULL);
376 }
377 else
378 {
379 crDebug("Sync thread killed before DLL_PROCESS_DETACH");
380 }
381 }
382 crLockMutex(mutex);
383#endif
384
385 crNetTearDown();
386 crMemset(&stub, 0, sizeof(stub));
387#ifdef CHROMIUM_THREADSAFE
388 crUnlockMutex(mutex);
389 crFreeMutex(mutex);
390#endif
391}
392
393
394static void stubExitHandler(void)
395{
396 stubSPUSafeTearDown();
397}
398
399/**
400 * Called when we receive a SIGTERM signal.
401 */
402static void stubSignalHandler(int signo)
403{
404 stubSPUSafeTearDown();
405 exit(0); /* this causes stubExitHandler() to be called */
406}
407
408
409/**
410 * Init variables in the stub structure, install signal handler.
411 */
412static void stubInitVars(void)
413{
414 WindowInfo *defaultWin;
415
416#ifdef CHROMIUM_THREADSAFE
417 crInitMutex(&stub.mutex);
418#endif
419
420 /* At the very least we want CR_RGB_BIT. */
421 stub.haveNativeOpenGL = GL_FALSE;
422 stub.spu = NULL;
423 stub.appDrawCursor = 0;
424 stub.minChromiumWindowWidth = 0;
425 stub.minChromiumWindowHeight = 0;
426 stub.maxChromiumWindowWidth = 0;
427 stub.maxChromiumWindowHeight = 0;
428 stub.matchChromiumWindowCount = 0;
429 stub.matchChromiumWindowID = NULL;
430 stub.matchWindowTitle = NULL;
431 stub.ignoreFreeglutMenus = 0;
432 stub.threadSafe = GL_FALSE;
433 stub.trackWindowSize = 0;
434 stub.trackWindowPos = 0;
435 stub.trackWindowVisibility = 0;
436 stub.trackWindowVisibleRgn = 0;
437 stub.mothershipPID = 0;
438 stub.spu_dir = NULL;
439
440 stub.freeContextNumber = MAGIC_CONTEXT_BASE;
441 stub.contextTable = crAllocHashtable();
442 stub.currentContext = NULL;
443
444 stub.windowTable = crAllocHashtable();
445
446#ifdef CR_NEWWINTRACK
447 stub.bShutdownSyncThread = false;
448 stub.hSyncThread = NIL_RTTHREAD;
449#endif
450
451 defaultWin = (WindowInfo *) crCalloc(sizeof(WindowInfo));
452 defaultWin->type = CHROMIUM;
453 defaultWin->spuWindow = 0; /* window 0 always exists */
454#ifdef WINDOWS
455 defaultWin->hVisibleRegion = INVALID_HANDLE_VALUE;
456#elif defined(GLX)
457 defaultWin->pVisibleRegions = NULL;
458 defaultWin->cVisibleRegions = 0;
459#endif
460 crHashtableAdd(stub.windowTable, 0, defaultWin);
461
462#if 1
463 atexit(stubExitHandler);
464 signal(SIGTERM, stubSignalHandler);
465 signal(SIGINT, stubSignalHandler);
466#ifndef WINDOWS
467 signal(SIGPIPE, SIG_IGN); /* the networking code should catch this */
468#endif
469#else
470 (void) stubExitHandler;
471 (void) stubSignalHandler;
472#endif
473}
474
475
476/**
477 * Return a free port number for the mothership to use, or -1 if we
478 * can't find one.
479 */
480static int
481GenerateMothershipPort(void)
482{
483 const int MAX_PORT = 10100;
484 unsigned short port;
485
486 /* generate initial port number randomly */
487 crRandAutoSeed();
488 port = (unsigned short) crRandInt(10001, MAX_PORT);
489
490#ifdef WINDOWS
491 /* XXX should implement a free port check here */
492 return port;
493#else
494 /*
495 * See if this port number really is free, try another if needed.
496 */
497 {
498 struct sockaddr_in servaddr;
499 int so_reuseaddr = 1;
500 int sock, k;
501
502 /* create socket */
503 sock = socket(AF_INET, SOCK_STREAM, 0);
504 CRASSERT(sock > 2);
505
506 /* deallocate socket/port when we exit */
507 k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
508 (char *) &so_reuseaddr, sizeof(so_reuseaddr));
509 CRASSERT(k == 0);
510
511 /* initialize the servaddr struct */
512 crMemset(&servaddr, 0, sizeof(servaddr) );
513 servaddr.sin_family = AF_INET;
514 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
515
516 while (port < MAX_PORT) {
517 /* Bind to the given port number, return -1 if we fail */
518 servaddr.sin_port = htons((unsigned short) port);
519 k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
520 if (k) {
521 /* failed to create port. try next one. */
522 port++;
523 }
524 else {
525 /* free the socket/port now so mothership can make it */
526 close(sock);
527 return port;
528 }
529 }
530 }
531#endif /* WINDOWS */
532 return -1;
533}
534
535
536/**
537 * Try to determine which mothership configuration to use for this program.
538 */
539static char **
540LookupMothershipConfig(const char *procName)
541{
542 const int procNameLen = crStrlen(procName);
543 FILE *f;
544 const char *home;
545 char configPath[1000];
546
547 /* first, check if the CR_CONFIG env var is set */
548 {
549 const char *conf = crGetenv("CR_CONFIG");
550 if (conf && crStrlen(conf) > 0)
551 return crStrSplit(conf, " ");
552 }
553
554 /* second, look up config name from config file */
555 home = crGetenv("HOME");
556 if (home)
557 sprintf(configPath, "%s/%s", home, CONFIG_LOOKUP_FILE);
558 else
559 crStrcpy(configPath, CONFIG_LOOKUP_FILE); /* from current dir */
560 /* Check if the CR_CONFIG_PATH env var is set. */
561 {
562 const char *conf = crGetenv("CR_CONFIG_PATH");
563 if (conf)
564 crStrcpy(configPath, conf); /* from env var */
565 }
566
567 f = fopen(configPath, "r");
568 if (!f) {
569 return NULL;
570 }
571
572 while (!feof(f)) {
573 char line[1000];
574 char **args;
575 fgets(line, 999, f);
576 line[crStrlen(line) - 1] = 0; /* remove trailing newline */
577 if (crStrncmp(line, procName, procNameLen) == 0 &&
578 (line[procNameLen] == ' ' || line[procNameLen] == '\t'))
579 {
580 crWarning("Using Chromium configuration for %s from %s",
581 procName, configPath);
582 args = crStrSplit(line + procNameLen + 1, " ");
583 return args;
584 }
585 }
586 fclose(f);
587 return NULL;
588}
589
590
591static int Mothership_Awake = 0;
592
593
594/**
595 * Signal handler to determine when mothership is ready.
596 */
597static void
598MothershipPhoneHome(int signo)
599{
600 crDebug("Got signal %d: mothership is awake!", signo);
601 Mothership_Awake = 1;
602}
603
604void stubSetDefaultConfigurationOptions(void)
605{
606 unsigned char key[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
607
608 stub.appDrawCursor = 0;
609 stub.minChromiumWindowWidth = 0;
610 stub.minChromiumWindowHeight = 0;
611 stub.maxChromiumWindowWidth = 0;
612 stub.maxChromiumWindowHeight = 0;
613 stub.matchChromiumWindowID = NULL;
614 stub.numIgnoreWindowID = 0;
615 stub.matchWindowTitle = NULL;
616 stub.ignoreFreeglutMenus = 0;
617 stub.trackWindowSize = 1;
618 stub.trackWindowPos = 1;
619 stub.trackWindowVisibility = 1;
620 stub.trackWindowVisibleRgn = 1;
621 stub.matchChromiumWindowCount = 0;
622 stub.spu_dir = NULL;
623 crNetSetRank(0);
624 crNetSetContextRange(32, 35);
625 crNetSetNodeRange("iam0", "iamvis20");
626 crNetSetKey(key,sizeof(key));
627 stub.force_pbuffers = 0;
628 stub.viewportHack = 0;
629
630#ifdef WINDOWS
631 {
632 char name[1000];
633 int i;
634
635 /* Apply viewport hack only if we're running under wine */
636 if (NULL!=GetModuleHandle("wined3d.dll"))
637 {
638 crGetProcName(name, 1000);
639 for (i=0; gsViewportHackApps[i]; ++i)
640 {
641 if (!stricmp(name, gsViewportHackApps[i]))
642 {
643 stub.viewportHack = 1;
644 break;
645 }
646 }
647 }
648 }
649#endif
650}
651
652#ifdef CR_NEWWINTRACK
653static void stubSyncTrCheckWindowsCB(unsigned long key, void *data1, void *data2)
654{
655 WindowInfo *pWindow = (WindowInfo *) data1;
656 ContextInfo *pCtx = (ContextInfo *) data2;
657
658 if (pWindow->type!=CHROMIUM || pWindow->spuWindow==0)
659 {
660 return;
661 }
662
663 stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID);
664
665 if (!stubSystemWindowExist(pWindow))
666 {
667#ifdef WINDOWS
668 crWindowDestroy((GLint)pWindow->hWnd);
669#else
670 crWindowDestroy((GLint)pWindow->drawable);
671#endif
672 /*No need to flush here as crWindowDestroy does it*/
673 return;
674 }
675
676 stubCheckWindowState(pWindow, GL_TRUE);
677}
678
679static DECLCALLBACK(int) stubSyncThreadProc(RTTHREAD ThreadSelf, void *pvUser)
680{
681#ifdef WINDOWS
682 MSG msg;
683#endif
684
685 (void) pvUser;
686
687 crDebug("Sync thread started");
688#ifdef WINDOWS
689 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
690#endif
691
692 crLockMutex(&stub.mutex);
693 stub.spu->dispatch_table.VBoxPackSetInjectThread();
694 crUnlockMutex(&stub.mutex);
695
696 RTThreadUserSignal(ThreadSelf);
697
698 while(!stub.bShutdownSyncThread)
699 {
700#ifdef WINDOWS
701 if (!PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
702 {
703 crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
704 RTThreadSleep(50);
705 }
706 else
707 {
708 if (WM_QUIT==msg.message)
709 {
710 crDebug("Sync thread got WM_QUIT");
711 break;
712 }
713 else
714 {
715 TranslateMessage(&msg);
716 DispatchMessage(&msg);
717 }
718 }
719#else
720 crLockMutex(&stub.mutex);
721 crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
722 crUnlockMutex(&stub.mutex);
723 RTThreadSleep(50);
724#endif
725 }
726
727 crDebug("Sync thread stopped");
728 return 0;
729}
730#endif
731
732/**
733 * Do one-time initializations for the faker.
734 * Returns TRUE on success, FALSE otherwise.
735 */
736bool
737stubInit(void)
738{
739 /* Here is where we contact the mothership to find out what we're supposed
740 * to be doing. Networking code in a DLL initializer. I sure hope this
741 * works :)
742 *
743 * HOW can I pass the mothership address to this if I already know it?
744 */
745
746 CRConnection *conn = NULL;
747 char response[1024];
748 char **spuchain;
749 int num_spus;
750 int *spu_ids;
751 char **spu_names;
752 const char *app_id;
753 int i;
754
755 if (stub_initialized)
756 return true;
757
758 stubInitVars();
759
760 crGetProcName(response, 1024);
761 crDebug("Stub launched for %s", response);
762
763 /* @todo check if it'd be of any use on other than guests, no use for windows */
764 app_id = crGetenv( "CR_APPLICATION_ID_NUMBER" );
765
766 crNetInit( NULL, NULL );
767
768#ifndef WINDOWS
769 {
770 CRNetServer ns;
771
772 ns.name = "vboxhgcm://host:0";
773 ns.buffer_size = 1024;
774 crNetServerConnect(&ns);
775 if (!ns.conn)
776 {
777 crWarning("Failed to connect to host. Make sure 3D acceleration is enabled for this VM.");
778 return false;
779 }
780 else
781 {
782 crNetFreeConnection(ns.conn);
783 }
784#ifdef CR_NEWWINTRACK
785 {
786 Status st = XInitThreads();
787 if (st==0)
788 {
789 crWarning("XInitThreads returned %i", (int)st);
790 }
791 }
792#endif
793 }
794#endif
795
796 strcpy(response, "2 0 feedback 1 pack");
797 spuchain = crStrSplit( response, " " );
798 num_spus = crStrToInt( spuchain[0] );
799 spu_ids = (int *) crAlloc( num_spus * sizeof( *spu_ids ) );
800 spu_names = (char **) crAlloc( num_spus * sizeof( *spu_names ) );
801 for (i = 0 ; i < num_spus ; i++)
802 {
803 spu_ids[i] = crStrToInt( spuchain[2*i+1] );
804 spu_names[i] = crStrdup( spuchain[2*i+2] );
805 crDebug( "SPU %d/%d: (%d) \"%s\"", i+1, num_spus, spu_ids[i], spu_names[i] );
806 }
807
808 stubSetDefaultConfigurationOptions();
809
810 stub.spu = crSPULoadChain( num_spus, spu_ids, spu_names, stub.spu_dir, NULL );
811
812 crFree( spuchain );
813 crFree( spu_ids );
814 for (i = 0; i < num_spus; ++i)
815 crFree(spu_names[i]);
816 crFree( spu_names );
817
818 // spu chain load failed somewhere
819 if (!stub.spu) {
820 return false;
821 }
822
823 crSPUInitDispatchTable( &glim );
824
825 /* This is unlikely to change -- We still want to initialize our dispatch
826 * table with the functions of the first SPU in the chain. */
827 stubInitSPUDispatch( stub.spu );
828
829 /* we need to plug one special stub function into the dispatch table */
830 glim.GetChromiumParametervCR = stub_GetChromiumParametervCR;
831
832#if !defined(VBOX_NO_NATIVEGL)
833 /* Load pointers to native OpenGL functions into stub.nativeDispatch */
834 stubInitNativeDispatch();
835#endif
836
837/*crDebug("stub init");
838raise(SIGINT);*/
839
840#ifdef WINDOWS
841# ifndef CR_NEWWINTRACK
842 stubInstallWindowMessageHook();
843# endif
844#endif
845
846#ifdef CR_NEWWINTRACK
847 {
848 int rc;
849
850 RTR3Init();
851
852 crDebug("Starting sync thread");
853
854 rc = RTThreadCreate(&stub.hSyncThread, stubSyncThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Sync");
855 if (RT_FAILURE(rc))
856 {
857 crError("Failed to start sync thread! (%x)", rc);
858 }
859 RTThreadUserWait(stub.hSyncThread, 60 * 1000);
860 RTThreadUserReset(stub.hSyncThread);
861
862 crDebug("Going on");
863 }
864#endif
865
866#ifdef GLX
867 stub.xshmSI.shmid = -1;
868 stub.bShmInitFailed = GL_FALSE;
869 stub.pGLXPixmapsHash = crAllocHashtable();
870#endif
871
872 stub_initialized = 1;
873 return true;
874}
875
876/* Sigh -- we can't do initialization at load time, since Windows forbids
877 * the loading of other libraries from DLLMain. */
878
879#ifdef LINUX
880/* GCC crap
881 *void (*stub_init_ptr)(void) __attribute__((section(".ctors"))) = __stubInit; */
882#endif
883
884#ifdef WINDOWS
885#define WIN32_LEAN_AND_MEAN
886#include <windows.h>
887
888/* Windows crap */
889BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
890{
891 (void) lpvReserved;
892
893 switch (fdwReason)
894 {
895 case DLL_PROCESS_ATTACH:
896 {
897 CRNetServer ns;
898
899 crNetInit(NULL, NULL);
900 ns.name = "vboxhgcm://host:0";
901 ns.buffer_size = 1024;
902 crNetServerConnect(&ns);
903 if (!ns.conn)
904 {
905 crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load.");
906 return FALSE;
907 }
908 else
909 crNetFreeConnection(ns.conn);
910
911 break;
912 }
913
914 case DLL_PROCESS_DETACH:
915 {
916 stubSPUSafeTearDown();
917 break;
918 }
919
920 case DLL_THREAD_ATTACH:
921 break;
922
923 case DLL_THREAD_DETACH:
924 break;
925
926 default:
927 break;
928 }
929
930 return TRUE;
931}
932#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