void REPLICATESPU_APIENTRY replicatespu_Finish( void ) { unsigned int i; GET_THREAD(thread); replicatespuFlushAll( (void *) thread ); for (i = 0; i < CR_MAX_REPLICANTS; i++) { int writeback = 1; if (!IS_CONNECTED(replicate_spu.rserver[i].conn)) continue; if (replicate_spu.swap) { crPackFinishSWAP(); crPackWritebackSWAP( &writeback ); } else { crPackFinish(); crPackWriteback( &writeback ); } replicatespuFlushOne(thread, i); while (writeback) crNetRecv(); } }
void PACKSPU_APIENTRY packspu_Finish( void ) { GET_THREAD(thread); GLint writeback = pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network; if (pack_spu.swap) { crPackFinishSWAP(); } else { crPackFinish(); } if (packspuSyncOnFlushes()) { if (writeback) { if (pack_spu.swap) crPackWritebackSWAP(&writeback); else crPackWriteback(&writeback); packspuFlush( (void *) thread ); while (writeback) crNetRecv(); } } }
/** * Implementation of glFinish for tilesorter */ void TILESORTSPU_APIENTRY tilesortspu_Finish(void) { GET_THREAD(thread); GLint writeback = tilesort_spu.num_servers; tilesortspuFlush( thread ); if (tilesort_spu.swap) { crPackFinishSWAP( ); } else { crPackFinish( ); } if (tilesort_spu.syncOnFinish) { if (tilesort_spu.swap) { crPackWritebackSWAP( &writeback ); } else { crPackWriteback( &writeback ); } } tilesortspuBroadcastGeom(0); tilesortspuShipBuffers(); if (tilesort_spu.syncOnFinish) { while(writeback) { crNetRecv(); } } }
void PACKSPU_APIENTRY packspu_Flush( void ) { GET_THREAD(thread); int writeback=1; int found=0; if (!thread->bInjectThread) { crPackFlush(); if (packspuSyncOnFlushes()) { crPackWriteback(&writeback); packspuFlush( (void *) thread ); while (writeback) crNetRecv(); } } else { int i; crLockMutex(&_PackMutex); /*Make sure we process commands in order they should appear, so flush other threads first*/ for (i=0; i<MAX_THREADS; ++i) { if (pack_spu.thread[i].inUse && (thread != &pack_spu.thread[i]) && pack_spu.thread[i].netServer.conn && pack_spu.thread[i].packer && pack_spu.thread[i].packer->currentBuffer) { packspuFlush((void *) &pack_spu.thread[i]); if (pack_spu.thread[i].netServer.conn->u32ClientID == thread->netServer.conn->u32InjectClientID) { found=1; } } } if (!found) { /*Thread we're supposed to inject commands for has been detached, so there's nothing to sync with and we should just pass commands through our own connection. */ thread->netServer.conn->u32InjectClientID=0; } packspuFlush((void *) thread); crUnlockMutex(&_PackMutex); } }
/** * Get the next message from the given network connection. If there isn't * one already in the linked list of received messages, call crNetRecv() * until we get something. * * \param message returns pointer to the message * \return total length of message (header + payload, in bytes) */ unsigned int crNetGetMessage( CRConnection *conn, CRMessage **message ) { /* Keep getting work to do */ for (;;) { int len = crNetPeekMessage( conn, message ); if (len) return len; crNetRecv(); } /* silence compiler */ return 0; }
int main( int argc, char *argv[] ) { char *mothership = NULL; crNetInit(crutProxyRecv, crutProxyClose); crutInitProxy(mothership); for (;;) crNetRecv(); #ifndef WINDOWS return 0; #endif }
/** * Get the next message from the given network connection. If there isn't * one already in the linked list of received messages, call crNetRecv() * until we get something. * * \param message returns pointer to the message * \return total length of message (header + payload, in bytes) */ unsigned int crNetGetMessage( CRConnection *conn, CRMessage **message ) { /* Keep getting work to do */ for (;;) { int len = crNetPeekMessage( conn, message ); if (len) return len; crNetRecv(); } #if !defined(WINDOWS) && !defined(IRIX) && !defined(IRIX64) /* silence compiler */ return 0; #endif }
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; } }
void REPLICATESPU_APIENTRY replicatespu_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ) { GET_THREAD(thread); unsigned int i; ContextInfo *ctx = thread->currentContext; CRClientState *clientState = &(ctx->State->client); replicatespuFlushAll( (void *) thread ); replicate_spu.ReadPixels++; /* * Only send ReadPixels to one server, the first active one we find. */ for (i = 1; i < CR_MAX_REPLICANTS; i++) { /* hijack the current packer context */ if (IS_CONNECTED(replicate_spu.rserver[i].conn)) { int writeback; if (replicate_spu.swap) { crPackReadPixelsSWAP( x, y, width, height, format, type, pixels, &(clientState->pack), &writeback ); } else { crPackReadPixels( x, y, width, height, format, type, pixels, &(clientState->pack), &writeback ); } replicatespuFlushOne(thread, i); while (replicate_spu.ReadPixels) crNetRecv(); /* Only need pixels from one server - all done now */ return; } } }
/** * Check if any of the clients need servicing. * If so, service one client and return. * Else, just return. */ void glStubServiceClients(void) { RunQueue *q; q = getNextClient(GL_FALSE); /* don't block */ if (q) { ClientStatus stat = glStubServiceClient(q); if (stat == CLIENT_NEXT && cr_server.run_queue->next) { /* advance to next client */ cr_server.run_queue = cr_server.run_queue->next; } } else { /* no clients ready, do a receive and maybe we'll get a new * client message */ crNetRecv(); } }
void PACKSPU_APIENTRY packspu_Finish( void ) { GET_THREAD(thread); GLint writeback = pack_spu.thread[0].netServer.conn->actual_network; if (pack_spu.swap) { crPackFinishSWAP( ); if (writeback) crPackWritebackSWAP( &writeback ); } else { crPackFinish( ); if (writeback) crPackWriteback( &writeback ); } packspuFlush( (void *) thread ); while (writeback) crNetRecv(); }
GLboolean PACKSPU_APIENTRY packspu_AreTexturesResident( GLsizei n, const GLuint * textures, GLboolean * residences ) { GET_THREAD(thread); int writeback = 1; GLboolean return_val = GL_TRUE; GLsizei i; if (!(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network)) { crError( "packspu_AreTexturesResident doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" ); } if (pack_spu.swap) { crPackAreTexturesResidentSWAP( n, textures, residences, &return_val, &writeback ); } else { crPackAreTexturesResident( n, textures, residences, &return_val, &writeback ); } packspuFlush( (void *) thread ); while (writeback) crNetRecv(); /* Since the Chromium packer/unpacker can't return both 'residences' * and the function's return value, compute the return value here. */ for (i = 0; i < n; i++) { if (!residences[i]) { return_val = GL_FALSE; break; } } 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_GetPixelMapusv( GLenum map, GLushort * values ) { GET_THREAD(thread); int writeback = 1; if (pack_spu.swap) { crPackGetPixelMapusvSWAP( map, values, &writeback ); } else { crPackGetPixelMapusv( map, values, &writeback ); } #ifdef CR_ARB_pixel_buffer_object if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) #endif { packspuFlush( (void *) thread ); while (writeback) crNetRecv(); } }
void PACKSPU_APIENTRY packspu_GetPolygonStipple( GLubyte * mask ) { GET_THREAD(thread); int writeback = 1; if (pack_spu.swap) { crPackGetPolygonStippleSWAP( mask, &writeback ); } else { crPackGetPolygonStipple( mask, &writeback ); } #ifdef CR_ARB_pixel_buffer_object if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) #endif { packspuFlush( (void *) thread ); while (writeback) crNetRecv(); } }
/** * Callback called by crHashTableWalk() below. * Used to create viewer-side windows for all the application windows. */ static void replicatespuReplicateWindow(unsigned long key, void *data1, void *data2) { ThreadInfo *thread = (ThreadInfo *) data2; WindowInfo *winInfo = (WindowInfo *) data1; GLint window = 0; GLint writeback = 1; Window root; int x, y; unsigned int width, height, bw, d; GLboolean unviewable = GL_FALSE; XWindowAttributes winAtt; CRASSERT(NewServerIndex >= 0); /* clear this flag, in case it was still set from an old connection */ winInfo->writeback[NewServerIndex] = 0; /** * Get application window's attributes */ old_xerror_handler = XSetErrorHandler( x11_error_handler ); XSync(replicate_spu.glx_display, 0); XGetGeometry(replicate_spu.glx_display, (Window)winInfo->nativeWindow, &root, &x, &y, &width, &height, &bw, &d ); XGetWindowAttributes(replicate_spu.glx_display, (Window) winInfo->nativeWindow, &winAtt); XSetErrorHandler( old_xerror_handler ); if (!caught_x11_error) { unviewable = (winAtt.map_state == IsUnviewable); } caught_x11_error = 0; /* * Create the server-side window */ if (replicate_spu.swap) crPackWindowCreateSWAP( replicate_spu.dpyName, winInfo->visBits, &window, &writeback); else crPackWindowCreate( replicate_spu.dpyName, winInfo->visBits, &window, &writeback); replicatespuFlushOne(thread, NewServerIndex); /* Get return value */ while (writeback) { crNetRecv(); } if (replicate_spu.swap) window = (GLint) SWAP32(window); /* save the server-side window ID */ winInfo->id[NewServerIndex] = window; crDebug("Replicate SPU: created server-side window %d", window); if (window < 0) { crWarning("Replicate SPU: failed to create server-side window"); return; } XVncChromiumMonitor(replicate_spu.glx_display, window, winInfo->nativeWindow); /* * If the app window is not visible, hide the server-side window too. */ if (unviewable) { if (replicate_spu.swap) crPackWindowShowSWAP( window, GL_FALSE ); else crPackWindowShow( window, GL_FALSE ); replicatespuFlushOne(thread, NewServerIndex); } }
/** * Find the next client in the run queue that's not blocked and has a * waiting message. * Check if all clients are blocked (on barriers, semaphores), if so we've * deadlocked! * If no clients have a waiting message, call crNetRecv to get something * if 'block' is true, else return NULL if 'block' if false. */ static RunQueue * getNextClient(GLboolean block) { while (1) { if (cr_server.run_queue) { GLboolean all_blocked = GL_TRUE; GLboolean done_something = GL_FALSE; RunQueue *start = cr_server.run_queue; /* check if this client's connection has gone away */ if (!cr_server.run_queue->client->conn || (cr_server.run_queue->client->conn->type == CR_NO_CONNECTION && crNetNumMessages(cr_server.run_queue->client->conn) == 0)) { glStubDeleteClient( cr_server.run_queue->client ); start = cr_server.run_queue; } if (cr_server.run_queue == NULL) { /* empty queue */ return NULL; } if (glStubClientInBeginEnd(cr_server.run_queue->client)) { /* We _must_ service this client and no other. * If we've got a message waiting on this client's connection we'll * service it. Else, return NULL. */ if (crNetNumMessages(cr_server.run_queue->client->conn) > 0) return cr_server.run_queue; else return NULL; } /* loop over entries in run queue, looking for next one that's ready */ while (!done_something || cr_server.run_queue != start) { done_something = GL_TRUE; if (!cr_server.run_queue->blocked) { all_blocked = GL_FALSE; } if (!cr_server.run_queue->blocked && cr_server.run_queue->client->conn && crNetNumMessages(cr_server.run_queue->client->conn) > 0) { /* OK, this client isn't blocked and has a queued message */ return cr_server.run_queue; } cr_server.run_queue = cr_server.run_queue->next; } if (all_blocked) { crWarning( "GLStub: DEADLOCK! (numClients=%d, all blocked)", cr_server.numClients ); if (cr_server.numClients < (int) cr_server.maxBarrierCount) { if (cr_server.exitIfNoClients) { crWarning("GLStub: exiting."); exit(0); } crWarning("GLStub: Waiting for more clients."); while (cr_server.numClients < (int) cr_server.maxBarrierCount) { crNetRecv(); } } } } if (!block) return NULL; /* no one had any work, get some! */ crNetRecv(); } /* while */ /* UNREACHED */ /* return NULL; */ }
/** * Implementation of SwapBuffers for tilesorter * * \param window * \param flags */ void TILESORTSPU_APIENTRY tilesortspu_SwapBuffers( GLint window, GLint flags ) { GET_THREAD(thread); GLint writeback = tilesort_spu.num_servers; WindowInfo *winInfo; int serverWindow; tilesortspuFlush( thread ); winInfo = tilesortspuGetWindowInfo(window, 0); CRASSERT(winInfo); /* NOTE: winInfo->server[n].window should be the same for all n! */ serverWindow = winInfo->server[0].window; /* Here's where we force quad-buffered stereo rendering. * We use an X trick to make the app draw each frame twice. */ if (winInfo->forceQuadBuffering) { if (winInfo->parity == 0) { /* we're swapping after drawing an even-numbered frame. * Even frames are for left eye, odd frames are for right eye. * Now, switch draw buffer to the right. */ /* crDebug("Swap: done with left. Send expose to 0x%x", (int) winInfo->xwin); */ tilesortspu_DrawBuffer(GL_BACK_RIGHT); /* * Trigger drawing the right view by sending an expose event to * the app to trick it into redrawing. */ #ifdef WINDOWS /** XXX \todo is there a Window equivalent here??? */ #elif defined(Darwin) /** XXX \todo is there a Darwin equivalent here??? */ #else CRASSERT(winInfo->dpy); CRASSERT(winInfo->xwin); XClearArea( winInfo->dpy, winInfo->xwin, 0, 0, winInfo->lastWidth, winInfo->lastHeight, True ); XSync(winInfo->dpy, 0); #endif } else { /* crDebug("Swap: done with right, now left"); */ /* We're swapping after drawing an odd frame. * Now, switch draw buffer back to the left. */ tilesortspu_DrawBuffer(GL_BACK_LEFT); } /* flip parity bit for next frame */ winInfo->parity = !winInfo->parity; /* only swap prior to even (left) frames */ if (winInfo->parity) return; } if (tilesort_spu.swap) crPackSwapBuffersSWAP( serverWindow, flags ); else crPackSwapBuffers( serverWindow, flags ); if (tilesort_spu.syncOnSwap) { if (tilesort_spu.swap) crPackWritebackSWAP( &writeback ); else crPackWriteback( &writeback ); } tilesortspuBroadcastGeom(0); tilesortspuShipBuffers(); if (tilesort_spu.syncOnSwap) { while(writeback) crNetRecv(); } /* want to emit a parameteri here */ if (tilesort_spu.emit_GATHER_POST_SWAPBUFFERS) { if (tilesort_spu.swap) crPackChromiumParameteriCRSWAP(GL_GATHER_POST_SWAPBUFFERS_CR, serverWindow); else crPackChromiumParameteriCR(GL_GATHER_POST_SWAPBUFFERS_CR, serverWindow); } }
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; }
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++; }
/** * Replicate our contexts on a new server (indicated by NewServerIndex). * XXX It may be a problem if we try to attach to a shared context, * when that shared context has not yet been created. */ static void replicatespuReplicateContext(void *element, void *arg) { GLint ctx = (GLint) element; ThreadInfo *thread = (ThreadInfo *) arg; ContextInfo *context = crHashtableSearch(replicate_spu.contextTable, ctx); ContextInfo *sharedContext = NULL; CRContext *tempState; GLint return_val = 0, shareCtx = context->shareCtx, sharedServerCtx = 0; int writeback; if (!context->State) { /* XXX need this? */ crWarning("ReplicateSPU: replicating context with no state!"); return; } if (shareCtx > 0) { sharedContext = (ContextInfo *) crHashtableSearch(replicate_spu.contextTable, shareCtx); if (sharedContext) sharedServerCtx = sharedContext->rserverCtx[NewServerIndex]; } /* * Send CreateContext to new server and get return value */ if (replicate_spu.swap) crPackCreateContextSWAP( replicate_spu.dpyName, context->visBits, sharedServerCtx, &return_val, &writeback); else crPackCreateContext( replicate_spu.dpyName, context->visBits, sharedServerCtx, &return_val, &writeback); replicatespuFlushOne(thread, NewServerIndex); writeback = 1; while (writeback) crNetRecv(); if (replicate_spu.swap) return_val = (GLint) SWAP32(return_val); if (return_val <= 0) { crWarning("Replicate SPU: CreateContext failed"); return; } context->rserverCtx[NewServerIndex] = return_val; /* * Create a new CRContext record representing the state of the new * server (all default state). We'll diff against this to send all the * needed state to the server. * When done, we can dispose of this context. */ tempState = crStateCreateContext(NULL, context->visBits, NULL); /* Bind the remote context. The window's not really significant. */ { int serverWindow; if (context->currentWindow) serverWindow = context->currentWindow->id[NewServerIndex]; else serverWindow = 0; if (replicate_spu.swap) crPackMakeCurrentSWAP( serverWindow, 0, return_val ); else crPackMakeCurrent( serverWindow, 0, return_val ); } /* Send state differences, all texture objects and all display lists * to the new server. * XXX We could be more efficient; in the case of a shared context, * we only need to replicate textures and display lists once... */ crStateDiffContext( tempState, context->State ); replicatespuReplicateTextures(tempState, context->State); replicatespuReplicateLists(tempState, context->displayListManager); /* XXX this call may not be needed */ replicatespuFlushOne(thread, NewServerIndex); /* Destroy the temporary context, no longer needed */ crStateDestroyContext( tempState ); }
int32_t crVBoxServerClientWrite(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t cbBuffer) { CRClient *pClient = NULL; int32_t i; #ifdef VBOXCR_LOGFPS uint64_t tstart, tend; #endif /*crDebug("=>crServer: ClientWrite u32ClientID=%d", u32ClientID);*/ for (i = 0; i < cr_server.numClients; i++) { if (cr_server.clients[i] && cr_server.clients[i]->conn && cr_server.clients[i]->conn->u32ClientID==u32ClientID) { pClient = cr_server.clients[i]; break; } } if (!pClient) return VERR_INVALID_PARAMETER; if (!pClient->conn->vMajor) return VERR_NOT_SUPPORTED; #ifdef VBOXCR_LOGFPS tstart = RTTimeNanoTS(); #endif CRASSERT(pBuffer); /* This should never fire unless we start to multithread */ CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0); /* Check if there's a blocker in queue and it's not this client */ if (cr_server.run_queue->client != pClient && crServerClientInBeginEnd(cr_server.run_queue->client)) { crDebug("crServer: client %d blocked, allow_redir_ptr = 0", u32ClientID); pClient->conn->allow_redir_ptr = 0; } else { pClient->conn->allow_redir_ptr = 1; } pClient->conn->pBuffer = pBuffer; pClient->conn->cbBuffer = cbBuffer; crNetRecv(); CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0); crServerServiceClients(); #if 0 if (pClient->currentMural) { crStateViewport( 0, 0, 500, 500 ); pClient->currentMural->viewportValidated = GL_FALSE; cr_server.head_spu->dispatch_table.Viewport( 0, 0, 500, 500 ); crStateViewport( 0, 0, 600, 600 ); pClient->currentMural->viewportValidated = GL_FALSE; cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 ); crStateMatrixMode(GL_PROJECTION); cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION); crServerDispatchLoadIdentity(); crStateFrustum(-0.6, 0.6, -0.5, 0.5, 1.5, 150.0); cr_server.head_spu->dispatch_table.Frustum(-0.6, 0.6, -0.5, 0.5, 1.5, 150.0); crServerDispatchLoadIdentity(); crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); crStateMatrixMode(GL_MODELVIEW); cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW); crServerDispatchLoadIdentity(); crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); crServerDispatchLoadIdentity(); } #endif crStateResetCurrentPointers(&cr_server.current); CRASSERT(!pClient->conn->allow_redir_ptr || crNetNumMessages(pClient->conn)==0); #ifdef VBOXCR_LOGFPS tend = RTTimeNanoTS(); pClient->timeUsed += tend-tstart; #endif /*crDebug("<=crServer: ClientWrite u32ClientID=%d", u32ClientID);*/ return VINF_SUCCESS; }
GLint 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++; }