GLboolean STATE_APIENTRY crStateIsBufferARB(GLuint buffer) { CRContext *g = GetCurrentContext(); CRBufferObjectState *b = &g->bufferobject; FLUSH(); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glIsBufferARB called in begin/end"); return GL_FALSE; } if (buffer && crHashtableSearch(g->shared->buffersTable, buffer)) return GL_TRUE; else return GL_FALSE; }
DECLEXPORT(void) WINAPI VBoxFlushToHost ( HGLRC hglrc ) { ContextInfo *context; CR_DDI_PROLOGUE(); // crHashtableLock(stub.windowTable); crHashtableLock(stub.contextTable); context = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) hglrc); if (context) stubConFlush(CR_CTX_CON(context)); else crWarning("invalid context %#x", hglrc); crHashtableUnlock(stub.contextTable); // crHashtableUnlock(stub.windowTable); }
static void RENDER_APIENTRY renderspuWindowShow( GLint win, GLint flag ) { WindowInfo *window; CRASSERT(win >= 0); window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win); if (window) { if (window->nativeWindow) { /* We're rendering back to the native app window instead of the * new window which we (the Render SPU) created earlier. * So, we never want to show the Render SPU's window. */ flag = 0; } renderspu_SystemShowWindow( window, (GLboolean) flag ); } else { crDebug("Render SPU: Attempt to hide/show invalid window (%d)", win); } }
DECLEXPORT(void) STATE_APIENTRY crStateBindRenderbufferEXT(GLenum target, GLuint renderbuffer) { CRContext *g = GetCurrentContext(); CRFramebufferObjectState *fbo = &g->framebufferobject; CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end"); CRSTATE_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target"); if (renderbuffer) { fbo->renderbuffer = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffer); if (!fbo->renderbuffer) { CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->rbTable, renderbuffer), GL_INVALID_OPERATION, "name is not a renderbuffer"); fbo->renderbuffer = crStateRenderbufferAllocate(g, renderbuffer); } CR_STATE_SHAREDOBJ_USAGE_SET(fbo->renderbuffer, g); } else fbo->renderbuffer = NULL; }
static void MATTESPU_APIENTRY matteDestroyContext(GLint ctx) { ContextInfo *contextInfo; GET_CONTEXT_INFO(currentContextInfo); /* If we're destroying the current context, the current * context goes to NULL. */ contextInfo = crHashtableSearch(matte_spu.contextTable, ctx); if (contextInfo == currentContextInfo) { SET_CONTEXT_INFO(NULL); } /* Destroy the context info record */ if (contextInfo != NULL) { crHashtableDelete(matte_spu.contextTable, ctx, matteFreeContextInfo); } /* Pass it along */ matte_spu.super.DestroyContext(ctx); }
void SERVER_DISPATCH_APIENTRY crServerDispatchSemaphoreCreateCR( GLuint name, GLuint count ) { CRServerSemaphore *sema; if (cr_server.ignore_papi) { cr_server.head_spu->dispatch_table.SemaphoreCreateCR( name, count ); return; } sema = crHashtableSearch(cr_server.semaphores, name); if (sema) return; /* already created */ sema = (CRServerSemaphore *) crAlloc( sizeof( *sema ) ); crHashtableAdd( cr_server.semaphores, name, sema ); sema->count = count; sema->waiting = sema->tail = NULL; if (cr_server.debug_barriers) crDebug("crserver: SemaphoreCreate(id=%d, count=%d)", name, count); }
DECLEXPORT(void) WINAPI VBoxCtxChromiumParameteriCR(HGLRC hglrc, GLenum param, GLint value) { ContextInfo *context; CR_DDI_PROLOGUE(); // crHashtableLock(stub.windowTable); crHashtableLock(stub.contextTable); context = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) hglrc); if (context) { stubCtxCheckCreate(context); stubConChromiumParameteriCR(CR_CTX_CON(context), param, value); } else crWarning("invalid context %#x", hglrc); crHashtableUnlock(stub.contextTable); // crHashtableUnlock(stub.windowTable); }
GLuint crHashtableAllocKeys( CRHashTable *h, GLsizei range) { GLuint res; int i; #ifdef CHROMIUM_THREADSAFE crLockMutex(&h->mutex); #endif res = crHashIdPoolAllocBlock (h->idPool, range); #ifdef DEBUG_misha Assert(res); for (i = 0; i < range; ++i) { void *search = crHashtableSearch( h, res+i ); Assert(!search); } #endif #ifdef CHROMIUM_THREADSAFE crUnlockMutex(&h->mutex); #endif return res; }
/* Semaphore signal */ void SERVER_DISPATCH_APIENTRY crServerDispatchSemaphoreVCR( GLuint name ) { CRServerSemaphore *sema; if (cr_server.ignore_papi) { cr_server.head_spu->dispatch_table.SemaphoreVCR( name ); return; } sema = (CRServerSemaphore *) crHashtableSearch( cr_server.semaphores, name ); if (!sema) { crError( "No such semaphore: %d", name ); } if (sema->waiting) { wqnode *temp = sema->waiting; if (cr_server.debug_barriers) crDebug("crserver: SemaphoreV(client=%p, id=%d, count=%d) - unblock.", cr_server.curClient, name, sema->count); /* unblock one waiter */ temp->q->blocked = 0; sema->waiting = temp->next; crFree( temp ); if (!sema->waiting) { sema->tail = NULL; } } else { /* nobody's waiting */ if (cr_server.debug_barriers) crDebug("crserver: SemaphoreV(client=%p, id=%d, count=%d) - increment to %d", cr_server.curClient, name, sema->count, sema->count + 1); sema->count++; } }
static void RENDER_APIENTRY renderspuVBoxPresentComposition( GLint win, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry ) { WindowInfo *window; CRASSERT(win >= 0); window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win); if (window) { if (pCompositor && CrVrScrCompositorIsEmpty(pCompositor) && !window->fCompositorPresentEmpty) pCompositor = NULL; if (pCompositor) window->fCompositorPresentEmpty = GL_FALSE; renderspuVBoxCompositorSet( window, pCompositor); if (pCompositor) { renderspu_SystemVBoxPresentComposition(window, pChangedEntry); } } else { crDebug("Render SPU: Attempt to PresentComposition for invalid window (%d)", win); } }
int DLM_APIENTRY crDLMGetReferences(CRDLM *dlm, unsigned long listIdentifier, int firstIndex, int sizeofBuffer, unsigned int *buffer) { DLMListInfo *listInfo; listInfo = (DLMListInfo *) crHashtableSearch(dlm->displayLists, listIdentifier); if (listInfo) { struct getRefsCallbackParms cbParms; cbParms.remainingOffset = firstIndex; cbParms.remainingCount = sizeofBuffer; cbParms.buffer = buffer; cbParms.totalCount = 0; crHashtableWalk(listInfo->references, getRefsCallback, (void *)&cbParms); return cbParms.totalCount; } else { /* No list exists; it therefore has no references */ return 0; } }
stubGetWindowInfo( Display *dpy, GLXDrawable drawable ) #endif { WindowInfo *winInfo = (WindowInfo *) crHashtableSearch(stub.windowTable, (unsigned int) drawable); if (!winInfo) { winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo)); if (!winInfo) return NULL; #ifdef GLX crStrncpy(winInfo->dpyName, DisplayString(dpy), MAX_DPY_NAME); winInfo->dpyName[MAX_DPY_NAME-1] = 0; winInfo->dpy = dpy; #elif defined(Darwin) winInfo->connection = _CGSDefaultConnection(); // store our connection as default #endif winInfo->drawable = drawable; winInfo->type = UNDECIDED; winInfo->spuWindow = -1; winInfo->mapped = -1; /* don't know */ crHashtableAdd(stub.windowTable, (unsigned int) drawable, winInfo); } return winInfo; }
static void RENDER_APIENTRY renderspuWindowSize( GLint win, GLint w, GLint h ) { WindowInfo *window; CRASSERT(win >= 0); window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win); if (window) { if (w != window->BltInfo.width || h != window->BltInfo.height) { /* window is resized, compositor data is no longer valid * this set also ensures all redraw operations are done in the redraw thread * and that no redraw is started until new Present request comes containing a valid presentation data */ renderspuVBoxCompositorSet( window, NULL); renderspu_SystemWindowSize( window, w, h ); window->BltInfo.width = w; window->BltInfo.height = h; } } else { crDebug("Render SPU: Attempt to resize invalid window (%d)", win); } }
static void RENDER_APIENTRY renderspuDestroyContext( GLint ctx ) { ContextInfo *context, *curCtx; CRASSERT(ctx); if (ctx == CR_RENDER_DEFAULT_CONTEXT_ID) { crWarning("request to destroy a default context, ignoring"); return; } context = (ContextInfo *) crHashtableSearch(render_spu.contextTable, ctx); CRASSERT(context); { if (!context) { crWarning("request to delete inexistent context"); return; } } curCtx = GET_CONTEXT_VAL(); CRASSERT(curCtx); if (curCtx == context) { renderspuMakeCurrent( CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID ); curCtx = GET_CONTEXT_VAL(); Assert(curCtx); Assert(curCtx != context); } crHashtableDelete(render_spu.contextTable, ctx, NULL); renderspuContextMarkDeletedAndRelease(context); }
void stubDestroyWindow( GLint con, GLint window ) { WindowInfo *winInfo = (WindowInfo *) crHashtableSearch(stub.windowTable, (unsigned int) window); if (winInfo && winInfo->type == CHROMIUM && stub.spu) { crHashtableLock(stub.windowTable); stub.spu->dispatch_table.VBoxWindowDestroy(con, winInfo->spuWindow ); #ifdef WINDOWS if (winInfo->hVisibleRegion != INVALID_HANDLE_VALUE) { DeleteObject(winInfo->hVisibleRegion); } #elif defined(GLX) if (winInfo->pVisibleRegions) { XFree(winInfo->pVisibleRegions); } # ifdef CR_NEWWINTRACK if (winInfo->syncDpy) { XCloseDisplay(winInfo->syncDpy); } # endif #endif stubForcedFlush(con); crHashtableWalk(stub.contextTable, stubWindowCleanupForContextsCB, winInfo); crHashtableDelete(stub.windowTable, window, crFree); crHashtableUnlock(stub.windowTable); } }
void stubDestroyContext( unsigned long contextId ) { ContextInfo *context; if (!stub.contextTable) { return; } /* the lock order is windowTable->contextTable (see wglMakeCurrent_prox, glXMakeCurrent) * this is why we need to take a windowTable lock since we will later do stub.windowTable access & locking */ crHashtableLock(stub.windowTable); crHashtableLock(stub.contextTable); context = (ContextInfo *) crHashtableSearch(stub.contextTable, contextId); if (context) stubDestroyContextLocked(context); else crError("No context."); #ifdef CHROMIUM_THREADSAFE if (stubGetCurrentContext() == context) { stubSetCurrentContext(NULL); } VBoxTlsRefMarkDestroy(context); VBoxTlsRefRelease(context); #else if (stubGetCurrentContext() == context) { stubSetCurrentContext(NULL); } stubContextFree(context); #endif crHashtableUnlock(stub.contextTable); crHashtableUnlock(stub.windowTable); }
void STATE_APIENTRY crStateGetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) { CRContext *g = GetCurrentContext(); CROcclusionState *o = &(g->occlusion); CROcclusionObject *q; FLUSH(); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGetGetQueryObjectuivARB called in begin/end"); return; } q = (CROcclusionObject *) crHashtableSearch(o->objects, id); if (!q || q->active) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGetQueryObjectuivARB"); return; } switch (pname) { case GL_QUERY_RESULT_ARB: *params = q->passedCounter; break; case GL_QUERY_RESULT_AVAILABLE_ARB: /* XXX revisit when we have a hardware implementation! */ *params = GL_TRUE; break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)"); return; } }
GLint RENDER_APIENTRY renderspuCreateContext(const char *dpyName, GLint visBits, GLint shareCtx) { ContextInfo *context, *sharedContext = NULL; VisualInfo *visual; if (shareCtx > 0) { sharedContext = (ContextInfo *) crHashtableSearch(render_spu.contextTable, shareCtx); } if (!dpyName || crStrlen(render_spu.display_string)>0) dpyName = render_spu.display_string; visual = renderspuFindVisual(dpyName, visBits); if (!visual) return -1; context = (ContextInfo *) crCalloc(sizeof(ContextInfo)); if (!context) return -1; context->id = render_spu.context_id; context->shared = sharedContext; if (!renderspu_SystemCreateContext(visual, context, sharedContext)) return -1; crHashtableAdd(render_spu.contextTable, render_spu.context_id, context); render_spu.context_id++; /* crDebug("Render SPU: CreateContext(%s, 0x%x) returning %d", dpyName, visBits, context->id); */ return context->id; }
void REPLICATESPU_APIENTRY replicatespu_WindowSize( GLint win, GLint w, GLint h ) { WindowInfo *winInfo = (WindowInfo *) crHashtableSearch( replicate_spu.windowTable, win ); GET_THREAD(thread); int i; winInfo->width = w; winInfo->height = h; replicatespuFlushAll( (void *) thread ); for (i = 0; i < CR_MAX_REPLICANTS; i++) { if (!IS_CONNECTED(replicate_spu.rserver[i].conn)) continue; if (replicate_spu.swap) crPackWindowSizeSWAP( winInfo->id[i], w, h ); else crPackWindowSize( winInfo->id[i], w, h ); replicatespuFlushOne(thread, i); } }
static void MATTESPU_APIENTRY matteMakeCurrent(GLint crWindow, GLint nativeWindow, GLint ctx) { ContextInfo *contextInfo; matte_spu.super.MakeCurrent(crWindow, nativeWindow, ctx); /* If we've already got a context record for this, use it. * Otherwise, make a new one. */ contextInfo = crHashtableSearch(matte_spu.contextTable, ctx); if (contextInfo == NULL) { /* Make our own. */ contextInfo = crCalloc(sizeof(ContextInfo)); if (contextInfo == NULL) { crError("matte: could not allocate context info record for context %d", ctx); return; } crHashtableAdd(matte_spu.contextTable, ctx, contextInfo); } /* Set this a s the current context */ SET_CONTEXT_INFO(contextInfo); }
void RENDER_APIENTRY renderspuWindowDestroy( GLint win ) { WindowInfo *window; CRASSERT(win >= 0); if (win == CR_RENDER_DEFAULT_WINDOW_ID) { crWarning("request to destroy a default mural, ignoring"); return; } window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win); if (window) { crDebug("Render SPU: Destroy window (%d)", win); renderspuWindowTerm( window ); /* remove window info from hash table, and free it */ crHashtableDelete(render_spu.windowTable, win, crFree); } else { crDebug("Render SPU: Attempt to destroy invalid window (%d)", win); } }
//we're not going to change icdTable at runtime, so callback is unused PICDTABLE APIENTRY DrvSetContext(HDC hdc, HGLRC hglrc, void *callback) { ContextInfo *context; WindowInfo *window; BOOL ret; CR_DDI_PROLOGUE(); /*crDebug( "DrvSetContext called(0x%x, 0x%x)", hdc, hglrc );*/ (void) (callback); crHashtableLock(stub.windowTable); crHashtableLock(stub.contextTable); context = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) hglrc); window = stubGetWindowInfo(hdc); ret = stubMakeCurrent(window, context); crHashtableUnlock(stub.contextTable); crHashtableUnlock(stub.windowTable); return ret ? &icdTable:NULL; }
void crServerSetVBoxConfigurationHGCM() { CRMuralInfo *defaultMural; int spu_ids[1] = {0}; char *spu_names[1] = {"render"}; char *spu_dir = NULL; int i; GLint dims[4]; const char * env; defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0); CRASSERT(defaultMural); //@todo should be moved to addclient so we have a chain for each client setDefaults(); /* Load the SPUs */ cr_server.head_spu = crSPULoadChain(1, spu_ids, spu_names, spu_dir, &cr_server); if (!cr_server.head_spu) return; env = crGetenv( "CR_SERVER_DEFAULT_RENDER_TYPE" ); if (env != NULL) { GLubyte redir = (env[0] - 0x30); if (redir <= CR_SERVER_REDIR_MAXVAL) { int rc = crServerSetOffscreenRenderingMode(redir); if (!RT_SUCCESS(rc)) crWarning("offscreen rendering unsupported, no offscreen rendering will be used.."); } else crWarning("invalid redir option %c", redir); } #if defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS) || defined(GLX) else { int rc = crServerSetOffscreenRenderingMode(CR_SERVER_REDIR_FBO_BLT); if (!RT_SUCCESS(rc)) crWarning("offscreen rendering unsupported, no offscreen rendering will be used.."); } #endif cr_server.bOffscreenRenderingDefault = cr_server.bForceOffscreenRendering; cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_POSITION_CR, 0, GL_INT, 2, &dims[0]); cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, 0, GL_INT, 2, &dims[2]); defaultMural->gX = dims[0]; defaultMural->gY = dims[1]; defaultMural->width = dims[2]; defaultMural->height = dims[3]; cr_server.mtu = 1024 * 250; cr_server.numClients = 0; strcpy(cr_server.protocol, "vboxhgcm"); for (i = 0; i < cr_server.numClients; i++) { CRClient *newClient = (CRClient *) crCalloc(sizeof(CRClient)); newClient->spu_id = 0; newClient->conn = crNetAcceptClient(cr_server.protocol, NULL, cr_server.tcpip_port, cr_server.mtu, 0); newClient->currentCtxInfo = &cr_server.MainContextInfo; crServerAddToRunQueue(newClient); cr_server.clients[i] = newClient; } /* set default client and mural */ if (cr_server.numClients > 0) { cr_server.curClient = cr_server.clients[0]; cr_server.curClient->currentMural = defaultMural; cr_server.client_spu_id =cr_server.clients[0]->spu_id; } }
/** * Allocate a new ContextInfo object, initialize it, put it into the * context hash table. If type==CHROMIUM, call the head SPU's * CreateContext() function too. */ ContextInfo * stubNewContext(char *dpyName, GLint visBits, ContextType type, unsigned long shareCtx #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) , struct VBOXUHGSMI *pHgsmi #endif ) { GLint spuContext = -1, spuShareCtx = 0, spuConnection = 0; ContextInfo *context; if (shareCtx > 0) { /* translate shareCtx to a SPU context ID */ context = (ContextInfo *) crHashtableSearch(stub.contextTable, shareCtx); if (context) spuShareCtx = context->spuContext; } if (type == CHROMIUM) { #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) if (pHgsmi) { spuConnection = stub.spu->dispatch_table.VBoxConCreate(pHgsmi); if (!spuConnection) { crWarning("VBoxConCreate failed"); return NULL; } } #endif spuContext = stub.spu->dispatch_table.VBoxCreateContext(spuConnection, dpyName, visBits, spuShareCtx); if (spuContext < 0) { crWarning("VBoxCreateContext failed"); #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) if (spuConnection) stub.spu->dispatch_table.VBoxConDestroy(spuConnection); #endif return NULL; } } context = crCalloc(sizeof(ContextInfo)); if (!context) { stub.spu->dispatch_table.DestroyContext(spuContext); #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) if (spuConnection) stub.spu->dispatch_table.VBoxConDestroy(spuConnection); #endif return NULL; } if (!dpyName) dpyName = ""; context->id = stub.freeContextNumber++; context->type = type; context->spuContext = spuContext; context->visBits = visBits; context->currentDrawable = NULL; crStrncpy(context->dpyName, dpyName, MAX_DPY_NAME); context->dpyName[MAX_DPY_NAME-1] = 0; #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) context->spuConnection = spuConnection; context->pHgsmi = pHgsmi; #endif #ifdef CHROMIUM_THREADSAFE VBoxTlsRefInit(context, stubContextDtor); #endif #if defined(GLX) || defined(DARWIN) context->share = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) shareCtx); #endif #ifdef GLX context->pGLXPixmapsHash = crAllocHashtable(); context->damageQueryFailed = GL_FALSE; context->damageEventsBase = 0; #endif crHashtableAdd(stub.contextTable, context->id, (void *) context); return context; }
void RENDER_APIENTRY renderspuMakeCurrent(GLint crWindow, GLint nativeWindow, GLint ctx) { WindowInfo *window; ContextInfo *context; /* crDebug("%s win=%d native=0x%x ctx=%d", __FUNCTION__, crWindow, (int) nativeWindow, ctx); */ window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, crWindow); context = (ContextInfo *) crHashtableSearch(render_spu.contextTable, ctx); if (window && context) { #ifdef CHROMIUM_THREADSAFE crSetTSD(&_RenderTSD, context); #else render_spu.currentContext = context; #endif context->currentWindow = window; if (!window) { crDebug("Render SPU: MakeCurrent invalid window id: %d", crWindow); return; } if (!context) { crDebug("Render SPU: MakeCurrent invalid context id: %d", ctx); return; } renderspu_SystemMakeCurrent( window, nativeWindow, context ); if (!context->everCurrent) { /* print OpenGL info */ const char *extString = (const char *) render_spu.ws.glGetString( GL_EXTENSIONS ); /* crDebug( "Render SPU: GL_EXTENSIONS: %s", render_spu.ws.glGetString( GL_EXTENSIONS ) ); */ crInfo( "Render SPU: GL_VENDOR: %s", render_spu.ws.glGetString( GL_VENDOR ) ); crInfo( "Render SPU: GL_RENDERER: %s", render_spu.ws.glGetString( GL_RENDERER ) ); crInfo( "Render SPU: GL_VERSION: %s", render_spu.ws.glGetString( GL_VERSION ) ); crInfo( "Render SPU: GL_EXTENSIONS: %s", render_spu.ws.glGetString( GL_EXTENSIONS ) ); if (crStrstr(extString, "GL_ARB_window_pos")) context->haveWindowPosARB = GL_TRUE; else context->haveWindowPosARB = GL_FALSE; context->everCurrent = GL_TRUE; } if (crWindow == CR_RENDER_DEFAULT_WINDOW_ID && window->mapPending && !render_spu.render_to_app_window && !render_spu.render_to_crut_window) { /* Window[CR_RENDER_DEFAULT_CONTEXT_ID] is special, it's the default window and normally hidden. * If the mapPending flag is set, then we should now make the window * visible. */ /*renderspu_SystemShowWindow( window, GL_TRUE );*/ window->mapPending = GL_FALSE; } window->everCurrent = GL_TRUE; } else if (!crWindow && !ctx) { renderspu_SystemMakeCurrent( NULL, 0, NULL ); #ifdef CHROMIUM_THREADSAFE crSetTSD(&_RenderTSD, NULL); #else render_spu.currentContext = NULL; #endif } else { crError("renderspuMakeCurrent invalid ids: crWindow(%d), ctx(%d)", crWindow, ctx); } }
void SERVER_DISPATCH_APIENTRY crServerDispatchDestroyContext( GLint ctx ) { CRContextInfo *crCtxInfo; CRContext *crCtx; int32_t client; CRClientNode *pNode; int found=false; crCtxInfo = (CRContextInfo *) crHashtableSearch(cr_server.contextTable, ctx); if (!crCtxInfo) { crWarning("CRServer: DestroyContext invalid context %d", ctx); return; } crCtx = crCtxInfo->pContext; CRASSERT(crCtx); crDebug("CRServer: DestroyContext context %d", ctx); crHashtableDelete(cr_server.contextTable, ctx, NULL); crStateDestroyContext( crCtx ); if (crCtxInfo->CreateInfo.pszDpyName) crFree(crCtxInfo->CreateInfo.pszDpyName); if (crCtxInfo->SpuContext >= 0) cr_server.head_spu->dispatch_table.DestroyContext(crCtxInfo->SpuContext); crFree(crCtxInfo); if (cr_server.curClient) { /* If we delete our current context, default back to the null context */ if (cr_server.curClient->currentCtxInfo == crCtxInfo) { cr_server.curClient->currentContextNumber = -1; cr_server.curClient->currentCtxInfo = &cr_server.MainContextInfo; } found = crServerRemoveClientContext(cr_server.curClient, ctx); /*Some application call destroy context not in a thread where it was created...have do deal with it.*/ if (!found) { for (client=0; client<cr_server.numClients; ++client) { if (cr_server.clients[client]==cr_server.curClient) continue; found = crServerRemoveClientContext(cr_server.clients[client], ctx); if (found) break; } } if (!found) { pNode=cr_server.pCleanupClient; while (pNode && !found) { found = crServerRemoveClientContext(pNode->pClient, ctx); pNode = pNode->next; } } CRASSERT(found); } /*Make sure this context isn't active in other clients*/ for (client=0; client<cr_server.numClients; ++client) { if (cr_server.clients[client]->currentCtxInfo == crCtxInfo) { cr_server.clients[client]->currentContextNumber = -1; cr_server.clients[client]->currentCtxInfo = &cr_server.MainContextInfo; } } pNode=cr_server.pCleanupClient; while (pNode) { if (pNode->pClient->currentCtxInfo == crCtxInfo) { pNode->pClient->currentContextNumber = -1; pNode->pClient->currentCtxInfo = &cr_server.MainContextInfo; } pNode = pNode->next; } }
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; } }
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; }
void crServerSetVBoxConfiguration() { CRMuralInfo *defaultMural; char response[8096]; char **spuchain; int num_spus; int *spu_ids; char **spu_names; char *spu_dir = NULL; int i; /* Quadrics defaults */ int my_rank = 0; int low_context = CR_QUADRICS_DEFAULT_LOW_CONTEXT; int high_context = CR_QUADRICS_DEFAULT_HIGH_CONTEXT; unsigned char key[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; char hostname[1024]; char **clientchain, **clientlist; GLint dims[4]; const char * env; defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0); CRASSERT(defaultMural); setDefaults(); /* * Get my hostname */ if (crGetHostname(hostname, sizeof(hostname))) { crError("CRServer: Couldn't get my own hostname?"); } strcpy(response, "1 0 render"); crDebug("CRServer: my SPU chain: %s", response); /* response will describe the SPU chain. * Example "2 5 wet 6 render" */ spuchain = crStrSplit(response, " "); num_spus = crStrToInt(spuchain[0]); spu_ids = (int *) crAlloc(num_spus * sizeof(*spu_ids)); spu_names = (char **) crAlloc((num_spus + 1) * sizeof(*spu_names)); for (i = 0; i < num_spus; i++) { spu_ids[i] = crStrToInt(spuchain[2 * i + 1]); spu_names[i] = crStrdup(spuchain[2 * i + 2]); crDebug("SPU %d/%d: (%d) \"%s\"", i + 1, num_spus, spu_ids[i], spu_names[i]); } spu_names[i] = NULL; //spu_dir = crStrdup(response); crNetSetRank(0); crNetSetContextRange(32, 35); crNetSetNodeRange("iam0", "iamvis20"); crNetSetKey(key,sizeof(key)); crNetSetKey(key,sizeof(key)); cr_server.tcpip_port = 7000; /*cr_server.optimizeBucket = crStrToInt(response); cr_server.localTileSpec = crStrToInt(response); cr_server.useL2 = crStrToInt(response); cr_server.ignore_papi = crStrToInt(response); if (crMothershipGetServerParam(conn, response, "overlap_blending")) { if (!crStrcmp(response, "blend")) cr_server.overlapBlending = 1; else if (!crStrcmp(response, "knockout")) cr_server.overlapBlending = 2; } if (crMothershipGetServerParam(conn, response, "overlap_levels")) cr_server.only_swap_once = crStrToInt(response); cr_server.debug_barriers = crStrToInt(response); cr_server.sharedDisplayLists = crStrToInt(response); cr_server.sharedTextureObjects = crStrToInt(response); cr_server.sharedPrograms = crStrToInt(response); cr_server.sharedWindows = crStrToInt(response); cr_server.uniqueWindows = crStrToInt(response); cr_server.useDMX = crStrToInt(response); if (crMothershipGetServerParam(conn, response, "vertprog_projection_param")) if (crMothershipGetServerParam(conn, response, "stereo_view")) if (crMothershipGetServerParam(conn, response, "view_matrix")) if (crMothershipGetServerParam(conn, response, "right_view_matrix")) if (crMothershipGetServerParam(conn, response, "projection_matrix")) if (crMothershipGetServerParam(conn, response, "right_projection_matrix"))*/ crDebug("CRServer: my port number is %d", cr_server.tcpip_port); /* * Load the SPUs */ cr_server.head_spu = crSPULoadChain(num_spus, spu_ids, spu_names, spu_dir, &cr_server); env = crGetenv( "CR_SERVER_DEFAULT_RENDER_TYPE" ); if (env != NULL) { GLubyte redir = (env[0] - 0x30); if (redir <= CR_SERVER_REDIR_MAXVAL) { int rc = crServerSetOffscreenRenderingMode(redir); if (!RT_SUCCESS(rc)) crWarning("offscreen rendering unsupported, no offscreen rendering will be used.."); } else crWarning("invalid redir option %c", redir); } #if defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS) || defined(GLX) else { int rc = crServerSetOffscreenRenderingMode(CR_SERVER_REDIR_FBO_BLT); if (!RT_SUCCESS(rc)) crWarning("offscreen rendering unsupported, no offscreen rendering will be used.."); } #endif cr_server.bOffscreenRenderingDefault = cr_server.bForceOffscreenRendering; /* Need to do this as early as possible */ cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_POSITION_CR, 0, GL_INT, 2, &dims[0]); cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, 0, GL_INT, 2, &dims[2]); defaultMural->gX = dims[0]; defaultMural->gY = dims[1]; defaultMural->width = dims[2]; defaultMural->height = dims[3]; crFree(spu_ids); crFreeStrings(spu_names); crFreeStrings(spuchain); if (spu_dir) crFree(spu_dir); cr_server.mtu = 1024 * 30; /* * Get a list of all the clients talking to me. */ if (cr_server.vncMode) { /* we're inside a vnc viewer */ /*if (!crMothershipSendString( conn, response, "getvncclient %s", hostname )) crError( "Bad Mothership response: %s", response );*/ } else { //crMothershipGetClients(conn, response); strcpy(response, "1 tcpip 1"); } crDebug("CRServer: my clients: %s", response); /* * 'response' will now contain a number indicating the number of clients * of this server, followed by a comma-separated list of protocol/SPU ID * pairs. * Example: "3 tcpip 1,gm 2,via 10" */ clientchain = crStrSplitn(response, " ", 1); cr_server.numClients = crStrToInt(clientchain[0]); if (cr_server.numClients == 0) { crError("I have no clients! What's a poor server to do?"); } clientlist = crStrSplit(clientchain[1], ","); /* * Connect to initial set of clients. * Call crNetAcceptClient() for each client. * Also, look for a client that's _not_ using the file: protocol. */ for (i = 0; i < cr_server.numClients; i++) { CRClient *newClient = (CRClient *) crCalloc(sizeof(CRClient)); #ifdef VBOX sscanf(clientlist[i], "%1023s %d", cr_server.protocol, &(newClient->spu_id)); #else sscanf(clientlist[i], "%s %d", cr_server.protocol, &(newClient->spu_id)); #endif newClient->conn = crNetAcceptClient(cr_server.protocol, NULL, cr_server.tcpip_port, cr_server.mtu, 0); newClient->currentCtxInfo = &cr_server.MainContextInfo; crServerAddToRunQueue(newClient); cr_server.clients[i] = newClient; } /* set default client and mural */ if (cr_server.numClients > 0) { cr_server.curClient = cr_server.clients[0]; cr_server.curClient->currentMural = defaultMural; cr_server.client_spu_id =cr_server.clients[0]->spu_id; } crFreeStrings(clientchain); crFreeStrings(clientlist); /* Ask the mothership for the tile info */ //crServerGetTileInfoFromMothership(conn, defaultMural); if (cr_server.vncMode) { /* In vnc mode, we reset the mothership configuration so that it can be * used by subsequent OpenGL apps without having to spawn a new mothership * on a new port. */ crDebug("CRServer: Resetting mothership to initial state"); //crMothershipReset(conn); } //crMothershipDisconnect(conn); }
void SERVER_DISPATCH_APIENTRY crServerDispatchBarrierCreateCR( GLuint name, GLuint count ) { CRServerBarrier *barrier; #if DEBUG_BARRIERS char debug_buf[4096]; #endif if (cr_server.ignore_papi) { cr_server.head_spu->dispatch_table.BarrierCreateCR( name, count ); return; } barrier = (CRServerBarrier *) crHashtableSearch( cr_server.barriers, name ); #if DEBUG_BARRIERS sprintf( debug_buf, "BarrierCreateCR( %d, %d )", name, count ); cr_server.head_spu->dispatch_table.ChromiumParametervCR( GL_PRINT_STRING_CR, GL_UNSIGNED_BYTE, sizeof(debug_buf), debug_buf ); #endif if (count == 0) { count = cr_server.numClients; #if DEBUG_BARRIERS sprintf( debug_buf, "changing count to %d", count ); cr_server.head_spu->dispatch_table.ChromiumParametervCR( GL_PRINT_STRING_CR, GL_UNSIGNED_BYTE, sizeof(debug_buf), debug_buf ); #endif } /* we use maxBarrierCount in Clear() and SwapBuffers() and also use it * in __getNextClient() for deadlock detection. The issue is that all * the existing clients may be blocked, but we might soon get another * client connection to break the apparent deadlock. */ if (count > cr_server.maxBarrierCount) cr_server.maxBarrierCount = count; if ( barrier == NULL ) { barrier = (CRServerBarrier *) crAlloc( sizeof(*barrier) ); barrier->count = count; barrier->num_waiting = 0; barrier->waiting = (RunQueue **) crAlloc( count * sizeof(*(barrier->waiting)) ); crHashtableAdd( cr_server.barriers, name, barrier ); #if DEBUG_BARRIERS sprintf( debug_buf, "This was a new barrier!" ); cr_server.head_spu->dispatch_table.ChromiumParametervCR( GL_PRINT_STRING_CR, GL_UNSIGNED_BYTE, sizeof(debug_buf), debug_buf ); #endif } else { /* HACK -- this allows everybody to create a barrier, and all but the first creation are ignored, assuming the count match. */ #if DEBUG_BARRIERS sprintf( debug_buf, "I already knew about this barrier." ); cr_server.head_spu->dispatch_table.ChromiumParametervCR( GL_PRINT_STRING_CR, GL_UNSIGNED_BYTE, sizeof(debug_buf), debug_buf ); #endif if ( barrier->count != count ) { #if DEBUG_BARRIERS sprintf( debug_buf, "And someone messed up the count!." ); cr_server.head_spu->dispatch_table.ChromiumParametervCR( GL_PRINT_STRING_CR, GL_UNSIGNED_BYTE, sizeof(debug_buf), debug_buf ); #endif crError( "Barrier name=%u created with count=%u, but already " "exists with count=%u", name, count, barrier->count ); } } if (cr_server.debug_barriers) crDebug("crserver: BarrierCreate(id=%d, count=%d)", name, barrier->count); }