1  /********************************************************************** <BR>


2  This file is part of Crack dot Com's free source code release of


3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for


4  information about compiling & licensing issues visit this URL</a>


5  <PRE> If that doesn't help, contact Jonathan Clark at


6  golgotha_source@usa.net (Subject should have "GOLG" in it)


7  ***********************************************************************/


8 


9  #include "arch.hh"


10  #include "math/num_type.hh"


11  #include "time/profile.hh"


12  #include "software/r1_software.hh"


13  #include "software/r1_software_globals.hh"


14  #include "software/mappers.hh"


15  #include "software/span_buffer.hh"


16  #include "software/inline_fpu.hh"


17 


18  #include "software/amd3d/amd3d.h"


19 


20  #ifndef USE_AMD3D


21 


22  i4_bool amd3d_build_triangle_span_lists() {}


23 


24  #else


25 


26  extern span_tri_info tri_stack;


27  extern span_edge active_list_head;


28  extern span_edge active_list_tail;


29 


30  extern span_edge *compare_here;


31  extern span_edge *temp_edge,*t1;


32 


33  inline void amd3d_sort_in_new_edges(span_edge *first)


34  {


35  compare_here = &active_list_head;


36 


37  while (first)


38  {


39  while (first>x > compare_here>next_active>x)


40  {


41  compare_here = compare_here>next_active;


42  }


43 


44  //store first>next. remember, >next and >last_active are a union


45  // (to save space)


46 


47  temp_edge = first>next;


48 


49  first>last_active = compare_here;


50  first>next_active = compare_here>next_active;


51 


52  compare_here>next_active>last_active = first;


53  compare_here>next_active = first;


54 


55  compare_here = first;


56 


57  #ifdef DEBUG


58  if (!first>next_active)


59  {


60  sw32 a=0;


61  }


62  #endif


63 


64  //first = first>next,see comment above


65  first = temp_edge;


66  }


67  }


68 


69  extern span_entry *next_new_span;


70  extern span_tri_info *cur_stack;


71  extern span_tri_info *temp_stack;


72  extern span_tri_info *e_tri;


73  extern i4_bool everything_transparent;


74  extern sw32 span_buff_x, span_buff_y,span_length;


75  extern w16 *cur_scanline;


76 


77  extern span_edge **new_edge_list;


78  extern span_edge **remove_edge_list;


79 


80  extern float fx_fy[2];


81 


82  extern float e_ooz;


83  extern float ooz_compare;


84 


85  extern i4_bool on_top;


86 


87  inline w32 greater_than_compare(float *arg1, float *arg2)


88  {


89  _asm


90  {


91  mov edx,dword ptr [arg1]


92  mov edi,dword ptr [arg2]


93 


94  movd mm0,dword ptr [edx]


95  movd mm1,dword ptr [edi]


96 


97  pfcmpgt (m0, m1)


98  movd eax, mm0


99  }


100  }


101 


102  inline void amd3d_depth_at_pixel(tri_gradients *grads, float *result)


103  {


104  _asm


105  {


106  mov eax,dword ptr [result]


107  movq mm0, qword ptr [fx_fy]


108 


109  mov edi,dword ptr [grads]


110  movq mm1, qword ptr [edi]tri_gradients.doozdx


111 


112  pfmul (m0, m1)


113  movq mm2, dword ptr [edi]tri_gradients.oozat00


114 


115  //low bits of mm0  fx * grads.doozdx


116  //high bits of mm0  fy * grads.doozdy


117 


118  //low bits of mm2  grads.oozat00


119 


120  pfacc (m0, m1) //m1 can be anything really


121  //low bits of mm0  fx * grads.doozdx + fy * grads.doozdy


122 


123  pfadd (m0, m2)


124  //low bits of mm0  grads.oozat00 + fx * grads.doozdx + fy*grads.doozdy


125 


126  movd dword ptr [eax], mm0


127  }


128  }


