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