示例#1
0
文件: renderspu.c 项目: apaka/vbox
static void
DoSync(void)
{
    CRMessage *in, out;

    out.header.type = CR_MESSAGE_OOB;

    if (render_spu.is_swap_master)
    {
        int a;

        for (a = 0; a < render_spu.num_swap_clients; a++)
        {
            crNetGetMessage( render_spu.swap_conns[a], &in );
            crNetFree( render_spu.swap_conns[a], in);
        }

        for (a = 0; a < render_spu.num_swap_clients; a++)
            crNetSend( render_spu.swap_conns[a], NULL, &out, sizeof(CRMessage));
    }
    else
    {
        crNetSend( render_spu.swap_conns[0], NULL, &out, sizeof(CRMessage));

        crNetGetMessage( render_spu.swap_conns[0], &in );
        crNetFree( render_spu.swap_conns[0], in);
    }
}
示例#2
0
void REPLICATESPU_APIENTRY replicatespu_End( void )
{
	GET_THREAD(thread);
	CRPackBuffer *buf = &thread->BeginEndBuffer;

	if ( thread->server.conn->Barf &&
		(thread->BeginEndMode == GL_LINES
		|| thread->BeginEndMode == GL_TRIANGLES
		|| thread->BeginEndMode == GL_QUADS
		|| thread->BeginEndMode == GL_POLYGON ) )
	{
		CRASSERT(buf->pack);

		crPackReleaseBuffer( thread->packer );
		crPackSetBuffer( thread->packer, &thread->normBuffer );
		if ( !crPackCanHoldBuffer( buf ) )
			replicatespuFlush( (void *) thread );

		crPackAppendBuffer( buf );
		crNetFree( thread->server.conn, buf->pack );
		buf->pack = NULL;
	}

	if (thread->currentContext->displayListMode != GL_FALSE) {
		crDLMCompileEnd();
	}
	if (replicate_spu.swap)
	{
		crPackEndSWAP();
	}
	else
	{
		crPackEnd();
	}
}
示例#3
0
/*
 * Send a Chromium opcode buffer across the given net connection.
 * size - size of opcode buffer in bytes.
 * exitFlag - if true, send 'exit' code to server.
 */
static void
SendOpcodes(CRConnection *conn, int size, int exitFlag)
{
	char *buffer, *firstCode;
	CRMessageOpcodes *msg;

	if (size <= MTU) {
		buffer = crNetAlloc(conn);

		msg = (CRMessageOpcodes *) buffer;
		msg->header.type = CR_MESSAGE_OPCODES;
		msg->numOpcodes = size;
		firstCode = buffer + sizeof(CRMessageOpcodes);
		if (exitFlag)
			 *firstCode = 42;
		else
			 *firstCode = 99;
		crNetSend(conn, NULL, buffer, MTU);

		crNetFree(conn, buffer);
	}
	else {
		/* send "huge" buffer */
		const int totalSize = size + 8 + sizeof(CRMessageOpcodes);
		unsigned int *uiptr;
		buffer = crAlloc(totalSize);
		msg = (CRMessageOpcodes *) buffer;
		msg->header.type = CR_MESSAGE_OPCODES;
		msg->numOpcodes = 1;
		uiptr = (unsigned int *) (buffer + sizeof(CRMessageOpcodes) + 4);
		uiptr[0] = size;

		firstCode = buffer + sizeof(CRMessageOpcodes);
		if (exitFlag)
			 *firstCode = 42;
		else
			 *firstCode = 99;

		crNetSend(conn, NULL, buffer, size);
		crFree(buffer);
	}
}
示例#4
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;
	}
}
示例#5
0
/**
 * This is the guts of the binaryswap operation.  Here, we call glReadPixels
 * to read a region of the color and depth buffers from the parent (render
 * SPU) window.	 We then begin the process of composition using binary swap.
 * Each node does a glReadPixels and sends its swap region to its swap 
 * partner.  Once we receive our partner's frame region, we use draw pixels to
 * composite against our frame.  This repeats for all swap partners.  Once we
 * have all of the regions composited against the one we are responsible for,
 * we issue another read and send our region to final display by glDrawPixels 
 * (and some other GL functions) on the child/downstream SPU to send our region
 * to the final display node.
 * Input:  window - the window we're processing
 *	   startx, starty - glReadPixels start coordinates
 *	   endx,   endy   - glReadPixels ending coordinates
 */