129 


130  inline void fy_float(sw32 y)


131  {


132  _asm


133  {


134  lea edi, dword ptr [y]


135 


136  pi2fd (m0, _edi)


137 


138  movd dword ptr [fx_fy+4],mm0


139  }


140  }


141 


142  inline void fx_float(sw32 x)


143  {


144  _asm


145  {


146  lea edi, dword ptr [x]


147 


148  pi2fd (m0, _edi)


149 


150  movd dword ptr [fx_fy],mm0


151  }


152  }


153 


154  i4_bool amd3d_build_triangle_span_lists()


155  {


156  register span_edge *e;


157 


158  new_edge_list = new_edges;


159  remove_edge_list = remove_edges;


160  cur_scanline = r1_software_render_buffer_ptr;


161  next_new_span = &global_span_list[num_global_spans];


162 


163  for (span_buff_y = 0; span_buff_y < r1_software_render_buffer_height;


164  span_buff_y++,cur_scanline += r1_software_render_buffer_wpl)


165  {


166  if (*new_edge_list)


167  {


168  amd3d_sort_in_new_edges(*new_edge_list);


169  }


170  new_edge_list++;


171 


172  tri_stack.has_leader = 0;


173  tri_stack.cur_span_start_x = 0;


174  tri_stack.cur_span_start_ooz = 99999.f;


175  tri_stack.next_stack = tri_stack.last_stack = &tri_stack;


176 


177  fy_float(span_buff_y); //fy = (float)y;


178 


179  //go through the x sorted active spans for this scanline


180  for (e=active_list_head.next_active; e != &active_list_tail; e=e>next_active)


181  {


182  //round to nearest x


183  span_buff_x = (e>x+0xFFFF) >> 16;


184 


185  fx_float(span_buff_x); //fx = (float)x;


186 


187  e_tri = e>tri_1;


188 


189  if (e>flags & LEADING_1)


190  {


191  if ((e_tri>has_leader++)==0)


192  {


193  //e_ooz = e_tri>grads.oozat00 + (fx*e_tri>grads.doozdx) + (fy*e_tri>grads.doozdy);


194  amd3d_depth_at_pixel(&e_tri>grads, &e_ooz);


195 


196  //leading edge. stack manipulation stuff


197  cur_stack = tri_stack.next_stack;


198 


199  everything_transparent = i4_T;


200  on_top = i4_T;


201 


202  //go down the stack until we find where this guy will go.


203  while (cur_stack != &tri_stack)


204  {


205  //ooz_compare = e_ooz  (cur_stack>grads.oozat00 +


206  //cur_stack>grads.doozdx * fx +


207  //cur_stack>grads.doozdy * fy);


208 


209  amd3d_depth_at_pixel(&cur_stack>grads, &ooz_compare);


210 


211  //ooz_compare = e_ooz  ooz_compare;


212  //if (ooz_compare > 0)


213  // break;


214 


215  if (greater_than_compare(&e_ooz, &ooz_compare))


216  break;


217 


218  if ((*(int *)&e_ooz) == (*(int *)&ooz_compare))


219  {


220  //edges are of equal depth. compare the gradient.


221  //if (e_tri>grads.doozdx > cur_stack>grads.doozdx)


222  // break;


223 


224  if (greater_than_compare(&e_tri>grads.doozdx, &cur_stack>grads.doozdx))


225  break;


226  }


227 


228  on_top = i4_F;


229 


230  //this will tell us if everything on top of (in front of) this surface is seethruable


231  if (cur_stack>type < SPAN_TRI_SEE_THRU)


232  everything_transparent = i4_F;


233 


234  cur_stack = cur_stack>next_stack;


235  }


236 


237  e_tri>next_stack = cur_stack;


238  e_tri>last_stack = cur_stack>last_stack;


239 


240  cur_stack>last_stack>next_stack = e_tri;


241  cur_stack>last_stack = e_tri;


242 


243  e_tri>cur_span_start_x = span_buff_x;


244  *(int *)&e_tri>cur_span_start_ooz = *(int *)&e_ooz; //for some reason the compiler did this with fld / fst


245 


246  //if this is a solid span, and everything above it is transparent, gotta draw whatever is below it


247  //if this is a solid span, and its on top, gotta draw whatever is below it


248 


249  if (e_tri>type<SPAN_TRI_SEE_THRU && (on_top  everything_transparent))


250  {


251  cur_stack = e_tri>next_stack;


252 


253  while (cur_stack != &tri_stack)


254  {


255  //we've gotta create spans for everything below this in the stack.


256  span_length = span_buff_x  cur_stack>cur_span_start_x;


257  if (span_length>0)


258  {


259  //make a span


260  next_new_span>s.x = cur_stack>cur_span_start_x;


261  next_new_span>s.y = span_buff_y;


262  next_new_span>s.width = span_length;


263  next_new_span>s.ooz = cur_stack>cur_span_start_ooz;


264  next_new_span>s.scanline_ptr = cur_scanline;


265 


266  //add to its triangles list of spans


267  next_new_span>s.next_tri_span = cur_stack>span_list_head;


268  cur_stack>span_list_head = num_global_spans;


269 


270  num_global_spans++;


271  next_new_span++;


272  if (num_global_spans>=MAX_SPANS) return i4_F;


273  }


274  if (cur_stack>type<SPAN_TRI_SEE_THRU) break;


275  cur_stack = cur_stack>next_stack;


276  }


277  }


278  }


279  }


280  else //is a trailer


281  if ((e_tri>has_leader)==1)


282  {


283  //trailing edge


284  //is this the end of a span for the tri currently on top of the stack?


285  if (tri_stack.next_stack==e_tri)


286  {


287  cur_stack = e_tri;


288 


289  span_length = span_buff_x  cur_stack>cur_span_start_x;


290  if (span_length>0)


291  {


292  //make a span


293  next_new_span>s.x = cur_stack>cur_span_start_x;


294  next_new_span>s.y = span_buff_y;


295  next_new_span>s.width = span_length;


296  next_new_span>s.ooz = cur_stack>cur_span_start_ooz;


297  next_new_span>s.scanline_ptr = cur_scanline;


298 


299  //add to its triangles list of spans


300  next_new_span>s.next_tri_span = cur_stack>span_list_head;


301  cur_stack>span_list_head = num_global_spans;


302 


303  num_global_spans++;


304  next_new_span++;


305  if (num_global_spans>=MAX_SPANS) return i4_F;


306  }


307 


308  //setup the start of the next span on the stack


309  //IF this one wasnt transparent. otherwise,


310  //we want the span start info for that span to be


311  //maintained (unaltered)


312  if (e_tri>type<SPAN_TRI_SEE_THRU)


313  {


314  do


315  {


316  cur_stack = cur_stack>next_stack;


317 


318  if (cur_stack==&tri_stack)


319  break;


320 


321  cur_stack>cur_span_start_x = span_buff_x;


322 


323  //calculate the ooz value for this span (needed for depth comparisons as well as actually


324  //writing out the span)


325 


326  amd3d_depth_at_pixel(&cur_stack>grads, &cur_stack>cur_span_start_ooz);


327  // = cur_stack>grads.oozat00 + (cur_stack>grads.doozdy * fy) + (cur_stack>grads.doozdx * fx);


328 


329  } while (cur_stack>type > SPAN_TRI_SEE_THRU);


330  }


331  }


332  else


333  {


334  //this span ends below whats on top of the stack.


335  //but if everything above this span is transparent, we need to draw it


336  temp_stack = e_tri>last_stack;


337 


338  while (temp_stack>type>SPAN_TRI_SEE_THRU)


339  temp_stack = temp_stack>last_stack;


340 


341  //did we make it past everything in the stack?


342  if (temp_stack==&tri_stack)


343  {


344  //if so, that means everything above us is transparent and this span


345  //will be seen, so we gotta draw it


346 


347  span_length = span_buff_x  e_tri>cur_span_start_x;


348  if (span_length>0)


349  {


350  //make a span


351  next_new_span>s.x = e_tri>cur_span_start_x;


352  next_new_span>s.y = span_buff_y;


353  next_new_span>s.width = span_length;


354  next_new_span>s.ooz = e_tri>cur_span_start_ooz;


355  next_new_span>s.scanline_ptr = cur_scanline;


356 


357  //add to its triangles list of spans


358  next_new_span>s.next_tri_span = e_tri>span_list_head;


359  e_tri>span_list_head = num_global_spans;


360 


361  num_global_spans++;


362  next_new_span++;


363  if (num_global_spans>=MAX_SPANS) return i4_F;


364  }


365 


366  //setup the start of the next span in


367  //IF this one wasnt transparent. otherwise,


368  //we want the span start info for that span to be


369  //maintained (unaltered)


370  temp_stack = e_tri;


371 


372  if (e_tri>type<SPAN_TRI_SEE_THRU)


373  {


374  do


375  {


376  temp_stack = temp_stack>next_stack;


377  if (temp_stack == &tri_stack)


378  break;


379 


380  temp_stack>cur_span_start_x = span_buff_x;


381 


382  //calculate the ooz value for this span (needed for depth comparisons as well as actually


383  //writing out the span)


384  //temp_stack>cur_span_start_ooz = temp_stack>grads.oozat00 +


385  // (temp_stack>grads.doozdy * fy) +


386  // (temp_stack>grads.doozdx * fx);


387 


388  amd3d_depth_at_pixel(&temp_stack>grads, &temp_stack>cur_span_start_ooz);


389 


390  } while (temp_stack>type > SPAN_TRI_SEE_THRU);


391  }


392  }


393  }


394 


395  e_tri>last_stack>next_stack = e_tri>next_stack;


396  e_tri>next_stack>last_stack = e_tri>last_stack;


397  }


398  }


399 


400  //done with this scanline.


401  //dont forget that IF we want to draw the background, we need to make one more span going from


402  //tri_stack.cur_span_start_x to the rightmost pixel on the screen (if that area is "open")


403 


404  //remove the ones that need removing


405  temp_edge = *remove_edge_list;


406  while (temp_edge)


407  {


408  temp_edge>last_active>next_active = temp_edge>next_active;


409  temp_edge>next_active>last_active = temp_edge>last_active;


410 


411  temp_edge = temp_edge>next_remove;


412  }


413  remove_edge_list++;


414 


415  //step the active edges


416  temp_edge = active_list_head.next_active;


417  while (temp_edge != &active_list_tail)


418  {


419  temp_edge>x += temp_edge>dxdy;


420 


421  //make sure the edges remain sorted


422  compare_here = temp_edge;


423  if (temp_edge>x < compare_here>last_active>x)


424  {


425  t1 = temp_edge>next_active;


426 


427  while (temp_edge>x < compare_here>last_active>x)


428  compare_here = compare_here>last_active;


429 


430  //get temp_edge out of its current spot


431  temp_edge>last_active>next_active = temp_edge>next_active;


432  temp_edge>next_active>last_active = temp_edge>last_active;


433 


434  //insert it between compare_here and its predecessor


435  compare_here>last_active>next_active = temp_edge;


436 


437  temp_edge>last_active = compare_here>last_active;


438  compare_here>last_active = temp_edge;


439 


440  temp_edge>next_active = compare_here;


441 


442  temp_edge = t1;


443  }


444  else


445  {


446  temp_edge = temp_edge>next_active;


447  }


448  }


449  }


450  return i4_T;


451  }


452 


453  #endif

