int32_t crVBoxServerClientWrite(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t cbBuffer) { CRClient *pClient = NULL; int32_t i; #ifdef VBOXCR_LOGFPS uint64_t tstart, tend; #endif /*crDebug("=>crServer: ClientWrite u32ClientID=%d", u32ClientID);*/ for (i = 0; i < cr_server.numClients; i++) { if (cr_server.clients[i] && cr_server.clients[i]->conn && cr_server.clients[i]->conn->u32ClientID==u32ClientID) { pClient = cr_server.clients[i]; break; } } if (!pClient) return VERR_INVALID_PARAMETER; if (!pClient->conn->vMajor) return VERR_NOT_SUPPORTED; #ifdef VBOXCR_LOGFPS tstart = RTTimeNanoTS(); #endif CRASSERT(pBuffer); /* This should never fire unless we start to multithread */ CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0); /* Check if there's a blocker in queue and it's not this client */ if (cr_server.run_queue->client != pClient && crServerClientInBeginEnd(cr_server.run_queue->client)) { crDebug("crServer: client %d blocked, allow_redir_ptr = 0", u32ClientID); pClient->conn->allow_redir_ptr = 0; } else { pClient->conn->allow_redir_ptr = 1; } pClient->conn->pBuffer = pBuffer; pClient->conn->cbBuffer = cbBuffer; crNetRecv(); CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0); crServerServiceClients(); #if 0 if (pClient->currentMural) { crStateViewport( 0, 0, 500, 500 ); pClient->currentMural->viewportValidated = GL_FALSE; cr_server.head_spu->dispatch_table.Viewport( 0, 0, 500, 500 ); crStateViewport( 0, 0, 600, 600 ); pClient->currentMural->viewportValidated = GL_FALSE; cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 ); crStateMatrixMode(GL_PROJECTION); cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION); crServerDispatchLoadIdentity(); crStateFrustum(-0.6, 0.6, -0.5, 0.5, 1.5, 150.0); cr_server.head_spu->dispatch_table.Frustum(-0.6, 0.6, -0.5, 0.5, 1.5, 150.0); crServerDispatchLoadIdentity(); crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); crStateMatrixMode(GL_MODELVIEW); cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW); crServerDispatchLoadIdentity(); crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); crServerDispatchLoadIdentity(); } #endif crStateResetCurrentPointers(&cr_server.current); CRASSERT(!pClient->conn->allow_redir_ptr || crNetNumMessages(pClient->conn)==0); #ifdef VBOXCR_LOGFPS tend = RTTimeNanoTS(); pClient->timeUsed += tend-tstart; #endif /*crDebug("<=crServer: ClientWrite u32ClientID=%d", u32ClientID);*/ return VINF_SUCCESS; }
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; }
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; }