Example #1
0
void
newimage(					/* start a new image */
	char *s
)
{
	int		newnp = 0;
						/* # rendering procs arg? */
	if (s != NULL)
		sscanf(s, "%d", &newnp);
						/* free old image */
	freepkids(&ptrunk);
						/* compute resolution */
	hresolu = dev->xsiz;
	vresolu = dev->ysiz;
	normaspect(viewaspect(&ourview), &dev->pixaspect, &hresolu, &vresolu);
	ptrunk.xmin = ptrunk.ymin = pframe.l = pframe.d = 0;
	ptrunk.xmax = pframe.r = hresolu;
	ptrunk.ymax = pframe.u = vresolu;
	pdepth = 0;
						/* clear device */
	(*dev->clear)(hresolu, vresolu);

	if (newparam) {				/* (re)start rendering procs */
		if (ray_pnprocs)
			ray_pclose(0);		/* should already be closed */
		if (newnp > 0)
			nproc = newnp;
		if (nproc > 1)
			ray_popen(nproc);
		newparam = 0;
	} else if ((newnp > 0) & (newnp != nproc)) {
		if (newnp == 1)			/* change # rendering procs */
			ray_pclose(0);
		else if (newnp < ray_pnprocs)
			ray_pclose(ray_pnprocs - newnp);
		else
			ray_popen(newnp - ray_pnprocs);
		nproc = newnp;
	}
	niflush = 0;				/* get first value */
	paint(&ptrunk);
}
void
ray_pdone(		/* reap children and free data */
	int	freall
)
{
	ray_pclose(0);			/* close child processes */

	if (shm_boundary != NULL) {	/* clear shared memory boundary */
		free((void *)shm_boundary);
		shm_boundary = NULL;
	}

	ray_done(freall);		/* free rendering data */
}
int
ray_presult(		/* check for a completed ray */
	RAY	*r,
	int	poll
)
{
	static struct timeval	tpoll;	/* zero timeval struct */
	static fd_set	readset, errset;
	int	n, ok;
	register int	pn;

	if (r == NULL)
		return(0);
					/* check queued results first */
	if (r_recv_first < r_recv_next) {
		*r = r_queue[r_recv_first++];
		return(1);
	}
	if (poll < 0)			/* immediate polling mode? */
		return(0);

	n = ray_pnprocs - ray_pnidle;	/* pending before flush? */

	if (ray_pflush() < 0)		/* send new rays to process */
		return(-1);
					/* reset receive queue */
	r_recv_first = r_recv_next = RAYQLEN;

	if (!poll)			/* count newly sent unless polling */
		n = ray_pnprocs - ray_pnidle;
	if (n <= 0)			/* return if nothing to await */
		return(0);
	if (!poll && ray_pnprocs == 1)	/* one process -> skip select() */
		FD_SET(r_proc[0].fd_recv, &readset);

getready:				/* any children waiting for us? */
	for (pn = ray_pnprocs; pn--; )
		if (FD_ISSET(r_proc[pn].fd_recv, &readset) ||
				FD_ISSET(r_proc[pn].fd_recv, &errset))
			break;
					/* call select() if we must */
	if (pn < 0) {
		FD_ZERO(&readset); FD_ZERO(&errset); n = 0;
		for (pn = ray_pnprocs; pn--; ) {
			if (r_proc[pn].npending > 0)
				FD_SET(r_proc[pn].fd_recv, &readset);
			FD_SET(r_proc[pn].fd_recv, &errset);
			if (r_proc[pn].fd_recv >= n)
				n = r_proc[pn].fd_recv + 1;
		}
					/* find out who is ready */
		while ((n = select(n, &readset, (fd_set *)NULL, &errset,
				poll ? &tpoll : (struct timeval *)NULL)) < 0)
			if (errno != EINTR) {
				error(WARNING,
					"select call failed in ray_presult()");
				ray_pclose(0);
				return(-1);
			}
		if (n > 0)		/* go back and get it */
			goto getready;
		return(0);		/* else poll came up empty */
	}
	if (r_recv_next + r_proc[pn].npending > sizeof(r_queue)/sizeof(RAY))
		error(CONSISTENCY, "buffer shortage in ray_presult()");

					/* read rendered ray data */
	n = readbuf(r_proc[pn].fd_recv, (char *)&r_queue[r_recv_next],
			sizeof(RAY)*r_proc[pn].npending);
	if (n > 0) {
		r_recv_next += n/sizeof(RAY);
		ok = (n == sizeof(RAY)*r_proc[pn].npending);
	} else
		ok = 0;
					/* reset child's status */
	FD_CLR(r_proc[pn].fd_recv, &readset);
	if (n <= 0)
		FD_CLR(r_proc[pn].fd_recv, &errset);
	r_proc[pn].npending = 0;
	ray_pnidle++;
					/* check for rendering errors */
	if (!ok) {
		ray_pclose(0);		/* process died -- clean up */
		return(-1);
	}
					/* preen returned rays */
	for (n = r_recv_next - r_recv_first; n--; ) {
		register RAY	*rp = &r_queue[r_recv_first + n];
		rp->rno = r_proc[pn].rno[n];
		rp->parent = NULL;
		rp->newcset = rp->clipset = NULL;
		rp->rox = NULL;
		rp->slights = NULL;
	}
					/* return first ray received */
	*r = r_queue[r_recv_first++];
	return(1);
}