/** * 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; }
/** * 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 }
/** * Process incoming/pending message for the given client (queue entry). * \return CLIENT_GONE if this client has gone away/exited, * CLIENT_NEXT if we can advance to the next client * CLIENT_MORE if we have to process more messages for this client. */ static ClientStatus glStubServiceClient(const RunQueue *qEntry) { CRMessage *msg; CRConnection *conn; /* set current client pointer */ cr_server.curClient = qEntry->client; conn = cr_server.run_queue->client->conn; /* service current client as long as we can */ while (conn && conn->type != CR_NO_CONNECTION && crNetNumMessages(conn) > 0) { unsigned int len; /* crDebug("%d messages on %p", crNetNumMessages(conn), (void *) conn); */ /* Don't use GetMessage, because we want to do our own crNetRecv() calls * here ourself. * Note that crNetPeekMessage() DOES remove the message from the queue * if there is one. */ len = crNetPeekMessage( conn, &msg ); CRASSERT(len > 0); if (msg->header.type != CR_MESSAGE_OPCODES) { crError( "SPU %d sent me CRAP (type=0x%x)", cr_server.curClient->spu_id, msg->header.type ); } /* Do the context switch here. No sense in switching before we * really have any work to process. This is a no-op if we're * not really switching contexts. * * XXX This isn't entirely sound. The crStateMakeCurrent() call * will compute the state difference and dispatch it using * the head SPU's dispatch table. * * This is a problem if this is the first buffer coming in, * and the head SPU hasn't had a chance to do a MakeCurrent() * yet (likely because the MakeCurrent() command is in the * buffer itself). * * At best, in this case, the functions are no-ops, and * are essentially ignored by the SPU. In the typical * case, things aren't too bad; if the SPU just calls * crState*() functions to update local state, everything * will work just fine. * * In the worst (but unusual) case where a nontrivial * SPU is at the head of a gl stub's SPU chain (say, * in a multiple-tiered "tilesort" arrangement, as * seen in the "multitilesort.conf" configuration), the * SPU may rely on state set during the MakeCurrent() that * may not be present yet, because no MakeCurrent() has * yet been dispatched. * * This headache will have to be revisited in the future; * for now, SPUs that could head a gl stub's SPU chain * will have to detect the case that their functions are * being called outside of a MakeCurrent(), and will have * to handle the situation gracefully. (This is currently * the case with the "tilesort" SPU.) */ #if 0 crStateMakeCurrent( cr_server.curClient->currentCtx ); #else crStateMakeCurrent( cr_server.curClient->currentCtx ); /* Check if the current window is the one that the client wants to * draw into. If not, dispatch a MakeCurrent to activate the proper * window. */ if (cr_server.curClient) { int clientWindow = cr_server.curClient->currentWindow; int clientContext = cr_server.curClient->currentContextNumber; if (clientWindow && clientWindow != cr_server.currentWindow) { glStubDispatchMakeCurrent(clientWindow, 0, clientContext); /* CRASSERT(cr_server.currentWindow == clientWindow); */ } } #endif /* Force scissor, viewport and projection matrix update in * glStubSetOutputBounds(). */ cr_server.currentSerialNo = 0; /* Commands get dispatched here */ glStubDispatchMessage(msg); crNetFree( conn, msg ); if (qEntry->blocked) { /* Note/assert: we should not be inside a glBegin/End or glNewList/ * glEndList pair at this time! */ return CLIENT_NEXT; } } /* while */ /* * Check if client/connection is gone */ if (!conn || conn->type == CR_NO_CONNECTION) { crDebug("Delete client %p at %d", cr_server.run_queue->client, __LINE__); glStubDeleteClient( cr_server.run_queue->client ); return CLIENT_GONE; } /* * Determine if we can advance to next client. * If we're currently inside a glBegin/End primitive or building a display * list we can't service another client until we're done with the * primitive/list. */ if (glStubClientInBeginEnd(cr_server.curClient)) { /* The next message has to come from the current client's connection. */ CRASSERT(!qEntry->blocked); return CLIENT_MORE; } else { /* get next client */ return CLIENT_NEXT; } }