source: golgotha/src/render/software/amd3d/span_buffer_amd3d.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 11 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 14.7 KB
Line 
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
22i4_bool amd3d_build_triangle_span_lists() {}
23
24#else
25
26extern span_tri_info tri_stack;
27extern span_edge active_list_head;
28extern span_edge active_list_tail;
29
30extern span_edge *compare_here;
31extern span_edge *temp_edge,*t1;
32
33inline 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
69extern span_entry *next_new_span;
70extern span_tri_info *cur_stack;
71extern span_tri_info *temp_stack;
72extern span_tri_info *e_tri;
73extern i4_bool everything_transparent;
74extern sw32 span_buff_x, span_buff_y,span_length;
75extern w16  *cur_scanline;
76
77extern span_edge **new_edge_list;
78extern span_edge **remove_edge_list;
79
80extern float fx_fy[2];
81
82extern float e_ooz;
83extern float ooz_compare;
84
85extern i4_bool on_top;
86
87inline 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
102inline 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
130inline 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
142inline 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
154i4_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 see-thru-able
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
Note: See TracBrowser for help on using the repository browser.