static void
CompositeNode(WindowInfo * window, int startx, int starty, int endx, int endy)
{
	int i = 0;
	int read_start_x = 0, read_start_y = 0;
	int read_width = 0, read_height = 0;
	CRMessage *incoming_msg = NULL;
	GLubyte *incoming_color = NULL;
	GLuint *incoming_depth = NULL;
	BinarySwapMsg *render_info = NULL;
	int draw_x = 0, draw_y = 0;
	int draw_width = 0, draw_height = 0;
	float other_depth = 0.0;

	int recalc_end_x = 0, recalc_end_y = 0;
	int recalc_start_x = 0, recalc_start_y = 0;
	int recalc_temp;

	CRASSERT(window->width > 0);
	CRASSERT(window->height > 0);
	/* figure out our portion for each stage */
	for (i = 0; i < binaryswap_spu.stages; i++)
	{
		BinarySwapMsg *msg = (BinarySwapMsg *) window->msgBuffer;

		/* set up message header */
		msg->start_x = window->read_x[i];
		msg->start_y = window->read_y[i];
		msg->width = window->read_width[i];
		msg->height = window->read_height[i];
		msg->depth = binaryswap_spu.depth;

		if (startx < window->read_x[i])
			msg->clipped_x = window->read_x[i];
		else
			msg->clipped_x = startx;

		if (starty < window->read_y[i])
			msg->clipped_y = window->read_y[i];
		else
			msg->clipped_y = starty;

		if (endx > (window->read_x[i] + window->read_width[i]))
			msg->clipped_width =
				(window->read_x[i] + window->read_width[i]) - msg->clipped_x;
		else
			msg->clipped_width = endx - msg->clipped_x;

		if (endy > (window->read_y[i] + window->read_height[i]))
			msg->clipped_height =
				(window->read_y[i] + window->read_height[i]) - msg->clipped_y;
		else
			msg->clipped_height = endy - msg->clipped_y;

		if (msg->clipped_width < 0)
			msg->clipped_width = 0;
		if (msg->clipped_height < 0)
			msg->clipped_height = 0;

		read_start_x = msg->clipped_x;
		read_start_y = msg->clipped_y;
		read_width = msg->clipped_width;
		read_height = msg->clipped_height;

		/* read our portion for this pass */
		/* figure out which mode to use, depth or alpha */
		if (binaryswap_spu.alpha_composite)
		{
			if (read_width > 0 && read_height > 0)
				binaryswap_spu.super.ReadPixels(read_start_x, read_start_y,
                                                read_width, read_height,
                                                GL_RGBA, GL_UNSIGNED_BYTE,
                                                (GLubyte *) window->msgBuffer +
                                                binaryswap_spu.offset);

			if (binaryswap_spu.highlow[i])
			{
				/* lower of pair => recv,send */
				crNetGetMessage(binaryswap_spu.peer_recv[i], &incoming_msg);
				crNetSend(binaryswap_spu.peer_send[i], NULL, window->msgBuffer,
                          (read_width * read_height * 4) + binaryswap_spu.offset);
			}
			else
			{
				/* higher of pair => send,recv */
				crNetSend(binaryswap_spu.peer_send[i], NULL, window->msgBuffer,
                          (read_width * read_height * 4) + binaryswap_spu.offset);
				crNetGetMessage(binaryswap_spu.peer_recv[i], &incoming_msg);
			}

			if (binaryswap_spu.mtu > binaryswap_spu.peer_send[i]->mtu)
				binaryswap_spu.mtu = binaryswap_spu.peer_send[i]->mtu;

			/* get render info from other node */
			render_info = (BinarySwapMsg *) incoming_msg;
			draw_x = render_info->clipped_x;
			draw_y = render_info->clipped_y;
			draw_width = render_info->clipped_width;
			draw_height = render_info->clipped_height;
			other_depth = render_info->depth;

			if (draw_width > 0 && draw_height > 0)
			{
				/* get incoming fb */
				incoming_color =
					(GLubyte *) ((GLubyte *) incoming_msg + binaryswap_spu.offset);
				/* figure out blend function based on z */
				binaryswap_spu.super.Enable(GL_BLEND);
				/* Other image is on top of ours! */
				if (binaryswap_spu.depth > other_depth)
				{
					/* over operator */
					binaryswap_spu.super.BlendFuncSeparateEXT(GL_SRC_ALPHA,
                                                              GL_ONE_MINUS_SRC_ALPHA,
                                                              GL_ONE, GL_ONE);
					binaryswap_spu.super.WindowPos2iARB(draw_x, draw_y);
					binaryswap_spu.super.DrawPixels(draw_width, draw_height,
                                                    GL_RGBA, GL_UNSIGNED_BYTE,
                                                    incoming_color);
				}
				/* other image is under ours */
				else if(binaryswap_spu.depth < other_depth)
				{
					/* under operator */
					binaryswap_spu.super.BlendFuncSeparateEXT(GL_ONE_MINUS_DST_ALPHA,
                                                              GL_DST_ALPHA,
                                                              GL_ONE,
                                                              GL_ONE);
					binaryswap_spu.super.WindowPos2iARB(draw_x, draw_y);
					binaryswap_spu.super.DrawPixels(draw_width, draw_height,
                                                    GL_RGBA, GL_UNSIGNED_BYTE,
                                                    incoming_color);
				}
				else
				{
					if(binaryswap_spu.highlow[i])
					{
						/* over operator */
						binaryswap_spu.super.BlendFuncSeparateEXT(GL_SRC_ALPHA,
																											GL_ONE_MINUS_SRC_ALPHA,
																											GL_ONE, GL_ONE);
						binaryswap_spu.super.WindowPos2iARB(draw_x, draw_y);
						binaryswap_spu.super.DrawPixels(draw_width, draw_height,
																						GL_RGBA, GL_UNSIGNED_BYTE,
																						incoming_color);
					}
					else
					{
						/* under operator */
						binaryswap_spu.super.BlendFuncSeparateEXT(GL_ONE_MINUS_DST_ALPHA,
																											GL_DST_ALPHA,
																											GL_ONE,
																											GL_ONE);
						binaryswap_spu.super.WindowPos2iARB(draw_x, draw_y);
						binaryswap_spu.super.DrawPixels(draw_width, draw_height,
																						GL_RGBA, GL_UNSIGNED_BYTE,
																						incoming_color);
					}
				}
				if (binaryswap_spu.depth > other_depth)
				{
					binaryswap_spu.depth = other_depth;
				}
			}
		}
		else
		{
			/* depth composite */
			if (read_width > 0 && read_height > 0)
			{
				GLubyte *colors =
					(GLubyte *) window->msgBuffer	+	binaryswap_spu.offset;
				GLuint *depths =
					(GLuint *) ((GLubyte *) window->msgBuffer +	/* base address */
											(read_width * read_height * 3) +	/* color information */
											binaryswap_spu.offset);	        /* message header */

				binaryswap_spu.super.ReadPixels(read_start_x, read_start_y,
																				read_width, read_height,
																				GL_RGB, GL_UNSIGNED_BYTE,
																				colors);
				binaryswap_spu.super.ReadPixels(read_start_x, read_start_y,
																				read_width, read_height,
																				GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,
																				depths);
			}

			if (binaryswap_spu.highlow[i])
			{
				/* lower of pair => recv,send */
				crNetGetMessage(binaryswap_spu.peer_recv[i], &incoming_msg);
				crNetSend(binaryswap_spu.peer_send[i], NULL, window->msgBuffer,
									read_width * read_height * (3 + 4) + binaryswap_spu.offset);
			}
			else
			{
				/* higher of pair => send,recv */
				crNetSend(binaryswap_spu.peer_send[i], NULL, window->msgBuffer,
									read_width * read_height * (3 + 4) + binaryswap_spu.offset);
				crNetGetMessage(binaryswap_spu.peer_recv[i], &incoming_msg);
			}
			if (binaryswap_spu.mtu > binaryswap_spu.peer_send[i]->mtu)
				binaryswap_spu.mtu = binaryswap_spu.peer_send[i]->mtu;

			/* get render info from other node */
			render_info = (BinarySwapMsg *) incoming_msg;
			draw_x = render_info->clipped_x;
			draw_y = render_info->clipped_y;
			draw_width = render_info->clipped_width;
			draw_height = render_info->clipped_height;

			if (draw_width > 0 && draw_height > 0)
			{
				/* get incoming fb */
				incoming_color =
					(GLubyte *) ((GLubyte *) incoming_msg + binaryswap_spu.offset);
				incoming_depth =
					(GLuint *) (incoming_color + draw_width * draw_height * 3);

				binaryswap_spu.super.WindowPos2iARB(draw_x, draw_y);

				/* Draw the depth image into the depth buffer, setting the stencil
				 * to one wherever we pass the Z test, clearinging to zero where
				 * we fail.
				 */
				binaryswap_spu.super.ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
				binaryswap_spu.super.StencilOp(GL_KEEP, GL_ZERO, GL_REPLACE);
				binaryswap_spu.super.StencilFunc(GL_ALWAYS, 1, ~0);
				binaryswap_spu.super.Enable(GL_STENCIL_TEST);
				binaryswap_spu.super.Enable(GL_DEPTH_TEST);
				binaryswap_spu.super.DepthFunc(GL_LEQUAL);
				binaryswap_spu.super.DrawPixels(draw_width, draw_height,
																				GL_DEPTH_COMPONENT,
																				GL_UNSIGNED_INT, incoming_depth);

				/* Now draw the RGBA image, only where the stencil is one, reset
				 * stencil to zero as we go
				 * (to avoid calling glClear(STENCIL_BUFFER_BIT)).
				 */
				binaryswap_spu.super.Disable(GL_DEPTH_TEST);
				binaryswap_spu.super.StencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
				binaryswap_spu.super.StencilFunc(GL_EQUAL, 1, ~0);
				binaryswap_spu.super.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
				binaryswap_spu.super.DrawPixels(draw_width, draw_height, GL_RGB,
																				GL_UNSIGNED_BYTE, incoming_color);
				binaryswap_spu.super.Disable(GL_STENCIL_TEST);
			}
		}

		/* make sure everything got drawn for next pass */
		binaryswap_spu.super.Flush();

		/* find optimal starting point for readback based on 
		   this node's region and the partner's region */
		recalc_start_x = render_info->start_x;
		if (startx < render_info->clipped_x)
		{
			recalc_temp = startx;
		}
		else
		{
			recalc_temp = render_info->clipped_x;
			if (render_info->clipped_width > 0 && render_info->clipped_height > 0)
				startx = recalc_temp;
		}
		if (recalc_temp > recalc_start_x)
		{
			recalc_start_x = recalc_temp;
		}

		recalc_start_y = render_info->start_y;
		if (starty < render_info->clipped_y)
		{
			recalc_temp = starty;
		}
		else
		{
			recalc_temp = render_info->clipped_y;
			if (render_info->clipped_width > 0 && render_info->clipped_height > 0)
				starty = recalc_temp;
		}
		if (recalc_temp > recalc_start_y)
		{
			recalc_start_y = recalc_temp;
		}

		/* find optimal ending point for readback based on 
		 * this node's region and the partner's region
		 */
		recalc_end_x = render_info->start_x + render_info->width;
		if (endx > (render_info->clipped_x + render_info->clipped_width))
		{
			recalc_temp = endx;
		}
		else
		{
			recalc_temp = (render_info->clipped_x + render_info->clipped_width);
			if (render_info->clipped_width > 0 && render_info->clipped_height > 0)
				endx = recalc_temp;
		}
		if (recalc_end_x > recalc_temp)
		{
			recalc_end_x = recalc_temp;
		}

		recalc_end_y = render_info->start_y + render_info->height;
		if (endy > (render_info->clipped_y + render_info->clipped_height))
		{
			recalc_temp = endy;
		}
		else
		{
			recalc_temp = (render_info->clipped_y + render_info->clipped_height);
			if (render_info->clipped_width > 0 && render_info->clipped_height > 0)
				endy = recalc_temp;
		}
		if (recalc_end_y > recalc_temp)
		{
			recalc_end_y = recalc_temp;
		}

		/* clean up the memory allocated for the recv */
		crNetFree(binaryswap_spu.peer_recv[i], incoming_msg);
	}
    
	draw_x = recalc_start_x;
	draw_y = recalc_start_y;
	draw_width = recalc_end_x - recalc_start_x;
	draw_height = recalc_end_y - recalc_start_y;

	if (draw_width > 0 && draw_height > 0)
	{
		/* send our final portion off to child */
		binaryswap_spu.super.ReadPixels(draw_x, draw_y, draw_width, draw_height,
																		GL_RGB, GL_UNSIGNED_BYTE,
																		window->msgBuffer +
																		binaryswap_spu.offset);

		/*
		 * Set the downstream viewport.  If we don't do this, and the
		 * downstream window is resized, the glRasterPos command doesn't
		 * seem to be reliable.  This is a problem both with Mesa and the
		 * NVIDIA drivers.  Technically, this may not be a driver bug at
		 * all since we're doing funny stuff.  Anyway, this fixes the problem.
		 * Note that the width and height are arbitrary since we only care
		 * about getting the origin right.  glDrawPixels, glClear, etc don't
		 * care what the viewport size is.  (BrianP)
		 */
		CRASSERT(window->width > 0);
		CRASSERT(window->height > 0);

		/* Begin critical region */
		binaryswap_spu.child.SemaphorePCR(MUTEX_SEMAPHORE);

		/* Update child window position, in case we're using the windowtracker
		 * and VNC SPUs.
		 */
		{
			GLint pos[2];
			binaryswap_spu.child.GetChromiumParametervCR(GL_WINDOW_POSITION_CR,
																									 window->childWindow,
																									 GL_INT, 2, pos);
			if (pos[0] != window->child_xpos ||
					pos[1] != window->child_ypos) {
				binaryswap_spu.child.WindowPosition(window->childWindow,
																						pos[0], pos[1]);
				window->child_xpos = pos[0];
				window->child_ypos = pos[1];
			}
		}

		binaryswap_spu.child.WindowPos2iARB(draw_x, draw_y);
		binaryswap_spu.child.DrawPixels(draw_width, draw_height,
																		GL_RGB, GL_UNSIGNED_BYTE,
																		window->msgBuffer +
																		binaryswap_spu.offset);

		/* end critical region */
		binaryswap_spu.child.SemaphoreVCR(MUTEX_SEMAPHORE);
	}
}