/** * Return the suffix to put onto hostnames to address the IB/SDP interface. * We'll check the CR_SDP_SUFFIX env var the first time called. * Note: "sdp" is the default. */ const char * crGetSDPHostnameSuffix(void) { static const char *suffix = NULL; if (!suffix) { suffix = crGetenv("CR_SDP_SUFFIX"); if (!suffix) suffix = "sdp"; } return suffix; }
void crStateError( int line, const char *file, GLenum error, const char *format, ... ) { CRContext *g = GetCurrentContext(); char errstr[8096]; va_list args; CRASSERT(error != GL_NO_ERROR); if (g->error == GL_NO_ERROR) g->error = error; #ifndef DEBUG_misha if (crGetenv("CR_DEBUG")) #endif { char *glerr; va_start( args, format ); vsprintf( errstr, format, args ); va_end( args ); switch (error) { case GL_NO_ERROR: glerr = "GL_NO_ERROR"; break; case GL_INVALID_VALUE: glerr = "GL_INVALID_VALUE"; break; case GL_INVALID_ENUM: glerr = "GL_INVALID_ENUM"; break; case GL_INVALID_OPERATION: glerr = "GL_INVALID_OPERATION"; break; case GL_STACK_OVERFLOW: glerr = "GL_STACK_OVERFLOW"; break; case GL_STACK_UNDERFLOW: glerr = "GL_STACK_UNDERFLOW"; break; case GL_OUT_OF_MEMORY: glerr = "GL_OUT_OF_MEMORY"; break; case GL_TABLE_TOO_LARGE: glerr = "GL_TABLE_TOO_LARGE"; break; default: glerr = "unknown"; break; } crWarning( "OpenGL error in %s, line %d: %s: %s\n", file, line, glerr, errstr ); } }
CRConnection *crMothershipConnect( void ) { const char *mother_server; crNetInit( NULL, NULL ); mother_server = crGetenv( "CRMOTHERSHIP" ); if (!mother_server) { crWarning( "Couldn't find the CRMOTHERSHIP environment variable, defaulting to localhost" ); mother_server = "localhost"; } return crNetConnectToServer( mother_server, DEFAULT_MOTHERSHIP_PORT, 8096, 0 ); }
DECLEXPORT(void) crError(const char *pszFormat, ...) { va_list va; #ifdef WINDOWS DWORD dwLastErr; #endif #ifdef WINDOWS /* Log last error on windows. */ dwLastErr = GetLastError(); if (dwLastErr != 0 && crGetenv("CR_WINDOWS_ERRORS") != NULL) { LPTSTR pszWindowsMessage; SetLastError(0); FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, dwLastErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&pszWindowsMessage, 0, NULL); if (pszWindowsMessage) { logMessage("OpenGL, Windows error: ", "%u\n%s", dwLastErr, pszWindowsMessage); LocalFree(pszWindowsMessage); } else logMessage("OpenGL, Windows error: ", "%u", dwLastErr); } #endif /* The message. */ va_start(va, pszFormat); logMessageV("OpenGL Error: ", pszFormat, va); va_end(va); #ifdef DEBUG /* Let's interrupt App execution only on debug builds and return * bad status to upper level on release ones. */ # ifdef IN_GUEST /* Trigger debugger's breakpoint handler. */ ASMBreakpoint(); # else /* Dump core or activate the debugger in debug builds. */ AssertFailed(); # endif #endif /* DEBUG */ }
static void set_display_string( RenderSPU *render_spu, const char *response ) { if (!crStrcmp(response, "DEFAULT")) { const char *display = crGetenv("DISPLAY"); if (display) crStrncpy(render_spu->display_string, display, sizeof(render_spu->display_string)); else crStrcpy(render_spu->display_string, ""); /* empty string */ } else { crStrncpy(render_spu->display_string, response, sizeof(render_spu->display_string)); } }
/* * This function is called by the packer functions when it detects and * OpenGL error. */ void __PackError( int line, const char *file, GLenum error, const char *info) { CR_GET_PACKER_CONTEXT(pc); if (pc->Error) pc->Error( line, file, error, info ); if (crGetenv("CR_DEBUG")) { char *glerr; switch (error) { case GL_NO_ERROR: glerr = "GL_NO_ERROR"; break; case GL_INVALID_VALUE: glerr = "GL_INVALID_VALUE"; break; case GL_INVALID_ENUM: glerr = "GL_INVALID_ENUM"; break; case GL_INVALID_OPERATION: glerr = "GL_INVALID_OPERATION"; break; case GL_STACK_OVERFLOW: glerr = "GL_STACK_OVERFLOW"; break; case GL_STACK_UNDERFLOW: glerr = "GL_STACK_UNDERFLOW"; break; case GL_OUT_OF_MEMORY: glerr = "GL_OUT_OF_MEMORY"; break; case GL_TABLE_TOO_LARGE: glerr = "GL_TABLE_TOO_LARGE"; break; default: glerr = "unknown"; break; } crWarning( "GL error in packer: %s, line %d: %s: %s", file, line, glerr, info ); } }
CRConnection *__copy_of_crMothershipConnect( void ) { CRConnection *conn; const char *mother_server = NULL; crNetInit( NULL, NULL ); mother_server = crGetenv( "CRMOTHERSHIP" ); if (!mother_server) { crWarning( "Couldn't find the CRMOTHERSHIP environment variable, defaulting to localhost" ); mother_server = "localhost"; } conn = crNetConnectToServer( mother_server, DEFAULT_MOTHERSHIP_PORT, 8096, 0 ); if (!conn) crError("Failed to connect to mothership\n"); return conn; }
/** * Do one-time initializations for the faker. * Returns TRUE on success, FALSE otherwise. */ static bool stubInitLocked(void) { /* Here is where we contact the mothership to find out what we're supposed * to be doing. Networking code in a DLL initializer. I sure hope this * works :) * * HOW can I pass the mothership address to this if I already know it? */ CRConnection *conn = NULL; char response[1024]; char **spuchain; int num_spus; int *spu_ids; char **spu_names; const char *app_id; int i; int disable_sync = 0; stubInitVars(); crGetProcName(response, 1024); crDebug("Stub launched for %s", response); #if defined(CR_NEWWINTRACK) && !defined(WINDOWS) /*@todo when vm boots with compiz turned on, new code causes hang in xcb_wait_for_reply in the sync thread * as at the start compiz runs our code under XGrabServer. */ if (!crStrcmp(response, "compiz") || !crStrcmp(response, "compiz_real") || !crStrcmp(response, "compiz.real") || !crStrcmp(response, "compiz-bin")) { disable_sync = 1; } #elif defined(WINDOWS) && defined(VBOX_WITH_WDDM) && defined(VBOX_WDDM_MINIPORT_WITH_VISIBLE_RECTS) if (GetModuleHandle(VBOX_MODNAME_DISPD3D)) { disable_sync = 1; crDebug("running with " VBOX_MODNAME_DISPD3D); stub.trackWindowVisibleRgn = 0; stub.bRunningUnderWDDM = true; } #endif /* @todo check if it'd be of any use on other than guests, no use for windows */ app_id = crGetenv( "CR_APPLICATION_ID_NUMBER" ); crNetInit( NULL, NULL ); #ifndef WINDOWS { CRNetServer ns; ns.name = "vboxhgcm://host:0"; ns.buffer_size = 1024; crNetServerConnect(&ns #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) , NULL #endif ); if (!ns.conn) { crWarning("Failed to connect to host. Make sure 3D acceleration is enabled for this VM."); return false; } else { crNetFreeConnection(ns.conn); } #if 0 && defined(CR_NEWWINTRACK) { Status st = XInitThreads(); if (st==0) { crWarning("XInitThreads returned %i", (int)st); } } #endif } #endif strcpy(response, "2 0 feedback 1 pack"); spuchain = crStrSplit( response, " " ); num_spus = crStrToInt( spuchain[0] ); spu_ids = (int *) crAlloc( num_spus * sizeof( *spu_ids ) ); spu_names = (char **) crAlloc( num_spus * sizeof( *spu_names ) ); for (i = 0 ; i < num_spus ; i++) { spu_ids[i] = crStrToInt( spuchain[2*i+1] ); spu_names[i] = crStrdup( spuchain[2*i+2] ); crDebug( "SPU %d/%d: (%d) \"%s\"", i+1, num_spus, spu_ids[i], spu_names[i] ); } stubSetDefaultConfigurationOptions(); stub.spu = crSPULoadChain( num_spus, spu_ids, spu_names, stub.spu_dir, NULL ); crFree( spuchain ); crFree( spu_ids ); for (i = 0; i < num_spus; ++i) crFree(spu_names[i]); crFree( spu_names ); // spu chain load failed somewhere if (!stub.spu) { return false; } crSPUInitDispatchTable( &glim ); /* This is unlikely to change -- We still want to initialize our dispatch * table with the functions of the first SPU in the chain. */ stubInitSPUDispatch( stub.spu ); /* we need to plug one special stub function into the dispatch table */ glim.GetChromiumParametervCR = stub_GetChromiumParametervCR; #if !defined(VBOX_NO_NATIVEGL) /* Load pointers to native OpenGL functions into stub.nativeDispatch */ stubInitNativeDispatch(); #endif /*crDebug("stub init"); raise(SIGINT);*/ #ifdef WINDOWS # ifndef CR_NEWWINTRACK stubInstallWindowMessageHook(); # endif #endif #ifdef CR_NEWWINTRACK { int rc; RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE); if (!disable_sync) { crDebug("Starting sync thread"); rc = RTThreadCreate(&stub.hSyncThread, stubSyncThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Sync"); if (RT_FAILURE(rc)) { crError("Failed to start sync thread! (%x)", rc); } RTThreadUserWait(stub.hSyncThread, 60 * 1000); RTThreadUserReset(stub.hSyncThread); crDebug("Going on"); } } #endif #ifdef GLX stub.xshmSI.shmid = -1; stub.bShmInitFailed = GL_FALSE; stub.pGLXPixmapsHash = crAllocHashtable(); stub.bXExtensionsChecked = GL_FALSE; stub.bHaveXComposite = GL_FALSE; stub.bHaveXFixes = GL_FALSE; #endif return true; }
void crServerSetVBoxConfiguration() { CRMuralInfo *defaultMural; char response[8096]; char **spuchain; int num_spus; int *spu_ids; char **spu_names; char *spu_dir = NULL; int i; /* Quadrics defaults */ int my_rank = 0; int low_context = CR_QUADRICS_DEFAULT_LOW_CONTEXT; int high_context = CR_QUADRICS_DEFAULT_HIGH_CONTEXT; unsigned char key[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; char hostname[1024]; char **clientchain, **clientlist; GLint dims[4]; const char * env; defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0); CRASSERT(defaultMural); setDefaults(); /* * Get my hostname */ if (crGetHostname(hostname, sizeof(hostname))) { crError("CRServer: Couldn't get my own hostname?"); } strcpy(response, "1 0 render"); crDebug("CRServer: my SPU chain: %s", response); /* response will describe the SPU chain. * Example "2 5 wet 6 render" */ spuchain = crStrSplit(response, " "); num_spus = crStrToInt(spuchain[0]); spu_ids = (int *) crAlloc(num_spus * sizeof(*spu_ids)); spu_names = (char **) crAlloc((num_spus + 1) * sizeof(*spu_names)); for (i = 0; i < num_spus; i++) { spu_ids[i] = crStrToInt(spuchain[2 * i + 1]); spu_names[i] = crStrdup(spuchain[2 * i + 2]); crDebug("SPU %d/%d: (%d) \"%s\"", i + 1, num_spus, spu_ids[i], spu_names[i]); } spu_names[i] = NULL; //spu_dir = crStrdup(response); crNetSetRank(0); crNetSetContextRange(32, 35); crNetSetNodeRange("iam0", "iamvis20"); crNetSetKey(key,sizeof(key)); crNetSetKey(key,sizeof(key)); cr_server.tcpip_port = 7000; /*cr_server.optimizeBucket = crStrToInt(response); cr_server.localTileSpec = crStrToInt(response); cr_server.useL2 = crStrToInt(response); cr_server.ignore_papi = crStrToInt(response); if (crMothershipGetServerParam(conn, response, "overlap_blending")) { if (!crStrcmp(response, "blend")) cr_server.overlapBlending = 1; else if (!crStrcmp(response, "knockout")) cr_server.overlapBlending = 2; } if (crMothershipGetServerParam(conn, response, "overlap_levels")) cr_server.only_swap_once = crStrToInt(response); cr_server.debug_barriers = crStrToInt(response); cr_server.sharedDisplayLists = crStrToInt(response); cr_server.sharedTextureObjects = crStrToInt(response); cr_server.sharedPrograms = crStrToInt(response); cr_server.sharedWindows = crStrToInt(response); cr_server.uniqueWindows = crStrToInt(response); cr_server.useDMX = crStrToInt(response); if (crMothershipGetServerParam(conn, response, "vertprog_projection_param")) if (crMothershipGetServerParam(conn, response, "stereo_view")) if (crMothershipGetServerParam(conn, response, "view_matrix")) if (crMothershipGetServerParam(conn, response, "right_view_matrix")) if (crMothershipGetServerParam(conn, response, "projection_matrix")) if (crMothershipGetServerParam(conn, response, "right_projection_matrix"))*/ crDebug("CRServer: my port number is %d", cr_server.tcpip_port); /* * Load the SPUs */ cr_server.head_spu = crSPULoadChain(num_spus, spu_ids, spu_names, spu_dir, &cr_server); env = crGetenv( "CR_SERVER_DEFAULT_RENDER_TYPE" ); if (env != NULL) { GLubyte redir = (env[0] - 0x30); if (redir <= CR_SERVER_REDIR_MAXVAL) { int rc = crServerSetOffscreenRenderingMode(redir); if (!RT_SUCCESS(rc)) crWarning("offscreen rendering unsupported, no offscreen rendering will be used.."); } else crWarning("invalid redir option %c", redir); } #if defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS) || defined(GLX) else { int rc = crServerSetOffscreenRenderingMode(CR_SERVER_REDIR_FBO_BLT); if (!RT_SUCCESS(rc)) crWarning("offscreen rendering unsupported, no offscreen rendering will be used.."); } #endif cr_server.bOffscreenRenderingDefault = cr_server.bForceOffscreenRendering; /* Need to do this as early as possible */ cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_POSITION_CR, 0, GL_INT, 2, &dims[0]); cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, 0, GL_INT, 2, &dims[2]); defaultMural->gX = dims[0]; defaultMural->gY = dims[1]; defaultMural->width = dims[2]; defaultMural->height = dims[3]; crFree(spu_ids); crFreeStrings(spu_names); crFreeStrings(spuchain); if (spu_dir) crFree(spu_dir); cr_server.mtu = 1024 * 30; /* * Get a list of all the clients talking to me. */ if (cr_server.vncMode) { /* we're inside a vnc viewer */ /*if (!crMothershipSendString( conn, response, "getvncclient %s", hostname )) crError( "Bad Mothership response: %s", response );*/ } else { //crMothershipGetClients(conn, response); strcpy(response, "1 tcpip 1"); } crDebug("CRServer: my clients: %s", response); /* * 'response' will now contain a number indicating the number of clients * of this server, followed by a comma-separated list of protocol/SPU ID * pairs. * Example: "3 tcpip 1,gm 2,via 10" */ clientchain = crStrSplitn(response, " ", 1); cr_server.numClients = crStrToInt(clientchain[0]); if (cr_server.numClients == 0) { crError("I have no clients! What's a poor server to do?"); } clientlist = crStrSplit(clientchain[1], ","); /* * Connect to initial set of clients. * Call crNetAcceptClient() for each client. * Also, look for a client that's _not_ using the file: protocol. */ for (i = 0; i < cr_server.numClients; i++) { CRClient *newClient = (CRClient *) crCalloc(sizeof(CRClient)); #ifdef VBOX sscanf(clientlist[i], "%1023s %d", cr_server.protocol, &(newClient->spu_id)); #else sscanf(clientlist[i], "%s %d", cr_server.protocol, &(newClient->spu_id)); #endif newClient->conn = crNetAcceptClient(cr_server.protocol, NULL, cr_server.tcpip_port, cr_server.mtu, 0); newClient->currentCtxInfo = &cr_server.MainContextInfo; crServerAddToRunQueue(newClient); cr_server.clients[i] = newClient; } /* set default client and mural */ if (cr_server.numClients > 0) { cr_server.curClient = cr_server.clients[0]; cr_server.curClient->currentMural = defaultMural; cr_server.client_spu_id =cr_server.clients[0]->spu_id; } crFreeStrings(clientchain); crFreeStrings(clientlist); /* Ask the mothership for the tile info */ //crServerGetTileInfoFromMothership(conn, defaultMural); if (cr_server.vncMode) { /* In vnc mode, we reset the mothership configuration so that it can be * used by subsequent OpenGL apps without having to spawn a new mothership * on a new port. */ crDebug("CRServer: Resetting mothership to initial state"); //crMothershipReset(conn); } //crMothershipDisconnect(conn); }
void crServerSetVBoxConfigurationHGCM() { CRMuralInfo *defaultMural; int spu_ids[1] = {0}; char *spu_names[1] = {"render"}; char *spu_dir = NULL; int i; GLint dims[4]; const char * env; defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0); CRASSERT(defaultMural); //@todo should be moved to addclient so we have a chain for each client setDefaults(); /* Load the SPUs */ cr_server.head_spu = crSPULoadChain(1, spu_ids, spu_names, spu_dir, &cr_server); if (!cr_server.head_spu) return; env = crGetenv( "CR_SERVER_DEFAULT_RENDER_TYPE" ); if (env != NULL) { GLubyte redir = (env[0] - 0x30); if (redir <= CR_SERVER_REDIR_MAXVAL) { int rc = crServerSetOffscreenRenderingMode(redir); if (!RT_SUCCESS(rc)) crWarning("offscreen rendering unsupported, no offscreen rendering will be used.."); } else crWarning("invalid redir option %c", redir); } #if defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS) || defined(GLX) else { int rc = crServerSetOffscreenRenderingMode(CR_SERVER_REDIR_FBO_BLT); if (!RT_SUCCESS(rc)) crWarning("offscreen rendering unsupported, no offscreen rendering will be used.."); } #endif cr_server.bOffscreenRenderingDefault = cr_server.bForceOffscreenRendering; cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_POSITION_CR, 0, GL_INT, 2, &dims[0]); cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, 0, GL_INT, 2, &dims[2]); defaultMural->gX = dims[0]; defaultMural->gY = dims[1]; defaultMural->width = dims[2]; defaultMural->height = dims[3]; cr_server.mtu = 1024 * 250; cr_server.numClients = 0; strcpy(cr_server.protocol, "vboxhgcm"); for (i = 0; i < cr_server.numClients; i++) { CRClient *newClient = (CRClient *) crCalloc(sizeof(CRClient)); newClient->spu_id = 0; newClient->conn = crNetAcceptClient(cr_server.protocol, NULL, cr_server.tcpip_port, cr_server.mtu, 0); newClient->currentCtxInfo = &cr_server.MainContextInfo; crServerAddToRunQueue(newClient); cr_server.clients[i] = newClient; } /* set default client and mural */ if (cr_server.numClients > 0) { cr_server.curClient = cr_server.clients[0]; cr_server.curClient->currentMural = defaultMural; cr_server.client_spu_id =cr_server.clients[0]->spu_id; } }
static SPUFunctions * renderSPUInit( int id, SPU *child, SPU *self, unsigned int context_id, unsigned int num_contexts ) { int numFuncs, numSpecial; GLint defaultWin, defaultCtx; WindowInfo *windowInfo; const char * pcpwSetting; int rc; (void) child; (void) context_id; (void) num_contexts; self->privatePtr = (void *) &render_spu; #ifdef CHROMIUM_THREADSAFE crDebug("Render SPU: thread-safe"); #endif crMemZero(&render_spu, sizeof(render_spu)); render_spu.id = id; renderspuSetVBoxConfiguration(&render_spu); if (render_spu.swap_master_url) swapsyncConnect(); /* Get our special functions. */ numSpecial = renderspuCreateFunctions( _cr_render_table ); #ifdef RT_OS_WINDOWS /* Start thread to create windows and process window messages */ crDebug("RenderSPU: Starting windows serving thread"); render_spu.hWinThreadReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (!render_spu.hWinThreadReadyEvent) { crError("RenderSPU: Failed to create WinThreadReadyEvent! (%x)", GetLastError()); return NULL; } if (!CreateThread(NULL, 0, renderSPUWindowThreadProc, 0, 0, &render_spu.dwWinThreadId)) { crError("RenderSPU: Failed to start windows thread! (%x)", GetLastError()); return NULL; } WaitForSingleObject(render_spu.hWinThreadReadyEvent, INFINITE); #endif /* Get the OpenGL functions. */ numFuncs = crLoadOpenGL( &render_spu.ws, _cr_render_table + numSpecial ); if (numFuncs == 0) { crError("The render SPU was unable to load the native OpenGL library"); return NULL; } numFuncs += numSpecial; render_spu.contextTable = crAllocHashtableEx(1, INT32_MAX); render_spu.windowTable = crAllocHashtableEx(1, INT32_MAX); render_spu.dummyWindowTable = crAllocHashtable(); pcpwSetting = crGetenv("CR_RENDER_ENABLE_SINGLE_PRESENT_CONTEXT"); if (pcpwSetting) { if (pcpwSetting[0] == '0') pcpwSetting = NULL; } if (pcpwSetting) { /* TODO: need proper blitter synchronization, do not use so far! * the problem is that rendering can be done in multiple thread: the main command (hgcm) thread and the redraw thread * we currently use per-window synchronization, while we'll need a per-blitter synchronization if one blitter is used for multiple windows * this is not done currently */ crWarning("TODO: need proper blitter synchronization, do not use so far!"); render_spu.blitterTable = crAllocHashtable(); CRASSERT(render_spu.blitterTable); } else render_spu.blitterTable = NULL; CRASSERT(render_spu.default_visual & CR_RGB_BIT); rc = renderspu_SystemInit(); if (!RT_SUCCESS(rc)) { crError("renderspu_SystemInit failed rc %d", rc); return NULL; } #ifdef USE_OSMESA if (render_spu.use_osmesa) { if (!crLoadOSMesa(&render_spu.OSMesaCreateContext, &render_spu.OSMesaMakeCurrent, &render_spu.OSMesaDestroyContext)) { crError("Unable to load OSMesa library"); } } #endif #ifdef DARWIN # ifdef VBOX_WITH_COCOA_QT # else /* VBOX_WITH_COCOA_QT */ render_spu.hRootVisibleRegion = 0; render_spu.currentBufferName = 1; render_spu.uiDockUpdateTS = 0; /* Create a mutex for synchronizing events from the main Qt thread & this thread */ RTSemFastMutexCreate(&render_spu.syncMutex); /* Create our window groups */ CreateWindowGroup(kWindowGroupAttrMoveTogether | kWindowGroupAttrLayerTogether | kWindowGroupAttrSharedActivation | kWindowGroupAttrHideOnCollapse | kWindowGroupAttrFixedLevel, &render_spu.pMasterGroup); CreateWindowGroup(kWindowGroupAttrMoveTogether | kWindowGroupAttrLayerTogether | kWindowGroupAttrSharedActivation | kWindowGroupAttrHideOnCollapse | kWindowGroupAttrFixedLevel, &render_spu.pParentGroup); /* Make the correct z-layering */ SendWindowGroupBehind (render_spu.pParentGroup, render_spu.pMasterGroup); /* and set the gParentGroup as parent for gMasterGroup. */ SetWindowGroupParent (render_spu.pMasterGroup, render_spu.pParentGroup); /* Install the event handlers */ EventTypeSpec eventList[] = { {kEventClassVBox, kEventVBoxUpdateContext}, /* Update the context after show/size/move events */ {kEventClassVBox, kEventVBoxBoundsChanged} /* Clip/Pos the OpenGL windows when the main window is changed in pos/size */ }; /* We need to process events from our main window */ render_spu.hParentEventHandler = NewEventHandlerUPP(windowEvtHndlr); InstallApplicationEventHandler (render_spu.hParentEventHandler, GetEventTypeCount(eventList), eventList, NULL, NULL); render_spu.fInit = true; # endif /* VBOX_WITH_COCOA_QT */ #endif /* DARWIN */ /* * Create the default window and context. Their indexes are zero and * a client can use them without calling CreateContext or WindowCreate. */ crDebug("Render SPU: Creating default window (visBits=0x%x, id=0)", render_spu.default_visual); defaultWin = renderspuWindowCreateEx( NULL, render_spu.default_visual, CR_RENDER_DEFAULT_WINDOW_ID ); if (defaultWin != CR_RENDER_DEFAULT_WINDOW_ID) { crError("Render SPU: Couldn't get a double-buffered, RGB visual with Z!"); return NULL; } crDebug( "Render SPU: WindowCreate returned %d (0=normal)", defaultWin ); crDebug("Render SPU: Creating default context, visBits=0x%x", render_spu.default_visual ); defaultCtx = renderspuCreateContextEx( NULL, render_spu.default_visual, CR_RENDER_DEFAULT_CONTEXT_ID, 0 ); if (defaultCtx != CR_RENDER_DEFAULT_CONTEXT_ID) { crError("Render SPU: failed to create default context!"); return NULL; } renderspuMakeCurrent( defaultWin, 0, defaultCtx ); /* Get windowInfo for the default window */ windowInfo = (WindowInfo *) crHashtableSearch(render_spu.windowTable, CR_RENDER_DEFAULT_WINDOW_ID); CRASSERT(windowInfo); windowInfo->mapPending = GL_TRUE; /* * Get the OpenGL extension functions. * SIGH -- we have to wait until the very bitter end to load the * extensions, because the context has to be bound before * wglGetProcAddress will work correctly. No such issue with GLX though. */ numFuncs += crLoadOpenGLExtensions( &render_spu.ws, _cr_render_table + numFuncs ); CRASSERT(numFuncs < 1000); #ifdef WINDOWS /* * Same problem as above, these are extensions so we need to * load them after a context has been bound. As they're WGL * extensions too, we can't simply tag them into the spu_loader. * So we do them here for now. * Grrr, NVIDIA driver uses EXT for GetExtensionsStringEXT, * but ARB for others. Need further testing here.... */ render_spu.ws.wglGetExtensionsStringEXT = (wglGetExtensionsStringEXTFunc_t) render_spu.ws.wglGetProcAddress( "wglGetExtensionsStringEXT" ); render_spu.ws.wglChoosePixelFormatEXT = (wglChoosePixelFormatEXTFunc_t) render_spu.ws.wglGetProcAddress( "wglChoosePixelFormatARB" ); render_spu.ws.wglGetPixelFormatAttribivEXT = (wglGetPixelFormatAttribivEXTFunc_t) render_spu.ws.wglGetProcAddress( "wglGetPixelFormatAttribivARB" ); render_spu.ws.wglGetPixelFormatAttribfvEXT = (wglGetPixelFormatAttribfvEXTFunc_t) render_spu.ws.wglGetProcAddress( "wglGetPixelFormatAttribfvARB" ); if (render_spu.ws.wglGetProcAddress("glCopyTexSubImage3D")) { _cr_render_table[numFuncs].name = crStrdup("CopyTexSubImage3D"); _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glCopyTexSubImage3D"); ++numFuncs; crDebug("Render SPU: Found glCopyTexSubImage3D function"); } if (render_spu.ws.wglGetProcAddress("glDrawRangeElements")) { _cr_render_table[numFuncs].name = crStrdup("DrawRangeElements"); _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glDrawRangeElements"); ++numFuncs; crDebug("Render SPU: Found glDrawRangeElements function"); } if (render_spu.ws.wglGetProcAddress("glTexSubImage3D")) { _cr_render_table[numFuncs].name = crStrdup("TexSubImage3D"); _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glTexSubImage3D"); ++numFuncs; crDebug("Render SPU: Found glTexSubImage3D function"); } if (render_spu.ws.wglGetProcAddress("glTexImage3D")) { _cr_render_table[numFuncs].name = crStrdup("TexImage3D"); _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glTexImage3D"); ++numFuncs; crDebug("Render SPU: Found glTexImage3D function"); } if (render_spu.ws.wglGetExtensionsStringEXT) { crDebug("WGL - found wglGetExtensionsStringEXT\n"); } if (render_spu.ws.wglChoosePixelFormatEXT) { crDebug("WGL - found wglChoosePixelFormatEXT\n"); } #endif render_spu.barrierHash = crAllocHashtable(); render_spu.cursorX = 0; render_spu.cursorY = 0; render_spu.use_L2 = 0; render_spu.gather_conns = NULL; numFuncs = renderspu_SystemPostprocessFunctions(_cr_render_table, numFuncs, RT_ELEMENTS(_cr_render_table)); crDebug("Render SPU: ---------- End of Init -------------"); return &render_functions; }
static BOOL bSetupPixelFormatNormal( HDC hdc, GLbitfield visAttribs ) { PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */ 1, /* version number */ PFD_DRAW_TO_WINDOW | /* support window */ PFD_SUPPORT_OPENGL, /* support OpenGL */ PFD_TYPE_RGBA, /* RGBA type */ 24, /* 24-bit color depth */ 0, 0, 0, 0, 0, 0, /* color bits ignored */ 0, /* no alpha buffer */ 0, /* shift bit ignored */ 0, /* no accumulation buffer */ 0, 0, 0, 0, /* accum bits ignored */ 0, /* set depth buffer */ 0, /* set stencil buffer */ 0, /* no auxiliary buffer */ PFD_MAIN_PLANE, /* main layer */ 0, /* reserved */ 0, 0, 0 /* layer masks ignored */ }; PIXELFORMATDESCRIPTOR *ppfd = &pfd; char s[1000]; GLbitfield b = 0; int pixelformat; renderspuMakeVisString( visAttribs, s ); crDebug( "Render SPU: WGL wants these visual capabilities: %s", s); /* These really come into play with sort-last configs */ if (visAttribs & CR_DEPTH_BIT) ppfd->cDepthBits = 24; if (visAttribs & CR_ACCUM_BIT) ppfd->cAccumBits = 16; if (visAttribs & CR_RGB_BIT) ppfd->cColorBits = 24; if (visAttribs & CR_STENCIL_BIT) ppfd->cStencilBits = 8; if (visAttribs & CR_ALPHA_BIT) ppfd->cAlphaBits = 8; if (visAttribs & CR_DOUBLE_BIT) ppfd->dwFlags |= PFD_DOUBLEBUFFER; if (visAttribs & CR_STEREO_BIT) ppfd->dwFlags |= PFD_STEREO; /* * We call the wgl functions directly if the SPU was loaded * by our faker library, otherwise we have to call the GDI * versions. */ if (crGetenv( "CR_WGL_DO_NOT_USE_GDI" ) != NULL) { pixelformat = render_spu.ws.wglChoosePixelFormat( hdc, ppfd ); /* doing this twice is normal Win32 magic */ pixelformat = render_spu.ws.wglChoosePixelFormat( hdc, ppfd ); if ( pixelformat == 0 ) { crError( "render_spu.ws.wglChoosePixelFormat failed" ); } if ( !render_spu.ws.wglSetPixelFormat( hdc, pixelformat, ppfd ) ) { crError( "render_spu.ws.wglSetPixelFormat failed" ); } render_spu.ws.wglDescribePixelFormat( hdc, pixelformat, sizeof(*ppfd), ppfd ); } else { /* Okay, we were loaded manually. Call the GDI functions. */ pixelformat = ChoosePixelFormat( hdc, ppfd ); /* doing this twice is normal Win32 magic */ pixelformat = ChoosePixelFormat( hdc, ppfd ); if ( pixelformat == 0 ) { crError( "ChoosePixelFormat failed" ); } if ( !SetPixelFormat( hdc, pixelformat, ppfd ) ) { crError( "SetPixelFormat failed (Error 0x%x)", GetLastError() ); } DescribePixelFormat( hdc, pixelformat, sizeof(*ppfd), ppfd ); } if (ppfd->cDepthBits > 0) b |= CR_DEPTH_BIT; if (ppfd->cAccumBits > 0) b |= CR_ACCUM_BIT; if (ppfd->cColorBits > 8) b |= CR_RGB_BIT; if (ppfd->cStencilBits > 0) b |= CR_STENCIL_BIT; if (ppfd->cAlphaBits > 0) b |= CR_ALPHA_BIT; if (ppfd->dwFlags & PFD_DOUBLEBUFFER) b |= CR_DOUBLE_BIT; if (ppfd->dwFlags & PFD_STEREO) b |= CR_STEREO_BIT; renderspuMakeVisString( b, s ); crDebug( "Render SPU: WGL chose these visual capabilities: %s", s); return TRUE; }
GLint RENDER_APIENTRY renderspuWindowCreate( const char *dpyName, GLint visBits ) { WindowInfo *window; VisualInfo *visual; GLboolean showIt; if (!dpyName || crStrlen(render_spu.display_string) > 0) dpyName = render_spu.display_string; visual = renderspuFindVisual( dpyName, visBits ); if (!visual) { crWarning( "Render SPU: Couldn't create a window, renderspuFindVisual returned NULL" ); return -1; } /* Allocate WindowInfo */ window = (WindowInfo *) crCalloc(sizeof(WindowInfo)); if (!window) { crWarning( "Render SPU: Couldn't create a window" ); return -1; } crHashtableAdd(render_spu.windowTable, render_spu.window_id, window); window->id = render_spu.window_id; render_spu.window_id++; window->x = render_spu.defaultX; window->y = render_spu.defaultY; window->width = render_spu.defaultWidth; window->height = render_spu.defaultHeight; if ((render_spu.render_to_app_window || render_spu.render_to_crut_window) && !crGetenv("CRNEWSERVER")) showIt = 0; else showIt = window->id > 0; /* Set window->title, replacing %i with the window ID number */ { const char *s = crStrstr(render_spu.window_title, "%i"); if (s) { int i, j, k; window->title = crAlloc(crStrlen(render_spu.window_title) + 10); for (i = 0; render_spu.window_title[i] != '%'; i++) window->title[i] = render_spu.window_title[i]; k = sprintf(window->title + i, "%d", window->id); CRASSERT(k < 10); i++; /* skip the 'i' after the '%' */ j = i + k; for (; (window->title[j] = s[i]) != 0; i++, j++) ; } else { window->title = crStrdup(render_spu.window_title); } } /* crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->id); */ /* Have GLX/WGL/AGL create the window */ if (!renderspu_SystemCreateWindow( visual, showIt, window )) { crFree(window); crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" ); return -1; } CRASSERT(window->visual == visual); return window->id; }
/* Windows crap */ BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved) { (void) lpvReserved; switch (fdwReason) { case DLL_PROCESS_ATTACH: { CRNetServer ns; const char * env; #if defined(DEBUG_misha) HMODULE hCrUtil; char aName[MAX_PATH]; GetModuleFileNameA(hDLLInst, aName, RT_ELEMENTS(aName)); crDbgCmdSymLoadPrint(aName, hDLLInst); hCrUtil = GetModuleHandleA("VBoxOGLcrutil.dll"); Assert(hCrUtil); crDbgCmdSymLoadPrint("VBoxOGLcrutil.dll", hCrUtil); #endif #ifdef CHROMIUM_THREADSAFE crInitTSD(&g_stubCurrentContextTSD); #endif crInitMutex(&stub_init_mutex); #ifdef VDBG_VEHANDLER env = crGetenv("CR_DBG_VEH_ENABLE"); g_VBoxVehEnable = crStrParseI32(env, # ifdef DEBUG_misha 1 # else 0 # endif ); if (g_VBoxVehEnable) { char procName[1024]; size_t cProcName; size_t cChars; env = crGetenv("CR_DBG_VEH_FLAGS"); g_VBoxVehFlags = crStrParseI32(env, 0 # ifdef DEBUG_misha | VBOXVEH_F_BREAK # else | VBOXVEH_F_DUMP # endif ); env = crGetenv("CR_DBG_VEH_DUMP_DIR"); if (!env) env = VBOXMD_DUMP_DIR_DEFAULT; g_cVBoxMdFilePrefixLen = strlen(env); if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) <= g_cVBoxMdFilePrefixLen + 26 + (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR)) { g_cVBoxMdFilePrefixLen = 0; env = ""; } mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix, g_cVBoxMdFilePrefixLen + 1, env, _TRUNCATE); Assert(cChars == g_cVBoxMdFilePrefixLen + 1); g_cVBoxMdFilePrefixLen = cChars - 1; if (g_cVBoxMdFilePrefixLen && g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen - 1] != L'\\') g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'\\'; memcpy(g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, VBOXMD_DUMP_NAME_PREFIX_W, sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)); g_cVBoxMdFilePrefixLen += (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR); crGetProcName(procName, RT_ELEMENTS(procName)); cProcName = strlen(procName); if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) > g_cVBoxMdFilePrefixLen + cProcName + 1 + 26) { mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, cProcName + 1, procName, _TRUNCATE); Assert(cChars == cProcName + 1); g_cVBoxMdFilePrefixLen += cChars - 1; g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'_'; } /* sanity */ g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen] = L'\0'; env = crGetenv("CR_DBG_VEH_DUMP_TYPE"); g_enmVBoxMdDumpType = crStrParseI32(env, MiniDumpNormal | MiniDumpWithDataSegs | MiniDumpWithFullMemory | MiniDumpWithHandleData //// | MiniDumpFilterMemory //// | MiniDumpScanMemory // | MiniDumpWithUnloadedModules //// | MiniDumpWithIndirectlyReferencedMemory //// | MiniDumpFilterModulePaths // | MiniDumpWithProcessThreadData // | MiniDumpWithPrivateReadWriteMemory //// | MiniDumpWithoutOptionalData // | MiniDumpWithFullMemoryInfo // | MiniDumpWithThreadInfo // | MiniDumpWithCodeSegs // | MiniDumpWithFullAuxiliaryState // | MiniDumpWithPrivateWriteCopyMemory // | MiniDumpIgnoreInaccessibleMemory // | MiniDumpWithTokenInformation //// | MiniDumpWithModuleHeaders //// | MiniDumpFilterTriage ); vboxVDbgVEHandlerRegister(); } #endif crNetInit(NULL, NULL); ns.name = "vboxhgcm://host:0"; ns.buffer_size = 1024; crNetServerConnect(&ns #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) , NULL #endif ); if (!ns.conn) { crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load."); #ifdef VDBG_VEHANDLER if (g_VBoxVehEnable) vboxVDbgVEHandlerUnregister(); #endif return FALSE; } else { crNetFreeConnection(ns.conn); } #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) VBoxCrHgsmiInit(); #endif break; } case DLL_PROCESS_DETACH: { /* do exactly the same thing as for DLL_THREAD_DETACH since * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */ stubSetCurrentContext(NULL); if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxDetachThread(); } #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) VBoxCrHgsmiTerm(); #endif stubSPUSafeTearDown(); #ifdef CHROMIUM_THREADSAFE crFreeTSD(&g_stubCurrentContextTSD); #endif #ifdef VDBG_VEHANDLER if (g_VBoxVehEnable) vboxVDbgVEHandlerUnregister(); #endif break; } case DLL_THREAD_ATTACH: { if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxAttachThread(); } break; } case DLL_THREAD_DETACH: { stubSetCurrentContext(NULL); if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxDetachThread(); } break; } default: break; } return TRUE; }
/** * This is the main routine responsible for replicating our GL state * for a new VNC viewer. Called when we detect that a new VNC viewer * has been started. * \param ipaddress the IP address where the new viewer is running. */ void replicatespuReplicate(int ipaddress) { GET_THREAD(thread); struct in_addr addr; char *hosturl; char *ipstring; int i, r_slot; int serverPort; crDebug("Replicate SPU: Enter replicatespuReplicate(ipaddress=0x%x)", ipaddress); replicatespuFlushAll( (void *)thread ); #ifdef CHROMIUM_THREADSAFE_notyet crLockMutex(&_ReplicateMutex); #endif /* * Find empty slot. * Slot 0 is the dummy slot (a non-existant server on devnull connection) */ for (r_slot = 1; r_slot < CR_MAX_REPLICANTS; r_slot++) { if (!IS_CONNECTED(replicate_spu.rserver[r_slot].conn)) break; } if (r_slot == CR_MAX_REPLICANTS) { crWarning("Replicate SPU: no more replicant slots available"); return; } /** ** OK, now rserver[r_slot] is free for use. **/ /* * At this time, we can only support one VNC viewer per host. * Check for that here. */ for (i = 1; i < CR_MAX_REPLICANTS; i++) { if (replicate_spu.ipnumbers[i] == ipaddress) { CRConnection *conn = replicate_spu.rserver[i].conn; /* If the connection appears to be active, it may actually be a dangling * connection. Try flushing it now. If flushing fails, the connection * type will definitely be CR_NO_CONNECTION (which we test below). */ if (conn) { if (conn->type != CR_NO_CONNECTION) { FlushConnection(i); } if (conn->type != CR_NO_CONNECTION) { crWarning("Replicate SPU: Can't connect to multiple VNC viewers on one host."); #if 0 /* The above test isn't 100% reliable and can prevent successful * restart of a viewer on a host. For now, just print warning and * continue. */ return; #endif } } } } replicate_spu.ipnumbers[r_slot] = ipaddress; serverPort = replicate_spu.chromium_start_port + r_slot; if (replicate_spu.vncAvailable) { /* Send a ChromiumStart message to the VNC Server. The VNC Server will * in turn send a ChromiumStart message to all the attached VNC viewers. * The VNC Viewer/Chromium module will tell its crserver that there's * a new OpenGL client. * We pass the mothership port and crserver port in this message. */ char protocol[100], hostname[1000]; const char *mothershipURL; unsigned short mothershipPort; mothershipURL = crGetenv("CRMOTHERSHIP"); crDebug("Replicate SPU: CRMOTHERSHIP env var = %s", mothershipURL); if (mothershipURL) crParseURL(mothershipURL, protocol, hostname, &mothershipPort, DEFAULT_MOTHERSHIP_PORT); else mothershipPort = DEFAULT_MOTHERSHIP_PORT; crDebug("Replicate SPU: Sending ChromiumStart msg to VNC server, port=%d", serverPort); if (!XVncChromiumStart(replicate_spu.glx_display, ipaddress, serverPort, mothershipPort)) { crWarning("Replicate SPU: XVncChromiumStart() call failed"); } } addr.s_addr = ipaddress; ipstring = inet_ntoa(addr); hosturl = crAlloc(crStrlen(ipstring) + 9); sprintf(hosturl, "tcpip://%s", ipstring); crDebug("Replicate SPU attaching to %s on port %d", hosturl, serverPort); /* connect to the remote VNC server */ replicate_spu.rserver[r_slot].name = crStrdup( replicate_spu.name ); replicate_spu.rserver[r_slot].buffer_size = replicate_spu.buffer_size; replicate_spu.rserver[r_slot].conn = crNetConnectToServer( hosturl, serverPort, replicate_spu.rserver[r_slot].buffer_size, 1); if (!replicate_spu.rserver[r_slot].conn) { crWarning("Replicate SPU: failed to connect to %s", hosturl); return; } CRASSERT(replicate_spu.rserver[r_slot].conn); /* * Setup the the packer flush function. While replicating state to * a particular server we definitely don't want to do any broadcast * flushing! */ crPackFlushFunc( thread->packer, replicatespuFlushOnePacker ); crPackSendHugeFunc( thread->packer, replicatespuHugeOnePacker ); NewServerIndex = r_slot; /* * Create server-side windows and contexts by walking tables of app windows * and contexts. Note that windows can be created in random order, * but contexts must be created in the order they were originally * created, or shared contexts will break. */ crHashtableWalk(replicate_spu.windowTable, replicatespuReplicateWindow, thread); crListApply(replicate_spu.contextList, replicatespuReplicateContext, thread); /* MakeCurrent, the current context */ if (thread->currentContext) { int serverWindow = thread->currentContext->currentWindow->id[r_slot]; int serverContext = thread->currentContext->rserverCtx[r_slot]; if (replicate_spu.swap) crPackMakeCurrentSWAP(serverWindow, 0, serverContext); else crPackMakeCurrent(serverWindow, 0, serverContext); crStateMakeCurrent( thread->currentContext->State ); } /* * Set window sizes */ crHashtableWalk(replicate_spu.windowTable, replicatespuResizeWindows, thread); replicatespuFlushOne(thread, NewServerIndex); /* * restore normal, broadcasting packer flush function now. */ crPackFlushFunc( thread->packer, replicatespuFlush ); crPackSendHugeFunc( thread->packer, replicatespuHuge ); NewServerIndex = -1; crDebug("Replicate SPU: leaving replicatespuReplicate"); #ifdef CHROMIUM_THREADSAFE_notyet crUnlockMutex(&_ReplicateMutex); #endif }