VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/crOpenGL/load.c@ 16381

Last change on this file since 16381 was 16381, checked in by vboxsync, 16 years ago

crOpenGL: some initial functionality on linux

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