load.c revision a051bdf4014b39aee0375b4a6df8f8cb7e11ece8
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* Copyright (c) 2001, Stanford University
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * All rights reserved
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * See the file LICENSE.txt for information on redistributing this software.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * If you change this, see the comments in tilesortspu_context.c
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic char* gsViewportHackApps[] = {"googleearth.exe", NULL};
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int stub_initialized = 0;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* NOTE: 'SPUDispatchTable glim' is declared in NULLfuncs.py now */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* NOTE: 'SPUDispatchTable stubThreadsafeDispatch' is declared in tsfuncs.c */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void stubInitNativeDispatch( void )
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync numFuncs = crLoadOpenGL( &stub.wsInterface, gl_funcs );
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* XXX call this after context binding */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync numFuncs += crLoadOpenGLExtensions( &stub.wsInterface, gl_funcs + numFuncs );
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crSPUInitDispatch( &stub.nativeDispatch, gl_funcs );
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/** Pointer to the SPU's real glClear and glViewport functions */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void stubCheckWindowState(WindowInfo *window, GLboolean bFlushOnChange)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync bool bForceUpdate = false;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync bool bChanged = false;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* @todo install hook and track for WM_DISPLAYCHANGE */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (devMode.dmPelsWidth!=window->dmPelsWidth || devMode.dmPelsHeight!=window->dmPelsHeight)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crDebug("Resolution changed(%d,%d), forcing window Pos/Size update", devMode.dmPelsWidth, devMode.dmPelsHeight);
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync bChanged = stubUpdateWindowGeometry(window, bForceUpdate) || bForceUpdate;
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync bChanged = stubUpdateWindowVisibileRegions(window) || bChanged;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (stub.trackWindowVisibility && window->type == CHROMIUM && window->drawable) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crDebug("Dispatched: WindowShow(%i, %i)", window->spuWindow, mapped);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync stub.spu->dispatch_table.WindowShow(window->spuWindow, mapped);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic bool stubSystemWindowExist(WindowInfo *pWindow)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return false;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!XGetGeometry(dpy, pWindow->drawable, &root, &x, &y, &w, &h, &border, &depth))
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return false;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return true;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void stubCheckWindowsCB(unsigned long key, void *data1, void *data2)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void stubCheckWindowsState(void)
241adddf415cbdf66230864a215b24415f482e72vboxsync CRASSERT(stub.trackWindowSize || stub.trackWindowPos);
241adddf415cbdf66230864a215b24415f482e72vboxsync stubCheckWindowState(stub.currentContext->currentDrawable, GL_TRUE);
241adddf415cbdf66230864a215b24415f482e72vboxsync crHashtableWalk(stub.windowTable, stubCheckWindowsCB, stub.currentContext);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Override the head SPU's glClear function.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * We're basically trapping this function so that we can poll the
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync * application window size at a regular interval.
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync /* call the original SPU glClear function */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * As above, but for glViewport. Most apps call glViewport before
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * glClear when a window is resized.
241adddf415cbdf66230864a215b24415f482e72vboxsyncstatic void SPU_APIENTRY trapViewport(GLint x, GLint y, GLsizei w, GLsizei h)
241adddf415cbdf66230864a215b24415f482e72vboxsync /* call the original SPU glViewport function */
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsyncstatic void SPU_APIENTRY trapSwapBuffers(GLint window, GLint flags)
241adddf415cbdf66230864a215b24415f482e72vboxsyncstatic void SPU_APIENTRY trapScissor(GLint x, GLint y, GLsizei w, GLsizei h)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Use the GL function pointers in <spu> to initialize the static glim
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * dispatch table.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crSPUCopyDispatchTable( &stub.spuDispatch, &(spu->dispatch_table) );
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (stub.trackWindowSize || stub.trackWindowPos || stub.trackWindowVisibleRgn) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* patch-in special glClear/Viewport function to track window sizing */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*stub.spuDispatch.SwapBuffers = trapSwapBuffers;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync stub.spuDispatch.DrawBuffer = trapDrawBuffer;*/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crSPUCopyDispatchTable( &glim, &stub.spuDispatch );
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync// Callback function, used to destroy all created contexts
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void hsWalkStubDestroyContexts(unsigned long key, void *data1, void *data2)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * This is called when we exit.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * We call all the SPU's cleanup functions.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void stubSPUTearDown(void)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync //delete all created contexts
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crHashtableWalk(stub.contextTable, hsWalkStubDestroyContexts, NULL);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* shutdown, now trap any calls to a NULL dispatcher */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void stubSPUSafeTearDown(void)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (RTThreadGetState(stub.hSyncThread)!=RTTHREADSTATE_TERMINATED)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (PostThreadMessage(RTThreadGetNative(stub.hSyncThread), WM_QUIT, 0, 0))
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crDebug("Sync thread killed before DLL_PROCESS_DETACH");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void stubExitHandler(void)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Called when we receive a SIGTERM signal.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync exit(0); /* this causes stubExitHandler() to be called */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Init variables in the stub structure, install signal handler.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void stubInitVars(void)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* At the very least we want CR_RGB_BIT. */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync defaultWin = (WindowInfo *) crCalloc(sizeof(WindowInfo));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync defaultWin->spuWindow = 0; /* window 0 always exists */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync signal(SIGPIPE, SIG_IGN); /* the networking code should catch this */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Return a free port number for the mothership to use, or -1 if we
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * can't find one.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync unsigned short port;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* generate initial port number randomly */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync port = (unsigned short) crRandInt(10001, MAX_PORT);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* XXX should implement a free port check here */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * See if this port number really is free, try another if needed.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* create socket */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* deallocate socket/port when we exit */
223935479ac42db56b7b7a7d16548d590022996avboxsync /* initialize the servaddr struct */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* Bind to the given port number, return -1 if we fail */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* failed to create port. try next one. */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* free the socket/port now so mothership can make it */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif /* WINDOWS */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Try to determine which mothership configuration to use for this program.
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsyncstatic char **
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync const char *home;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* first, check if the CR_CONFIG env var is set */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* second, look up config name from config file */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync sprintf(configPath, "%s/%s", home, CONFIG_LOOKUP_FILE);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crStrcpy(configPath, CONFIG_LOOKUP_FILE); /* from current dir */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* Check if the CR_CONFIG_PATH env var is set. */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync while (!feof(f)) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync line[crStrlen(line) - 1] = 0; /* remove trailing newline */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (line[procNameLen] == ' ' || line[procNameLen] == '\t'))
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crWarning("Using Chromium configuration for %s from %s",
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic int Mothership_Awake = 0;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Signal handler to determine when mothership is ready.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crDebug("Got signal %d: mothership is awake!", signo);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync unsigned char key[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* Apply viewport hack only if we're running under wine */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for (i=0; gsViewportHackApps[i]; ++i)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void stubSyncTrCheckWindowsCB(unsigned long key, void *data1, void *data2)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (pWindow->type!=CHROMIUM || pWindow->spuWindow==0)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /*No need to flush here as crWindowDestroy does it*/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic DECLCALLBACK(int) stubSyncThreadProc(RTTHREAD ThreadSelf, void *pvUser)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync stub.spu->dispatch_table.VBoxPackSetInjectThread();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Do one-time initializations for the faker.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Returns TRUE on success, FALSE otherwise.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* Here is where we contact the mothership to find out what we're supposed
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * to be doing. Networking code in a DLL initializer. I sure hope this
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * HOW can I pass the mothership address to this if I already know it?
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync const char *app_id;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return true;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* @todo check if it'd be of any use on other than guests, no use for windows */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crWarning("Failed to connect to host. Make sure 3D acceleration is enabled for this VM.");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return false;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#if 0 && defined(CR_NEWWINTRACK)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync spu_ids = (int *) crAlloc( num_spus * sizeof( *spu_ids ) );
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync spu_names = (char **) crAlloc( num_spus * sizeof( *spu_names ) );
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for (i = 0 ; i < num_spus ; i++)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crDebug( "SPU %d/%d: (%d) \"%s\"", i+1, num_spus, spu_ids[i], spu_names[i] );
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync stub.spu = crSPULoadChain( num_spus, spu_ids, spu_names, stub.spu_dir, NULL );
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for (i = 0; i < num_spus; ++i)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // spu chain load failed somewhere
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return false;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* This is unlikely to change -- We still want to initialize our dispatch
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * table with the functions of the first SPU in the chain. */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* we need to plug one special stub function into the dispatch table */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync glim.GetChromiumParametervCR = stub_GetChromiumParametervCR;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* Load pointers to native OpenGL functions into stub.nativeDispatch */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/*crDebug("stub init");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncraise(SIGINT);*/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync rc = RTThreadCreate(&stub.hSyncThread, stubSyncThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Sync");
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return true;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* Sigh -- we can't do initialization at load time, since Windows forbids
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * the loading of other libraries from DLLMain. */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync *void (*stub_init_ptr)(void) __attribute__((section(".ctors"))) = __stubInit; */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* Windows crap */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncBOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load.");