Beispiel #1
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();
	}

	/* silence compiler */
	return 0;
}
Beispiel #2
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
}
Beispiel #3
0
/**
 * 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;
	}
}