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 && env[0] != '\0') { unsigned int redir = (unsigned int)crServerVBoxParseNumerics(env, CR_SERVER_REDIR_F_NONE); if (redir <= CR_SERVER_REDIR_F_ALL) { 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) if (cr_server.fPresentMode == CR_SERVER_REDIR_F_NONE) { /* the CR_SERVER_REDIR_F_FBO_BLT is set only if parent window is received, which means we are not in headles */ int rc = crServerSetOffscreenRenderingMode(CR_SERVER_REDIR_F_FBO | CR_SERVER_REDIR_F_DISPLAY); if (!RT_SUCCESS(rc)) crWarning("offscreen rendering unsupported, no offscreen rendering will be used.."); } #endif cr_server.fPresentModeDefault = cr_server.fPresentMode; cr_server.fVramPresentModeDefault = CR_SERVER_REDIR_F_FBO_RAM/* | CR_SERVER_REDIR_F_FBO_RPW*/; /* 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); }
GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLint shareCtx, GLint preloadCtxID, int32_t internalID) { GLint retVal = -1; CRContext *newCtx; CRContextInfo *pContextInfo; GLboolean fFirst = GL_FALSE; if (shareCtx > 0) { crWarning("CRServer: context sharing not implemented."); shareCtx = 0; } pContextInfo = (CRContextInfo *) crAlloc(sizeof (CRContextInfo)); if (!pContextInfo) { crWarning("failed to alloc context info!"); return -1; } pContextInfo->CreateInfo.visualBits = visualBits; /* Since the Cr server serialized all incoming clients/contexts into * one outgoing GL stream, we only need to create one context for the * head SPU. We'll only have to make it current once too, below. */ if (cr_server.firstCallCreateContext) { cr_server.MainContextInfo.CreateInfo.visualBits = visualBits; cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table. CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.visualBits, shareCtx); if (cr_server.MainContextInfo.SpuContext < 0) { crWarning("crServerDispatchCreateContext() failed."); crFree(pContextInfo); return -1; } cr_server.firstCallCreateContext = GL_FALSE; fFirst = GL_TRUE; } else { /* second or third or ... context */ if (!cr_server.bUseMultipleContexts && ((visualBits & cr_server.MainContextInfo.CreateInfo.visualBits) != visualBits)) { int oldSpuContext; /* the new context needs new visual attributes */ cr_server.MainContextInfo.CreateInfo.visualBits |= visualBits; crDebug("crServerDispatchCreateContext requires new visual (0x%x).", cr_server.MainContextInfo.CreateInfo.visualBits); /* Here, we used to just destroy the old rendering context. * Unfortunately, this had the side effect of destroying * all display lists and textures that had been loaded on * the old context as well. * * Now, first try to create a new context, with a suitable * visual, sharing display lists and textures with the * old context. Then destroy the old context. */ /* create new rendering context with suitable visual */ oldSpuContext = cr_server.MainContextInfo.SpuContext; cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table. CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.visualBits, cr_server.MainContextInfo.SpuContext); /* destroy old rendering context */ cr_server.head_spu->dispatch_table.DestroyContext(oldSpuContext); if (cr_server.MainContextInfo.SpuContext < 0) { crWarning("crServerDispatchCreateContext() failed."); crFree(pContextInfo); return -1; } } } if (cr_server.bUseMultipleContexts) { pContextInfo->SpuContext = cr_server.head_spu->dispatch_table. CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.visualBits, cr_server.MainContextInfo.SpuContext); if (pContextInfo->SpuContext < 0) { crWarning("crServerDispatchCreateContext() failed."); crStateEnableDiffOnMakeCurrent(GL_TRUE); cr_server.bUseMultipleContexts = GL_FALSE; if (!fFirst) crError("creating shared context failed, while it is expected to work!"); } else if (fFirst) { crStateEnableDiffOnMakeCurrent(GL_FALSE); } } else { pContextInfo->SpuContext = -1; } /* Now create a new state-tracker context and initialize the * dispatch function pointers. */ newCtx = crStateCreateContextEx(&cr_server.limits, visualBits, NULL, internalID); if (newCtx) { crStateSetCurrentPointers( newCtx, &(cr_server.current) ); crStateResetCurrentPointers(&(cr_server.current)); retVal = preloadCtxID<0 ? crServerGenerateID(&cr_server.idsPool.freeContextID) : preloadCtxID; pContextInfo->pContext = newCtx; pContextInfo->CreateInfo.visualBits = visualBits; pContextInfo->CreateInfo.externalID = retVal; pContextInfo->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL; crHashtableAdd(cr_server.contextTable, retVal, pContextInfo); } if (retVal != -1 && !cr_server.bIsInLoadingState) { int pos; for (pos = 0; pos < CR_MAX_CONTEXTS; pos++) { if (cr_server.curClient->contextList[pos] == 0) { cr_server.curClient->contextList[pos] = retVal; break; } } } { /* As we're using only one host context to serve all client contexts, newly created context will still * hold last error value from any previous failed opengl call. Proper solution would be to redirect any * client glGetError calls to our state tracker, but right now it's missing quite a lot of checks and doesn't * reflect host driver/gpu specific issues. Thus we just reset last opengl error at context creation. */ GLint err; err = cr_server.head_spu->dispatch_table.GetError(); if (err!=GL_NO_ERROR) { #ifdef DEBUG_misha crDebug("Cleared gl error %#x on context creation", err); #else crWarning("Cleared gl error %#x on context creation", err); #endif } } crServerReturnValue( &retVal, sizeof(retVal) ); return retVal; }
static void set_format(void *foo, const char *response) { saveframe_spu.format = crStrdup(response); }
/** * This function is called by MakeCurrent() and determines whether or * not a new rendering context should be bound to Chromium or the native * OpenGL. * \return GL_FALSE if native OpenGL should be used, or GL_TRUE if Chromium * should be used. */ static GLboolean stubCheckUseChromium( WindowInfo *window ) { int x, y; unsigned int w, h; /* If the provided window is CHROMIUM, we're clearly intended * to create a CHROMIUM context. */ if (window->type == CHROMIUM) return GL_TRUE; if (stub.ignoreFreeglutMenus) { const char *glutMenuTitle = "freeglut menu"; char title[1000]; GetWindowTitle(window, title); if (crStrcmp(title, glutMenuTitle) == 0) { crDebug("GL faker: Ignoring freeglut menu window"); return GL_FALSE; } } /* If the user's specified a window count for Chromium, see if * this window satisfies that criterium. */ stub.matchChromiumWindowCounter++; if (stub.matchChromiumWindowCount > 0) { if (stub.matchChromiumWindowCounter != stub.matchChromiumWindowCount) { crDebug("Using native GL, app window doesn't meet match_window_count"); return GL_FALSE; } } /* If the user's specified a window list to ignore, see if this * window satisfies that criterium. */ if (stub.matchChromiumWindowID) { GLuint i; for (i = 0; i <= stub.numIgnoreWindowID; i++) { if (stub.matchChromiumWindowID[i] == stub.matchChromiumWindowCounter) { crDebug("Ignore window ID %d, using native GL", stub.matchChromiumWindowID[i]); return GL_FALSE; } } } /* If the user's specified a minimum window size for Chromium, see if * this window satisfies that criterium. */ if (stub.minChromiumWindowWidth > 0 && stub.minChromiumWindowHeight > 0) { stubGetWindowGeometry( window, &x, &y, &w, &h ); if (w >= stub.minChromiumWindowWidth && h >= stub.minChromiumWindowHeight) { /* Check for maximum sized window now too */ if (stub.maxChromiumWindowWidth && stub.maxChromiumWindowHeight) { if (w < stub.maxChromiumWindowWidth && h < stub.maxChromiumWindowHeight) return GL_TRUE; else return GL_FALSE; } return GL_TRUE; } crDebug("Using native GL, app window doesn't meet minimum_window_size"); return GL_FALSE; } else if (stub.matchWindowTitle) { /* If the user's specified a window title for Chromium, see if this * window satisfies that criterium. */ GLboolean wildcard = GL_FALSE; char title[1000]; char *titlePattern; int len; /* check for leading '*' wildcard */ if (stub.matchWindowTitle[0] == '*') { titlePattern = crStrdup( stub.matchWindowTitle + 1 ); wildcard = GL_TRUE; } else { titlePattern = crStrdup( stub.matchWindowTitle ); } /* check for trailing '*' wildcard */ len = crStrlen(titlePattern); if (len > 0 && titlePattern[len - 1] == '*') { titlePattern[len - 1] = '\0'; /* terminate here */ wildcard = GL_TRUE; } GetWindowTitle( window, title ); if (title[0]) { if (wildcard) { if (crStrstr(title, titlePattern)) { crFree(titlePattern); return GL_TRUE; } } else if (crStrcmp(title, titlePattern) == 0) { crFree(titlePattern); return GL_TRUE; } } crFree(titlePattern); crDebug("Using native GL, app window title doesn't match match_window_title string (\"%s\" != \"%s\")", title, stub.matchWindowTitle); return GL_FALSE; } /* Window title and size don't matter */ CRASSERT(stub.minChromiumWindowWidth == 0); CRASSERT(stub.minChromiumWindowHeight == 0); CRASSERT(stub.matchWindowTitle == NULL); /* User hasn't specified a width/height or window title. * We'll use chromium for this window (and context) if no other is. */ return GL_TRUE; /* use Chromium! */ }
GLint PACKSPU_APIENTRY packspu_VBoxPackSetInjectThread(struct VBOXUHGSMI *pHgsmi) { GLint con = 0; int i; GET_THREAD(thread); CRASSERT(!thread); crLockMutex(&_PackMutex); { CRASSERT(CRPACKSPU_IS_WDDM_CRHGSMI() || (pack_spu.numThreads>0)); CRASSERT(pack_spu.numThreads<MAX_THREADS); for (i=0; i<MAX_THREADS; ++i) { if (!pack_spu.thread[i].inUse) { thread = &pack_spu.thread[i]; break; } } CRASSERT(thread); thread->inUse = GL_TRUE; if (!CRPACKSPU_IS_WDDM_CRHGSMI()) thread->id = crThreadID(); else thread->id = THREAD_OFFSET_MAGIC + i; thread->currentContext = NULL; thread->bInjectThread = GL_TRUE; thread->netServer.name = crStrdup(pack_spu.name); thread->netServer.buffer_size = 64 * 1024; packspuConnectToServer(&(thread->netServer) #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) , pHgsmi #endif ); CRASSERT(thread->netServer.conn); CRASSERT(thread->packer == NULL); thread->packer = crPackNewContext( pack_spu.swap ); CRASSERT(thread->packer); crPackInitBuffer(&(thread->buffer), crNetAlloc(thread->netServer.conn), thread->netServer.conn->buffer_size, thread->netServer.conn->mtu); thread->buffer.canBarf = thread->netServer.conn->Barf ? GL_TRUE : GL_FALSE; crPackSetBuffer( thread->packer, &thread->buffer ); crPackFlushFunc( thread->packer, packspuFlush ); crPackFlushArg( thread->packer, (void *) thread ); crPackSendHugeFunc( thread->packer, packspuHuge ); crPackSetContext( thread->packer ); crSetTSD(&_PackTSD, thread); pack_spu.numThreads++; } crUnlockMutex(&_PackMutex); if (CRPACKSPU_IS_WDDM_CRHGSMI()) { CRASSERT(thread->id - THREAD_OFFSET_MAGIC < RT_ELEMENTS(pack_spu.thread) && GET_THREAD_VAL_ID(thread->id) == thread); con = thread->id; } return con; }
/* * Initialize the CRLimitsState object to Chromium's defaults. */ void crStateLimitsInit (CRLimitsState *l) { l->maxTextureUnits = CR_MAX_TEXTURE_UNITS; l->maxTextureSize = CR_MAX_TEXTURE_SIZE; l->max3DTextureSize = CR_MAX_3D_TEXTURE_SIZE; l->maxCubeMapTextureSize = CR_MAX_CUBE_TEXTURE_SIZE; #ifdef CR_NV_texture_rectangle l->maxRectTextureSize = CR_MAX_RECTANGLE_TEXTURE_SIZE; #endif l->maxTextureAnisotropy = CR_MAX_TEXTURE_ANISOTROPY; l->maxGeneralCombiners = CR_MAX_GENERAL_COMBINERS; l->maxLights = CR_MAX_LIGHTS; l->maxClipPlanes = CR_MAX_CLIP_PLANES; l->maxClientAttribStackDepth = CR_MAX_ATTRIB_STACK_DEPTH; l->maxProjectionStackDepth = CR_MAX_PROJECTION_STACK_DEPTH; l->maxModelviewStackDepth = CR_MAX_MODELVIEW_STACK_DEPTH; l->maxTextureStackDepth = CR_MAX_TEXTURE_STACK_DEPTH; l->maxColorStackDepth = CR_MAX_COLOR_STACK_DEPTH; l->maxAttribStackDepth = CR_MAX_ATTRIB_STACK_DEPTH; l->maxClientAttribStackDepth = CR_MAX_ATTRIB_STACK_DEPTH; l->maxNameStackDepth = CR_MAX_NAME_STACK_DEPTH; l->maxElementsIndices = CR_MAX_ELEMENTS_INDICES; l->maxElementsVertices = CR_MAX_ELEMENTS_VERTICES; l->maxEvalOrder = CR_MAX_EVAL_ORDER; l->maxListNesting = CR_MAX_LIST_NESTING; l->maxPixelMapTable = CR_MAX_PIXEL_MAP_TABLE; l->maxViewportDims[0] = l->maxViewportDims[1] = CR_MAX_VIEWPORT_DIM; l->subpixelBits = CR_SUBPIXEL_BITS; l->aliasedPointSizeRange[0] = CR_ALIASED_POINT_SIZE_MIN; l->aliasedPointSizeRange[1] = CR_ALIASED_POINT_SIZE_MAX; l->smoothPointSizeRange[0] = CR_SMOOTH_POINT_SIZE_MIN; l->smoothPointSizeRange[1] = CR_SMOOTH_POINT_SIZE_MAX; l->pointSizeGranularity = CR_POINT_SIZE_GRANULARITY; l->aliasedLineWidthRange[0] = CR_ALIASED_LINE_WIDTH_MIN; l->aliasedLineWidthRange[1] = CR_ALIASED_LINE_WIDTH_MAX; l->smoothLineWidthRange[0] = CR_SMOOTH_LINE_WIDTH_MIN; l->smoothLineWidthRange[1] = CR_SMOOTH_LINE_WIDTH_MAX; l->lineWidthGranularity = CR_LINE_WIDTH_GRANULARITY; #ifdef CR_EXT_texture_lod_bias l->maxTextureLodBias = CR_MAX_TEXTURE_LOD_BIAS; #endif #ifdef CR_NV_fragment_program l->maxTextureCoords = CR_MAX_TEXTURE_COORDS; l->maxTextureImageUnits = CR_MAX_TEXTURE_IMAGE_UNITS; l->maxFragmentProgramLocalParams = CR_MAX_FRAGMENT_LOCAL_PARAMS; #endif #ifdef CR_NV_vertex_program l->maxProgramMatrixStackDepth = CR_MAX_PROGRAM_MATRIX_STACK_DEPTH; l->maxProgramMatrices = CR_MAX_PROGRAM_MATRICES; #endif #ifdef CR_ARB_fragment_program l->maxFragmentProgramInstructions = CR_MAX_FRAGMENT_PROGRAM_INSTRUCTIONS; l->maxFragmentProgramLocalParams = CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; l->maxFragmentProgramEnvParams = CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS; l->maxFragmentProgramTemps = CR_MAX_FRAGMENT_PROGRAM_TEMPS; l->maxFragmentProgramAttribs = CR_MAX_FRAGMENT_PROGRAM_ATTRIBS; l->maxFragmentProgramAddressRegs = CR_MAX_FRAGMENT_PROGRAM_ADDRESS_REGS; l->maxFragmentProgramAluInstructions = CR_MAX_FRAGMENT_PROGRAM_ALU_INSTRUCTIONS; l->maxFragmentProgramTexInstructions = CR_MAX_FRAGMENT_PROGRAM_TEX_INSTRUCTIONS; l->maxFragmentProgramTexIndirections = CR_MAX_FRAGMENT_PROGRAM_TEX_INDIRECTIONS; #endif #ifdef CR_ARB_vertex_program l->maxVertexProgramInstructions = CR_MAX_VERTEX_PROGRAM_INSTRUCTIONS; l->maxVertexProgramLocalParams = CR_MAX_VERTEX_PROGRAM_LOCAL_PARAMS; l->maxVertexProgramEnvParams = CR_MAX_VERTEX_PROGRAM_ENV_PARAMS; l->maxVertexProgramTemps = CR_MAX_VERTEX_PROGRAM_TEMPS; l->maxVertexProgramAttribs = CR_MAX_VERTEX_PROGRAM_ATTRIBS; l->maxVertexProgramAddressRegs = CR_MAX_VERTEX_PROGRAM_ADDRESS_REGS; #endif l->extensions = (GLubyte *) crStrdup(crExtensions); /* These will get properly set in crStateCreateContext() by examining * the visBits bitfield parameter. */ l->redBits = 0; l->greenBits = 0; l->blueBits = 0; l->alphaBits = 0; l->depthBits = 0; l->stencilBits = 0; l->accumRedBits = 0; l->accumGreenBits = 0; l->accumBlueBits = 0; l->accumAlphaBits = 0; l->auxBuffers = 0; l->rgbaMode = GL_TRUE; l->doubleBuffer = GL_FALSE; l->stereo = GL_FALSE; l->sampleBuffers = 0; l->samples = 0; l->level = 0; (void) crAppOnlyExtensions; /* silence warning */ }
static void set_title( RenderSPU *render_spu, const char *response ) { crFree( render_spu->window_title ); render_spu->window_title = crStrdup( response ); }
const GLubyte * PACKSPU_APIENTRY packspu_GetString( GLenum name ) { GET_CONTEXT(ctx); switch(name) { case GL_EXTENSIONS: return GetExtensions(); case GL_VERSION: #if 0 && defined(WINDOWS) if (packspuRunningUnderWine()) { GetString(GL_REAL_VERSION, ctx->pszRealVersion); return ctx->pszRealVersion; } else #endif { char *oldlocale; float version; oldlocale = setlocale(LC_NUMERIC, NULL); oldlocale = crStrdup(oldlocale); setlocale(LC_NUMERIC, "C"); version = GetVersionString(); sprintf((char*)ctx->glVersion, "%.1f Chromium %s", version, CR_VERSION_STRING); if (oldlocale) { setlocale(LC_NUMERIC, oldlocale); crFree(oldlocale); } return ctx->glVersion; } case GL_VENDOR: #ifdef WINDOWS if (packspuRunningUnderWine()) { GetString(GL_REAL_VENDOR, ctx->pszRealVendor); return ctx->pszRealVendor; } else #endif { return crStateGetString(name); } case GL_RENDERER: #ifdef WINDOWS if (packspuRunningUnderWine()) { GetString(GL_REAL_RENDERER, ctx->pszRealRenderer); return ctx->pszRealRenderer; } else #endif { return crStateGetString(name); } #ifdef CR_OPENGL_VERSION_2_0 case GL_SHADING_LANGUAGE_VERSION: { static GLboolean fInitialized = GL_FALSE; if (!fInitialized) { GetString(GL_SHADING_LANGUAGE_VERSION, gpszShadingVersion); fInitialized = GL_TRUE; } return gpszShadingVersion; } #endif #ifdef GL_CR_real_vendor_strings case GL_REAL_VENDOR: GetString(GL_REAL_VENDOR, ctx->pszRealVendor); return ctx->pszRealVendor; case GL_REAL_VERSION: GetString(GL_REAL_VERSION, ctx->pszRealVersion); return ctx->pszRealVersion; case GL_REAL_RENDERER: GetString(GL_REAL_RENDERER, ctx->pszRealRenderer); return ctx->pszRealRenderer; #endif default: return crStateGetString(name); } }
static void crSDPAccept( CRConnection *conn, const char *hostname, unsigned short port ) { int err; socklen_t addr_length; struct sockaddr_in servaddr; struct sockaddr addr; struct hostent *host; struct in_addr sin_addr; if (port != last_port) { /* with the new OOB stuff, we can have multiple ports being * accepted on, so we need to redo the server socket every time. */ cr_sdp.server_sock = socket( AF_INET_SDP, SOCK_STREAM, 0 ); if ( cr_sdp.server_sock == -1 ) { err = crSDPErrno( ); crError( "Couldn't create socket: %s", crSDPErrorString( err ) ); } spankSocket( cr_sdp.server_sock ); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_port = htons( port ); if ( bind( cr_sdp.server_sock, (struct sockaddr *) &servaddr, sizeof(servaddr) ) ) { err = crSDPErrno( ); crError( "Couldn't bind to socket (port=%d): %s", port, crSDPErrorString( err ) ); } last_port = port; if ( listen( cr_sdp.server_sock, 100 /* max pending connections */ ) ) { err = crSDPErrno( ); crError( "Couldn't listen on socket: %s", crSDPErrorString( err ) ); } } if (conn->broker) { CRConnection *mother; char response[8096]; char my_hostname[256]; char *temp; mother = __copy_of_crMothershipConnect( ); if (!hostname) { if ( crGetHostname( my_hostname, sizeof( my_hostname ) ) ) { crError( "Couldn't determine my own hostname in crSDPAccept!" ); } } else crStrcpy(my_hostname, hostname); /* Hack hostname, YUCK!!! */ temp = strtok(my_hostname, "."); crStrcat(temp, crGetSDPHostnameSuffix()); (void) temp; if (!__copy_of_crMothershipSendString( mother, response, "acceptrequest sdp %s %d %d", temp, conn->port, conn->endianness ) ) { crError( "Mothership didn't like my accept request" ); } __copy_of_crMothershipDisconnect( mother ); sscanf( response, "%u", &(conn->id) ); } addr_length = sizeof( addr ); conn->sdp_socket = accept( cr_sdp.server_sock, (struct sockaddr *) &addr, &addr_length ); if (conn->sdp_socket == -1) { err = crSDPErrno( ); crError( "Couldn't accept client: %s", crSDPErrorString( err ) ); } sin_addr = ((struct sockaddr_in *) &addr)->sin_addr; host = gethostbyaddr( (char *) &sin_addr, sizeof( sin_addr), AF_INET_SDP ); if (host == NULL ) { char *temp = inet_ntoa( sin_addr ); conn->hostname = crStrdup( temp ); } else { char *temp; conn->hostname = crStrdup( host->h_name ); temp = conn->hostname; while (*temp && *temp != '.' ) temp++; *temp = '\0'; } #ifdef RECV_BAIL_OUT err = sizeof(unsigned int); if ( getsockopt( conn->sdp_socket, SOL_SOCKET, SO_RCVBUF, (char *) &conn->krecv_buf_size, &err ) ) { conn->krecv_buf_size = 0; } #endif crDebug( "Accepted connection from \"%s\".", conn->hostname ); }
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; }
GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLint shareCtx, GLint preloadCtxID, int32_t internalID) { GLint retVal = -1; CRContext *newCtx; CRContextInfo *pContextInfo; GLboolean fFirst = GL_FALSE; dpyName = ""; if (shareCtx > 0) { crWarning("CRServer: context sharing not implemented."); shareCtx = 0; } pContextInfo = (CRContextInfo *) crAlloc(sizeof (CRContextInfo)); if (!pContextInfo) { crWarning("failed to alloc context info!"); return -1; } pContextInfo->currentMural = NULL; pContextInfo->CreateInfo.requestedVisualBits = visualBits; if (cr_server.fVisualBitsDefault) visualBits = cr_server.fVisualBitsDefault; pContextInfo->CreateInfo.realVisualBits = visualBits; /* Since the Cr server serialized all incoming clients/contexts into * one outgoing GL stream, we only need to create one context for the * head SPU. We'll only have to make it current once too, below. */ if (cr_server.firstCallCreateContext) { cr_server.MainContextInfo.CreateInfo.realVisualBits = visualBits; cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table. CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, shareCtx); if (cr_server.MainContextInfo.SpuContext < 0) { crWarning("crServerDispatchCreateContext() failed."); crFree(pContextInfo); return -1; } cr_server.MainContextInfo.pContext = crStateCreateContext(&cr_server.limits, visualBits, NULL); CRASSERT(cr_server.MainContextInfo.pContext); cr_server.firstCallCreateContext = GL_FALSE; fFirst = GL_TRUE; cr_server.head_spu->dispatch_table.ChromiumParameteriCR(GL_HH_SET_DEFAULT_SHARED_CTX, cr_server.MainContextInfo.SpuContext); } else { /* second or third or ... context */ if (!cr_server.bUseMultipleContexts && ((visualBits & cr_server.MainContextInfo.CreateInfo.realVisualBits) != visualBits)) { int oldSpuContext; /* should never be here */ CRASSERT(0); /* the new context needs new visual attributes */ cr_server.MainContextInfo.CreateInfo.realVisualBits |= visualBits; crWarning("crServerDispatchCreateContext requires new visual (0x%x).", cr_server.MainContextInfo.CreateInfo.realVisualBits); /* Here, we used to just destroy the old rendering context. * Unfortunately, this had the side effect of destroying * all display lists and textures that had been loaded on * the old context as well. * * Now, first try to create a new context, with a suitable * visual, sharing display lists and textures with the * old context. Then destroy the old context. */ /* create new rendering context with suitable visual */ oldSpuContext = cr_server.MainContextInfo.SpuContext; cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table. CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext); /* destroy old rendering context */ cr_server.head_spu->dispatch_table.DestroyContext(oldSpuContext); if (cr_server.MainContextInfo.SpuContext < 0) { crWarning("crServerDispatchCreateContext() failed."); crFree(pContextInfo); return -1; } /* we do not need to clean up the old default context explicitly, since the above cr_server.head_spu->dispatch_table.DestroyContext call * will do that for us */ cr_server.head_spu->dispatch_table.ChromiumParameteriCR(GL_HH_SET_DEFAULT_SHARED_CTX, cr_server.MainContextInfo.SpuContext); } } if (cr_server.bUseMultipleContexts) { pContextInfo->SpuContext = cr_server.head_spu->dispatch_table. CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext); if (pContextInfo->SpuContext < 0) { crWarning("crServerDispatchCreateContext() failed."); crStateEnableDiffOnMakeCurrent(GL_TRUE); cr_server.bUseMultipleContexts = GL_FALSE; if (!fFirst) crError("creating shared context failed, while it is expected to work!"); } else if (fFirst) { crStateEnableDiffOnMakeCurrent(GL_FALSE); } } else { pContextInfo->SpuContext = -1; } /* Now create a new state-tracker context and initialize the * dispatch function pointers. */ newCtx = crStateCreateContextEx(&cr_server.limits, visualBits, NULL, internalID); if (newCtx) { crStateSetCurrentPointers( newCtx, &(cr_server.current) ); crStateResetCurrentPointers(&(cr_server.current)); retVal = preloadCtxID<0 ? (GLint)crHashtableAllocKeys( cr_server.contextTable, 1 ) : preloadCtxID; pContextInfo->pContext = newCtx; Assert(pContextInfo->CreateInfo.realVisualBits == visualBits); pContextInfo->CreateInfo.externalID = retVal; pContextInfo->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL; crHashtableAdd(cr_server.contextTable, retVal, pContextInfo); } if (retVal != -1 && !cr_server.bIsInLoadingState) { int pos; for (pos = 0; pos < CR_MAX_CONTEXTS; pos++) { if (cr_server.curClient->contextList[pos] == 0) { cr_server.curClient->contextList[pos] = retVal; break; } } } crServerReturnValue( &retVal, sizeof(retVal) ); return retVal; }
void crServerGatherConfiguration(char *mothership) { CRMuralInfo *defaultMural; CRConnection *conn; 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; char *low_node = "none"; char *high_node = "none"; 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; defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0); CRASSERT(defaultMural); setDefaults(); if (mothership) { crSetenv("CRMOTHERSHIP", mothership); } conn = crMothershipConnect(); if (!conn) { crError("Couldn't connect to the mothership, I have no idea what to do!"); } /* * Get my hostname */ if (crGetHostname(hostname, sizeof(hostname))) { crError("CRServer: Couldn't get my own hostname?"); } /* Identify ourselves to the mothership */ if (cr_server.vncMode) { /* we're running inside a vnc viewer */ if (!crMothershipSendString( conn, response, "vncserver %s", hostname )) crError( "Bad Mothership response: %s", response ); } else { crMothershipIdentifyServer(conn, response); } 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; /* * Gather configuration options. * NOTE: when you add new options, be sure to update the * mothership/tools/crtypes.py file's NetworkNode class's notion of * config options. * XXX Use the SPU option parser code here someday. */ if (crMothershipGetServerParam( conn, response, "spu_dir" ) && crStrlen(response) > 0) { spu_dir = crStrdup(response); } /* Quadrics networking stuff */ if (crMothershipGetRank(conn, response)) { my_rank = crStrToInt(response); } crNetSetRank(my_rank); if (crMothershipGetParam(conn, "low_context", response)) { low_context = crStrToInt(response); } if (crMothershipGetParam(conn, "high_context", response)) { high_context = crStrToInt(response); } crNetSetContextRange(low_context, high_context); if (crMothershipGetParam(conn, "low_node", response)) { low_node = crStrdup(response); } if (crMothershipGetParam(conn, "high_node", response)) { high_node = crStrdup(response); } crNetSetNodeRange(low_node, high_node); if (low_node) crFree(low_node); if (high_node) crFree(high_node); if (crMothershipGetParam(conn, "comm_key", response)) { unsigned int a; char **words, *found; /* remove the silly []'s */ while ((found = crStrchr(response, '[')) != NULL) *found = ' '; while ((found = crStrchr(response, ']')) != NULL) *found = ' '; words = crStrSplit(response, ","); a = 0; while (words[a] != NULL && a < sizeof(key)) { key[a]= crStrToInt(words[a]); a++; } crFreeStrings(words); } crNetSetKey(key,sizeof(key)); if (crMothershipGetServerParam(conn, response, "port")) { cr_server.tcpip_port = crStrToInt(response); } if (crMothershipGetServerParam(conn, response, "optimize_bucket")) { cr_server.optimizeBucket = crStrToInt(response); } if (crMothershipGetServerParam(conn, response, "local_tile_spec")) { cr_server.localTileSpec = crStrToInt(response); } if (crMothershipGetServerParam(conn, response, "lightning2")) { cr_server.useL2 = crStrToInt(response); } if (crMothershipGetServerParam(conn, response, "ignore_papi")) { 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")) { int a; char **levels, *found; /* remove the []'s */ while ((found = crStrchr(response, '['))) *found = ' '; while ((found = crStrchr(response, ']'))) *found = ' '; levels = crStrSplit(response, ","); a = 0; while (levels[a] != NULL) { crDebug("%d: %s", a, levels[a]); cr_server.num_overlap_intens++; a++; } cr_server.overlap_intens = (float *)crAlloc(cr_server.num_overlap_intens*sizeof(float)); for (a=0; a<cr_server.num_overlap_intens; a++) cr_server.overlap_intens[a] = crStrToFloat(levels[a]); crFreeStrings(levels); } if (crMothershipGetServerParam(conn, response, "only_swap_once")) { cr_server.only_swap_once = crStrToInt(response); } if (crMothershipGetServerParam(conn, response, "debug_barriers")) { cr_server.debug_barriers = crStrToInt(response); } if (crMothershipGetServerParam(conn, response, "shared_display_lists")) { cr_server.sharedDisplayLists = crStrToInt(response); } if (crMothershipGetServerParam(conn, response, "shared_texture_objects")) { cr_server.sharedTextureObjects = crStrToInt(response); } if (crMothershipGetServerParam(conn, response, "shared_programs")) { cr_server.sharedPrograms = crStrToInt(response); } if (crMothershipGetServerParam(conn, response, "shared_windows")) { cr_server.sharedWindows = crStrToInt(response); } if (crMothershipGetServerParam(conn, response, "unique_window_ids")) { cr_server.uniqueWindows = crStrToInt(response); } if (crMothershipGetServerParam(conn, response, "use_dmx")) { cr_server.useDMX = crStrToInt(response); } if (crMothershipGetServerParam(conn, response, "vertprog_projection_param")) { if (crIsDigit(response[0])) { cr_server.vpProjectionMatrixParameter = crStrToInt(response); } else { cr_server.vpProjectionMatrixVariable = crStrdup(response); } } if (crMothershipGetServerParam(conn, response, "stereo_view")) { if (crStrcmp(response, "left") == 0) cr_server.stereoView = 0x1; else if (crStrcmp(response, "right") == 0) cr_server.stereoView = 0x2; else if (crStrcmp(response, "both") == 0) cr_server.stereoView = 0x3; else cr_server.stereoView = 0x3; } if (crMothershipGetServerParam(conn, response, "view_matrix")) { crMatrixInitFromString(&cr_server.viewMatrix[0], response); cr_server.viewOverride = GL_TRUE; } if (crMothershipGetServerParam(conn, response, "right_view_matrix")) { crMatrixInitFromString(&cr_server.viewMatrix[1], response); cr_server.viewOverride = GL_TRUE; } if (crMothershipGetServerParam(conn, response, "projection_matrix")) { crMatrixInitFromString(&cr_server.projectionMatrix[0], response); cr_server.projectionOverride = GL_TRUE; } if (crMothershipGetServerParam(conn, response, "right_projection_matrix")) { crMatrixInitFromString(&cr_server.projectionMatrix[1], response); cr_server.projectionOverride = GL_TRUE; } if (crMothershipGetServerParam(conn, response, "exit_if_no_clients")) { cr_server.exitIfNoClients = crStrToInt(response); } 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); /* Need to do this as early as possible */ /* XXX DMX get window size instead? */ cr_server.head_spu->dispatch_table.GetIntegerv(GL_VIEWPORT, (GLint *) defaultMural->underlyingDisplay); crFree(spu_ids); crFreeStrings(spu_names); crFreeStrings(spuchain); if (spu_dir) crFree(spu_dir); cr_server.mtu = crMothershipGetMTU( conn ); /* * 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); } 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)); sscanf(clientlist[i], "%s %d", cr_server.protocol, &(newClient->spu_id)); newClient->conn = crNetAcceptClient(cr_server.protocol, NULL, cr_server.tcpip_port, cr_server.mtu, 1); newClient->currentCtx = cr_server.DummyContext; 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); }
/* * Allocate a new ThreadInfo structure, setup a connection to the * server, allocate/init a packer context, bind this ThreadInfo to * the calling thread with crSetTSD(). * We'll always call this function at least once even if we're not * using threads. */ ThreadInfo *packspuNewThread( unsigned long id ) { ThreadInfo *thread=NULL; int i; #ifdef CHROMIUM_THREADSAFE crLockMutex(&_PackMutex); #else CRASSERT(pack_spu.numThreads == 0); #endif CRASSERT(pack_spu.numThreads < MAX_THREADS); for (i=0; i<MAX_THREADS; ++i) { if (!pack_spu.thread[i].inUse) { thread = &pack_spu.thread[i]; break; } } CRASSERT(thread); thread->inUse = GL_TRUE; thread->id = id; thread->currentContext = NULL; thread->bInjectThread = GL_FALSE; /* connect to the server */ thread->netServer.name = crStrdup( pack_spu.name ); thread->netServer.buffer_size = pack_spu.buffer_size; if (pack_spu.numThreads == 0) { packspuConnectToServer( &(thread->netServer) ); if (!thread->netServer.conn) { return NULL; } pack_spu.swap = thread->netServer.conn->swap; } else { /* a new pthread */ crNetNewClient(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn, &(thread->netServer)); CRASSERT(thread->netServer.conn); } /* packer setup */ CRASSERT(thread->packer == NULL); thread->packer = crPackNewContext( pack_spu.swap ); CRASSERT(thread->packer); crPackInitBuffer( &(thread->buffer), crNetAlloc(thread->netServer.conn), thread->netServer.conn->buffer_size, thread->netServer.conn->mtu ); thread->buffer.canBarf = thread->netServer.conn->Barf ? GL_TRUE : GL_FALSE; crPackSetBuffer( thread->packer, &thread->buffer ); crPackFlushFunc( thread->packer, packspuFlush ); crPackFlushArg( thread->packer, (void *) thread ); crPackSendHugeFunc( thread->packer, packspuHuge ); crPackSetContext( thread->packer ); #ifdef CHROMIUM_THREADSAFE crSetTSD(&_PackTSD, thread); #endif pack_spu.numThreads++; #ifdef CHROMIUM_THREADSAFE crUnlockMutex(&_PackMutex); #endif return thread; }
/** * 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; #if defined(WINDOWS) && defined(VBOX_WITH_WDDM) HMODULE hVBoxD3D = NULL; #endif 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; } #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."); # ifdef VBOXOGL_FAKEDRI return false; # else exit(1); # endif } else { crNetFreeConnection(ns.conn); } } #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(); #if defined(WINDOWS) && defined(VBOX_WITH_WDDM) hVBoxD3D = NULL; if (!GetModuleHandleEx(0, VBOX_MODNAME_DISPD3D, &hVBoxD3D)) { crDebug("GetModuleHandleEx failed err %d", GetLastError()); hVBoxD3D = NULL; } if (hVBoxD3D) { disable_sync = 1; crDebug("running with %s", VBOX_MODNAME_DISPD3D); stub.trackWindowVisibleRgn = 0; /* @todo: should we enable that? */ stub.trackWindowSize = 0; stub.trackWindowPos = 0; stub.trackWindowVisibility = 0; stub.bRunningUnderWDDM = true; } #endif 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; }
/** * Establish a connection with a server. * \param server the server to connect to, in the form * "protocol://servername:port" where the port specifier * is optional and if the protocol is missing it is assumed * to be "tcpip". * \param default_port the port to connect to, if port not specified in the * server URL string. * \param mtu desired maximum transmission unit size (in bytes) * \param broker either 1 or 0 to indicate if connection is brokered through * the mothership */ CRConnection * crNetConnectToServer( const char *server, unsigned short default_port, int mtu, int broker ) { char hostname[4096], protocol[4096]; unsigned short port; CRConnection *conn; crDebug( "In crNetConnectToServer( \"%s\", port=%d, mtu=%d, broker=%d )", server, default_port, mtu, broker ); CRASSERT( cr_net.initialized ); if (mtu < CR_MINIMUM_MTU) { crError( "You tried to connect to server \"%s\" with an mtu of %d, " "but the minimum MTU is %d", server, mtu, CR_MINIMUM_MTU ); } /* Tear the URL apart into relevant portions. */ if ( !crParseURL( server, protocol, hostname, &port, default_port ) ) { crError( "Malformed URL: \"%s\"", server ); } /* If the host name is "localhost" replace it with the _real_ name * of the localhost. If we don't do this, there seems to be * confusion in the mothership as to whether or not "localhost" and * "foo.bar.com" are the same machine. */ if (crStrcmp(hostname, "localhost") == 0) { int rv = crGetHostname(hostname, 4096); CRASSERT(rv == 0); (void) rv; } /* XXX why is this here??? I think it could be moved into the * crTeacConnection() function with no problem. I.e. change the * connection's port, teac_rank and tcscomm_rank there. (BrianP) */ if ( !crStrcmp( protocol, "quadrics" ) || !crStrcmp( protocol, "quadrics-tcscomm" ) ) { /* For Quadrics protocols, treat "port" as "rank" */ if ( port > CR_QUADRICS_HIGHEST_RANK ) { crWarning( "Invalid crserver rank, %d, defaulting to %d\n", port, CR_QUADRICS_LOWEST_RANK ); port = CR_QUADRICS_LOWEST_RANK; } } crDebug( "Connecting to %s on port %d, with protocol %s", hostname, port, protocol ); #ifdef SDP_SUPPORT /* This makes me ill, but we need to "fix" the hostname for sdp. MCH */ if (!crStrcmp(protocol, "sdp")) { char* temp; temp = strtok(hostname, "."); crStrcat(temp, crGetSDPHostnameSuffix()); crStrcpy(hostname, temp); crDebug("SDP rename hostname: %s", hostname); } #endif conn = (CRConnection *) crCalloc( sizeof(*conn) ); if (!conn) return NULL; /* init the non-zero fields */ conn->type = CR_NO_CONNECTION; /* we don't know yet */ conn->recv_credits = CR_INITIAL_RECV_CREDITS; conn->hostname = crStrdup( hostname ); conn->port = port; conn->mtu = mtu; conn->buffer_size = mtu; conn->broker = broker; conn->endianness = crDetermineEndianness(); /* XXX why are these here??? Move them into the crTeacConnection() * and crTcscommConnection() functions. */ conn->teac_id = -1; conn->teac_rank = port; conn->tcscomm_id = -1; conn->tcscomm_rank = port; #ifdef CHROMIUM_THREADSAFE crInitMutex(&conn->messageList.lock); crInitCondition(&conn->messageList.nonEmpty); #endif /* now, just dispatch to the appropriate protocol's initialization functions. */ InitConnection(conn, protocol, mtu); if (!crNetConnect( conn )) { crDebug("crNetConnectToServer() failed, freeing the connection"); crFree( conn ); return NULL; } crDebug( "Done connecting to %s (swapping=%d)", server, conn->swap ); return conn; }
/** * Get the tile information (count, extents, etc) from the servers * and build our corresponding data structures. * This is called once during SPU initialization. * Input: conn - mothership connection */ void tilesortspuGetTilingFromServers(CRConnection *conn, WindowInfo *winInfo) { ThreadInfo *thread0 = &(tilesort_spu.thread[0]); char response[8096]; char **serverchain, **serverlist; int num_servers; int i; crDebug("Getting tile information from servers."); /* The response to this tells us how many servers and where they are * * For example: 2 tcpip://foo tcpip://bar */ crMothershipGetServers(conn, response); serverchain = crStrSplitn(response, " ", 1); num_servers = crStrToInt(serverchain[0]); CRASSERT(num_servers == tilesort_spu.num_servers); serverlist = crStrSplit(serverchain[1], ","); tilesort_spu.thread[0].netServer = (CRNetServer *) crCalloc(num_servers * sizeof(CRNetServer)); tilesort_spu.thread[0].buffer = (CRPackBuffer *) crCalloc(num_servers * sizeof(CRPackBuffer)); /** XXX: \todo there is lots of overlap between these cases. merge! */ if (tilesort_spu.localTileSpec) { char **displaylist, **displaychain; double *corners; int num_displays, idx; double world_bbox[4]; /* * Here we has tiles specified relative to the origin of * whichever display they happen to land in. First, gather * the list of displays, then get the tiles that belong on it */ crMothershipGetDisplays(conn, response); displaychain = crStrSplitn(response, " ", 1); displaylist = crStrSplit(displaychain[1], ","); num_displays = crStrToInt(displaychain[0]); corners = (double *) crAlloc(num_displays * 8 * sizeof(double)); tilesort_spu.displays = (WarpDisplayInfo *) crAlloc(num_displays * sizeof(WarpDisplayInfo)); idx = 0; for (i = 0; i < num_displays; i++) { float pnt[2], warped[2]; sscanf(displaylist[i], "%d %d %d %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f", &tilesort_spu.displays[i].id, &tilesort_spu.displays[i].width, &tilesort_spu.displays[i].height, &tilesort_spu.displays[i].correct[0], &tilesort_spu.displays[i].correct[1], &tilesort_spu.displays[i].correct[2], &tilesort_spu.displays[i].correct[3], &tilesort_spu.displays[i].correct[4], &tilesort_spu.displays[i].correct[5], &tilesort_spu.displays[i].correct[6], &tilesort_spu.displays[i].correct[7], &tilesort_spu.displays[i].correct[8], &tilesort_spu.displays[i].correct_inv[0], &tilesort_spu.displays[i].correct_inv[1], &tilesort_spu.displays[i].correct_inv[2], &tilesort_spu.displays[i].correct_inv[3], &tilesort_spu.displays[i].correct_inv[4], &tilesort_spu.displays[i].correct_inv[5], &tilesort_spu.displays[i].correct_inv[6], &tilesort_spu.displays[i].correct_inv[7], &tilesort_spu.displays[i].correct_inv[8]); pnt[0] = -1; pnt[1] = -1; crWarpPoint(tilesort_spu.displays[i].correct_inv, pnt, warped); corners[idx] = warped[0]; corners[idx + 1] = warped[1]; idx += 2; pnt[0] = -1; pnt[1] = 1; crWarpPoint(tilesort_spu.displays[i].correct_inv, pnt, warped); corners[idx] = warped[0]; corners[idx + 1] = warped[1]; idx += 2; pnt[0] = 1; pnt[1] = 1; crWarpPoint(tilesort_spu.displays[i].correct_inv, pnt, warped); corners[idx] = warped[0]; corners[idx + 1] = warped[1]; idx += 2; pnt[0] = 1; pnt[1] = -1; crWarpPoint(tilesort_spu.displays[i].correct_inv, pnt, warped); corners[idx] = warped[0]; corners[idx + 1] = warped[1]; idx += 2; } crHullInteriorBox(corners, idx / 2, world_bbox); crFree(corners); /* dummy values in case i forget to override them later */ winInfo->muralWidth = tilesort_spu.displays[0].width; winInfo->muralHeight = tilesort_spu.displays[0].height; winInfo->passiveStereo = GL_FALSE; /* may be set true below */ for (i = 0; i < num_servers; i++) { char server_url[1024]; ServerWindowInfo *servWinInfo = winInfo->server + i; char **tilechain, **tilelist; int tile; double cent[2], Sx, Sy; sscanf(serverlist[i], "%s", server_url); crDebug("Server %d: %s", i + 1, server_url); thread0->netServer[i].name = crStrdup(server_url); thread0->netServer[i].buffer_size = tilesort_spu.buffer_size; /* response is just like regular GetTiles, but each tile * is preceeded by a display id */ if (!crMothershipGetDisplayTiles(conn, response, i)) { crError("No tile information for server %d! I can't continue!", i); } tilechain = crStrSplitn(response, " ", 1); servWinInfo->num_extents = crStrToInt(tilechain[0]); tilelist = crStrSplit(tilechain[1], ","); servWinInfo->eyeFlags = EYE_LEFT | EYE_RIGHT; if (crMothershipGetServerParamFromSPU( conn, i, "stereo_view", response)) { if (crStrcmp(response, "left") == 0) { servWinInfo->eyeFlags = EYE_LEFT; winInfo->passiveStereo = GL_TRUE; } else if (crStrcmp(response, "right") == 0) { servWinInfo->eyeFlags = EYE_RIGHT; winInfo->passiveStereo = GL_TRUE; } } Sx = 2.0 / (world_bbox[2] - world_bbox[0]); Sy = 2.0 / (world_bbox[3] - world_bbox[1]); cent[0] = (world_bbox[0] + world_bbox[2]) / (2.); cent[1] = (world_bbox[1] + world_bbox[3]) / (2.); for (tile = 0; tile < servWinInfo->num_extents; tile++) { int id, x, y, w, h, a; float disp_w, disp_h, warped[2], *align; sscanf(tilelist[tile], "%d %d %d %d %d", &id, &x, &y, &w, &h); /* this is the local coordinate tiling */ servWinInfo->display_ndx[tile] = -1; for (a = 0; a < num_displays; a++) { if (tilesort_spu.displays[a].id == id) servWinInfo->display_ndx[tile] = a; } if (servWinInfo->display_ndx[tile] == -1) crError("Invalid Display ID %d", id); servWinInfo->extents[tile].x1 = x; servWinInfo->extents[tile].y1 = y; servWinInfo->extents[tile].x2 = x + w; servWinInfo->extents[tile].y2 = y + h; /* warp the tile to mural space */ disp_w = (float) tilesort_spu.displays[servWinInfo->display_ndx[tile]].width; disp_h = (float) tilesort_spu.displays[servWinInfo->display_ndx[tile]].height; servWinInfo->world_extents[tile][0] = (float) x / disp_w; servWinInfo->world_extents[tile][1] = (float) y / disp_h; servWinInfo->world_extents[tile][2] = (float) x / disp_w; servWinInfo->world_extents[tile][3] = (float) (y + h) / disp_h; servWinInfo->world_extents[tile][4] = (float) (x + w) / disp_w; servWinInfo->world_extents[tile][5] = (float) (y + h) / disp_h; servWinInfo->world_extents[tile][6] = (float) (x + w) / disp_w; servWinInfo->world_extents[tile][7] = (float) y / disp_h; for (a = 0; a < 8; a++) servWinInfo->world_extents[tile][a] = (float)2.0 * servWinInfo->world_extents[tile][a] - (float)1.0; align = tilesort_spu.displays[servWinInfo->display_ndx[tile]].correct_inv; for (a = 0; a < 4; a++) { crWarpPoint(align, servWinInfo->world_extents[tile] + 2 * a, warped); warped[0] = (warped[0] - (float)cent[0]) * (float) Sx; warped[1] = (warped[1] - (float)cent[1]) * (float) Sy; crDebug("%f %f warps to %f %f", servWinInfo->world_extents[tile][2 * a], servWinInfo->world_extents[tile][2 * a + 1], warped[0], warped[1]); servWinInfo->world_extents[tile][2 * a] = warped[0]; servWinInfo->world_extents[tile][2 * a + 1] = warped[1]; } /** XXX: \todo check that the tile fits w/i the display it is on */ } crFreeStrings(tilechain); crFreeStrings(tilelist); } crFreeStrings(displaychain); crFreeStrings(displaylist); /* can't do any fancy bucketing with this */ tilesort_spu.defaultBucketMode = WARPED_GRID; } else { /* * Get the list of tiles from all servers. * And compute mural size. */ winInfo->muralWidth = 0; winInfo->muralHeight = 0; for (i = 0; i < num_servers; i++) { char server_url[1024]; ServerWindowInfo *servWinInfo = winInfo->server + i; char **tilechain, **tilelist; int tile; sscanf(serverlist[i], "%s", server_url); crDebug("Server %d: %s", i + 1, server_url); thread0->netServer[i].name = crStrdup(server_url); thread0->netServer[i].buffer_size = tilesort_spu.buffer_size; if (!crMothershipGetTiles(conn, response, i)) { crError("No tile information for server %d! I can't continue!", i); } tilechain = crStrSplitn(response, " ", 1); servWinInfo->num_extents = crStrToInt(tilechain[0]); tilelist = crStrSplit(tilechain[1], ","); for (tile = 0; tile < servWinInfo->num_extents; tile++) { int x, y, w, h; sscanf(tilelist[tile], "%d %d %d %d", &x, &y, &w, &h); servWinInfo->extents[tile].x1 = x; servWinInfo->extents[tile].y1 = y; servWinInfo->extents[tile].x2 = x + w; servWinInfo->extents[tile].y2 = y + h; /* update mural size */ if (servWinInfo->extents[tile].x2 > (int) winInfo->muralWidth) { winInfo->muralWidth = servWinInfo->extents[tile].x2; } if (servWinInfo->extents[tile].y2 > (int) winInfo->muralHeight) { winInfo->muralHeight = servWinInfo->extents[tile].y2; } } crFreeStrings(tilechain); crFreeStrings(tilelist); /* Determine if the server should receieve left, right or both eye * views when running in passive stereo mode. */ servWinInfo->eyeFlags = EYE_LEFT | EYE_RIGHT; if (crMothershipGetServerParamFromSPU( conn, i, "stereo_view", response)) { if (crStrcmp(response, "left") == 0) { servWinInfo->eyeFlags = EYE_LEFT; winInfo->passiveStereo = GL_TRUE; } else if (crStrcmp(response, "right") == 0) { servWinInfo->eyeFlags = EYE_RIGHT; winInfo->passiveStereo = GL_TRUE; } } /* get view matrices from the server */ if (crMothershipGetServerParamFromSPU( conn, i, "view_matrix", response)) { crMatrixInitFromString(&servWinInfo->viewMatrix[0], response); if (!crMatrixIsIdentity(&servWinInfo->viewMatrix[0])) winInfo->matrixSource = MATRIX_SOURCE_SERVERS; } if (crMothershipGetServerParamFromSPU( conn, i, "right_view_matrix", response)) { crMatrixInitFromString(&servWinInfo->viewMatrix[1], response); if (!crMatrixIsIdentity(&servWinInfo->viewMatrix[1])) winInfo->matrixSource = MATRIX_SOURCE_SERVERS; } /* crMatrixPrint("Left view", &servWinInfo->viewMatrix[0]); crMatrixPrint("Right view", &servWinInfo->viewMatrix[1]); */ /* Also get overriding projection matrix. * Note that this matrix is only relevant to FRUSTUM bucketing. */ if (crMothershipGetServerParamFromSPU( conn, i, "projection_matrix", response)) { /** XXX \todo projection_matrix is obsolete, keep for a while though */ crMatrixInitFromString(&servWinInfo->projectionMatrix[0], response); if (!crMatrixIsIdentity(&servWinInfo->projectionMatrix[0])) winInfo->matrixSource = MATRIX_SOURCE_SERVERS; } if (crMothershipGetServerParamFromSPU( conn, i, "right_projection_matrix", response)) { crMatrixInitFromString(&servWinInfo->projectionMatrix[1], response); if (!crMatrixIsIdentity(&servWinInfo->projectionMatrix[1])) winInfo->matrixSource = MATRIX_SOURCE_SERVERS; } /* crMatrixPrint("Left proj", &servWinInfo->projectionMatrix[0]); crMatrixPrint("Right proj", &servWinInfo->projectionMatrix[1]); */ } } crFreeStrings(serverchain); crFreeStrings(serverlist); tilesortspuBucketingInit( winInfo ); }
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; }
/** * 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 }