Files
CydandClaude Fable 5 db7745fcd0 sda4: commit the Glaze developer hard-drive dump
Un-ignored: the dev drive is the ground truth the restoration and
emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer
source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio
content). Kept in-repo for the pod-owner community.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 19:41:15 -05:00

3237 lines
84 KiB
C++

/*{{{ comment*/
/*
File render.c
Contains all rendering entrypoints
Phil Atkin
(c) Division Ltd. 1991
*/
/*
generates tristrips direct as output, for optimum HSP performance
algorithm - walk down tristrip, substituting plane equation into
viewpoint. As soon as sign change occurs, render current tristrip
with appropriate surface properties, and restart from offending printf
vertex
*/
/*}}} */
/*{{{ includes*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dnc.h>
#include <math.h>
#include "pazpl5.h"
#include "viz.h"
#include "macros.h"
#include "pazstore.h"
#include "geometry.h"
#include "lighting.h"
#include "texture.h"
#include "matrix.h"
#include "pazread.h"
#include "optfloat.h"
#include "speclght.h"
#include "cm200io.h"
#include "pxpl5sup\divpxmap.h"
#include "pxpl5sup\pxpl5sup.h"
#include "pxpl5sup\pxpl5tri.h"
#include "pxpl5sup\dmaengn.h"
#include "u:\projects\dbi0150\dbi0151\ucode\igc_opco.h"
#include "u:\projects\dbi0150\dbi0151\ucode\igc_comm.h"
#include "i860sem.h"
#include "sfx.h"
/*}}} */
/*{{{ typedefs an ting*/
typedef int* (*vertex_fn)(int*, float*, float*, float* );
typedef void (*draw_fn)(VERTEX*, VERTEX*, VERTEX*, int, int, VIEW *);
typedef void (*strip_fn)(VSTRIP*, VERTEX*, VIEW*, int );
typedef void (*flip_fn)(int, int );
draw_fn draw_triangle;
strip_fn draw_strip;
flip_fn flipper;
vertex_fn draw_vertex;
/*}}} */
/*{{{ externs, statics*/
#define set_head(v,h,w,a) if (v->strip_type==strip_type_tri) h=w; else h=a
extern int total_grab_patch,
total_grab_light;
extern SCENE *currentScene;
extern VIEWRT *vrthead;
extern void spin ( int link );
extern void fn_solve_strip ( float *p, float *pl, int n_tris, int twosided, float texscale );
extern void fn_solve_pmesh ( float *p, float *pl, int n_tris, int twosided, float texscale );
extern void vertex_copy( VERTEX *render_strip, VERTEX *render_head, int n);
extern void matrix_copy ( MATRIX, MATRIX );
extern int* tile_poke_address;
extern int* wait_poke_address;
extern int* trans_wait_poke_address;
extern unsigned int __frameTime;
extern int cull_pass_microsex;
extern unsigned int __trianglesRendered;
void render_all_patches ( patch_render_chunk *);
int *texture_table_iptr=NULL;
unsigned int __verticesRendered=0;
int nodes, back_colour=-1;
int tex=0;
int type_override=0;
int my_id, view_id, total_views;
int then=0, now=0;
int x_display_tiles, y_display_tiles;
float ambient_value;
float curr_texscale=1.0f;
float Hz=0.0f;
poly_pool_list *poly_pool_head=NULL;
TEXRAMP *texture_ramps;
static MATERIAL *last_surf=NULL;
static float rendering_frame_rate=0.0f;
static int display_tile_base=0;
static int timing_frames=0;
static int rendered_frames=0;
static int very_first_frame=0;
extern int *opaque_endoftex_DMAptr;
/*}}} */
/*{{{ multiple i860 control*/
extern int _processorId,
_numProcessors;
concurrency_control *shared_cntl; /* =(concurrency_control *) 0xfffff880; */
VSTRIP longest_strip,
longest_verts,
longest_tris;
int prev_longest_strip=0,
prev_longest_verts=0,
prev_longest_tris=0;
/*}}} */
/*{{{ void multisync()*/
int multisyncs=0;
void multisync(void) /* char * str ) */
{
/*{{{ multisync algorithm*/
/*
this function interlocks all processors on a shared memory board,
and must leave the shared_cntl region in the same state as when
it entered
algorithm - a single lock determines how many processors are
currently spinning. The processor which increments the lock up
to numProcessors clears the lock and triggers all other processors
to go -
semwait();
shared->lock++;
if (shared->lock==num_processors) {
shared->lock=0;
for (i=0; i<num_processors; i++) {
go[i]=0;
}
semsignal();
}
else {
go[i]=1;
semsignal();
while (go[i])
bla();
}
}
*/
/*}}} */
concurrency_control *shared=shared_cntl;
Semaphore *sem=&shared->sem;
int i, t,
me =_processorId,
them=_numProcessors,
*spin=&shared->go[me];
return;
multisyncs++;
/*
printf ("(%d) multisync %d : %s\n",
_processorId, multisyncs, str );
*/
SemWait ( sem, me );
t=++shared->locker;
if (t==them) {
shared->locker=0;
shared->go[0]=0;
shared->go[1]=0;
shared->go[2]=0;
shared->go[3]=0;
}
else
*spin=1;
/* quick signal */
sem->lock[me]=0;
while (*spin)
bla(100); /* hit uncached ram every 3 uS */
}
/*}}} */
/* some performance tracing */
static int unclipped_tris = 0;
static int farz_drawn_tris = 0;
static int farz_rejected_tris = 0;
static int clipped_tris = 0;
static int clipped_patches = 0;
static int unclipped_patches = 0;
/*{{{ static void start_frame_stats ( void )*/
static void start_frame_stats ( void )
{
unclipped_tris = 0;
farz_drawn_tris = 0;
farz_rejected_tris = 0;
clipped_tris = 0;
clipped_patches = 0;
unclipped_patches = 0;
}
/*}}} */
/*{{{ void init_HSP ( int link, char *string, int magic )*/
void init_HSP ( int link, char *string, int magic )
{
return;
}
/*}}} */
/*{{{ static void render_pxpl5_tristrip ( VERTEX *w0,*/
static void render_pxpl5_tristrip ( VERTEX *w0,
int tristrip,
int n_tris,
int front_face,
int opcode1,
float mtl_code,
pxpl5tri_fn tri_fn,
int clip_code,
float proj_clip )
{
int icoeff_p =(int) coefficient_ptr;
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
register VERTEX *v1, *v2, *v3;
v1=w0;
v2=w0+1;
v3=w0+2;
while (n_tris) {
int proceed=0;
if (clip_code) {
if (v1->position[2] > proj_clip) {
if (v2->position[2] > proj_clip) {
if (v3->position[2] > proj_clip) {
proceed=1;
}
}
}
}
else
proceed=1;
if (proceed) {
if (icoeff_p > icoeff_base) {
icoeff_p=(int) next_coeffchunk ();
icoeff_base=COEFF_FULL + (int) last_coeffchunk;
}
if (front_face) {
icoeff_p = (*tri_fn)( icoeff_p, mtl_code, opcode1,
v1,
v2,
v3 );
}
else
icoeff_p = (*tri_fn)( icoeff_p, mtl_code, opcode1,
v3,
v2,
v1 );
}
v3++;
v2++;
if (tristrip) {
v1++;
front_face^=1;
}
n_tris--;
}
coefficient_ptr=(float *) icoeff_p;
}
/*}}} */
/*{{{ void NULL_flip ( int me, int nodes )*/
void NULL_flip ( int me, int nodes )
{
return;
}
/*}}} */
static int first_add_opcode=1;
/*{{{ static void add_DMA_opcodes ( screenbin *bin, int *opcodes, int n_opcodes )*/
static void add_DMA_opcodes ( screenbin *bin, int *opcodes, int n_opcodes )
{
binchunk *chunk=bin->tail;
int usage=chunk->usage;
int index=usage>>2;
/* usage in bytes */
if (first_add_opcode) {
first_add_opcode=0;
/*
printf ("adding %d opcodes to bin 0x%x, address 0x%x\n",
n_opcodes, bin, &chunk->DMA_opcodes[index] );
*/
}
if ((BIN_FULL - usage) < (n_opcodes << 2)) {
/*{{{ grab a new one*/
chunk->next=next_binchunk ();
chunk->DMA_opcodes[index ]=(int) (&chunk->next->DMA_opcodes[0]);
chunk->DMA_opcodes[index+1]=DMA_GOTO_VAL;
chunk->usage=BIN_FULL;
chunk=chunk->next;
chunk->next=NULL;
bin->tail=chunk;
usage=0;
index=0;
/*}}} */
}
memcpy ( &chunk->DMA_opcodes[index], opcodes, n_opcodes<<2 );
chunk->usage+=n_opcodes<<2;
}
/*}}} */
/*{{{ void XP_flush()*/
void XP_flush()
{
manual_flush(shared_cntl->uncached_flush_location);
}
/*}}} */
/*{{{ debug variables for XP*/
VSTRIP *__current_strip;
VERTEX *__current_head;
int __current_count;
int __render_count;
VERTEX *__render_head;
/*}}} */
#if 0
/* the C model for the hand-coded version */
/*{{{ static void xform_light_project ( )*/
static void xform_light_project ( VERTEX *v1,
int n_verts,
int strip_shade,
int front_face,
VIEW *eye,
LIGHTSOURCE *blondie,
MATRIX quad_aligned_m,
MATERIAL *surf,
int do_project,
float ks )
{
/*{{{ floating point registers*/
/*{{{ 12 matrix registers total 12*/
register float m00, m01, m02,
m10, m11, m12,
m20, m21, m22,
tx, ty, tz;
/*}}} */
/*{{{ 7 viewport scaling 18*/
register float wx, wy, wz,
eye_d,
zmax,
shx, shy;
/*}}} */
/*{{{ 2 lighting registers 20*/
/*
NB - kd is intrinsic colour, held in frame buffer. ks is now also
held in frame buffer as a 4-bit number, so we 6% control over specular
stuff.
*/
register float normfactor;
/*}}} */
/*{{{ 10 temporary registers 31 all used up and more ! ! !*/
register float fdot;
register float invz;
/* temporary registers, re-loaded per vertex */
register float px, py, pz;
#define nx px
#define ny py
#define nz pz
register float cdiff, cspec;
register float lx, ly, lz;
#define rx lx
#define ry ly
#define rz lz
/*}}} */
/*}}} */
/*{{{ integer registers*/
/* 8 register parameters in use */
/* if cooked, dolighting=0, lightbump = 0 */
/* if smooth, dolighting=1, lightbump = 1 */
/* if flat, dolighting=nv-2, lightbump = -1 */
/* per vertex, dolighting+=lightbump */
VERTEX *light_v;
LIGHTSOURCE *bulb;
int dolighting;
int lightbump;
float *light;
float *half;
float *norm;
float *phong_table;
int dot;
/*}}} */
/*{{{ initialize*/
/*{{{ cache matrix ...use fld.q if possible*/
m00=quad_aligned_m[0][0];
m01=quad_aligned_m[0][1];
m02=quad_aligned_m[0][2];
m10=quad_aligned_m[1][0];
m11=quad_aligned_m[1][1];
m12=quad_aligned_m[1][2];
m20=quad_aligned_m[2][0];
m21=quad_aligned_m[2][1];
m22=quad_aligned_m[2][2];
tx =quad_aligned_m[3][0];
ty =quad_aligned_m[3][1];
tz =quad_aligned_m[3][2];
/*}}} */
phong_table=surf->specular_table;
wx =eye->screen_half_width;
wy =eye->screen_half_height;
wz =eye->zscale;
eye_d=eye->d;
zmax =1.0f;
shx=wx*(eye->shift_x + 1.0f);
shy=wy*(eye->shift_y + 1.0f);
if (strip_shade & strip_shade_coloured) {
dolighting = 0;
lightbump = 0;
}
else if (strip_shade & strip_shade_smooth) {
dolighting = 1;
lightbump = 0;
light_v = v1;
}
else {
dolighting = n_verts-2;
lightbump = -1;
light_v = v1+1;
}
/*}}} */
/*{{{ which surface ?*/
if (front_face)
normfactor = 1.0f;
else
normfactor =-1.0f;
/*}}} */
while (n_verts) {
/*{{{ transform 18 flops*/
/* ****************
transform this point
*/
px=v1->position[0];
py=v1->position[1];
pz=v1->position[2];
rx=(px*m00)+(py*m10)+(pz*m20)+tx;
ry=(px*m01)+(py*m11)+(pz*m21)+ty;
rz=(px*m02)+(py*m12)+(pz*m22)+tz;
/*}}} */
/*{{{ project 18 flops*/
if (do_project) {
/* **************
project it to screen-space
*/
invz=eye_d/rz;
px=(rx*wx*invz)+shx;
py=(ry*wy*invz)+shy;
pz=wz*invz;
v1->position[0] = px;
v1->position[1] = py;
v1->position[2] = pz;
}
else {
v1->position[0] = rx;
v1->position[1] = ry;
v1->position[2] = rz;
}
/*}}} */
/*{{{ light 16 flops*/
if (dolighting) {
norm=light_v->normcol;
/* ********************
light this point
*/
/* NOTE - force into adjacent registers for f0 and fst.d */
cdiff=0.0f;
cspec=0.0f;
nx=normfactor*norm[0];
ny=normfactor*norm[1];
nz=normfactor*norm[2];
for (bulb=blondie; bulb; bulb=bulb->next ) {
/*{{{ light up this vertex according to bulb type*/
light=&bulb->xformpos[0];
/* do diffuse shading */
lx=light[0];
ly=light[1];
lz=light[2];
fdot=(nx*lx) + (ny*ly) + (nz*lz);
/* the multiply by light colour happens at end-of-frame */
if (fdot > 0.0f)
cdiff+=fdot;
/* do specular shading - NOTE power factor has gone */
half=(float *) *(int *) &(bulb->xformpos[3]);
lx=half[0];
ly=half[1];
lz=half[2];
dot=(int) ((nx*lx) + (ny*ly) + (nz*lz));
if (dot > 0) {
if (dot > (phong_precision - 1))
dot = phong_precision-1;
/* the multiply by light colour happens at end-of-frame */
/* ditto ks */
cspec +=phong_table[dot];
}
/*}}} */
}
/* fst.d .. */
norm[0]=cdiff*255.0;
norm[1]=cspec*255.0;
}
/*}}} */
v1++;
light_v++;
dolighting+=lightbump;
n_verts--;
}
}
/*}}} */
#endif
/*{{{ declare fn_xform_light_project*/
extern void fn_xform_light_project ( VERTEX *v1,
int n_verts,
int strip_shade,
int front_face,
VIEW *eye,
LIGHTSOURCE *blondie,
MATRIX quad_aligned_m,
MATERIAL *surf,
int do_project,
float ks,
int pmesh );
/*}}} */
#if 0
/*{{{ frustum clipping*/
extern void smintersect(SMOOTHPOINT pi, SMOOTHPOINT p1, SMOOTHPOINT p2, int axis,
float edge);
extern void copy_spoint( SMOOTHPOINT s, SMOOTHPOINT d );
/*{{{ static int smooth_clip (SMOOTHPOINT *out, SMOOTHPOINT *in,int inn, int axis, int sign, float edge)*/
static int smooth_clip ( SMOOTHPOINT *out, SMOOTHPOINT *in,
int inn, int axis, int sign, float edge)
{
register int outn=0, b1, b2;
SMOOTHPOINT *p1=in+inn-1, *p2=in;
register float v1, v2, vv1, vv2;
vv1=(*p1)[axis];
if (sign!=0) v1=vv1-edge;
else v1=edge-vv1;
b1=(v1>=0);
for (; inn>0; inn--) {
vv2=(*p2)[axis];
if (sign!=0) v2=vv2-edge;
else v2=edge-vv2;
b2=(v2>=0);
if (b1 && b2) {
copy_spoint (*p2,*out);
out++; outn++;
}
else {
if (b2||b1) {
smintersect (*out, *p2, *p1, axis, edge);
out++; outn++;
}
if (b2) {
copy_spoint (*p2,*out);
out++; outn++;
}
}
vv1=vv2; v1=v2; p1=p2; b1=b2; p2++;
}
return (outn);
}
/*}}} */
/*{{{ static void clip_smooth_triangle ( VERTEX *aa, VERTEX *bb, VERTEX *cc,*/
static void clip_smooth_triangle ( VERTEX *aa,
VERTEX *bb,
VERTEX *cc,
VIEW *eye,
int front_face, int clip_planes,
int smooth )
{
SMOOTHPOINT *tmp;
SMOOTHPOINT clip_poly [9],
bounce_poly [9];
SMOOTHPOINT *q,*p=&clip_poly[0], *b=&bounce_poly[0];
register int nv=3;
float *pp;
#define swap_ptrs(a,b) tmp=a;a=b;b=tmp
/* printf ("copy tri into poly\n" ); */
if (smooth) {
/*{{{ copy triangle into poly*/
q=p;
pp=(float *) q;
pp[0]=aa->position[0];
pp[1]=aa->position[1];
pp[2]=aa->position[2];
if (texture) {
pp[R] =aa->normcol[0];
pp[R+1]=aa->normcol[1];
pp[R+2]=aa->normcol[2];
}
else {
pp[R] =aa->normcol[0];
pp[R+1]=aa->normcol[1];
pp[R+2]=aa->normcol[2];
}
q++;
pp=(float *) q;
pp[0]=bb->position[0];
pp[1]=bb->position[1];
pp[2]=bb->position[2];
if (texture) {
#ifdef TEXHSP
hsp_tex_colour ( &pp[R], bb->normcol, bb->texcoords );
#else
pp[R] =bb->normcol[0];
pp[R+1]=bb->normcol[1];
pp[R+2]=bb->normcol[2];
#endif
}
else {
pp[R]=bb->normcol[0];
pp[R+1]=bb->normcol[1];
pp[R+2]=bb->normcol[2];
}
q++;
pp=(float *) q;
pp[0]=cc->position[0];
pp[1]=cc->position[1];
pp[2]=cc->position[2];
if (texture) {
/*{{{ */
#ifdef TEXHSP
hsp_tex_colour ( &pp[R], cc->normcol, cc->texcoords );
#else
pp[R] =cc->normcol[0];
pp[R+1]=cc->normcol[1];
pp[R+2]=cc->normcol[2];
#endif
/*}}} */
}
else {
pp[R]=cc->normcol[0];
pp[R+1]=cc->normcol[1];
pp[R+2]=cc->normcol[2];
}
/*}}} */
}
else {
/*{{{ copy triangle into poly USE VERTEX 1 FOR COLOUR*/
q=p;
pp=(float *) q;
pp[0]=aa->position[0];
pp[1]=aa->position[1];
pp[2]=aa->position[2];
if (texture) {
pp[R] =bb->normcol[0];
pp[R+1]=bb->normcol[1];
pp[R+2]=bb->normcol[2];
}
else {
pp[R]=bb->normcol[0];
pp[R+1]=bb->normcol[1];
pp[R+2]=bb->normcol[2];
}
q++;
pp=(float *) q;
pp[0]=bb->position[0];
pp[1]=bb->position[1];
pp[2]=bb->position[2];
if (texture) {
pp[R] =bb->normcol[0];
pp[R+1]=bb->normcol[1];
pp[R+2]=bb->normcol[2];
}
else {
pp[R]=bb->normcol[0];
pp[R+1]=bb->normcol[1];
pp[R+2]=bb->normcol[2];
}
q++;
pp=(float *) q;
pp[0]=cc->position[0];
pp[1]=cc->position[1];
pp[2]=cc->position[2];
if (texture) {
pp[R] =bb->normcol[0];
pp[R+1]=bb->normcol[1];
pp[R+2]=bb->normcol[2];
}
else {
pp[R]=bb->normcol[0];
pp[R+1]=bb->normcol[1];
pp[R+2]=bb->normcol[2];
}
/*}}} */
}
/*{{{ if (clip_planes&clip_hither)*/
if (clip_planes&clip_hither)
{
nv=smooth_clip (b,p,nv,Z,1,eye->hither );
swap_ptrs(p,b);
}
/*}}} */
if (nv<3) return;
/*{{{ if (clip_planes&clip_yon)*/
if (clip_planes&clip_yon)
{
nv=smooth_clip (b,p,nv,Z,0,eye->yon );
swap_ptrs(p,b);
}
/*}}} */
/*{{{ do perspeccy stuff*/
/* normalize view volume */
/* do perspective */
/* scale viewport */
{
float z_offs;
if (front_face) {
z_offs=maxZbufVal+(realOne*2); /* front */
}
else {
z_offs = maxZbufVal+(realOne * 4);
}
project_points ( (float *) p, eye, nv, z_offs, 8 );
}
/*}}} */
if (nv<3) return;
/*{{{ if (clip_planes&clip_x0)*/
if (clip_planes&clip_x0)
{
nv=smooth_clip (b,p,nv,X,1,0);
swap_ptrs(p,b);
}
/*}}} */
if (nv<3) return;
/*{{{ if (clip_planes&clip_x1)*/
if (clip_planes&clip_x1)
{
nv=smooth_clip (b,p,nv,X,0,eye->screen_width);
swap_ptrs(p,b);
}
/*}}} */
if (nv<3) return;
/*{{{ if (clip_planes&clip_y0)*/
if (clip_planes&clip_y0)
{
nv=smooth_clip (b,p,nv,Y,1,0);
swap_ptrs(p,b);
}
/*}}} */
if (nv<3) return;
/*{{{ if (clip_planes&clip_y1)*/
if (clip_planes&clip_y1)
{
nv=smooth_clip (b,p,nv,Y,0,eye->screen_height);
swap_ptrs(p,b);
}
/*}}} */
if (nv<3) return;
/*{{{ render optimised triangles*/
{
int n;
VERTEX va, vb, vc;
float *pp= (float *) p;
int *buf0, *buf, words=(nv*3)+1;
__trianglesRendered+=(nv-2);
buf0=wait_for_room ( eye, words );
buf=buf0;
*buf++ = (words-1) | (1 << 8); /* its a POLYSTRIP */
for (n=0; n<nv; n++ ) {
pp=(float *) p;
/*
MUST call hsp_vert, not draw_vertex, since the texture coords
are already in the colour slots ! ! !
*/
buf=hsp_vert ( buf, pp, pp+R, (float *) aa->texcoords );
p++;
}
inform_driver ( eye, buf0, words );
}
/*}}} */
}
/*}}} */
/*}}} */
#endif
#define check_dbl(p,s) if (((int) (p)) & 0x4) printf("misaligned vertex 0x%x in %s\n", p, s)
/*{{{ static int hither_clip ( VERTEX *out, VERTEX *in,*/
static int hither_clip ( VERTEX *out,
VERTEX *in,
float edge,
int texture,
int smooth )
{
#define clip(f,ix,t) \
out->f[ix]=p1->f[ix]+(t*((p2->f[ix])-(p1->f[ix])))
register int i, outn=0, b1, b2;
VERTEX *p1=in+2, *p2=in;
register float v1, v2, vv1, vv2;
vv1=p1->position[Z];
v1=vv1-edge;
b1=(v1>=0);
for (i = 0; i<3; i++ ) {
vv2=p2->position[Z];
v2=vv2-edge;
b2=(v2>=0);
if (b1 && b2) {
/* check_dbl(out,"hither_clip"); */
vertex_copy ( out, p2, 1 );
out++; outn++;
}
else {
if (b2||b1) {
/*{{{ intersect*/
float t;
t = (edge - vv1) / (vv2 - vv1);
clip ( position, X, t );
clip ( position, Y, t );
if (texture) {
clip ( texcoords, 0, t );
clip ( texcoords, 1, t );
}
if (smooth) {
clip ( normcol, 0, t );
clip ( normcol, 1, t );
clip ( normcol, 2, t );
}
else {
out->normcol[0]=p1->normcol[0];
out->normcol[1]=p1->normcol[1];
out->normcol[2]=p1->normcol[2];
}
out->position[2]=edge;
/*}}} */
out++; outn++;
}
if (b2) {
/* check_dbl(out, "hither_clip"); */
vertex_copy ( out, p2, 1 );
out++; outn++;
}
}
vv1=vv2; v1=v2; p1=p2; b1=b2; p2++;
}
return (outn);
}
/*}}} */
#if 0
/*{{{ static int yon_clip ( VERTEX *out, VERTEX *in,*/
static int yon_clip ( VERTEX *out, VERTEX *in,
float edge, int texture, int smooth )
{
#define clip(f,ix,t) \
out->f[ix]=p1->f[ix]+(t*((p2->f[ix])-(p1->f[ix])))
register int i, outn=0, b1, b2;
VERTEX *p1=in+2, *p2=in;
register float v1, v2, vv1, vv2;
vv1=p1->position[Z];
v1=edge-vv1;
b1=(v1>=0);
for (i=0; i<3; i++ ) {
vv2=p2->position[Z];
v2=edge-vv2;
b2=(v2>=0);
if (b1 && b2) {
/* check_dbl(out, "hither_clip"); */
vertex_copy ( out, p2, 1 );
out++; outn++;
}
else {
if (b2||b1) {
/*{{{ intersect*/
float t;
t = (edge - vv1) / (vv2 - vv1);
clip ( position, X, t );
clip ( position, Y, t );
if (texture) {
clip ( texcoords, 0, t );
clip ( texcoords, 1, t );
}
if (smooth) {
clip ( normcol, 0, t );
clip ( normcol, 1, t );
clip ( normcol, 2, t );
}
else {
out->normcol[0]=p1->normcol[0];
out->normcol[1]=p1->normcol[1];
out->normcol[2]=p1->normcol[2];
}
out->position[2]=edge;
/*}}} */
out++; outn++;
}
if (b2) {
/* check_dbl(out); */
vertex_copy ( out, p2, 1 );
out++; outn++;
}
}
vv1=vv2; v1=v2; p1=p2; b1=b2; p2++;
}
return (outn);
}
/*}}} */
#endif
/*{{{ static void pp5_clip_triangle ( VSTRIP *v, VERTEX *va, VERTEX *vb, VERTEX *vc,*/
static void pp5_clip_triangle ( VSTRIP *v,
VERTEX *va, VERTEX *vb, VERTEX *vc,
VERTEX *vtec,
VIEW *eye,
int frontness,
MATERIAL *front_surf,
int texture, int clip_code )
{
VERTEX quad[8]; /* caters for 3 in, 4 out */
VERTEX *vt=&quad[0];
register float minz=eye->hither;
register int flat = ((v->strip_shade&strip_shade_flat_mask) == strip_shade_flat);
register int outv;
/* only clip triangle if any of its z coords straddle clipping plane */
if ((va->position[Z] < minz) ||
(vb->position[Z] < minz) ||
(vc->position[Z] < minz)) {
/*{{{ do clip*/
/* make copy of input triangle */
/* check_dbl(vt,"pp5_clip"); */
vertex_copy( vt, va, 1 );
vertex_copy( vt+1, vb, 1 );
vertex_copy( vt+2, vc, 1 );
/* first deal with flat shading - copy flat colour to all 3 vertices */
if (flat) {
VERTEX *v1=&quad[1], *v2=&quad[2];
register float r, g, b;
r=v1->normcol[0];
g=v1->normcol[1];
b=v1->normcol[2];
vt->normcol[0]=r;
v2->normcol[0]=r;
vt->normcol[1]=g;
v2->normcol[1]=g;
vt->normcol[2]=b;
v2->normcol[2]=b;
}
/* perform hither clipping */
outv = hither_clip ( &quad[3], vt, minz, texture, flat==0 );
/* skip input triangle */
vt=&quad[3];
/* remember stride in floats yechh?? */
if (outv > 2) {
project_points ( &vt->position[0], eye, outv, sizeof(VERTEX) >> 2 );
render_pxpl5_tristrip ( vt,
0, outv-2,
frontness>>1,
front_surf->pxpl5opcode,
*(float *) &(front_surf->pxpl5codeword),
front_surf->triangle_fn,
0, 0.0f );
}
/*}}} */
}
else {
/*{{{ tri on-screen, just project then draw*/
int icoeff_p =(int) coefficient_ptr;
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
if (icoeff_p > icoeff_base)
coefficient_ptr=(float *) next_coeffchunk ();
/* check_dbl(vt,"pp5_clip"); */
vertex_copy( vt, va, 1 );
vertex_copy( vt+1, vb, 1 );
vertex_copy( vt+2, vc, 1 );
/* remember stride in floats yechh?? */
project_points ( &vt->position[0], eye, 3, sizeof(VERTEX) >> 2 );
if (frontness & 2) {
coefficient_ptr = (*front_surf->triangle_fn)( coefficient_ptr,
*(float *) &(front_surf->pxpl5codeword),
front_surf->pxpl5opcode,
vt,
vt+1,
vt+2);
}
else {
coefficient_ptr = (*front_surf->triangle_fn)( coefficient_ptr,
*(float *) &(front_surf->pxpl5codeword),
front_surf->pxpl5opcode,
vt+2,
vt+1,
vt );
}
/*}}} */
}
}
/*}}} */
/*{{{ static void render_triangles ( VSTRIP *v,*/
/* the big bad wolf version */
int veryFirst=1;
static void render_triangles ( VSTRIP *v,
MATERIAL *front_surf,
VERTEX *render_head,
int n_tris,
int frontness,
MATRIX total,
LIGHTSOURCE *blonde,
VIEW *eye,
int clip_code )
{
int i;
VERTEX *r_strip=render_strip;
int texture=(v->strip_shade&strip_shade_textured)!=0;
if (n_tris==0) return;
last_surf=front_surf;
/*{{{ copy verts to r_strip*/
if (v->strip_type==strip_type_tri) {
/* check_dbl(r_strip,"render_triangles"); */
vertex_copy ( r_strip, render_head, n_tris+2 );
}
else {
/* check_dbl(r_strip,"render_triangles"); */
vertex_copy ( r_strip, v->head, 1 );
vertex_copy ( r_strip+1, render_head, n_tris+1 );
}
/*}}} */
if ((clip_code & (clip_hither | clip_yon)) == 0) {
/*{{{ no z-clipping*/
unclipped_tris+=n_tris;
/* transform and light with projecting */
fn_xform_light_project ( r_strip,
n_tris+2,
v->strip_shade, frontness&1,
eye, blonde, total, front_surf, 1 | (texture<<1),
front_surf->ks*255.0f, 0 );
render_pxpl5_tristrip ( r_strip,
(v->strip_type == strip_type_tri),
n_tris,
frontness>>1,
front_surf->pxpl5opcode,
*(float *) &(front_surf->pxpl5codeword),
front_surf->triangle_fn,
0, 0.0f );
/*}}} */
}
else if ((clip_code & clip_hither) == 0) {
/*{{{ just far-clip, easy*/
/* transform and light with projecting */
float proj_clip=eye->zscale*eye->d*1.04857588E+6 / eye->yon;
unclipped_tris+=n_tris;
fn_xform_light_project ( r_strip,
n_tris+2,
v->strip_shade, frontness&1,
eye, blonde, total, front_surf, 1 | (texture<<1),
front_surf->ks*255.0f, 0 );
render_pxpl5_tristrip ( r_strip,
(v->strip_type == strip_type_tri),
n_tris,
frontness>>1,
front_surf->pxpl5opcode,
*(float *) &(front_surf->pxpl5codeword),
front_surf->triangle_fn,
clip_code, proj_clip );
/*}}} */
}
else {
/*{{{ nasty, near clip*/
VERTEX *va, *vb, *vc, *vtec;
/* hard case, do fully general clipping */
/* transform and light without projecting */
fn_xform_light_project ( r_strip,
n_tris+2,
v->strip_shade, frontness&1,
eye, blonde, total, front_surf, 0,
front_surf->ks*255.0f, 0 );
va=render_strip;
vtec=va;
vb=va+1;
vc=vb+1;
for (i=0; i<n_tris; i++ ) {
clipped_tris++;
pp5_clip_triangle ( v, va,vb,vc, vtec, eye, frontness, front_surf, texture, clip_code );
if (v->strip_type == strip_type_tri) {
va++;
frontness^=2;
}
vb++;
vc++;
vtec++;
}
/*}}} */
}
__trianglesRendered+=n_tris;
__verticesRendered+=(n_tris+2);
veryFirst=0;
}
/*}}} */
/*{{{ static VSTRIP *strip_copy ( VSTRIP *v )*/
static VSTRIP *strip_copy ( VSTRIP *v )
{
if (v==NULL)
return NULL;
else {
VSTRIP *stripcopy=&longest_strip;
VERTEX *vert=v->head,
*copy=stripcopy->head;
stripcopy->normals = v->normals;
stripcopy->strip_type = v->strip_type;
stripcopy->strip_render = v->strip_render;
stripcopy->strip_shade = v->strip_shade;
stripcopy->vertex_count = v->vertex_count;
/* check_dbl(copy,"strip_copy"); */
vertex_copy ( copy, vert, v->vertex_count );
return stripcopy;
}
}
/*}}} */
/*{{{ static VSTRIP *copy_pmesh_verts ( VSTRIP *v )*/
static VSTRIP *copy_pmesh_verts ( VSTRIP *v )
{
if (v==NULL) return NULL;
else {
VSTRIP *stripcopy=&longest_verts;
VERTEX *vert=v->head,
*copy=stripcopy->head;
stripcopy->next = v->next;
stripcopy->normals = v->normals;
stripcopy->strip_type = v->strip_type;
stripcopy->strip_render = v->strip_render;
stripcopy->strip_shade = v->strip_shade;
stripcopy->vertex_count = v->vertex_count;
/* check_dbl(copy,"copy_pmesh_verts"); */
vertex_copy ( copy, vert, v->vertex_count );
return stripcopy;
}
}
/*}}} */
/*{{{ static VSTRIP *copy_pmesh_tris ( VSTRIP *tris, VSTRIP *verts )*/
static VSTRIP *copy_pmesh_tris ( VSTRIP *tris, VERTEX *first_vert )
{
#if 0
/*{{{ */
VSTRIP *stripcopy=&longest_tris;
VERTEX *tri =tris->head,
*copy=stripcopy->head;
int delta;
int *itri=(int *) tri;
int *icop=(int *) copy;
int n, a, b, c, d;
double da, db;
stripcopy->vertex_count = tris->vertex_count;
/*
the trick here is, we copy the triangle pointers and add a
delta, which is new_address-old_address, and thus end up with
a sound data structure
*/
delta=((int) (longest_verts.head)) - ((int) first_vert);
for (n=tris->vertex_count; n; n--) {
a=itri[0];
b=itri[1];
c=itri[2];
icop[0]=a+delta;
icop[1]=b+delta;
icop[2]=c+delta;
icop[3]=0;
/* do plane eqn */
da=((double *) itri)[2];
db=((double *) itri)[3];
((double *) icop)[2]=da;
((double *) icop)[3]=db;
itri +=(sizeof(VERTEX)>>2);
icop +=(sizeof(VERTEX)>>2);
}
return stripcopy;
/*}}} */
#else
/*{{{ */
extern void pmesh_tri_copy ( VERTEX *, VERTEX *, int, int );
VSTRIP *stripcopy=&longest_tris;
stripcopy->vertex_count = tris->vertex_count;
pmesh_tri_copy ( stripcopy->head, tris->head, tris->vertex_count,
((int) (longest_verts.head)) - ((int) first_vert));
return stripcopy;
/*}}} */
#endif
}
/*}}} */
static float sphere_scale;
extern float* sphere_zb_rgb ( float *coeffs,
float material,
int opcode1,
VERTEX *v1,
VERTEX *v2,
VERTEX *v3 );
#if 0
/*{{{ the C-coded sphere functions*/
/*{{{ float* sphere_zb_d ( float *coeffs,*/
float* sphere_zb_d ( float *coeffs,
float material,
int opcode1,
VERTEX *v1,
VERTEX *v2,
VERTEX *v3 )
{
float x =v1->position[0], /* 0 */
y =v1->position[1], /* 4 */
z =v1->position[2], /* 8 */
r =v1->position[3], /* 12 */
rz=v1->planeEqn[3], /* 28 */
lx=v2->planeEqn[0], /* 16 */
ly=v2->planeEqn[1], /* 20 */
lz=v2->planeEqn[2]; /* 24 */
float two=2.0f, fA, fB, fC, fD;
float r2=r*r,
x2y2=(x*x)+(y*y),
r12=1.0f/r2;
float K, r_invlz;
int *coeffptr=(int *) coeffs;
/*
scan-convert - g(x,y) = Ax + By + C - Q
A = 2a, B = 2b C = r2 - a2 - b2, Q = x2 + y2
Note that r is screen-space radius,
rz is radius in z-buffer space
d SAME AS f FOR SQUARE PIXEL DISPLAYS
*/
r2-=x2y2;
fA=x*two;
fB=y*two;
fC=r2;
fD=-1.0f;
/* *****************************
switch on pixels inside circle
*/
*coeffptr++=opcode1;
IGC_FBITS ( coeffptr, 22 );
IGC_TREEgeZERO_Q6 ( coeffptr, fA, fB, fC, fD, 0.0f, fD );
/* **************
z-buffer pixels
*/
K=rz*r12;
fA*=K;
fB*=K;
fC=(z+rz)-(x2y2*K);
fD=-K;
IGC_MEMltTREE_Q6 ( coeffptr, dvpx_zbuf, dvpx_zbufbits,
fA, fB, fC, fD, 0.0f, fD );
IGC_TREEclmpintoMEM_Q0 ( coeffptr, dvpx_zbuf, dvpx_zbufbits );
/* **********************
shade pixels
*/
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_scalar, dvpx_scalarbits,
*(int *)&material );
IGC_CLEAR ( coeffptr, dvpx_specular, 8 );
r_invlz=r/lz;
K=-255.99f*lz*r12;
lx*=r_invlz;
ly*=r_invlz;
fA=K*((x*two) - lx);
fB=K*((y*two) - ly);
fC=K*(r2 + (lx*x + ly*y));
fD=-K;
IGC_TREEclmpintoMEM_Q6 ( coeffptr, dvpx_diffuse, 8,
fA, fB, fC, fD, 0.0f, fD );
IGC_FBITS ( coeffptr, 15 );
/* *****************
binitize it
*/
{
int ic =(int) coeffptr;
int ic0=(int) coeffs;
int words;
if (ic&7) {
ic+=4;
*coeffptr++=0;
}
words=ic-ic0;
binitize ( ic0, DMA_SEND(words>>3),
x-r, y-r,
x+r, y+r,
1023, 767, 16 );
ic+= 31;
ic&=~31;
return (float *) ic;
}
}
/*}}} */
/*{{{ float* sphere_zb_d_s ( float *coeffs,*/
float* sphere_zb_d_s ( float *coeffs,
float material,
int opcode1,
VERTEX *v1,
VERTEX *v2,
VERTEX *v3 )
{
float x =v1->position[0],
y =v1->position[1],
z =v1->position[2],
r =v1->position[3],
rz=v1->planeEqn[3],
lx=v2->planeEqn[0],
ly=v2->planeEqn[1],
lz=v2->planeEqn[2];
float two=2.0f, fA, fB, fC, fD;
float r2=r*r,
x2y2=(x*x)+(y*y),
r12=1.0f/r2;
float K, r_invlz;
int *coeffptr=(int *) coeffs;
/*
scan-convert - g(x,y) = Ax + By + C - Q
A = 2a, B = 2b C = r2 - a2 - b2, Q = x2 + y2
Note that r is screen-space radius,
rz is radius in z-buffer space
d SAME AS f FOR SQUARE PIXEL DISPLAYS
*/
r2-=x2y2;
fA=x*two;
fB=y*two;
fC=r2;
fD=-1.0f;
/* *****************************
switch on pixels inside circle
*/
*coeffptr++=opcode1;
IGC_FBITS ( coeffptr, 22 );
IGC_TREEgeZERO_Q6 ( coeffptr, fA, fB, fC, fD, 0.0f, fD );
/* **************
z-buffer pixels
*/
K=rz*r12;
fA*=K;
fB*=K;
fC=(z+rz)-(x2y2*K);
fD=-K;
IGC_MEMltTREE_Q6 ( coeffptr, dvpx_zbuf, dvpx_zbufbits,
fA, fB, fC, fD, 0.0f, fD );
IGC_TREEclmpintoMEM_Q0 ( coeffptr, dvpx_zbuf, dvpx_zbufbits );
/* **********************
shade pixels
*/
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_scalar, dvpx_scalarbits,
*(int *)&material );
IGC_CLEAR ( coeffptr, dvpx_diffuse, 16 );
/* do diffuse bit */
r_invlz=r/lz;
K=-255.99f*lz*r12;
lx*=r_invlz;
ly*=r_invlz;
fA=K*((x*two) - lx);
fB=K*((y*two) - ly);
fC=K*(r2 + (lx*x + ly*y));
fD=-K;
IGC_TREEclmpintoMEM_Q6 ( coeffptr, dvpx_diffuse, 8, fA, fB, fC, fD, 0.0f, fD );
lx=v2->normcol[0];
ly=v2->normcol[1];
lz=v2->normcol[2];
r_invlz=r/lz;
K=-127.9f*lz*r12;
lx*=r_invlz;
ly*=r_invlz;
fA=K*((x*two) - lx);
fB=K*((y*two) - ly);
fC=K*(r2 + (lx*x + ly*y));
fD=-K;
IGC_TREEclmpintoMEM_Q6 ( coeffptr, dvpx_specular, 7, fA, fB, fC, fD, 0.0f, fD );
IGC_CLEAR ( coeffptr, dvpx_specular+7, 1 );
IGC_FBITS ( coeffptr, 15 );
/* *****************
binitize it
*/
{
int ic =(int) coeffptr;
int ic0=(int) coeffs;
int words;
if (ic&7) {
ic+=4;
*coeffptr++=0;
}
words=ic-ic0;
binitize ( ic0, DMA_SEND(words>>3),
x-r, y-r,
x+r, y+r,
1023, 767, 16 );
ic+= 31;
ic&=~31;
return (float *) ic;
}
}
/*}}} */
/*}}} */
/*{{{ float* sphere_zb_rgb_a ( float *coeffs,*/
float* sphere_zb_rgb_a ( float *coeffs,
float material,
int opcode1,
dpl_CONNECTION *conn )
{
dpl_VERTEX *v1=conn->indices[0];
dpl_VERTEX *v2=conn->indices[1];
float x =v1->xform_posn[0],
y =v1->xform_posn[1],
z =v1->xform_posn[2],
r =v1->xform_posn[3],
rz=v2->xform_posn[3],
lx=v2->xform_posn[0],
ly=v2->xform_posn[1],
lz=v2->xform_posn[2];
float two=2.0f, fA, fB, fC, fD;
float r2=r*r,
x2y2=(x*x)+(y*y),
r12=1.0f/r2;
float K, r_invlz;
int *coeffptr=(int *) coeffs;
/*
scan-convert - g(x,y) = Ax + By + C - Q
A = 2a, B = 2b C = r2 - a2 - b2, Q = x2 + y2
Note that r is screen-space radius,
rz is radius in z-buffer space
d SAME AS f FOR SQUARE PIXEL DISPLAYS
*/
r2-=x2y2;
fA=x*two;
fB=y*two;
fC=r2;
fD=-1.0f;
/* *****************************
switch on pixels inside circle
*/
*coeffptr++=opcode1;
IGC_FBITS ( coeffptr, 22 );
IGC_TREEgeZERO_Q6 ( coeffptr, fA, fB, fC, fD, 0.0f, fD );
/* **************
z-buffer pixels
*/
K=rz*r12;
fA*=K;
fB*=K;
fC=(z+rz)-(x2y2*K);
fD=-K;
IGC_MEMltTREE_Q6 ( coeffptr, dvpx_zbuf, dvpx_zbufbits,
fA, fB, fC, fD, 0.0f, fD );
IGC_TREEclmpintoMEM_Q0 ( coeffptr, dvpx_zbuf, dvpx_zbufbits );
/* **********************
shade pixels
*/
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_scalar, dvpx_scalarbits,
*(int *)&material );
IGC_CLEAR ( coeffptr, dvpx_diffuse, 16 );
/* do diffuse bit */
r_invlz=r/lz;
K=-255.99f*lz*r12;
lx*=r_invlz;
ly*=r_invlz;
fA=K*((x*two) - lx);
fB=K*((y*two) - ly);
fC=K*(r2 + (lx*x + ly*y));
fD=-K;
IGC_TREEclmpintoMEM_Q6 ( coeffptr, dvpx_diffuse, 8, fA, fB, fC, fD, 0.0f, fD );
lx=v2->normcol[0];
ly=v2->normcol[1];
lz=v2->normcol[2];
r_invlz=r/lz;
K=-127.9f*lz*r12;
lx*=r_invlz;
ly*=r_invlz;
fA=K*((x*two) - lx);
fB=K*((y*two) - ly);
fC=K*(r2 + (lx*x + ly*y));
fD=-K;
IGC_TREEclmpintoMEM_Q6 ( coeffptr, dvpx_specular, 7, fA, fB, fC, fD, 0.0f, fD );
IGC_CLEAR ( coeffptr, dvpx_specular+7, 1 );
IGC_FBITS ( coeffptr, 15 );
/* *****************
binitize it
*/
{
int ic =(int) coeffptr;
int ic0=(int) coeffs;
int words;
if (ic&7) {
ic+=4;
*coeffptr++=0;
}
words=ic-ic0;
binitize ( ic0, DMA_SEND(words>>3),
x-r, y-r,
x+r, y+r,
1023, 767, 16 );
ic+= 31;
ic&=~31;
return (float *) ic;
}
}
/*}}} */
#endif
float shading_frame=0.0f;
/*{{{ static int alpha_texture ( MATERIAL *front_surf, MATERIAL *back_surf)*/
static int alpha_texture ( MATERIAL *front_surf, MATERIAL *back_surf)
{
int alpha=0;
if (front_surf) {
if (front_surf->tex) {
if (front_surf->tex->texture_type == TEXTURE_TYPE_24_ALPHA) {
alpha=1;
}
}
}
if (back_surf) {
if (back_surf->tex) {
if (back_surf->tex->texture_type == TEXTURE_TYPE_24_ALPHA) {
alpha=1;
}
}
}
return alpha;
}
/*}}} */
/*{{{ static int mtl_traced=0;*/
static int mtl_traced=0;
static void no_surface ( PATCH *p )
{
char *s;
s=(p->patch_type==patch_type_patch) ? "patch" : "pmesh";
printf ("not rendering %s, no surface for %s\n",
s, p->fmaterial_name );
if (mtl_traced==0) trace_materials();
mtl_traced=1;
}
/*}}} */
/*{{{ void renderPatch ( PATCH *p,*/
void renderPatch ( PATCH *p,
MATRIX forward,
MATRIX back,
LIGHTSOURCE *blonde,
VIEW *eye,
MATERIAL *front_surf,
MATERIAL *back_surf,
int clip_code )
{
VSTRIP *v, *viva;
register float *xform_eye=((float *) back)+12;
register int twosided=(back_surf != NULL);
register int bb;
screenbin *pushscreenbins=screenbins;
if (front_surf==NULL) {
no_surface(p);
return;
}
if (clip_code == 0) unclipped_patches++;
else clipped_patches++;
/* printf ("renderPatch\n" ); */
pxpl5izePatch ( p, front_surf, back_surf );
if (alpha_texture(front_surf, back_surf))
screenbins=trans_screenbins;
for (viva=p->head; viva!=NULL; viva=viva->next ) {
VERTEX *w, *a, *b, *render_head;
register int last, this, n=1, front=3;
v=strip_copy(viva);
n=1;
w=v->head;
bb=v->vertex_count-2;
fn_solve_strip ( xform_eye, (float *) w, bb, twosided,
eye->hither * 1.048e6 );
last=1&(*(int *) (&v->head->position[3]));
render_head=w;
w++;
a=w+1;
b=a+1;
bb--;
if (v->strip_type == strip_type_tri) {
/*{{{ render triangle strip*/
while (bb) {
this=1&(*(int *) (&w->position[3]));
if (this!=last) {
if (last) {
/* transition, prev were front, new is back-facing */
render_triangles ( v, front_surf, render_head,n, front,
forward, blonde, eye, clip_code );
}
else if (twosided) {
/* transition, prev were back, new is front-facing */
render_triangles ( v, back_surf, render_head, n, front^3,
forward, blonde, eye, clip_code );
}
render_head=w;
/*
now be careful with tristrips and front-backness - since every
other triangle alternates direction, we must force a direction
change in the drawer (NOT the shader) if an odd number of
triangles pops out of this
and remember that 'front' is bit-packed, and 2 indicates that
the polygons should be DRAWN forwards, 1 that they should be
SHADED forwards
*/
front^=((n&1)<<1);
n=0;
}
else if (n==14) {
if (last)
render_triangles ( v, front_surf, render_head,n, front,
forward, blonde, eye, clip_code );
else if (twosided)
render_triangles ( v, back_surf, render_head, n, front^3,
forward, blonde, eye, clip_code );
render_head=w;
n=0;
/* retain old value of front */
}
else {
n++;
w++;
b++;
bb--;
}
last=this;
}
if (last)
render_triangles ( v, front_surf,render_head, n, front,
forward, blonde, eye, clip_code );
else if (twosided)
render_triangles ( v, back_surf,render_head, n, front^3,
forward, blonde, eye, clip_code );
/*}}} */
}
else {
/*{{{ render polystrip*/
render_head=w;
while (bb) {
this=1&(*(int *) (&w->position[3]));
if (this!=last) {
if (last)
/* draw AND shade forwards */
render_triangles ( v, front_surf, render_head,n, 3,
forward, blonde, eye, clip_code );
else if (twosided)
/* draw AND shade backwards */
render_triangles ( v, back_surf, render_head, n, 0,
forward, blonde, eye, clip_code );
render_head=a;
n=0;
}
else if (n==14) {
if (last)
/* draw AND shade forwards */
render_triangles ( v,front_surf,render_head,n, 3,
forward, blonde, eye, clip_code );
else if (twosided)
/* draw AND shade backwards */
render_triangles ( v,back_surf,render_head,n, 0,
forward, blonde, eye, clip_code );
render_head=a;
n=0;
}
else {
n++;
w=a;
a=b;
b++;
bb--;
}
last=this;
}
if (last)
render_triangles ( v, front_surf,render_head, n, 3,
forward, blonde, eye, clip_code );
else if (twosided)
render_triangles ( v, back_surf,render_head, n, 0,
forward, blonde, eye, clip_code );
/*}}} */
}
}
screenbins=pushscreenbins;
}
/*}}} */
/*{{{ void renderPmesh ( PATCH *p,*/
static int debug_pfs=0;
void renderPmesh ( PATCH *p,
MATRIX forward,
MATRIX back,
LIGHTSOURCE *blonde,
VIEW *eye,
MATERIAL *front_surf,
MATERIAL *back_surf,
int clip_code )
/*
pmesh rendering - a pmesh is stored as 2 VSTRIPs,
VSTRIP *head is the original, untransformed set of vertices
VSTRIP *tail is frigged as the connectivity list. The list contains
one VERTEX per triangle in the PMESH, and the X,Y,Z coordinates
are typecast into VERTEX pointers. Yes, this is wretched, but
*/
{
/*{{{ variables*/
VSTRIP *verts, *triangles;
register int opcode, bopcode;
register pxpl5tri_fn funky, bfunky;
register float material, bmaterial;
screenbin *pushscreenbins=screenbins;
/* VERTEX *vt; */
int *vti;
int i, texture;
register int twosided=(back_surf != NULL);
/*}}} */
/*{{{ init*/
verts=p->head;
texture=(verts->strip_shade&strip_shade_textured)!=0;
if (front_surf==NULL) {
no_surface(p);
return;
}
pxpl5izePatch ( p, front_surf, back_surf );
if (alpha_texture(front_surf, back_surf))
screenbins=trans_screenbins;
verts=p->head;
triangles=verts->next;
triangles=copy_pmesh_tris ( triangles, verts->head );
verts =copy_pmesh_verts ( verts );
/*}}} */
if (clip_code == 0) unclipped_patches++;
else clipped_patches++;
/* printf ("renderPmesh\n" ); */
fn_solve_pmesh ( &back[3][0], (float *) (triangles->head),
triangles->vertex_count, twosided,
eye->hither * 1.048e6 );
/*{{{ set up funky, bfunky etc*/
funky =front_surf->triangle_fn;
material=*(float *) &(front_surf->pxpl5codeword),
opcode =front_surf->pxpl5opcode;
if (twosided) {
bfunky =back_surf->triangle_fn;
bmaterial=*(float *) &(back_surf->pxpl5codeword),
bopcode =back_surf->pxpl5opcode;
}
/*}}} */
if ((clip_code & (clip_yon|clip_hither)) == 0) {
/*{{{ no z-clipping*/
/*{{{ */
int icoeff_p =(int) coefficient_ptr;
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
/*}}} */
unclipped_tris+=triangles->vertex_count;
fn_xform_light_project ( verts->head,
verts->vertex_count,
verts->strip_shade, 1,
eye, blonde, forward,
front_surf, 1 | (texture<<1),
front_surf->ks*255.0f, twosided==0 );
vti=(int *) triangles->head->position;
for (i=triangles->vertex_count; i; i--, vti+=(sizeof(VERTEX)>>2)) {
if (vti[3]&1) {
/*
if (debug_pfs<8) {
VERTEX *vt=(VERTEX *) vti[0];
printf ("vertex rgb=%f, %f, %f\n",
vt->normcol[0],
vt->normcol[1],
vt->normcol[2] );
debug_pfs++;
}
*/
if (icoeff_p > icoeff_base) {
icoeff_p=(int) next_coeffchunk ();
icoeff_base=icoeff_p + COEFF_FULL;
}
icoeff_p = funky ( icoeff_p,
material,
opcode,
vti[0],
vti[1],
vti[2] );
}
else if (twosided) {
if (icoeff_p > icoeff_base) {
icoeff_p=(int) next_coeffchunk ();
icoeff_base=icoeff_p + COEFF_FULL;
}
icoeff_p = bfunky ( icoeff_p,
bmaterial,
bopcode,
vti[2],
vti[1],
vti[0] );
}
}
coefficient_ptr=(float *) icoeff_p;
/*}}} */
}
else if ((clip_code & clip_hither) == 0) {
/*{{{ far clip only*/
int icoeff_p =(int) coefficient_ptr;
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
float proj_clip=eye->hither * 1.048576E+6 / eye->yon;
/* float proj_clip=eye->zscale*eye->d*1.04857588E+6 / eye->yon; */
fn_xform_light_project ( verts->head,
verts->vertex_count,
verts->strip_shade, 1,
eye, blonde, forward,
front_surf, 1 | (texture<<1),
front_surf->ks*255.0f, twosided==0 );
/* vt=triangles->head; */
vti=(int *) triangles->head->position;
for (i=triangles->vertex_count; i; i--, vti+=(sizeof(VERTEX)>>2)) {
int proceed=0;
VERTEX *va=(VERTEX *)(vti[0]);
VERTEX *vb=(VERTEX *)(vti[1]);
VERTEX *vc=(VERTEX *)(vti[2]);
if (va->position[2] > proj_clip) proceed=1;
if (vb->position[2] > proj_clip) proceed=1;
if (vc->position[2] > proj_clip) proceed=1;
if (proceed) {
farz_drawn_tris++;
/*{{{ do the triangle*/
if (vti[3]&1) {
if (icoeff_p > icoeff_base) {
icoeff_p=(int) next_coeffchunk ();
icoeff_base=icoeff_p + COEFF_FULL;
}
icoeff_p = funky ( icoeff_p,
material,
opcode,
vti[0],
vti[1],
vti[2] );
}
else if (twosided) {
if (icoeff_p > icoeff_base) {
icoeff_p=(int) next_coeffchunk ();
icoeff_base=icoeff_p + COEFF_FULL;
}
icoeff_p = bfunky ( icoeff_p,
bmaterial,
bopcode,
vti[2],
vti[1],
vti[0] );
}
/*}}} */
}
else {
farz_rejected_tris++;
}
}
coefficient_ptr=(float *) icoeff_p;
/*}}} */
}
else {
/*{{{ nasty, near clip*/
VERTEX *vt;
fn_xform_light_project ( verts->head,
verts->vertex_count,
verts->strip_shade, 1,
eye, blonde, forward, front_surf, 0,
front_surf->ks*255.0f, twosided==0 );
vt=triangles->head;
for (i=triangles->vertex_count; i; i--, vt++ ) {
int *ipos=(int *) vt->position;
if (ipos[3]&1) {
clipped_tris++;
pp5_clip_triangle ( verts,
(VERTEX *) (ipos[0]),
(VERTEX *) (ipos[1]),
(VERTEX *) (ipos[2]),
vt,
eye, 2, front_surf, texture, clip_code );
}
else if (twosided) {
clipped_tris++;
pp5_clip_triangle ( verts,
(VERTEX *) (ipos[2]),
(VERTEX *) (ipos[1]),
(VERTEX *) (ipos[0]),
vt,
eye, 2, back_surf, texture, clip_code );
}
}
/*}}} */
}
screenbins=pushscreenbins;
}
/*}}} */
/*{{{ void renderSmesh ( PATCH *p,*/
void renderSmesh ( PATCH *p,
MATRIX forward,
MATRIX back,
LIGHTSOURCE *blonde,
VIEW *eye,
MATERIAL *front_surf,
MATERIAL *back_surf,
int clip_code )
{
/*{{{ variables*/
VSTRIP *verts;
register int opcode;
register pxpl5tri_fn funky;
register float material;
int icoeff_p =(int) coefficient_ptr;
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
VERTEX *vti, *vti0;
int i;
float scale_fac= sphere_scale;
/*}}} */
/*{{{ init*/
verts=p->head;
if (front_surf==NULL)
return;
pxpl5izeSpheres ( p, front_surf, back_surf );
verts=p->head;
verts =copy_pmesh_verts ( verts );
/*}}} */
/*{{{ set up funky, bfunky etc*/
funky = &sphere_zb_rgb;
material=*(float *) &(front_surf->pxpl5codeword);
opcode =front_surf->pxpl5opcode;
/*}}} */
/* printf ("renderSmesh\n" ); */
fn_xform_strip ( verts->head, forward, verts->vertex_count );
/*{{{ do lighting*/
/* drop diffuse component in */
verts->head->planeEqn[0]= 0.0f; /* sin(shading_frame/11.0f); */
verts->head->planeEqn[1]= 0.0f; /* 0.577f; */
verts->head->planeEqn[2]= -1.0f; /* cos(shading_frame/11.0f); */
{
float hyp, dx, dy, dz;
dx=verts->head->planeEqn[0];
dy=verts->head->planeEqn[1];
dz=verts->head->planeEqn[2];
hyp=1.0f/ sqrt(dx*dx + dy*dy + dz*dz );
verts->head->planeEqn[0]=dx*hyp;
verts->head->planeEqn[1]=dy*hyp;
verts->head->planeEqn[2]=dz*hyp;
}
/* drop specular component in */
verts->head->normcol[0]= sin(shading_frame/140.0f);
verts->head->normcol[1]=-0.577f;
verts->head->normcol[2]= cos(shading_frame/140.0f);
/*}}} */
vti=verts->head;
vti0=vti;
if ((clip_code & (clip_yon|clip_hither)) == 0) {
/*{{{ do all-in-one*/
project_spheres ( verts->head->position, eye,
verts->vertex_count,
sizeof(VERTEX) >> 2,
scale_fac );
for (i=verts->vertex_count; i; i--, vti++ ) {
if (icoeff_p > icoeff_base) {
icoeff_p=(int) next_coeffchunk ();
icoeff_base=icoeff_p + COEFF_FULL;
}
icoeff_p = funky ( icoeff_p,
material,
opcode,
vti,
vti0, /* this for lighting */
vti ); /* this not used */
}
/*}}} */
}
else {
for ( i=verts->vertex_count; i; i--, vti++ ) {
/*{{{ project + draw one sphere*/
if ((vti->position[2] - vti->position[3]) > eye->hither) {
project_spheres ( vti->position, eye,
1, sizeof(VERTEX) >> 2,
scale_fac );
if (icoeff_p > icoeff_base) {
icoeff_p=(int) next_coeffchunk ();
icoeff_base=icoeff_p + COEFF_FULL;
}
icoeff_p = funky ( icoeff_p,
material,
opcode,
vti,
vti0, /* this for lighting */
vti ); /* this not used */
}
/*}}} */
}
}
coefficient_ptr=(float *) icoeff_p;
}
/*}}} */
/*{{{ static void render_all_patches ( patch_render_chunk *patch_head )*/
static void render_all_patches ( patch_render_chunk *patch_head )
{
MATERIAL stack_f, *pf,
stack_b, *pb;
register int my_id=_processorId;
/* printf ("render_all_patches, patch_head=0x%x\n", patch_head ); */
for (; patch_head; patch_head=patch_head->next ) {
register int pcount =patch_head->patch_count;
register char *pchar=patch_head->patch_data;
if (pcount==0)
return;
while (pcount) {
register patch_render_rec *p=(patch_render_rec *) pchar;
#if 0
/*{{{ */
SemWait (&p->sem, my_id);
if (p->rendered)
SemSignal(&p->sem, my_id);
else {
p->rendered=1;
SemSignal(&p->sem, my_id);
}
/*}}} */
#endif
/*{{{ deal with materials*/
if (p->front_mtl) {
memcpy ( &stack_f, p->front_mtl, sizeof(MATERIAL));
pf=&stack_f;
}
else
pf=NULL;
if (p->back_mtl) {
memcpy ( &stack_b, p->back_mtl, sizeof(MATERIAL));
pb=&stack_b;
}
else
pb=NULL;
stack_f.tex=p->front_tex;
stack_b.tex=p->back_tex;
/*}}} */
sphere_scale=p->sphere_scale;
/* printf ("pcount=%d, render patch 0x%x\n", pcount, p->p ); */
p->render_me( p->p,
p->forward, p->back,
p->blonde, p->eye,
pf, pb,
p->clip_code );
pcount--;
pchar+=patch_bump_val;
}
}
}
/*}}} */
/*{{{ int render_displaylist ( int left_eye )*/
static int renders=0;
int render_displaylist ( int left_eye )
{
int pthen, pnow;
screenbin *pushscreen =screenbins;
screenbin *pushtscreen=trans_screenbins;
/* printf ("render_displaylist\n" ); */
renders++;
if (left_eye==0) {
/* printf ("left_eye==0, doing right eye bin stuff\n" ); */
screenbins=screenrbins;
trans_screenbins=trans_screenrbins;
}
dN_timer(&pthen);
if (shared_cntl->patch_list_active) {
/* printf ("shared_cntl patch_list_active, sorting out patch list\n" ); */
/*{{{ sort out patch list*/
/*
the patch traverser stops on a NULL next, OR on a zero
patch count, so plonk a zero into next->patch_count
*/
shared_cntl->patch_list_active->patch_count=shared_cntl->patch_count;
if (shared_cntl->patch_count) {
patch_render_chunk *next=shared_cntl->patch_list_active->next;
if (next)
next->patch_count=0;
}
/*}}} */
/* printf ("render_all_patches\n" ); */
render_all_patches( shared_cntl->patch_list_head );
/* printf ("rendered_all_patches, unsort patch list\n" ); */
/*{{{ unsort out patch list*/
shared_cntl->patch_list_active=shared_cntl->patch_list_head;
shared_cntl->patch_count=0;
shared_cntl->patch_usage=0;
shared_cntl->free_patch_rec=&shared_cntl->patch_list_active->patch_data[0];
/*}}} */
/* printf ("rendered_all_patches, unsort light list\n" ); */
/*{{{ unsort out light list*/
shared_cntl->light_list_active=shared_cntl->light_list_head;
shared_cntl->light_count=0;
shared_cntl->light_usage=0;
shared_cntl->free_light_rec=&shared_cntl->light_list_active->light_data[0];
/*}}} */
}
dN_timer(&pnow);
if (left_eye==0) {
screenbins=pushscreen;
trans_screenbins=pushtscreen;
}
return (pnow-pthen);
}
/*}}} */
static int first_framebuf_y = 0,
framebuf_flip = 4,
second_screen_flip=16;
static screenbin *prevBin=NULL;
static int prevX,
prevY;
/*{{{ void setpxpl5VideoMode ( int magicVal )*/
void setpxpl5VideoMode ( int mode )
{
if (mode & 4) {
first_framebuf_y= 16;
framebuf_flip = 4;
}
else if (mode & 16) {
framebuf_flip = 4;
}
else if (mode & 8) {
/* hi-res 1024x1024 */
first_framebuf_y = 0;
framebuf_flip = 8;
}
else {
first_framebuf_y = 0;
framebuf_flip = 4;
}
if (mode & 128)
first_framebuf_y= 16;
}
/*}}} */
static int *DMA_copy,
*transp_DMA_copy;
int recompute_end_of_frame=0;
/*{{{ static screenbin *strap_up_transptiles ( int x_display_tiles,*/
static screenbin *strap_up_transptiles ( int x_display_tiles,
int y_display_tiles,
screenbin *screenbins,
screenbin *trans_screenbins,
int first_framebuf_y,
int strap_last )
{
/* ************************************************
This is a bit tricky, since we are dealing with the PREVIOUS opaque
tile and the CURRENT transparent tile. We are holding a pointer to
the previous opaque bin, a pointer to the current opaque bin, and
a pointer to the current transparent bin. If there is any transparent
stuff, we patch the PREV opaque to point to the current transp. Then
patch the current transp to point to the current opaque. If no transp
stuff, we patch the previous opaque to the current opaque. At the end,
we just patch the previous opaque bin to NULL.
************************************* */
int x, y,
px=prevX,
py=prevY;
screenbin *prevbin=prevBin;
screenbin *headbin=NULL;
int *DMA_seq = shared_cntl->eof_DMA_sequence;
int *transp_DMA_seq = shared_cntl->transp_eof_DMA_sequence;
int *eot_DMA_seq = shared_cntl->eot_DMA_sequence;
int *transp_eot_DMA_seq = shared_cntl->transp_eot_DMA_sequence;
int eofwords = shared_cntl->eof_DMA_words;
int transp_eofwords = shared_cntl->transp_eof_DMA_words;
for (x=0; x<x_display_tiles; x++ ) {
for (y=0; y<y_display_tiles; y++ ) {
screenbin *thisbin =&screenbins [x+(y*(1024/64))];
screenbin *transbin=&trans_screenbins[x+(y*(1024/64))];
float *hack =(float *) &thisbin->head->DMA_opcodes[0];
float *trans_hack=(float *) &transbin->head->DMA_opcodes[0];
if (transbin->head->usage!=transbin->head->DMA_opcodes[63]) {
/*{{{ transparent branch*/
/* copy end-of-frame DMA opcodes into opaque bin */
if (prevbin != NULL) {
*tile_poke_address =px | ((py+display_tile_base) << 5);
*wait_poke_address =DMA_WAIT_VAL;
/* prev opaque GOTO this transp */
DMA_seq[eofwords ]=(int) &transbin->head->DMA_opcodes[2];
DMA_seq[eofwords+1]=DMA_GOTO_VAL;
/* this transp GOTO this opaque */
transp_DMA_seq[transp_eofwords ]=(int) &thisbin->head->DMA_opcodes[2];
transp_DMA_seq[transp_eofwords+1]=DMA_GOTO_VAL;
add_DMA_opcodes ( prevbin, DMA_seq, eofwords+2 );
add_DMA_opcodes ( transbin, transp_DMA_seq, transp_eofwords+2 );
*trans_wait_poke_address=DMA_WAIT_VAL;
}
else {
/* must patch up the transp bin, as he is head of DMA execute op */
headbin=transbin;
transbin->head->DMA_opcodes[0]=0;
transbin->head->DMA_opcodes[1]=0;
/* this transp GOTO this opaque */
transp_DMA_seq[transp_eofwords ]=(int) &thisbin->head->DMA_opcodes[2];
transp_DMA_seq[transp_eofwords+1]=DMA_GOTO_VAL;
add_DMA_opcodes ( transbin, transp_DMA_seq, transp_eofwords+2 );
*trans_wait_poke_address=DMA_WAIT_VAL;
}
/*}}} */
}
else {
/*{{{ opaque*/
if (prevbin != NULL) {
*tile_poke_address=px | ((py+display_tile_base) << 5);
DMA_seq[eofwords ]=(int) &thisbin->head->DMA_opcodes[2];
DMA_seq[eofwords+1]=DMA_GOTO_VAL;
add_DMA_opcodes ( prevbin, DMA_seq, eofwords+2 );
*wait_poke_address=DMA_WAIT_VAL;
}
else {
headbin=thisbin;
thisbin->head->DMA_opcodes[0]=0;
thisbin->head->DMA_opcodes[1]=0;
}
/*}}} */
}
py=y+first_framebuf_y;
px=x;
prevbin=thisbin;
}
}
if (strap_last) {
*tile_poke_address=px | ((py+display_tile_base) << 5);
DMA_seq[eofwords ]=0;
DMA_seq[eofwords+1]=DMA_STOP_VAL | 0x08000000;
add_DMA_opcodes ( prevbin, DMA_seq, eofwords+2 );
}
else
prevBin =prevbin;
prevX=px;
prevY=py;
return headbin;
}
/*}}} */
/*{{{ static void redo_end_of_frame()*/
extern int eof_FOG_rval,
eof_FOG_gval,
eof_FOG_bval,
eof_backR,
eof_backG,
eof_backB,
eof_Z_near,
eof_Z_far,
eof_farZ;
static void redo_end_of_frame ( void )
{
shared_cntl->eof_DMA_words = short_end_of_frame_DMA ( shared_cntl->eof_DMA_sequence,
shared_cntl->eof_sequence,
shared_cntl->eot_DMA_sequence );
shared_cntl->eot_DMA_words = end_of_textr_DMA ( shared_cntl->eot_DMA_sequence,
shared_cntl->eot_sequence );
recompute_end_of_frame=0;
}
/*}}} */
/*{{{ static void pxpl5_flip ( int me, int nodes )*/
static void pxpl5_flip ( int me, int nodes )
{
/*{{{ what we do*/
/* *********************************
We need to construct a linked list of tiles.
For all tiles the first DMA instruction is a GOT0 (next tile). For the
last tile, the destination is NULL. These instructions are
never executed, but they are used by the driver to re-trigger
the DMA engine per tile.
*/
/*}}} */
/*{{{ declare variables*/
extern int dN_pxpl5_dma ( int *address, int *ack_address, int *txdn_address,
vfptr pre_dma );
extern int replying;
screenbin *headbin;
int stereo=0;
int spintime, words;
int i;
int pthen, pnow, pmicrosex;
/*}}} */
prevBin=NULL;
/*{{{ patch in texture ramps*/
if (texture_table_iptr) {
for (i=0; i<MAX_TEX_RAMPS; i++ ) {
texture_table_iptr[(i*3)+2]=texture_ramps[i].codeWord;
}
}
/*}}} */
/*{{{ strap up tiles*/
/*
this now does NO interrupting of tranny, except for very last tile
this needs tidying, all these fn calls will cost around 1mS!!
*/
headbin=strap_up_transptiles ( x_display_tiles, y_display_tiles,
screenbins, trans_screenbins,
first_framebuf_y,
renders == 1 );
if (renders > 1) {
stereo=1;
strap_up_transptiles ( x_display_tiles, y_display_tiles,
screenrbins, trans_screenrbins,
first_framebuf_y^second_screen_flip,
1 );
}
renders=0;
/*}}} */
/*{{{ RENDER THIS FRAME ! ! ! ! do DMA rendering*/
/* spin on an uncached location */
if (_processorId==0) {
/* flush(); */
vfptr eof;
if (recompute_end_of_frame)
eof=&redo_end_of_frame;
else
eof=NULL;
spintime=dN_pxpl5_dma ((int *)(headbin->head),
shared_cntl->uncache_debug_block,
shared_cntl->eot_DMA_sequence,
eof );
if (spintime > 500000)
printf ("is this right - spintime=%d\n", spintime );
recompute_end_of_frame=0;
#if 1
/*{{{ print rendering speed*/
if ((then == 0) && (now == 0)) {
dN_timer (&then);
}
else {
int usecs;
extern int _dN_transactions;
timing_frames++;
if (replying && (timing_frames==40)) {
dN_timer (&now);
usecs=((now - then) / timing_frames);
then=now;
printf ("%f (cull %d stereo=%d)\n",
rendering_frame_rate=(1.0e6f / (float) usecs),
cull_pass_microsex,
stereo );
printf ("%d unclp_p %d clp_p %d unclp_t %d clp_t %d zrej_t %d zacpt\n",
unclipped_patches,
clipped_patches,
unclipped_tris,
clipped_tris,
farz_rejected_tris,
farz_drawn_tris );
timing_frames=0;
}
rendered_frames++;
}
/*}}} */
#endif
multisync();
}
else {
multisync();
}
/*}}} */
start_frame_stats();
/*{{{ flip all buffer space*/
if (screenbins == screen0bins) {
screenbins =screen1bins;
screenrbins=screenr1bins;
trans_screenbins =trans_screen1bins;
trans_screenrbins=trans_screenr1bins;
}
else if (screenbins == screen1bins) {
screenbins =screen0bins;
screenrbins=screenr0bins;
trans_screenbins =trans_screen0bins;
trans_screenrbins=trans_screenr0bins;
}
else {
printf ("WHOAH - screenbins neither screen0 nor screen1 0x%x 0x%x 0x%x\n",
screenbins, screen0bins, screen1bins );
while (1)
;
}
liberate_screenbins ( screenbins, 1024, 768 );
liberate_screenbins ( trans_screenbins, 1024, 768 );
if (stereo) {
liberate_screenbins ( screenrbins, 1024, 768 );
liberate_screenbins ( trans_screenrbins, 1024, 768 );
}
if (lastcoeffptr == coeffstore0) {
coefficient_ptr = (float *) coeffstore1;
last_coeffchunk = coeffstore1;
}
else {
coefficient_ptr = (float *) coeffstore0;
last_coeffchunk = coeffstore0;
}
lastcoeffptr=coefficient_ptr;
/*}}} */
/*{{{ housekeeping*/
display_tile_base^=framebuf_flip;
/*}}} */
debug_pfs=0;
}
/*}}} */
/*{{{ void flip_screens( int me, int nodes )*/
void flip_screens( int me, int nodes )
{
int xd, yd, back_c;
shading_frame+=1.0f;
if (very_first_frame==0) {
int i, j, tile=0;
int *cptr=shared_cntl->eof_sequence,
*cptr0=cptr;
for (i=0; i<64; i++ )
cptr[i]=0x0;
IGC_SETENABS ( cptr );
IGC_CLEAR ( cptr, 0, 32 );
IGC_BSWAIT ( cptr );
IGC_NOOP ( cptr );
IGC_NOOP ( cptr );
IGC_NOOP ( cptr );
IGC_VRAMWrite ( cptr, 4 );
IGC_NOOP ( cptr );
IGC_NOOP ( cptr );
IGC_NOOP ( cptr );
IGC_NOOP ( cptr );
for ( i=0; i<32; i++ ) {
/*{{{ */
int *ptr =shared_cntl->eof_DMA_sequence,
*ptr0=ptr;
*ptr++=0x0;
*ptr++=0x0;
for (j=0; j<32; j++ ) {
*ptr++=tile;
*ptr++=DMA_TILE_VAL;
*ptr++=cptr;
*ptr++=DMA_FLUSH_VAL;
*ptr++=cptr;
*ptr++=DMA_FLUSH_VAL;
*ptr++=cptr0;
*ptr++=DMA_SEND_VAL | 16;
*ptr++=cptr;
*ptr++=DMA_FLUSH_VAL;
*ptr++=0;
*ptr++=DMA_FLUSH_VAL;
tile++;
}
*ptr++=0;
*ptr++=DMA_STOP_VAL | 0x08000000;
/*}}} */
dN_pxpl5_dma (ptr0,
shared_cntl->uncache_debug_block,
shared_cntl->eot_DMA_sequence,
NULL );
}
very_first_frame++;
shared_cntl->eof_DMA_words = short_end_of_frame_DMA ( shared_cntl->eof_DMA_sequence,
shared_cntl->eof_sequence,
shared_cntl->eot_DMA_sequence );
}
pxpl5_flip ( me, nodes );
return;
if (very_first_frame < 2) {
back_c=back_colour;
back_colour=0;
yd=y_display_tiles;
xd=x_display_tiles;
x_display_tiles= 1024/64;
y_display_tiles= 768/128;
}
pxpl5_flip ( me, nodes );
if (very_first_frame<2) {
back_colour=back_c;
y_display_tiles=yd;
x_display_tiles=xd;
very_first_frame++;
}
}
/*}}} */
/*{{{ void render_init()*/
extern int getFsr ( void );
extern void setFsr ( int fsr );
extern float second_ ( void);
extern int give_fp ( void );
extern float fn_inv ( float p );
MATERIAL *mdefault;
int inited=0;
texcell *fx_cell;
void render_init( int x_size, int y_size )
{
int i, j;
int *p;
float then, now;
int *time_end_of_frame;
multisync();
if (inited == 0) {
int fsr;
inited=1;
longest_strip.head=NULL;
longest_verts.head=NULL;
longest_tris.head=NULL;
texture_ramps=(TEXRAMP *) malloc(MAX_TEX_RAMPS*sizeof(TEXRAMP));
ambient_value=120;
setRampEntry ( 0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0 );
setRampEntry ( 1, 0.3, 0.0, 0.0, 1.0, 1.0, 0.9 );
setRampEntry ( 2, 0.0, 0.5, 0.0, 1.0, 1.0, 1.0 );
setRampEntry ( 3, 0.0, 0.0, 0.4, 0.9, 0.9, 1.0 );
texInit ();
/* grab 1st 64x64 texture as flame holding thing */
/* fx_cell=allocateHSPtexture( 64, 64 ); */
setFsr(1|getFsr());
x_display_tiles=(x_size + 63) >> 6;
y_display_tiles=(y_size + 127) >> 7;
display_tile_base=0;
/*
printf ( "x_tiles = %d y_tiles = %d\n",
x_display_tiles,
y_display_tiles );
*/
init_phong ();
sceneGeometry.head=NULL;
sceneGeometry.tail=NULL;
mdefault = create_material ();
add_material(mdefault);
mdefault=newName ( mdefault, viz_createMaterial );
if (_processorId==0) {
/* printf ("render_init shared_cntl at 0x%x\n", shared_cntl ); */
shared_cntl->patch_list_head=NULL;
shared_cntl->light_list_head=NULL;
shared_cntl->length_longest_strip=0;
shared_cntl->length_longest_verts=0;
shared_cntl->length_longest_tris =0;
shared_cntl->patch_list_active=NULL;
shared_cntl->light_list_active=NULL;
shared_cntl->patch_usage=0;
shared_cntl->light_usage=0;
shared_cntl->patch_count=0;
shared_cntl->light_count=0;
shared_cntl->free_patch_rec=NULL;
shared_cntl->free_light_rec=NULL;
shared_cntl->uncache_debug_block = newBytes(4096*2);
shared_cntl->eof_DMA_sequence = newBytes(4096*2);
shared_cntl->eof_sequence = newBytes(4096*2);
DMA_copy=malloc(2048);
shared_cntl->transp_eof_DMA_sequence = newBytes(4096*2);
shared_cntl->transp_eof_sequence = newBytes(4096*2);
transp_DMA_copy=malloc(2048);
shared_cntl->eot_DMA_sequence = newBytes(4096*2);
shared_cntl->eot_sequence = newBytes(4096*2);
shared_cntl->transp_eot_DMA_sequence = newBytes(4096*2);
shared_cntl->transp_eot_sequence = newBytes(4096*2);
shared_cntl->uncached_flush_location = newBytes(4096*2);
/*
printf ("eof_DMA_sequence = 0x%x\n", shared_cntl->eof_DMA_sequence );
printf ("eof_sequence = 0x%x\n", shared_cntl->eof_sequence );
printf ("eot_DMA_sequence = 0x%x\n", shared_cntl->eot_DMA_sequence );
printf ("eot_sequence = 0x%x\n", shared_cntl->eot_sequence );
printf ("treof_DMA_sequence = 0x%x\n", shared_cntl->transp_eof_DMA_sequence );
printf ("treof_sequence = 0x%x\n", shared_cntl->transp_eof_sequence );
printf ("treot_DMA_sequence = 0x%x\n", shared_cntl->transp_eot_DMA_sequence );
printf ("treot_sequence = 0x%x\n", shared_cntl->transp_eot_sequence );
*/
/* we have 64k bytes to fit in end_of_frame and end_of_texture sequences */
shared_cntl->eot_DMA_words = end_of_textr_DMA ( shared_cntl->eot_DMA_sequence,
shared_cntl->eot_sequence );
shared_cntl->transp_eot_DMA_words = end_of_transp_DMA ( shared_cntl->transp_eot_DMA_sequence,
shared_cntl->transp_eot_sequence );
shared_cntl->eof_DMA_words = short_end_of_frame_DMA ( shared_cntl->eof_DMA_sequence,
shared_cntl->eof_sequence,
shared_cntl->eot_DMA_sequence,
45, 66, 135, 20 );
shared_cntl->transp_eof_DMA_words = end_of_transframe_DMA ( shared_cntl->transp_eof_DMA_sequence,
shared_cntl->transp_eof_sequence,
shared_cntl->transp_eot_DMA_sequence );
/* patch list startup */
shared_cntl->patch_list_head =(patch_render_chunk *) newBytes(4096);
shared_cntl->patch_list_active=shared_cntl->patch_list_head;
shared_cntl->patch_list_active->next=NULL;
shared_cntl->patch_count=0;
shared_cntl->patch_usage=0;
shared_cntl->free_patch_rec=shared_cntl->patch_list_active->patch_data;
/* light list startup */
shared_cntl->light_list_head =(light_render_chunk *) newBytes(4096);
shared_cntl->light_list_active=shared_cntl->light_list_head;
shared_cntl->light_list_active->next=NULL;
shared_cntl->light_count=0;
shared_cntl->light_usage=0;
shared_cntl->free_light_rec=shared_cntl->light_list_active->light_data;
multisync();
}
else
multisync();
/*
if ((_processorId==0) && (output_device!=pxpl5_device))
printf ( "Warning : device type not pxpl5_device (0x%x 0x%x)\n",
output_device, pxpl5_device );
*/
flipper = &pxpl5_flip;
#if 0
/*{{{ time end of frame*/
/* attempt to time end-of-frame, end of texture */
time_end_of_frame=newBytes(128*4*(shared_cntl->eot_DMA_words+shared_cntl->eof_DMA_words));
{
int usecs, then, now, index=0, ix;
time_end_of_frame[index++]=0x0;
time_end_of_frame[index++]=0x0;
for (i=0; i<128;i++) {
for (ix=0; ix<shared_cntl->eof_DMA_words;ix++ ) {
time_end_of_frame[index++]=shared_cntl->eof_DMA_sequence[ix];
}
}
time_end_of_frame[index++]=0x0;
time_end_of_frame[index++]=0xf8000000;
dN_timer (&then);
for (i=0; i<128; i++ )
dN_pxpl5_dma ( time_end_of_frame, shared_cntl->uncache_debug_block, shared_cntl->eot_DMA_sequence );
dN_timer (&now);
usecs=now - then;
then=now;
printf ("%d uSecs for 16384 end-of-frames\n", usecs );
}
/*}}} */
/*{{{ time end of texture*/
/* attempt to time end-of-frame, end of texture */
time_end_of_frame=newBytes(128*4*(shared_cntl->eot_DMA_words+shared_cntl->eof_DMA_words));
{
int usecs, then, now, index=0, ix;
time_end_of_frame[index++]=0x0;
time_end_of_frame[index++]=0x0;
for (i=0; i<128;i++) {
for (ix=0; ix<shared_cntl->eot_DMA_words;ix++ ) {
time_end_of_frame[index++]=shared_cntl->eot_DMA_sequence[ix];
}
}
time_end_of_frame[index++]=0x0;
time_end_of_frame[index++]=0xf8000000;
dN_timer (&then);
for (i=0; i<128; i++ )
dN_pxpl5_dma ( time_end_of_frame, shared_cntl->uncache_debug_block, shared_cntl->eot_DMA_sequence );
dN_timer (&now);
usecs=now - then;
then=now;
printf ("%d uSecs for 16384 end-of-textures\n", usecs );
}
/*}}} */
/*{{{ time end of frame and texture*/
/* attempt to time end-of-frame, end of texture */
time_end_of_frame=newBytes(128*4*(shared_cntl->eot_DMA_words+shared_cntl->eof_DMA_words));
{
int usecs, then, now, index=0, ix;
time_end_of_frame[index++]=0x0;
time_end_of_frame[index++]=0x0;
for (i=0; i<128;i++) {
for (ix=0; ix<shared_cntl->eof_DMA_words;ix++ ) {
time_end_of_frame[index++]=shared_cntl->eof_DMA_sequence[ix];
}
for (ix=0; ix<shared_cntl->eot_DMA_words;ix++ ) {
time_end_of_frame[index++]=shared_cntl->eot_DMA_sequence[ix];
}
}
time_end_of_frame[index++]=0x0;
time_end_of_frame[index++]=0xf8000000;
dN_timer (&then);
for (i=0; i<128; i++ )
dN_pxpl5_dma ( time_end_of_frame, shared_cntl->uncache_debug_block, shared_cntl->eot_DMA_sequence );
dN_timer (&now);
usecs=now - then;
then=now;
printf ("%d uSecs for 16384 end-of-frame / textures\n", usecs );
}
/*}}} */
#endif
create_screenbins ( 1024, 768, x_size == 1024 );
{
extern float Cmax_y, Cmax_x;
Cmax_x=((float) x_size) - 0.01f;
Cmax_y=((float) y_size) - 0.01f;
}
/*
printf ("screen0bins =0x%x\n", screen0bins );
printf ("screen1bins =0x%x\n", screen1bins );
printf ("screenr0bins=0x%x\n", screenr0bins );
printf ("screenr1bins=0x%x\n", screenr1bins );
printf ("and screenbins=0x%x\n", screenbins );
*/
multisync();
}
}
/*}}} */