static SPUFunctions * packSPUInit( int id, SPU *child, SPU *self, unsigned int context_id, unsigned int num_contexts ) { ThreadInfo *thread; (void) context_id; (void) num_contexts; (void) child; (void) self; #if defined(CHROMIUM_THREADSAFE) && !defined(WINDOWS) crInitMutex(&_PackMutex); #endif pack_spu.id = id; packspuSetVBoxConfiguration( child ); /* This connects to the server, sets up the packer, etc. */ thread = packspuNewThread( crThreadID() ); if (!thread) { return NULL; } CRASSERT( thread == &(pack_spu.thread[0]) ); pack_spu.idxThreadInUse = 0; packspuCreateFunctions(); crStateInit(); return &pack_functions; }
static void stubCheckMultithread( void ) { static unsigned long knownID; static GLboolean firstCall = GL_TRUE; if (stub.threadSafe) return; /* nothing new, nothing to do */ if (firstCall) { knownID = crThreadID(); firstCall = GL_FALSE; } else if (knownID != crThreadID()) { /* going thread-safe now! */ stub.threadSafe = GL_TRUE; crSPUCopyDispatchTable(&glim, &stubThreadsafeDispatch); } }
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); }
void PACKSPU_APIENTRY packspu_VBoxPackAttachThread() { #if 0 int i; GET_THREAD(thread); for (i=0; i<MAX_THREADS; ++i) { if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i] && thread->id==crThreadID()) { crError("2nd attach to same thread"); } } #endif crSetTSD(&_PackTSD, NULL); }
int32_t crVBoxServerClientRead(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t *pcbBuffer) { CRClient *pClient=NULL; int32_t i; //crDebug("crServer: [%x] ClientRead u32ClientID=%d", crThreadID(), 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; if (pClient->conn->cbHostBuffer > *pcbBuffer) { crDebug("crServer: [%lx] ClientRead u32ClientID=%d FAIL, host buffer too small %d of %d", crThreadID(), u32ClientID, *pcbBuffer, pClient->conn->cbHostBuffer); /* Return the size of needed buffer */ *pcbBuffer = pClient->conn->cbHostBuffer; return VERR_BUFFER_OVERFLOW; } *pcbBuffer = pClient->conn->cbHostBuffer; if (*pcbBuffer) { CRASSERT(pClient->conn->pHostBuffer); crMemcpy(pBuffer, pClient->conn->pHostBuffer, *pcbBuffer); pClient->conn->cbHostBuffer = 0; } return VINF_SUCCESS; }
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(); }
static DWORD WINAPI renderSPUWindowThreadProc(void* unused) { MSG msg; bool bRet; (void) unused; /* Force system to create the message queue. * Else, there's a chance that render spu will issue PostThreadMessage * before this thread calls GetMessage for first time. */ PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); crDebug("RenderSPU: Window thread started (%x)", crThreadID()); SetEvent(render_spu.hWinThreadReadyEvent); while( (bRet = GetMessage( &msg, 0, 0, 0 )) != 0) { if (bRet == -1) { crError("RenderSPU: Window thread GetMessage failed (%x)", GetLastError()); break; } else { if (msg.message == WM_VBOX_RENDERSPU_CREATE_WINDOW) { LPCREATESTRUCT pCS = (LPCREATESTRUCT) msg.lParam; HWND hWnd; WindowInfo *pWindow = (WindowInfo *)pCS->lpCreateParams; CRASSERT(msg.lParam && !msg.wParam && pCS->lpCreateParams); hWnd = CreateWindowEx(pCS->dwExStyle, pCS->lpszName, pCS->lpszClass, pCS->style, pCS->x, pCS->y, pCS->cx, pCS->cy, pCS->hwndParent, pCS->hMenu, pCS->hInstance, &render_spu); pWindow->hWnd = hWnd; SetEvent(render_spu.hWinThreadReadyEvent); } else if (msg.message == WM_VBOX_RENDERSPU_DESTROY_WINDOW) { CRASSERT(msg.lParam && !msg.wParam); DestroyWindow(((VBOX_RENDERSPU_DESTROY_WINDOW*) msg.lParam)->hWnd); SetEvent(render_spu.hWinThreadReadyEvent); } else { TranslateMessage(&msg); DispatchMessage(&msg); } } } render_spu.dwWinThreadId = 0; crDebug("RenderSPU: Window thread stopped (%x)", crThreadID()); SetEvent(render_spu.hWinThreadReadyEvent); return 0; }
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; }
void stubInstallWindowMessageHook() { stub.hMessageHook = SetWindowsHookEx(WH_CALLWNDPROCRET, stubCBWindowMessageHookProc, 0, crThreadID()); if (!stub.hMessageHook) crWarning("Window message hook install failed! (not fatal)"); }
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; }
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); } }