VirtualBox

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

最後變更 在這個檔案從16710是 16640,由 vboxsync 提交於 16 年 前

crOpenGL: use shared memory to access xserver pixmaps data

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

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