/* * 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 *replicatespuNewThread( CRthread id ) { ThreadInfo *thread; #ifdef CHROMIUM_THREADSAFE_notyet crLockMutex(&_ReplicateMutex); #else CRASSERT(replicate_spu.numThreads == 0); #endif CRASSERT(replicate_spu.numThreads < MAX_THREADS); thread = &(replicate_spu.thread[replicate_spu.numThreads]); thread->id = id; thread->currentContext = NULL; /* connect to the server */ thread->server.name = crStrdup( replicate_spu.name ); thread->server.buffer_size = replicate_spu.buffer_size; if (replicate_spu.numThreads == 0) { replicatespuConnectToServer( &(thread->server) ); CRASSERT(thread->server.conn); replicate_spu.swap = thread->server.conn->swap; } else { /* a new pthread */ replicatespuFlushAll( &(replicate_spu.thread[0]) ); crNetNewClient( replicate_spu.thread[0].server.conn, &(thread->server)); CRASSERT(thread->server.conn); } /* packer setup */ CRASSERT(thread->packer == NULL); thread->packer = crPackNewContext( replicate_spu.swap ); CRASSERT(thread->packer); crPackInitBuffer( &(thread->buffer), crNetAlloc(thread->server.conn), thread->server.conn->buffer_size, thread->server.conn->mtu ); thread->buffer.canBarf = thread->server.conn->Barf ? GL_TRUE : GL_FALSE; crPackSetBuffer( thread->packer, &thread->buffer ); crPackFlushFunc( thread->packer, replicatespuFlush ); crPackFlushArg( thread->packer, (void *) thread ); crPackSendHugeFunc( thread->packer, replicatespuHuge ); crPackSetContext( thread->packer ); #ifdef CHROMIUM_THREADSAFE_notyet crSetTSD(&_ReplicateTSD, thread); #endif replicate_spu.numThreads++; #ifdef CHROMIUM_THREADSAFE_notyet crUnlockMutex(&_ReplicateMutex); #endif return thread; }
void PACKSPU_APIENTRY packspu_VBoxWindowDestroy( GLint con, GLint window ) { if (CRPACKSPU_IS_WDDM_CRHGSMI()) { GET_THREAD(thread); if (con) { CRPackContext * curPacker = crPackGetContext(); CRASSERT(!thread || !thread->bInjectThread); thread = GET_THREAD_VAL_ID(con); crPackSetContext(thread->packer); crPackWindowDestroy(window); if (curPacker != thread->packer) crPackSetContext(curPacker); return; } CRASSERT(thread); CRASSERT(thread->bInjectThread); } crPackWindowDestroy(window); }
void PACKSPU_APIENTRY packspu_VBoxPackSetInjectThread(void) { crLockMutex(&_PackMutex); { int i; GET_THREAD(thread); CRASSERT(!thread); CRASSERT((pack_spu.numThreads>0) && (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 = crThreadID(); thread->currentContext = NULL; thread->bInjectThread = GL_TRUE; thread->netServer.name = crStrdup(pack_spu.name); thread->netServer.buffer_size = 64 * 1024; crNetNewClient(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn, &(thread->netServer)); 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); }
GLint PACKSPU_APIENTRY packspu_WindowCreate( const char *dpyName, GLint visBits ) { static int num_calls = 0; int writeback = pack_spu.thread[0].netServer.conn->actual_network; GLint return_val = (GLint) 0; WindowInfo *WInfo; /* WindowCreate is special - just like CreateContext. * GET_THREAD(thread) doesn't work as the thread won't have called * MakeCurrent yet, so we've got to use the first thread's packer * buffer. */ crPackSetContext( pack_spu.thread[0].packer ); if (pack_spu.swap) { crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback ); } else { crPackWindowCreate( dpyName, visBits, &return_val, &writeback ); } packspuFlush( &pack_spu.thread[0] ); if (!(pack_spu.thread[0].netServer.conn->actual_network)) { return num_calls++; } else { while (writeback) crNetRecv(); if (pack_spu.swap) { return_val = (GLint) SWAP32(return_val); } WInfo = (WindowInfo *) crAlloc(sizeof(WindowInfo)); WInfo->XWindow = 0; WInfo->visual = visBits; crHashtableAdd(pack_spu.XWindows,return_val,WInfo); return return_val; } }
GLint PACKSPU_APIENTRY packspu_WindowCreate( const char *dpyName, GLint visBits ) { GET_THREAD(thread); static int num_calls = 0; int writeback = pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network; GLint return_val = (GLint) 0; if (!thread) { thread = packspuNewThread( crThreadID() ); } CRASSERT(thread); CRASSERT(thread->packer); crPackSetContext(thread->packer); if (pack_spu.swap) { crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback ); } else { crPackWindowCreate( dpyName, visBits, &return_val, &writeback ); } packspuFlush(thread); if (!(thread->netServer.conn->actual_network)) { return num_calls++; } else { while (writeback) crNetRecv(); if (pack_spu.swap) { return_val = (GLint) SWAP32(return_val); } return return_val; } }
void PACKSPU_APIENTRY packspu_VBoxDetachThread() { int i; GET_THREAD(thread); if (thread) { crLockMutex(&_PackMutex); for (i=0; i<MAX_THREADS; ++i) { if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i] && thread->id==crThreadID() && thread->netServer.conn) { CRASSERT(pack_spu.numThreads>0); packspuFlush((void *) thread); if (pack_spu.thread[i].packer) { CR_LOCK_PACKER_CONTEXT(thread->packer); crPackSetContext(NULL); CR_UNLOCK_PACKER_CONTEXT(thread->packer); crPackDeleteContext(pack_spu.thread[i].packer); } crNetFreeConnection(pack_spu.thread[i].netServer.conn); pack_spu.numThreads--; /*note can't shift the array here, because other threads have TLS references to array elements*/ crMemZero(&pack_spu.thread[i], sizeof(ThreadInfo)); crSetTSD(&_PackTSD, NULL); if (i==pack_spu.idxThreadInUse) { for (i=0; i<MAX_THREADS; ++i) { if (pack_spu.thread[i].inUse) { pack_spu.idxThreadInUse=i; break; } } } break; } } for (i=0; i<CR_MAX_CONTEXTS; ++i) { ContextInfo *ctx = &pack_spu.context[i]; if (ctx->currentThread == thread) { CRASSERT(ctx->fAutoFlush); ctx->currentThread = NULL; } } crUnlockMutex(&_PackMutex); } crStateVBoxDetachThread(); }
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; }
GLint PACKSPU_APIENTRY packspu_VBoxWindowCreate( GLint con, const char *dpyName, GLint visBits ) { GET_THREAD(thread); static int num_calls = 0; int writeback = CRPACKSPU_IS_WDDM_CRHGSMI() ? 1 : pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network; GLint return_val = (GLint) 0; ThreadInfo *curThread = thread; GLint retVal; if (CRPACKSPU_IS_WDDM_CRHGSMI()) { if (!con) { crError("connection expected!"); return 0; } thread = GET_THREAD_VAL_ID(con); } else { CRASSERT(!con); if (!thread) { thread = packspuNewThread( #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) NULL #endif ); } } CRASSERT(thread); CRASSERT(thread->packer); CRASSERT(crPackGetContext() == (curThread ? curThread->packer : NULL)); crPackSetContext(thread->packer); if (pack_spu.swap) { crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback ); } else { crPackWindowCreate( dpyName, visBits, &return_val, &writeback ); } packspuFlush(thread); if (!(thread->netServer.conn->actual_network)) { retVal = num_calls++; } else { CRPACKSPU_WRITEBACK_WAIT(thread, writeback); if (pack_spu.swap) { return_val = (GLint) SWAP32(return_val); } retVal = return_val; } if (CRPACKSPU_IS_WDDM_CRHGSMI()) { if (thread != curThread) { if (curThread) crPackSetContext(curThread->packer); else crPackSetContext(NULL); } } return retVal; }
void REPLICATESPU_APIENTRY replicatespu_MakeCurrent( GLint window, GLint nativeWindow, GLint ctx ) { unsigned int i; unsigned int show_window = 0; WindowInfo *winInfo = (WindowInfo *) crHashtableSearch( replicate_spu.windowTable, window ); ContextInfo *newCtx = (ContextInfo *) crHashtableSearch( replicate_spu.contextTable, ctx ); GET_THREAD(thread); if (!winInfo) { crWarning("Replicate SPU: Invalid window ID %d passed to MakeCurrent", window); return; } if (thread) replicatespuFlushAll( (void *)thread ); if (!thread) { thread = replicatespuNewThread( crThreadID() ); } CRASSERT(thread); CRASSERT(thread->packer); if (newCtx && winInfo) { newCtx->currentWindow = winInfo; #if 000 /* This appears to be obsolete code */ if (replicate_spu.render_to_crut_window && !nativeWindow) { char response[8096]; CRConnection *conn = crMothershipConnect(); if (!conn) { crError("Replicate SPU: Couldn't connect to the mothership to get CRUT drawable-- " "I have no idea what to do!"); } crMothershipGetParam( conn, "crut_drawable", response ); nativeWindow = crStrToInt(response); crDebug("Replicate SPU: using CRUT drawable: 0x%x", nativeWindow); crMothershipDisconnect(conn); } #endif if (replicate_spu.glx_display && winInfo && winInfo->nativeWindow != nativeWindow) { winInfo->nativeWindow = nativeWindow; replicatespuMonitorWindow(winInfo); replicatespuRePositionWindow(winInfo); show_window = 1; } CRASSERT(newCtx->State); /* verify valid */ crPackSetContext( thread->packer ); } /* * Send the MakeCurrent to all crservers (vnc viewers) */ for (i = 0; i < CR_MAX_REPLICANTS; i++) { const GLint serverWin = winInfo ? winInfo->id[i] : -1; const GLint serverCtx = newCtx ? newCtx->rserverCtx[i] : -1; if (!IS_CONNECTED(replicate_spu.rserver[i].conn)) continue; /* Note: app's native window ID not needed on server side; pass zero */ if (replicate_spu.swap) crPackMakeCurrentSWAP(serverWin, 0, serverCtx); else crPackMakeCurrent(serverWin, 0, serverCtx); if (show_window) { /* We may find that the window was mapped before we * called MakeCurrent, if that's the case then ensure * the remote end gets the WindowShow event */ if (winInfo->viewable) { if (replicate_spu.swap) crPackWindowShowSWAP(serverWin, GL_TRUE); else crPackWindowShow(serverWin, GL_TRUE); } } replicatespuFlushOne(thread, i); } if (newCtx) { crStateMakeCurrent( newCtx->State ); crDLMSetCurrentState(newCtx->dlmState); } else { crStateMakeCurrent( NULL ); crDLMSetCurrentState(NULL); } thread->currentContext = newCtx; }
GLint REPLICATESPU_APIENTRY replicatespu_WindowCreate( const char *dpyName, GLint visBits ) { unsigned int i; static GLint freeWinID = 400; WindowInfo *winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo)); GET_THREAD(thread); if (!winInfo) return -1; if (thread) replicatespuFlushAll( (void *) thread ); else thread = replicatespuNewThread( crThreadID() ); replicatespuFlushAll( (void *) thread ); crPackSetContext( thread->packer ); #ifdef CHROMIUM_THREADSAFE_notyet crLockMutex(&_ReplicateMutex); #endif for (i = 1; i < CR_MAX_REPLICANTS; i++) { if (IS_CONNECTED(replicate_spu.rserver[i].conn)) { int writeback = 1; int return_val = -1; if (replicate_spu.swap) crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback ); else crPackWindowCreate( dpyName, visBits, &return_val, &writeback ); replicatespuFlushOne(thread, i); while (writeback) crNetRecv(); if (replicate_spu.swap) return_val = (GLint) SWAP32(return_val); if (return_val < 0) crWarning("Replicate SPU: server %d returned window id -1", i); /* XXX temp */ crDebug("Replicate SPU: Window create, server %d returned %d", i, return_val); winInfo->id[i] = return_val; } else { winInfo->id[i] = -1; } } winInfo->visBits = visBits; winInfo->width = 0; winInfo->height = 0; winInfo->nativeWindow = 0; winInfo->viewable = GL_FALSE; crHashtableAdd(replicate_spu.windowTable, freeWinID, winInfo); #ifdef CHROMIUM_THREADSAFE_notyet crUnlockMutex(&_ReplicateMutex); #endif return freeWinID++; }
GLint PACKSPU_APIENTRY packspu_CreateContext( const char *dpyName, GLint visual, GLint shareCtx ) { GET_THREAD(thread); int writeback = 1; GLint serverCtx = (GLint) -1; int slot; #ifdef CHROMIUM_THREADSAFE crLockMutex(&_PackMutex); #endif if (!thread) { thread = packspuNewThread(crThreadID()); } CRASSERT(thread); CRASSERT(thread->packer); if (shareCtx > 0) { /* translate to server ctx id */ shareCtx -= MAGIC_OFFSET; if (shareCtx >= 0 && shareCtx < pack_spu.numContexts) { shareCtx = pack_spu.context[shareCtx].serverCtx; } } crPackSetContext( thread->packer ); /* Pack the command */ if (pack_spu.swap) crPackCreateContextSWAP( dpyName, visual, shareCtx, &serverCtx, &writeback ); else crPackCreateContext( dpyName, visual, shareCtx, &serverCtx, &writeback ); /* Flush buffer and get return value */ packspuFlush(thread); if (!(thread->netServer.conn->actual_network)) { /* HUMUNGOUS HACK TO MATCH SERVER NUMBERING * * The hack exists solely to make file networking work for now. This * is totally gross, but since the server expects the numbers to start * from 5000, we need to write them out this way. This would be * marginally less gross if the numbers (500 and 5000) were maybe * some sort of #define'd constants somewhere so the client and the * server could be aware of how each other were numbering things in * cases like file networking where they actually * care. * * -Humper * */ serverCtx = 5000; } else { while (writeback) crNetRecv(); if (pack_spu.swap) { serverCtx = (GLint) SWAP32(serverCtx); } if (serverCtx < 0) { #ifdef CHROMIUM_THREADSAFE crUnlockMutex(&_PackMutex); #endif crWarning("Failure in packspu_CreateContext"); return -1; /* failed */ } } /* find an empty context slot */ for (slot = 0; slot < pack_spu.numContexts; slot++) { if (!pack_spu.context[slot].clientState) { /* found empty slot */ break; } } if (slot == pack_spu.numContexts) { pack_spu.numContexts++; } /* Fill in the new context info */ /* XXX fix-up sharedCtx param here */ pack_spu.context[slot].clientState = crStateCreateContext(NULL, visual, NULL); pack_spu.context[slot].clientState->bufferobject.retainBufferData = GL_TRUE; pack_spu.context[slot].serverCtx = serverCtx; #ifdef CHROMIUM_THREADSAFE crUnlockMutex(&_PackMutex); #endif return MAGIC_OFFSET + slot; }
/* * 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; }
void PACKSPU_APIENTRY packspu_MakeCurrent( GLint window, GLint nativeWindow, GLint ctx ) { GET_THREAD(thread); GLint serverCtx; ContextInfo *newCtx; if (!thread) { thread = packspuNewThread( crThreadID() ); } CRASSERT(thread); CRASSERT(thread->packer); if (ctx) { const int slot = ctx - MAGIC_OFFSET; CRASSERT(slot >= 0); CRASSERT(slot < pack_spu.numContexts); newCtx = &pack_spu.context[slot]; CRASSERT(newCtx->clientState); /* verify valid */ if (newCtx->fAutoFlush) { if (newCtx->currentThread && newCtx->currentThread != thread) { crLockMutex(&_PackMutex); /* do a flush for the previusly assigned thread * to ensure all commands issued there are submitted */ if (newCtx->currentThread && newCtx->currentThread->inUse && newCtx->currentThread->netServer.conn && newCtx->currentThread->packer && newCtx->currentThread->packer->currentBuffer) { packspuFlush((void *) newCtx->currentThread); } crUnlockMutex(&_PackMutex); } newCtx->currentThread = thread; } thread->currentContext = newCtx; crPackSetContext( thread->packer ); crStateMakeCurrent( newCtx->clientState ); //crStateSetCurrentPointers(newCtx->clientState, &thread->packer->current); serverCtx = pack_spu.context[slot].serverCtx; } else { thread->currentContext = NULL; crStateMakeCurrent( NULL ); newCtx = NULL; serverCtx = 0; } if (pack_spu.swap) crPackMakeCurrentSWAP( window, nativeWindow, serverCtx ); else crPackMakeCurrent( window, nativeWindow, serverCtx ); { GET_THREAD(t); (void) t; CRASSERT(t); } }