/*************************************************************************/
/*                                                                       */
/*  Copyright (c) 1994 Stanford University                               */
/*                                                                       */
/*  All rights reserved.                                                 */
/*                                                                       */
/*  Permission is given to use, copy, and modify this software for any   */
/*  non-commercial purpose as long as this copyright notice is not       */
/*  removed.  All other uses, including redistribution in whole or in    */
/*  part, are forbidden without prior written permission.                */
/*                                                                       */
/*  This software is provided with absolutely no warranty and no         */
/*  support.                                                             */
/*                                                                       */
/*************************************************************************/


/*
 * NAME
 *	raystack.c
 *
 * DESCRIPTION
 *	This file contains the private data and code for managing the ray tree
 *	stack of ray messages.
 *
 *	A stack is used to eliminate recursion when processing a ray tree.
 *
 *	The ray tree stack contains ray messages for secondary reflection and
 *	refraction rays for pixel.  Shadow rays are not put on the stack; they
 *	are processed sequentially after a ray tree node hit.
 *
 *	The storage for the stack is allocated initially before processing any
 *	rays.  The size is dependent on max_ray_tree_step.  Each copy of this
 *	code needs to have its own private stack.
 */


#include <stdio.h>
#include <math.h>
#include "rt.h"

#define PAGE_SIZE    4096

struct r_struct {
INT 	pad1[PAGE_SIZE];		/* This pad is inserted to avoid
					   false-sharing due to artifacts 
					   of not having a private space
					   in the sproc model */
RAY	*Stack; 			/* Ptr to ray tree stack.	     */
INT	StackTop;			/* Top of ray tree stack.	     */
INT	StackSize;			/* Maximum size of ray tree stack.   */
INT 	pad2[PAGE_SIZE];		/* This pad is inserted to avoid
					   false-sharing due to artifacts 
					   of not having a private space
					   in the sproc model */

} raystruct[MAX_PROCS];


/*
 * NAME
 *	CopyRayMsg - copy a ray structure from a source to a destination
 *
 * SYNOPSIS
 *	VOID	CopyRayMsg(rdst, rsrc)
 *	RAY	*rdst;			// Destination ray message.
 *	RAY	*rsrc;			// Source ray message.
 *
 * RETURNS
 *	Nothing.
 */

VOID	CopyRayMsg(rdst, rsrc)
RAY	*rdst;
RAY	*rsrc;
	{
	rdst->id = rsrc->id;
	rdst->x  = rsrc->x;
	rdst->y  = rsrc->y;

	VecCopy(rdst->P, rsrc->P);
	VecCopy(rdst->D, rsrc->D);

	rdst->level  = rsrc->level;
	rdst->weight = rsrc->weight;

	/* Other fields are initialized with InitRay. */
	}



/*
 * NAME
 *	InitRayTreeStack - initialize the ray tree stack
 *
 * SYNOPSIS
 *	VOID	InitRayTreeStack(TreeDepth,pid)
 *	INT	TreeDepth.		// Max depth of a ray tree.
 *	INT	pid.
 *
 * DESCRIPTION
 *	Initialize the ray tree stack by setting the stack pointer to 0 and
 *	allocating memory for the stack.
 *
 * RETURNS
 *	Nothing.
 */

VOID	InitRayTreeStack(TreeDepth, pid)
INT	TreeDepth;
INT	pid;
	{
	unsigned int powint();

	raystruct[pid].StackSize   = powint(2, TreeDepth) - 1;
	raystruct[pid].StackSize  += NumSubRays;
	raystruct[pid].Stack	    = LocalMalloc(raystruct[pid].StackSize*sizeof(RAY), "raystack.c");
	raystruct[pid].StackTop    = -1;	  /* Empty condition. */
	}


unsigned int powint(i,j)
  int i,j;
  {
  int k;
  int temp = 1;

  for (k = 0; k < j; k++)
      temp = temp*i;
  return temp;
}


/*
 * NAME
 *	PushRayTreeStack - push a ray message onto the ray tree stack
 *
 * SYNOPSIS
 *	VOID	PushRayTreeStack(rmsg,pid)
 *	RAY	*rmsg;			// Ray message.
 *	INT	pid.
 *
 * RETURNS
 *	Nothing.
 */

VOID	PushRayTreeStack(rmsg, pid)
RAY	*rmsg;
INT	pid;
	{
	raystruct[pid].StackTop++;

	if (raystruct[pid].StackTop == raystruct[pid].StackSize)
		{
		fprintf(stderr,"%s: Ray tree stack overflow.\n", ProgName);
		exit(-1);
		}

	CopyRayMsg(&(raystruct[pid].Stack[raystruct[pid].StackTop]), rmsg);
	}



/*
 * NAME
 *	PopRayTreeStack - pop a ray message from the ray tree stack
 *
 * SYNOPSIS
 *	INT	PopRayTreeStack(rmsg)
 *	RAY	*rmsg;			// Will receive popped ray message.
 *	INT 	pid;
 *
 * RETURNS
 *	Either empty or popped status code.
 */

INT	PopRayTreeStack(rmsg, pid)
RAY	*rmsg;
INT	pid;
	{
	if (raystruct[pid].StackTop < 0)
		return (RTS_EMPTY);

	CopyRayMsg(rmsg, &(raystruct[pid].Stack[raystruct[pid].StackTop]));

	raystruct[pid].StackTop--;
	return (RTS_VALID);
	}

