VirtualBox

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

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

crOpenGL: hack for google earth view size, turned off

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 17.1 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#ifndef WINDOWS
22#include <sys/types.h>
23#include <unistd.h>
24#endif
25#ifdef CHROMIUM_THREADSAFE
26#include "cr_threads.h"
27#endif
28
29/**
30 * If you change this, see the comments in tilesortspu_context.c
31 */
32#define MAGIC_CONTEXT_BASE 500
33
34#define CONFIG_LOOKUP_FILE ".crconfigs"
35
36#ifdef WINDOWS
37#define PYTHON_EXE "python.exe"
38#else
39#define PYTHON_EXE "python"
40#endif
41
42static int stub_initialized = 0;
43
44/* NOTE: 'SPUDispatchTable glim' is declared in NULLfuncs.py now */
45/* NOTE: 'SPUDispatchTable stubThreadsafeDispatch' is declared in tsfuncs.c */
46Stub stub;
47
48
49static void stubInitNativeDispatch( void )
50{
51#define MAX_FUNCS 1000
52 SPUNamedFunctionTable gl_funcs[MAX_FUNCS];
53 int numFuncs;
54
55 numFuncs = crLoadOpenGL( &stub.wsInterface, gl_funcs );
56
57 stub.haveNativeOpenGL = (numFuncs > 0);
58
59 /* XXX call this after context binding */
60 numFuncs += crLoadOpenGLExtensions( &stub.wsInterface, gl_funcs + numFuncs );
61
62 CRASSERT(numFuncs < MAX_FUNCS);
63
64 crSPUInitDispatchTable( &stub.nativeDispatch );
65 crSPUInitDispatch( &stub.nativeDispatch, gl_funcs );
66 crSPUInitDispatchNops( &stub.nativeDispatch );
67#undef MAX_FUNCS
68}
69
70
71/** Pointer to the SPU's real glClear and glViewport functions */
72static ClearFunc_t origClear;
73static ViewportFunc_t origViewport;
74static SwapBuffersFunc_t origSwapBuffers;
75static DrawBufferFunc_t origDrawBuffer;
76static ScissorFunc_t origScissor;
77
78static void stubCheckWindowState(void)
79{
80 WindowInfo *window;
81 bool bForceUpdate = false;
82
83 CRASSERT(stub.trackWindowSize || stub.trackWindowPos);
84
85 if (!stub.currentContext)
86 return;
87
88 window = stub.currentContext->currentDrawable;
89
90#ifdef WINDOWS
91 /* @todo install hook and track for WM_DISPLAYCHANGE */
92 {
93 DEVMODE devMode;
94
95 devMode.dmSize = sizeof(DEVMODE);
96 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);
97
98 if (devMode.dmPelsWidth!=window->dmPelsWidth || devMode.dmPelsHeight!=window->dmPelsHeight)
99 {
100 crDebug("Resolution changed(%d,%d), forcing window Pos/Size update", devMode.dmPelsWidth, devMode.dmPelsHeight);
101 window->dmPelsWidth = devMode.dmPelsWidth;
102 window->dmPelsHeight = devMode.dmPelsHeight;
103 bForceUpdate = true;
104 }
105 }
106#endif
107
108 stubUpdateWindowGeometry(window, bForceUpdate);
109
110#if defined(GLX) || defined (WINDOWS)
111 if (stub.trackWindowVisibleRgn)
112 {
113 stubUpdateWindowVisibileRegions(window);
114 }
115#endif
116
117 if (stub.trackWindowVisibility && window->type == CHROMIUM && window->drawable) {
118 const int mapped = stubIsWindowVisible(window);
119 if (mapped != window->mapped) {
120 crDebug("Dispatched: WindowShow(%i, %i)", window->spuWindow, mapped);
121 stub.spu->dispatch_table.WindowShow(window->spuWindow, mapped);
122 window->mapped = mapped;
123 }
124 }
125}
126
127
128/**
129 * Override the head SPU's glClear function.
130 * We're basically trapping this function so that we can poll the
131 * application window size at a regular interval.
132 */
133static void SPU_APIENTRY trapClear(GLbitfield mask)
134{
135 stubCheckWindowState();
136 /* call the original SPU glClear function */
137 origClear(mask);
138}
139
140/**
141 * As above, but for glViewport. Most apps call glViewport before
142 * glClear when a window is resized.
143 */
144static void SPU_APIENTRY trapViewport(GLint x, GLint y, GLsizei w, GLsizei h)
145{
146 stubCheckWindowState();
147 /* call the original SPU glViewport function */
148 origViewport(x, y, w, h);
149
150 /*
151 {
152 int winX, winY;
153 unsigned int winW, winH;
154 WindowInfo *pWindow;
155 pWindow = stub.currentContext->currentDrawable;
156 stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
157 origViewport(0, 0, winW, winH);
158 }
159 */
160}
161
162static void SPU_APIENTRY trapSwapBuffers(GLint window, GLint flags)
163{
164 stubCheckWindowState();
165 origSwapBuffers(window, flags);
166}
167
168static void SPU_APIENTRY trapDrawBuffer(GLenum buf)
169{
170 stubCheckWindowState();
171 origDrawBuffer(buf);
172}
173
174static void SPU_APIENTRY trapScissor(GLint x, GLint y, GLsizei w, GLsizei h)
175{
176 origScissor(x, y, w, h);
177
178 /*
179 {
180 int winX, winY;
181 unsigned int winW, winH;
182 WindowInfo *pWindow;
183 pWindow = stub.currentContext->currentDrawable;
184 stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
185 origScissor(0, 0, winW, winH);
186 }
187 */
188}
189
190/**
191 * Use the GL function pointers in <spu> to initialize the static glim
192 * dispatch table.
193 */
194static void stubInitSPUDispatch(SPU *spu)
195{
196 crSPUInitDispatchTable( &stub.spuDispatch );
197 crSPUCopyDispatchTable( &stub.spuDispatch, &(spu->dispatch_table) );
198
199 if (stub.trackWindowSize || stub.trackWindowPos || stub.trackWindowVisibleRgn) {
200 /* patch-in special glClear/Viewport function to track window sizing */
201 origClear = stub.spuDispatch.Clear;
202 origViewport = stub.spuDispatch.Viewport;
203 origSwapBuffers = stub.spuDispatch.SwapBuffers;
204 origDrawBuffer = stub.spuDispatch.DrawBuffer;
205 origScissor = stub.spuDispatch.Scissor;
206 stub.spuDispatch.Clear = trapClear;
207 stub.spuDispatch.Viewport = trapViewport;
208 /*stub.spuDispatch.Scissor = trapScissor;*/
209 /*stub.spuDispatch.SwapBuffers = trapSwapBuffers;
210 stub.spuDispatch.DrawBuffer = trapDrawBuffer;*/
211 }
212
213 crSPUCopyDispatchTable( &glim, &stub.spuDispatch );
214}
215
216// Callback function, used to destroy all created contexts
217static void hsWalkStubDestroyContexts(unsigned long key, void *data1, void *data2)
218{
219 stubDestroyContext(key);
220}
221
222/**
223 * This is called when we exit.
224 * We call all the SPU's cleanup functions.
225 */
226static void stubSPUTearDown(void)
227{
228 crDebug("stubSPUTearDown");
229 if (!stub_initialized) return;
230
231 stub_initialized = 0;
232
233#ifdef WINDOWS
234 stubUninstallWindowMessageHook();
235#endif
236
237 //delete all created contexts
238 stubMakeCurrent( NULL, NULL);
239 crHashtableWalk(stub.contextTable, hsWalkStubDestroyContexts, NULL);
240
241 /* shutdown, now trap any calls to a NULL dispatcher */
242 crSPUCopyDispatchTable(&glim, &stubNULLDispatch);
243
244 crSPUUnloadChain(stub.spu);
245 stub.spu = NULL;
246
247#ifndef Linux
248 crUnloadOpenGL();
249#endif
250
251 crNetTearDown();
252
253#ifdef GLX
254 if (stub.xshmSI.shmid>=0)
255 {
256 shmctl(stub.xshmSI.shmid, IPC_RMID, 0);
257 shmdt(stub.xshmSI.shmaddr);
258 }
259#endif
260
261 crMemset(&stub, 0, sizeof(stub) );
262}
263
264static void stubSPUSafeTearDown(void)
265{
266#ifdef CHROMIUM_THREADSAFE
267 CRmutex *mutex;
268#endif
269
270 if (!stub_initialized) return;
271 stub_initialized = 0;
272
273#ifdef CHROMIUM_THREADSAFE
274 mutex = &stub.mutex;
275 crLockMutex(mutex);
276#endif
277 crDebug("stubSPUSafeTearDown");
278 crNetTearDown();
279#ifdef WINDOWS
280 stubUninstallWindowMessageHook();
281#endif
282 crMemset(&stub, 0, sizeof(stub));
283#ifdef CHROMIUM_THREADSAFE
284 crUnlockMutex(mutex);
285 crFreeMutex(mutex);
286#endif
287}
288
289
290static void stubExitHandler(void)
291{
292 stubSPUSafeTearDown();
293}
294
295/**
296 * Called when we receive a SIGTERM signal.
297 */
298static void stubSignalHandler(int signo)
299{
300 stubSPUSafeTearDown();
301 exit(0); /* this causes stubExitHandler() to be called */
302}
303
304
305/**
306 * Init variables in the stub structure, install signal handler.
307 */
308static void stubInitVars(void)
309{
310 WindowInfo *defaultWin;
311
312#ifdef CHROMIUM_THREADSAFE
313 crInitMutex(&stub.mutex);
314#endif
315
316 /* At the very least we want CR_RGB_BIT. */
317 stub.haveNativeOpenGL = GL_FALSE;
318 stub.spu = NULL;
319 stub.appDrawCursor = 0;
320 stub.minChromiumWindowWidth = 0;
321 stub.minChromiumWindowHeight = 0;
322 stub.maxChromiumWindowWidth = 0;
323 stub.maxChromiumWindowHeight = 0;
324 stub.matchChromiumWindowCount = 0;
325 stub.matchChromiumWindowID = NULL;
326 stub.matchWindowTitle = NULL;
327 stub.ignoreFreeglutMenus = 1;
328 stub.threadSafe = GL_FALSE;
329 stub.trackWindowSize = 0;
330 stub.trackWindowPos = 0;
331 stub.trackWindowVisibility = 0;
332 stub.trackWindowVisibleRgn = 0;
333 stub.mothershipPID = 0;
334 stub.spu_dir = NULL;
335
336 stub.freeContextNumber = MAGIC_CONTEXT_BASE;
337 stub.contextTable = crAllocHashtable();
338 stub.currentContext = NULL;
339
340 stub.windowTable = crAllocHashtable();
341
342 defaultWin = (WindowInfo *) crCalloc(sizeof(WindowInfo));
343 defaultWin->type = CHROMIUM;
344 defaultWin->spuWindow = 0; /* window 0 always exists */
345#ifdef WINDOWS
346 defaultWin->hVisibleRegion = INVALID_HANDLE_VALUE;
347#elif defined(GLX)
348 defaultWin->pVisibleRegions = NULL;
349 defaultWin->cVisibleRegions = 0;
350#endif
351 crHashtableAdd(stub.windowTable, 0, defaultWin);
352
353#if 1
354 atexit(stubExitHandler);
355 signal(SIGTERM, stubSignalHandler);
356 signal(SIGINT, stubSignalHandler);
357#ifndef WINDOWS
358 signal(SIGPIPE, SIG_IGN); /* the networking code should catch this */
359#endif
360#else
361 (void) stubExitHandler;
362 (void) stubSignalHandler;
363#endif
364}
365
366
367/**
368 * Return a free port number for the mothership to use, or -1 if we
369 * can't find one.
370 */
371static int
372GenerateMothershipPort(void)
373{
374 const int MAX_PORT = 10100;
375 unsigned short port;
376
377 /* generate initial port number randomly */
378 crRandAutoSeed();
379 port = (unsigned short) crRandInt(10001, MAX_PORT);
380
381#ifdef WINDOWS
382 /* XXX should implement a free port check here */
383 return port;
384#else
385 /*
386 * See if this port number really is free, try another if needed.
387 */
388 {
389 struct sockaddr_in servaddr;
390 int so_reuseaddr = 1;
391 int sock, k;
392
393 /* create socket */
394 sock = socket(AF_INET, SOCK_STREAM, 0);
395 CRASSERT(sock > 2);
396
397 /* deallocate socket/port when we exit */
398 k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
399 (char *) &so_reuseaddr, sizeof(so_reuseaddr));
400 CRASSERT(k == 0);
401
402 /* initialize the servaddr struct */
403 crMemset(&servaddr, 0, sizeof(servaddr) );
404 servaddr.sin_family = AF_INET;
405 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
406
407 while (port < MAX_PORT) {
408 /* Bind to the given port number, return -1 if we fail */
409 servaddr.sin_port = htons((unsigned short) port);
410 k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
411 if (k) {
412 /* failed to create port. try next one. */
413 port++;
414 }
415 else {
416 /* free the socket/port now so mothership can make it */
417 close(sock);
418 return port;
419 }
420 }
421 }
422#endif /* WINDOWS */
423 return -1;
424}
425
426
427/**
428 * Try to determine which mothership configuration to use for this program.
429 */
430static char **
431LookupMothershipConfig(const char *procName)
432{
433 const int procNameLen = crStrlen(procName);
434 FILE *f;
435 const char *home;
436 char configPath[1000];
437
438 /* first, check if the CR_CONFIG env var is set */
439 {
440 const char *conf = crGetenv("CR_CONFIG");
441 if (conf && crStrlen(conf) > 0)
442 return crStrSplit(conf, " ");
443 }
444
445 /* second, look up config name from config file */
446 home = crGetenv("HOME");
447 if (home)
448 sprintf(configPath, "%s/%s", home, CONFIG_LOOKUP_FILE);
449 else
450 crStrcpy(configPath, CONFIG_LOOKUP_FILE); /* from current dir */
451 /* Check if the CR_CONFIG_PATH env var is set. */
452 {
453 const char *conf = crGetenv("CR_CONFIG_PATH");
454 if (conf)
455 crStrcpy(configPath, conf); /* from env var */
456 }
457
458 f = fopen(configPath, "r");
459 if (!f) {
460 return NULL;
461 }
462
463 while (!feof(f)) {
464 char line[1000];
465 char **args;
466 fgets(line, 999, f);
467 line[crStrlen(line) - 1] = 0; /* remove trailing newline */
468 if (crStrncmp(line, procName, procNameLen) == 0 &&
469 (line[procNameLen] == ' ' || line[procNameLen] == '\t'))
470 {
471 crWarning("Using Chromium configuration for %s from %s",
472 procName, configPath);
473 args = crStrSplit(line + procNameLen + 1, " ");
474 return args;
475 }
476 }
477 fclose(f);
478 return NULL;
479}
480
481
482static int Mothership_Awake = 0;
483
484
485/**
486 * Signal handler to determine when mothership is ready.
487 */
488static void
489MothershipPhoneHome(int signo)
490{
491 crDebug("Got signal %d: mothership is awake!", signo);
492 Mothership_Awake = 1;
493}
494
495void stubSetDefaultConfigurationOptions(void)
496{
497 unsigned char key[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
498
499 stub.appDrawCursor = 0;
500 stub.minChromiumWindowWidth = 0;
501 stub.minChromiumWindowHeight = 0;
502 stub.maxChromiumWindowWidth = 0;
503 stub.maxChromiumWindowHeight = 0;
504 stub.matchChromiumWindowID = NULL;
505 stub.numIgnoreWindowID = 0;
506 stub.matchWindowTitle = NULL;
507 stub.ignoreFreeglutMenus = 1;
508 stub.trackWindowSize = 1;
509 stub.trackWindowPos = 1;
510 stub.trackWindowVisibility = 1;
511 stub.trackWindowVisibleRgn = 1;
512 stub.matchChromiumWindowCount = 0;
513 stub.spu_dir = NULL;
514 crNetSetRank(0);
515 crNetSetContextRange(32, 35);
516 crNetSetNodeRange("iam0", "iamvis20");
517 crNetSetKey(key,sizeof(key));
518 stub.force_pbuffers = 0;
519}
520
521/**
522 * Do one-time initializations for the faker.
523 * Returns TRUE on success, FALSE otherwise.
524 */
525bool
526stubInit(void)
527{
528 /* Here is where we contact the mothership to find out what we're supposed
529 * to be doing. Networking code in a DLL initializer. I sure hope this
530 * works :)
531 *
532 * HOW can I pass the mothership address to this if I already know it?
533 */
534
535 CRConnection *conn = NULL;
536 char response[1024];
537 char **spuchain;
538 int num_spus;
539 int *spu_ids;
540 char **spu_names;
541 const char *app_id;
542 int i;
543
544 if (stub_initialized)
545 return true;
546
547 stubInitVars();
548
549 /* @todo check if it'd be of any use on other than guests, no use for windows */
550 app_id = crGetenv( "CR_APPLICATION_ID_NUMBER" );
551
552 crNetInit( NULL, NULL );
553
554#ifndef WINDOWS
555 {
556 CRNetServer ns;
557
558 ns.name = "vboxhgcm://host:0";
559 ns.buffer_size = 1024;
560 crNetServerConnect(&ns);
561 if (!ns.conn)
562 {
563 crWarning("Failed to connect to host. Make sure 3D acceleration is enabled for this VM.");
564 return false;
565 }
566 else
567 {
568 crNetFreeConnection(ns.conn);
569 }
570 }
571#endif
572
573 strcpy(response, "3 0 array 1 feedback 2 pack");
574 spuchain = crStrSplit( response, " " );
575 num_spus = crStrToInt( spuchain[0] );
576 spu_ids = (int *) crAlloc( num_spus * sizeof( *spu_ids ) );
577 spu_names = (char **) crAlloc( num_spus * sizeof( *spu_names ) );
578 for (i = 0 ; i < num_spus ; i++)
579 {
580 spu_ids[i] = crStrToInt( spuchain[2*i+1] );
581 spu_names[i] = crStrdup( spuchain[2*i+2] );
582 crDebug( "SPU %d/%d: (%d) \"%s\"", i+1, num_spus, spu_ids[i], spu_names[i] );
583 }
584
585 stubSetDefaultConfigurationOptions();
586
587 stub.spu = crSPULoadChain( num_spus, spu_ids, spu_names, stub.spu_dir, NULL );
588
589 crFree( spuchain );
590 crFree( spu_ids );
591 for (i = 0; i < num_spus; ++i)
592 crFree(spu_names[i]);
593 crFree( spu_names );
594
595 // spu chain load failed somewhere
596 if (!stub.spu) {
597 return false;
598 }
599
600 crSPUInitDispatchTable( &glim );
601
602 /* This is unlikely to change -- We still want to initialize our dispatch
603 * table with the functions of the first SPU in the chain. */
604 stubInitSPUDispatch( stub.spu );
605
606 /* we need to plug one special stub function into the dispatch table */
607 glim.GetChromiumParametervCR = stub_GetChromiumParametervCR;
608
609#if !defined(VBOX_NO_NATIVEGL)
610 /* Load pointers to native OpenGL functions into stub.nativeDispatch */
611 stubInitNativeDispatch();
612#endif
613
614/*crDebug("stub init");
615raise(SIGINT);*/
616
617#ifdef WINDOWS
618 stubInstallWindowMessageHook();
619#endif
620
621#ifdef GLX
622 stub.xshmSI.shmid = -1;
623 stub.bShmInitFailed = GL_FALSE;
624#endif
625
626 stub_initialized = 1;
627 return true;
628}
629
630
631
632/* Sigh -- we can't do initialization at load time, since Windows forbids
633 * the loading of other libraries from DLLMain. */
634
635#ifdef LINUX
636/* GCC crap
637 *void (*stub_init_ptr)(void) __attribute__((section(".ctors"))) = __stubInit; */
638#endif
639
640#ifdef WINDOWS
641#define WIN32_LEAN_AND_MEAN
642#include <windows.h>
643
644/* Windows crap */
645BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
646{
647 (void) lpvReserved;
648
649 switch (fdwReason)
650 {
651 case DLL_PROCESS_ATTACH:
652 {
653 CRNetServer ns;
654
655 crNetInit(NULL, NULL);
656 ns.name = "vboxhgcm://host:0";
657 ns.buffer_size = 1024;
658 crNetServerConnect(&ns);
659 if (!ns.conn)
660 {
661 crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load.");
662 return FALSE;
663 }
664 else
665 crNetFreeConnection(ns.conn);
666
667 break;
668 }
669
670 case DLL_PROCESS_DETACH:
671 {
672 stubSPUSafeTearDown();
673 break;
674 }
675
676 case DLL_THREAD_ATTACH:
677 break;
678
679 case DLL_THREAD_DETACH:
680 break;
681
682 default:
683 break;
684 }
685
686 return TRUE;
687}
688#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