static SPUFunctions *feedbackSPUInit( int id, SPU *child, SPU *self, unsigned int context_id, unsigned int num_contexts ) { CRContext *ctx; (void) context_id; (void) num_contexts; feedback_spu.id = id; feedback_spu.has_child = 0; if (child) { crSPUInitDispatchTable( &(feedback_spu.child) ); crSPUCopyDispatchTable( &(feedback_spu.child), &(child->dispatch_table) ); feedback_spu.has_child = 1; } crSPUInitDispatchTable( &(feedback_spu.super) ); crSPUCopyDispatchTable( &(feedback_spu.super), &(self->superSPU->dispatch_table) ); feedbackspuGatherConfiguration(); /* create/init default state tracker */ crStateInit(); ctx = crStateGetCurrent(); CRASSERT(ctx); crStateSetCurrentPointers(ctx, &feedback_spu.current); return &feedback_functions; }
void SERVER_DISPATCH_APIENTRY crServerDispatchMakeCurrent( GLint window, GLint nativeWindow, GLint context ) { CRMuralInfo *mural, *oldMural; CRContextInfo *ctxInfo = NULL; CRContext *ctx, *oldCtx = NULL; if (context >= 0 && window >= 0) { mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window); if (!mural) { crWarning("CRServer: invalid window %d passed to crServerDispatchMakeCurrent()", window); return; } /* Update the state tracker's current context */ ctxInfo = (CRContextInfo *) crHashtableSearch(cr_server.contextTable, context); if (!ctxInfo) { crWarning("CRserver: NULL context in MakeCurrent %d", context); return; } } else { #if 0 oldMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, cr_server.currentWindow); if (oldMural && oldMural->bUseFBO && crServerSupportRedirMuralFBO()) { if (!crStateGetCurrent()->framebufferobject.drawFB) { cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0); } if (!crStateGetCurrent()->framebufferobject.readFB) { cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0); } } ctxInfo = &cr_server.MainContextInfo; window = -1; mural = NULL; #endif cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE; return; } cr_server.bForceMakeCurrentOnClientSwitch = GL_FALSE; ctx = ctxInfo->pContext; CRASSERT(ctx); oldMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, cr_server.currentWindow); /* Ubuntu 11.04 hosts misbehave if context window switch is * done with non-default framebuffer object settings. * crStateSwichPrepare & crStateSwichPostprocess are supposed to work around this problem * crStateSwichPrepare restores the FBO state to its default values before the context window switch, * while crStateSwichPostprocess restores it back to the original values */ oldCtx = crStateSwichPrepare(ctx, cr_server.bUseMultipleContexts, oldMural && oldMural->bUseFBO && crServerSupportRedirMuralFBO() ? oldMural->idFBO : 0); /* crDebug("**** %s client %d curCtx=%d curWin=%d", __func__, cr_server.curClient->number, ctxPos, window); */ cr_server.curClient->currentContextNumber = context; cr_server.curClient->currentCtxInfo = ctxInfo; cr_server.curClient->currentMural = mural; cr_server.curClient->currentWindow = window; CRASSERT(cr_server.curClient->currentCtxInfo); CRASSERT(cr_server.curClient->currentCtxInfo->pContext); /* This is a hack to force updating the 'current' attribs */ crStateUpdateColorBits(); if (ctx) crStateSetCurrentPointers( ctx, &(cr_server.current) ); /* check if being made current for first time, update viewport */ #if 0 if (ctx) { /* initialize the viewport */ if (ctx->viewport.viewportW == 0) { ctx->viewport.viewportW = mural->width; ctx->viewport.viewportH = mural->height; ctx->viewport.scissorW = mural->width; ctx->viewport.scissorH = mural->height; } } #endif /* crDebug("**** %s currentWindow %d newWindow %d", __func__, cr_server.currentWindow, window); */ if (1/*cr_server.firstCallMakeCurrent || cr_server.currentWindow != window || cr_server.currentNativeWindow != nativeWindow*/) { /* Since the cr server serialized all incoming contexts/clients into * one output stream of GL commands, we only need to call the head * SPU's MakeCurrent() function once. * BUT, if we're rendering to multiple windows, we do have to issue * MakeCurrent() calls sometimes. The same GL context will always be * used though. */ cr_server.head_spu->dispatch_table.MakeCurrent( mural->spuWindow, nativeWindow, ctxInfo->SpuContext >= 0 ? ctxInfo->SpuContext : cr_server.MainContextInfo.SpuContext); cr_server.firstCallMakeCurrent = GL_FALSE; cr_server.currentCtxInfo = ctxInfo; cr_server.currentWindow = window; cr_server.currentNativeWindow = nativeWindow; } /* This used to be earlier, after crStateUpdateColorBits() call */ crStateMakeCurrent( ctx ); crStateSwichPostprocess(oldCtx, cr_server.bUseMultipleContexts, mural->bUseFBO && crServerSupportRedirMuralFBO() ? mural->idFBO : 0); if (!ctx->framebufferobject.drawFB && (ctx->buffer.drawBuffer == GL_FRONT || ctx->buffer.drawBuffer == GL_FRONT_LEFT)) cr_server.curClient->currentMural->bFbDraw = GL_TRUE; if (!mural->bUseFBO) { ctx->buffer.width = mural->width; ctx->buffer.height = mural->height; } else { ctx->buffer.width = 0; ctx->buffer.height = 0; } }
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; }
void crServerPerformMakeCurrent( CRMuralInfo *mural, CRContextInfo *ctxInfo ) { CRMuralInfo *oldMural; CRContext *ctx, *oldCtx = NULL; GLuint idDrawFBO, idReadFBO; GLint context = ctxInfo->CreateInfo.externalID; GLint window = mural->CreateInfo.externalID; cr_server.bForceMakeCurrentOnClientSwitch = GL_FALSE; ctx = ctxInfo->pContext; CRASSERT(ctx); oldMural = cr_server.currentMural; /* Ubuntu 11.04 hosts misbehave if context window switch is * done with non-default framebuffer object settings. * crStateSwitchPrepare & crStateSwitchPostprocess are supposed to work around this problem * crStateSwitchPrepare restores the FBO state to its default values before the context window switch, * while crStateSwitchPostprocess restores it back to the original values */ oldCtx = crStateGetCurrent(); if (oldMural && oldMural->fRedirected && crServerSupportRedirMuralFBO()) { idDrawFBO = CR_SERVER_FBO_FOR_IDX(oldMural, oldMural->iCurDrawBuffer); idReadFBO = CR_SERVER_FBO_FOR_IDX(oldMural, oldMural->iCurReadBuffer); } else { idDrawFBO = 0; idReadFBO = 0; } crStateSwitchPrepare(cr_server.bUseMultipleContexts ? NULL : ctx, oldCtx, idDrawFBO, idReadFBO); if (cr_server.curClient) { /* crDebug("**** %s client %d curCtx=%d curWin=%d", __func__, cr_server.curClient->number, ctxPos, window); */ cr_server.curClient->currentContextNumber = context; cr_server.curClient->currentCtxInfo = ctxInfo; cr_server.curClient->currentMural = mural; cr_server.curClient->currentWindow = window; CRASSERT(cr_server.curClient->currentCtxInfo); CRASSERT(cr_server.curClient->currentCtxInfo->pContext); } /* This is a hack to force updating the 'current' attribs */ crStateUpdateColorBits(); if (ctx) crStateSetCurrentPointers( ctx, &(cr_server.current) ); /* check if being made current for first time, update viewport */ #if 0 if (ctx) { /* initialize the viewport */ if (ctx->viewport.viewportW == 0) { ctx->viewport.viewportW = mural->width; ctx->viewport.viewportH = mural->height; ctx->viewport.scissorW = mural->width; ctx->viewport.scissorH = mural->height; } } #endif /* crDebug("**** %s currentWindow %d newWindow %d", __func__, cr_server.currentWindow, window); */ if (1/*cr_server.firstCallMakeCurrent || cr_server.currentWindow != window || cr_server.currentNativeWindow != nativeWindow*/) { /* Since the cr server serialized all incoming contexts/clients into * one output stream of GL commands, we only need to call the head * SPU's MakeCurrent() function once. * BUT, if we're rendering to multiple windows, we do have to issue * MakeCurrent() calls sometimes. The same GL context will always be * used though. */ cr_server.head_spu->dispatch_table.MakeCurrent( mural->spuWindow, 0, ctxInfo->SpuContext >= 0 ? ctxInfo->SpuContext : cr_server.MainContextInfo.SpuContext); CR_STATE_SHAREDOBJ_USAGE_SET(mural, ctx); if (cr_server.currentCtxInfo) cr_server.currentCtxInfo->currentMural = NULL; ctxInfo->currentMural = mural; cr_server.firstCallMakeCurrent = GL_FALSE; cr_server.currentCtxInfo = ctxInfo; cr_server.currentWindow = window; cr_server.currentNativeWindow = 0; cr_server.currentMural = mural; } /* This used to be earlier, after crStateUpdateColorBits() call */ crStateMakeCurrent( ctx ); if (mural && mural->fRedirected && crServerSupportRedirMuralFBO()) { GLuint id = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer); if (id != mural->iCurDrawBuffer) { crDebug("DBO draw buffer changed on make current"); mural->iCurDrawBuffer = id; } id = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer); if (id != mural->iCurReadBuffer) { crDebug("DBO read buffer changed on make current"); mural->iCurReadBuffer = id; } idDrawFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer); idReadFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer); } else { idDrawFBO = 0; idReadFBO = 0; } crStateSwitchPostprocess(ctx, cr_server.bUseMultipleContexts ? NULL : oldCtx, idDrawFBO, idReadFBO); if (!ctx->framebufferobject.drawFB && (ctx->buffer.drawBuffer == GL_FRONT || ctx->buffer.drawBuffer == GL_FRONT_LEFT) && cr_server.curClient) cr_server.curClient->currentMural->bFbDraw = GL_TRUE; if (!mural->fRedirected) { ctx->buffer.width = mural->width; ctx->buffer.height = mural->height; } else { ctx->buffer.width = 0; ctx->buffer.height = 0; } }
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; }
GLint REPLICATESPU_APIENTRY replicatespu_CreateContext( const char *dpyName, GLint visual, GLint shareCtx ) { static GLint freeCtxID = MAGIC_OFFSET; char headspuname[10]; ContextInfo *context, *sharedContext = NULL; unsigned int i; if (shareCtx > 0) { sharedContext = (ContextInfo *) crHashtableSearch(replicate_spu.contextTable, shareCtx); } replicatespuFlushAll( &(replicate_spu.thread[0]) ); #ifdef CHROMIUM_THREADSAFE_notyet crLockMutex(&_ReplicateMutex); #endif replicatespuStartVnc(dpyName); /* * Alloc new ContextInfo object */ context = (ContextInfo *) crCalloc(sizeof(ContextInfo)); if (!context) { crWarning("Replicate SPU: Out of memory in CreateContext"); return -1; } /* Contexts that don't share display lists get their own * display list managers. Contexts that do, share the * display list managers of the contexts they're sharing * with (man, some grammarian has to go over that and make * it actually sound like English). */ if (sharedContext) { context->displayListManager = sharedContext->displayListManager; /* Let the DLM know that a second context is using the * same display list manager, so it can manage when its * resources are released. */ crDLMUseDLM(context->displayListManager); } else { context->displayListManager = crDLMNewDLM(0, NULL); if (!context->displayListManager) { crWarning("Replicate SPU: could not initialize display list manager."); } } /* Fill in the new context info */ if (sharedContext) context->State = crStateCreateContext(NULL, visual, sharedContext->State); else context->State = crStateCreateContext(NULL, visual, NULL); context->rserverCtx[0] = 1; /* not really used */ context->visBits = visual; context->currentWindow = 0; /* not bound */ context->dlmState = crDLMNewContext(context->displayListManager); context->displayListMode = GL_FALSE; /* not compiling */ context->displayListIdentifier = 0; context->shareCtx = shareCtx; #if 0 /* Set the Current pointers now.... */ crStateSetCurrentPointers( context->State, &(replicate_spu.thread[0].packer->current) ); #endif for (i = 1; i < CR_MAX_REPLICANTS; i++) { int r_writeback = 1, rserverCtx = -1; int sharedServerCtx; sharedServerCtx = sharedContext ? sharedContext->rserverCtx[i] : 0; if (!IS_CONNECTED(replicate_spu.rserver[i].conn)) continue; if (replicate_spu.swap) crPackCreateContextSWAP( dpyName, visual, sharedServerCtx, &rserverCtx, &r_writeback ); else crPackCreateContext( dpyName, visual, sharedServerCtx, &rserverCtx, &r_writeback ); /* Flush buffer and get return value */ replicatespuFlushOne( &(replicate_spu.thread[0]), i ); while (r_writeback) crNetRecv(); if (replicate_spu.swap) rserverCtx = (GLint) SWAP32(rserverCtx); if (rserverCtx < 0) { #ifdef CHROMIUM_THREADSAFE_notyet crUnlockMutex(&_ReplicateMutex); #endif crWarning("Replicate SPU: CreateContext failed."); return -1; /* failed */ } context->rserverCtx[i] = rserverCtx; } if (!crStrcmp( headspuname, "nop" )) replicate_spu.NOP = 0; else replicate_spu.NOP = 1; #ifdef CHROMIUM_THREADSAFE_notyet crUnlockMutex(&_ReplicateMutex); #endif crListPushBack(replicate_spu.contextList, (void *)freeCtxID); crHashtableAdd(replicate_spu.contextTable, freeCtxID, context); return freeCtxID++; }