Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. //
  21. // r_drawa.s
  22. // x86 assembly-language edge clipping and emission code
  23. //
  24.  
  25. #include "asm_i386.h"
  26. #include "quakeasm.h"
  27. #include "asm_draw.h"
  28. #include "d_ifacea.h"
  29.  
  30. #if     id386
  31.  
  32. // !!! if these are changed, they must be changed in r_draw.c too !!!
  33. #define FULLY_CLIPPED_CACHED    0x80000000
  34. #define FRAMECOUNT_MASK                 0x7FFFFFFF
  35.  
  36.         .data
  37.  
  38. Ld0:                    .single         0.0
  39. Ld1:                    .single         0.0
  40. Lstack:                 .long           0
  41. Lfp_near_clip:  .single         NEAR_CLIP
  42. Lceilv0:                .long           0
  43. Lv:                             .long           0
  44. Lu0:                    .long           0
  45. Lv0:                    .long           0
  46. Lzi0:                   .long           0
  47.  
  48.         .text
  49.  
  50. //----------------------------------------------------------------------
  51. // edge clipping code
  52. //----------------------------------------------------------------------
  53.  
  54. #define pv0             4+12
  55. #define pv1             8+12
  56. #define clip    12+12
  57.  
  58.         .align 4
  59. .globl C(R_ClipEdge)
  60. C(R_ClipEdge):
  61.         pushl   %esi                            // preserve register variables
  62.         pushl   %edi
  63.         pushl   %ebx
  64.         movl    %esp,Lstack                     // for clearing the stack later
  65.  
  66. //      float           d0, d1, f;
  67. //      mvertex_t       clipvert;
  68.  
  69.         movl    clip(%esp),%ebx
  70.         movl    pv0(%esp),%esi
  71.         movl    pv1(%esp),%edx
  72.  
  73. //      if (clip)
  74. //      {
  75.         testl   %ebx,%ebx
  76.         jz              Lemit
  77.  
  78. //              do
  79. //              {
  80.  
  81. Lcliploop:
  82.  
  83. //                      d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
  84. //                      d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
  85.         flds    mv_position+0(%esi)
  86.         fmuls   cp_normal+0(%ebx)
  87.         flds    mv_position+4(%esi)
  88.         fmuls   cp_normal+4(%ebx)
  89.         flds    mv_position+8(%esi)
  90.         fmuls   cp_normal+8(%ebx)
  91.         fxch    %st(1)
  92.         faddp   %st(0),%st(2)           // d0mul2 | d0add0
  93.  
  94.         flds    mv_position+0(%edx)
  95.         fmuls   cp_normal+0(%ebx)
  96.         flds    mv_position+4(%edx)
  97.         fmuls   cp_normal+4(%ebx)
  98.         flds    mv_position+8(%edx)
  99.         fmuls   cp_normal+8(%ebx)
  100.         fxch    %st(1)
  101.         faddp   %st(0),%st(2)           // d1mul2 | d1add0 | d0mul2 | d0add0
  102.         fxch    %st(3)                          // d0add0 | d1add0 | d0mul2 | d1mul2
  103.  
  104.         faddp   %st(0),%st(2)           // d1add0 | dot0 | d1mul2
  105.         faddp   %st(0),%st(2)           // dot0 | dot1
  106.  
  107.         fsubs   cp_dist(%ebx)           // d0 | dot1
  108.         fxch    %st(1)                          // dot1 | d0
  109.         fsubs   cp_dist(%ebx)           // d1 | d0
  110.         fxch    %st(1)
  111.         fstps   Ld0
  112.         fstps   Ld1
  113.  
  114. //                      if (d0 >= 0)
  115. //                      {
  116.         movl    Ld0,%eax
  117.         movl    Ld1,%ecx
  118.         orl             %eax,%ecx
  119.         js              Lp2
  120.  
  121. // both points are unclipped
  122.  
  123. Lcontinue:
  124.  
  125. //
  126. //                              R_ClipEdge (&clipvert, pv1, clip->next);
  127. //                              return;
  128. //                      }
  129. //              } while ((clip = clip->next) != NULL);
  130.         movl    cp_next(%ebx),%ebx
  131.         testl   %ebx,%ebx
  132.         jnz             Lcliploop
  133.  
  134. //      }
  135.  
  136. //// add the edge
  137. //      R_EmitEdge (pv0, pv1);
  138. Lemit:
  139.  
  140. //
  141. // set integer rounding to ceil mode, set to single precision
  142. //
  143. // FIXME: do away with by manually extracting integers from floats?
  144. // FIXME: set less often
  145.         fldcw   ceil_cw
  146.  
  147. //      edge_t  *edge, *pcheck;
  148. //      int             u_check;
  149. //      float   u, u_step;
  150. //      vec3_t  local, transformed;
  151. //      float   *world;
  152. //      int             v, v2, ceilv0;
  153. //      float   scale, lzi0, u0, v0;
  154. //      int             side;
  155.  
  156. //      if (r_lastvertvalid)
  157. //      {
  158.         cmpl    $0,C(r_lastvertvalid)
  159.         jz              LCalcFirst
  160.  
  161. //              u0 = r_u1;
  162. //              v0 = r_v1;
  163. //              lzi0 = r_lzi1;
  164. //              ceilv0 = r_ceilv1;
  165.         movl    C(r_lzi1),%eax
  166.         movl    C(r_u1),%ecx
  167.         movl    %eax,Lzi0
  168.         movl    %ecx,Lu0
  169.         movl    C(r_v1),%ecx
  170.         movl    C(r_ceilv1),%eax
  171.         movl    %ecx,Lv0
  172.         movl    %eax,Lceilv0
  173.         jmp             LCalcSecond
  174.  
  175. //      }
  176.  
  177. LCalcFirst:
  178.  
  179. //      else
  180. //      {
  181. //              world = &pv0->position[0];
  182.  
  183.         call    LTransformAndProject    // v0 | lzi0 | u0
  184.  
  185.         fsts    Lv0
  186.         fxch    %st(2)                                  // u0 | lzi0 | v0
  187.         fstps   Lu0                                             // lzi0 | v0
  188.         fstps   Lzi0                                    // v0
  189.  
  190. //              ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
  191.         fistpl  Lceilv0
  192.  
  193. //      }
  194.  
  195. LCalcSecond:
  196.  
  197. //      world = &pv1->position[0];
  198.         movl    %edx,%esi
  199.  
  200.         call    LTransformAndProject    // v1 | lzi1 | u1
  201.  
  202.         flds    Lu0                                             // u0 | v1 | lzi1 | u1
  203.         fxch    %st(3)                                  // u1 | v1 | lzi1 | u0
  204.         flds    Lzi0                                    // lzi0 | u1 | v1 | lzi1 | u0
  205.         fxch    %st(3)                                  // lzi1 | u1 | v1 | lzi0 | u0
  206.         flds    Lv0                                             // v0 | lzi1 | u1 | v1 | lzi0 | u0
  207.         fxch    %st(3)                                  // v1 | lzi1 | u1 | v0 | lzi0 | u0
  208.  
  209. //      r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
  210.         fistl   C(r_ceilv1)
  211.  
  212.         fldcw   single_cw                               // put back normal floating-point state
  213.  
  214.         fsts    C(r_v1)
  215.         fxch    %st(4)                                  // lzi0 | lzi1 | u1 | v0 | v1 | u0
  216.  
  217. //      if (r_lzi1 > lzi0)
  218. //              lzi0 = r_lzi1;
  219.         fcom    %st(1)
  220.         fnstsw  %ax
  221.         testb   $1,%ah
  222.         jz              LP0
  223.         fstp    %st(0)
  224.         fld             %st(0)
  225. LP0:
  226.  
  227.         fxch    %st(1)                                  // lzi1 | lzi0 | u1 | v0 | v1 | u0
  228.         fstps   C(r_lzi1)                               // lzi0 | u1 | v0 | v1 | u0
  229.         fxch    %st(1)
  230.         fsts    C(r_u1)
  231.         fxch    %st(1)
  232.  
  233. //      if (lzi0 > r_nearzi)    // for mipmap finding
  234. //              r_nearzi = lzi0;
  235.         fcoms   C(r_nearzi)
  236.         fnstsw  %ax
  237.         testb   $0x45,%ah
  238.         jnz             LP1
  239.         fsts    C(r_nearzi)
  240. LP1:
  241.  
  242. // // for right edges, all we want is the effect on 1/z
  243. //      if (r_nearzionly)
  244. //              return;
  245.         movl    C(r_nearzionly),%eax
  246.         testl   %eax,%eax
  247.         jz              LP2
  248. LPop5AndDone:
  249.         movl    C(cacheoffset),%eax
  250.         movl    C(r_framecount),%edx
  251.         cmpl    $0x7FFFFFFF,%eax
  252.         jz              LDoPop
  253.         andl    $(FRAMECOUNT_MASK),%edx
  254.         orl             $(FULLY_CLIPPED_CACHED),%edx
  255.         movl    %edx,C(cacheoffset)
  256.  
  257. LDoPop:
  258.         fstp    %st(0)                  // u1 | v0 | v1 | u0
  259.         fstp    %st(0)                  // v0 | v1 | u0
  260.         fstp    %st(0)                  // v1 | u0
  261.         fstp    %st(0)                  // u0
  262.         fstp    %st(0)
  263.         jmp             Ldone
  264.  
  265. LP2:
  266.  
  267. // // create the edge
  268. //      if (ceilv0 == r_ceilv1)
  269. //              return;         // horizontal edge
  270.         movl    Lceilv0,%ebx
  271.         movl    C(edge_p),%edi
  272.         movl    C(r_ceilv1),%ecx
  273.         movl    %edi,%edx
  274.         movl    C(r_pedge),%esi
  275.         addl    $(et_size),%edx
  276.         cmpl    %ecx,%ebx
  277.         jz              LPop5AndDone
  278.  
  279.         movl    C(r_pedge),%eax
  280.         movl    %eax,et_owner(%edi)
  281.  
  282. //      side = ceilv0 > r_ceilv1;
  283. //
  284. //      edge->nearzi = lzi0;
  285.         fstps   et_nearzi(%edi)         // u1 | v0 | v1 | u0
  286.  
  287. //      if (side == 1)
  288. //      {
  289.         jc              LSide0
  290.  
  291. LSide1:
  292.  
  293. //      // leading edge (go from p2 to p1)
  294.  
  295. //              u_step = ((u0 - r_u1) / (v0 - r_v1));
  296.         fsubrp  %st(0),%st(3)           // v0 | v1 | u0-u1
  297.         fsub    %st(1),%st(0)           // v0-v1 | v1 | u0-u1
  298.         fdivrp  %st(0),%st(2)           // v1 | ustep
  299.  
  300. //      r_emitted = 1;
  301.         movl    $1,C(r_emitted)
  302.  
  303. //      edge = edge_p++;
  304.         movl    %edx,C(edge_p)
  305.  
  306. // pretouch next edge
  307.         movl    (%edx),%eax
  308.  
  309. //              v2 = ceilv0 - 1;
  310. //              v = r_ceilv1;
  311.         movl    %ecx,%eax
  312.         leal    -1(%ebx),%ecx
  313.         movl    %eax,%ebx
  314.  
  315. //              edge->surfs[0] = 0;
  316. //              edge->surfs[1] = surface_p - surfaces;
  317.         movl    C(surface_p),%eax
  318.         movl    C(surfaces),%esi
  319.         subl    %edx,%edx
  320.         subl    %esi,%eax
  321.         shrl    $(SURF_T_SHIFT),%eax
  322.         movl    %edx,et_surfs(%edi)
  323.         movl    %eax,et_surfs+2(%edi)
  324.  
  325.         subl    %esi,%esi
  326.  
  327. //              u = r_u1 + ((float)v - r_v1) * u_step;
  328.         movl    %ebx,Lv
  329.         fildl   Lv                                      // v | v1 | ustep
  330.         fsubp   %st(0),%st(1)           // v-v1 | ustep
  331.         fmul    %st(1),%st(0)           // (v-v1)*ustep | ustep
  332.         fadds   C(r_u1)                         // u | ustep
  333.  
  334.         jmp             LSideDone
  335.  
  336. //      }
  337.  
  338. LSide0:
  339.  
  340. //      else
  341. //      {
  342. //      // trailing edge (go from p1 to p2)
  343.  
  344. //              u_step = ((r_u1 - u0) / (r_v1 - v0));
  345.         fsub    %st(3),%st(0)           // u1-u0 | v0 | v1 | u0
  346.         fxch    %st(2)                          // v1 | v0 | u1-u0 | u0
  347.         fsub    %st(1),%st(0)           // v1-v0 | v0 | u1-u0 | u0
  348.         fdivrp  %st(0),%st(2)           // v0 | ustep | u0
  349.  
  350. //      r_emitted = 1;
  351.         movl    $1,C(r_emitted)
  352.  
  353. //      edge = edge_p++;
  354.         movl    %edx,C(edge_p)
  355.  
  356. // pretouch next edge
  357.         movl    (%edx),%eax
  358.  
  359. //              v = ceilv0;
  360. //              v2 = r_ceilv1 - 1;
  361.         decl    %ecx
  362.  
  363. //              edge->surfs[0] = surface_p - surfaces;
  364. //              edge->surfs[1] = 0;
  365.         movl    C(surface_p),%eax
  366.         movl    C(surfaces),%esi
  367.         subl    %edx,%edx
  368.         subl    %esi,%eax
  369.         shrl    $(SURF_T_SHIFT),%eax
  370.         movl    %edx,et_surfs+2(%edi)
  371.         movl    %eax,et_surfs(%edi)
  372.  
  373.         movl    $1,%esi
  374.  
  375. //              u = u0 + ((float)v - v0) * u_step;
  376.         movl    %ebx,Lv
  377.         fildl   Lv                                      // v | v0 | ustep | u0
  378.         fsubp   %st(0),%st(1)           // v-v0 | ustep | u0
  379.         fmul    %st(1),%st(0)           // (v-v0)*ustep | ustep | u0
  380.         faddp   %st(0),%st(2)           // ustep | u
  381.         fxch    %st(1)                          // u | ustep
  382.  
  383. //      }
  384.  
  385. LSideDone:
  386.  
  387. //      edge->u_step = u_step*0x100000;
  388. //      edge->u = u*0x100000 + 0xFFFFF;
  389.  
  390.         fmuls   fp_1m                           // u*0x100000 | ustep
  391.         fxch    %st(1)                          // ustep | u*0x100000
  392.         fmuls   fp_1m                           // ustep*0x100000 | u*0x100000
  393.         fxch    %st(1)                          // u*0x100000 | ustep*0x100000
  394.         fadds   fp_1m_minus_1           // u*0x100000 + 0xFFFFF | ustep*0x100000
  395.         fxch    %st(1)                          // ustep*0x100000 | u*0x100000 + 0xFFFFF
  396.         fistpl  et_u_step(%edi)         // u*0x100000 + 0xFFFFF
  397.         fistpl  et_u(%edi)
  398.  
  399. // // we need to do this to avoid stepping off the edges if a very nearly
  400. // // horizontal edge is less than epsilon above a scan, and numeric error
  401. // // causes it to incorrectly extend to the scan, and the extension of the
  402. // // line goes off the edge of the screen
  403. // // FIXME: is this actually needed?
  404. //      if (edge->u < r_refdef.vrect_x_adj_shift20)
  405. //              edge->u = r_refdef.vrect_x_adj_shift20;
  406. //      if (edge->u > r_refdef.vrectright_adj_shift20)
  407. //              edge->u = r_refdef.vrectright_adj_shift20;
  408.         movl    et_u(%edi),%eax
  409.         movl    C(r_refdef)+rd_vrect_x_adj_shift20,%edx
  410.         cmpl    %edx,%eax
  411.         jl              LP4
  412.         movl    C(r_refdef)+rd_vrectright_adj_shift20,%edx
  413.         cmpl    %edx,%eax
  414.         jng             LP5
  415. LP4:
  416.         movl    %edx,et_u(%edi)
  417.         movl    %edx,%eax
  418. LP5:
  419.  
  420. // // sort the edge in normally
  421. //      u_check = edge->u;
  422. //
  423. //      if (edge->surfs[0])
  424. //              u_check++;      // sort trailers after leaders
  425.         addl    %esi,%eax
  426.  
  427. //      if (!newedges[v] || newedges[v]->u >= u_check)
  428. //      {
  429.         movl    C(newedges)(,%ebx,4),%esi
  430.         testl   %esi,%esi
  431.         jz              LDoFirst
  432.         cmpl    %eax,et_u(%esi)
  433.         jl              LNotFirst
  434. LDoFirst:
  435.  
  436. //              edge->next = newedges[v];
  437. //              newedges[v] = edge;
  438.         movl    %esi,et_next(%edi)
  439.         movl    %edi,C(newedges)(,%ebx,4)
  440.  
  441.         jmp             LSetRemove
  442.  
  443. //      }
  444.  
  445. LNotFirst:
  446.  
  447. //      else
  448. //      {
  449. //              pcheck = newedges[v];
  450. //
  451. //              while (pcheck->next && pcheck->next->u < u_check)
  452. //                      pcheck = pcheck->next;
  453. LFindInsertLoop:
  454.         movl    %esi,%edx
  455.         movl    et_next(%esi),%esi
  456.         testl   %esi,%esi
  457.         jz              LInsertFound
  458.         cmpl    %eax,et_u(%esi)
  459.         jl              LFindInsertLoop
  460.  
  461. LInsertFound:
  462.  
  463. //              edge->next = pcheck->next;
  464. //              pcheck->next = edge;
  465.         movl    %esi,et_next(%edi)
  466.         movl    %edi,et_next(%edx)
  467.  
  468. //      }
  469.  
  470. LSetRemove:
  471.  
  472. //      edge->nextremove = removeedges[v2];
  473. //      removeedges[v2] = edge;
  474.         movl    C(removeedges)(,%ecx,4),%eax
  475.         movl    %edi,C(removeedges)(,%ecx,4)
  476.         movl    %eax,et_nextremove(%edi)
  477.  
  478. Ldone:
  479.         movl    Lstack,%esp                     // clear temporary variables from stack
  480.  
  481.         popl    %ebx                            // restore register variables
  482.         popl    %edi
  483.         popl    %esi
  484.         ret
  485.  
  486. // at least one point is clipped
  487.  
  488. Lp2:
  489.         testl   %eax,%eax
  490.         jns             Lp1
  491.  
  492. //                      else
  493. //                      {
  494. //                      // point 0 is clipped
  495.  
  496. //                              if (d1 < 0)
  497. //                              {
  498.         movl    Ld1,%eax
  499.         testl   %eax,%eax
  500.         jns             Lp3
  501.  
  502. //                              // both points are clipped
  503. //                              // we do cache fully clipped edges
  504. //                                      if (!leftclipped)
  505.         movl    C(r_leftclipped),%eax
  506.         movl    C(r_pedge),%ecx
  507.         testl   %eax,%eax
  508.         jnz             Ldone
  509.  
  510. //                                              r_pedge->framecount = r_framecount;
  511.         movl    C(r_framecount),%eax
  512.         andl    $(FRAMECOUNT_MASK),%eax
  513.         orl             $(FULLY_CLIPPED_CACHED),%eax
  514.         movl    %eax,C(cacheoffset)
  515.  
  516. //                                      return;
  517.         jmp             Ldone
  518.  
  519. //                              }
  520.  
  521. Lp1:
  522.  
  523. //                      // point 0 is unclipped
  524. //                              if (d1 >= 0)
  525. //                              {
  526. //                              // both points are unclipped
  527. //                                      continue;
  528.  
  529. //                      // only point 1 is clipped
  530.  
  531. //                              f = d0 / (d0 - d1);
  532.         flds    Ld0
  533.         flds    Ld1
  534.         fsubr   %st(1),%st(0)
  535.  
  536. //                      // we don't cache partially clipped edges
  537.         movl    $0x7FFFFFFF,C(cacheoffset)
  538.  
  539.         fdivrp  %st(0),%st(1)
  540.  
  541.         subl    $(mv_size),%esp                 // allocate space for clipvert
  542.  
  543. //                              clipvert.position[0] = pv0->position[0] +
  544. //                                              f * (pv1->position[0] - pv0->position[0]);
  545. //                              clipvert.position[1] = pv0->position[1] +
  546. //                                              f * (pv1->position[1] - pv0->position[1]);
  547. //                              clipvert.position[2] = pv0->position[2] +
  548. //                                              f * (pv1->position[2] - pv0->position[2]);
  549.         flds    mv_position+8(%edx)
  550.         fsubs   mv_position+8(%esi)
  551.         flds    mv_position+4(%edx)
  552.         fsubs   mv_position+4(%esi)
  553.         flds    mv_position+0(%edx)
  554.         fsubs   mv_position+0(%esi)             // 0 | 1 | 2
  555.  
  556. // replace pv1 with the clip point
  557.         movl    %esp,%edx
  558.         movl    cp_leftedge(%ebx),%eax
  559.         testb   %al,%al
  560.  
  561.         fmul    %st(3),%st(0)
  562.         fxch    %st(1)                                  // 1 | 0 | 2
  563.         fmul    %st(3),%st(0)
  564.         fxch    %st(2)                                  // 2 | 0 | 1
  565.         fmulp   %st(0),%st(3)                   // 0 | 1 | 2
  566.         fadds   mv_position+0(%esi)
  567.         fxch    %st(1)                                  // 1 | 0 | 2
  568.         fadds   mv_position+4(%esi)
  569.         fxch    %st(2)                                  // 2 | 0 | 1
  570.         fadds   mv_position+8(%esi)
  571.         fxch    %st(1)                                  // 0 | 2 | 1
  572.         fstps   mv_position+0(%esp)             // 2 | 1
  573.         fstps   mv_position+8(%esp)             // 1
  574.         fstps   mv_position+4(%esp)
  575.  
  576. //                              if (clip->leftedge)
  577. //                              {
  578.         jz              Ltestright
  579.  
  580. //                                      r_leftclipped = true;
  581. //                                      r_leftexit = clipvert;
  582.         movl    $1,C(r_leftclipped)
  583.         movl    mv_position+0(%esp),%eax
  584.         movl    %eax,C(r_leftexit)+mv_position+0
  585.         movl    mv_position+4(%esp),%eax
  586.         movl    %eax,C(r_leftexit)+mv_position+4
  587.         movl    mv_position+8(%esp),%eax
  588.         movl    %eax,C(r_leftexit)+mv_position+8
  589.  
  590.         jmp             Lcontinue
  591.  
  592. //                              }
  593.  
  594. Ltestright:
  595. //                              else if (clip->rightedge)
  596. //                              {
  597.         testb   %ah,%ah
  598.         jz              Lcontinue
  599.  
  600. //                                      r_rightclipped = true;
  601. //                                      r_rightexit = clipvert;
  602.         movl    $1,C(r_rightclipped)
  603.         movl    mv_position+0(%esp),%eax
  604.         movl    %eax,C(r_rightexit)+mv_position+0
  605.         movl    mv_position+4(%esp),%eax
  606.         movl    %eax,C(r_rightexit)+mv_position+4
  607.         movl    mv_position+8(%esp),%eax
  608.         movl    %eax,C(r_rightexit)+mv_position+8
  609.  
  610. //                              }
  611. //
  612. //                              R_ClipEdge (pv0, &clipvert, clip->next);
  613. //                              return;
  614. //                      }
  615.         jmp             Lcontinue
  616.  
  617. //                      }
  618.  
  619. Lp3:
  620.  
  621. //                      // only point 0 is clipped
  622. //                              r_lastvertvalid = false;
  623.  
  624.         movl    $0,C(r_lastvertvalid)
  625.  
  626. //                              f = d0 / (d0 - d1);
  627.         flds    Ld0
  628.         flds    Ld1
  629.         fsubr   %st(1),%st(0)
  630.  
  631. //                      // we don't cache partially clipped edges
  632.         movl    $0x7FFFFFFF,C(cacheoffset)
  633.  
  634.         fdivrp  %st(0),%st(1)
  635.  
  636.         subl    $(mv_size),%esp                 // allocate space for clipvert
  637.  
  638. //                              clipvert.position[0] = pv0->position[0] +
  639. //                                              f * (pv1->position[0] - pv0->position[0]);
  640. //                              clipvert.position[1] = pv0->position[1] +
  641. //                                              f * (pv1->position[1] - pv0->position[1]);
  642. //                              clipvert.position[2] = pv0->position[2] +
  643. //                                              f * (pv1->position[2] - pv0->position[2]);
  644.         flds    mv_position+8(%edx)
  645.         fsubs   mv_position+8(%esi)
  646.         flds    mv_position+4(%edx)
  647.         fsubs   mv_position+4(%esi)
  648.         flds    mv_position+0(%edx)
  649.         fsubs   mv_position+0(%esi)             // 0 | 1 | 2
  650.  
  651.         movl    cp_leftedge(%ebx),%eax
  652.         testb   %al,%al
  653.  
  654.         fmul    %st(3),%st(0)
  655.         fxch    %st(1)                                  // 1 | 0 | 2
  656.         fmul    %st(3),%st(0)
  657.         fxch    %st(2)                                  // 2 | 0 | 1
  658.         fmulp   %st(0),%st(3)                   // 0 | 1 | 2
  659.         fadds   mv_position+0(%esi)
  660.         fxch    %st(1)                                  // 1 | 0 | 2
  661.         fadds   mv_position+4(%esi)
  662.         fxch    %st(2)                                  // 2 | 0 | 1
  663.         fadds   mv_position+8(%esi)
  664.         fxch    %st(1)                                  // 0 | 2 | 1
  665.         fstps   mv_position+0(%esp)             // 2 | 1
  666.         fstps   mv_position+8(%esp)             // 1
  667.         fstps   mv_position+4(%esp)
  668.  
  669. // replace pv0 with the clip point
  670.         movl    %esp,%esi
  671.  
  672. //                              if (clip->leftedge)
  673. //                              {
  674.         jz              Ltestright2
  675.  
  676. //                                      r_leftclipped = true;
  677. //                                      r_leftenter = clipvert;
  678.         movl    $1,C(r_leftclipped)
  679.         movl    mv_position+0(%esp),%eax
  680.         movl    %eax,C(r_leftenter)+mv_position+0
  681.         movl    mv_position+4(%esp),%eax
  682.         movl    %eax,C(r_leftenter)+mv_position+4
  683.         movl    mv_position+8(%esp),%eax
  684.         movl    %eax,C(r_leftenter)+mv_position+8
  685.  
  686.         jmp             Lcontinue
  687.  
  688. //                              }
  689.  
  690. Ltestright2:
  691. //                              else if (clip->rightedge)
  692. //                              {
  693.         testb   %ah,%ah
  694.         jz              Lcontinue
  695.  
  696. //                                      r_rightclipped = true;
  697. //                                      r_rightenter = clipvert;
  698.         movl    $1,C(r_rightclipped)
  699.         movl    mv_position+0(%esp),%eax
  700.         movl    %eax,C(r_rightenter)+mv_position+0
  701.         movl    mv_position+4(%esp),%eax
  702.         movl    %eax,C(r_rightenter)+mv_position+4
  703.         movl    mv_position+8(%esp),%eax
  704.         movl    %eax,C(r_rightenter)+mv_position+8
  705.  
  706. //                              }
  707.         jmp             Lcontinue
  708.  
  709. // %esi = vec3_t point to transform and project
  710. // %edx preserved
  711. LTransformAndProject:
  712.  
  713. //      // transform and project
  714. //              VectorSubtract (world, modelorg, local);
  715.         flds    mv_position+0(%esi)
  716.         fsubs   C(modelorg)+0
  717.         flds    mv_position+4(%esi)
  718.         fsubs   C(modelorg)+4
  719.         flds    mv_position+8(%esi)    
  720.         fsubs   C(modelorg)+8
  721.         fxch    %st(2)                          // local[0] | local[1] | local[2]
  722.  
  723. //              TransformVector (local, transformed);
  724. //     
  725. //              if (transformed[2] < NEAR_CLIP)
  726. //                      transformed[2] = NEAR_CLIP;
  727. //     
  728. //              lzi0 = 1.0 / transformed[2];
  729.         fld             %st(0)                          // local[0] | local[0] | local[1] | local[2]
  730.         fmuls   C(vpn)+0                        // zm0 | local[0] | local[1] | local[2]
  731.         fld             %st(1)                          // local[0] | zm0 | local[0] | local[1] |
  732.                                                                 //  local[2]
  733.         fmuls   C(vright)+0                     // xm0 | zm0 | local[0] | local[1] | local[2]
  734.         fxch    %st(2)                          // local[0] | zm0 | xm0 | local[1] | local[2]
  735.         fmuls   C(vup)+0                        // ym0 |  zm0 | xm0 | local[1] | local[2]
  736.         fld             %st(3)                          // local[1] | ym0 |  zm0 | xm0 | local[1] |
  737.                                                                 //  local[2]
  738.         fmuls   C(vpn)+4                        // zm1 | ym0 | zm0 | xm0 | local[1] |
  739.                                                                 //  local[2]
  740.         fld             %st(4)                          // local[1] | zm1 | ym0 | zm0 | xm0 |
  741.                                                                 //  local[1] | local[2]
  742.         fmuls   C(vright)+4                     // xm1 | zm1 | ym0 |  zm0 | xm0 |
  743.                                                                 //  local[1] | local[2]
  744.         fxch    %st(5)                          // local[1] | zm1 | ym0 | zm0 | xm0 |
  745.                                                                 //  xm1 | local[2]
  746.         fmuls   C(vup)+4                        // ym1 | zm1 | ym0 | zm0 | xm0 |
  747.                                                                 //  xm1 | local[2]
  748.         fxch    %st(1)                          // zm1 | ym1 | ym0 | zm0 | xm0 |
  749.                                                                 //  xm1 | local[2]
  750.         faddp   %st(0),%st(3)           // ym1 | ym0 | zm2 | xm0 | xm1 | local[2]
  751.         fxch    %st(3)                          // xm0 | ym0 | zm2 | ym1 | xm1 | local[2]
  752.         faddp   %st(0),%st(4)           // ym0 | zm2 | ym1 | xm2 | local[2]
  753.         faddp   %st(0),%st(2)           // zm2 | ym2 | xm2 | local[2]
  754.         fld             %st(3)                          // local[2] | zm2 | ym2 | xm2 | local[2]
  755.         fmuls   C(vpn)+8                        // zm3 | zm2 | ym2 | xm2 | local[2]
  756.         fld             %st(4)                          // local[2] | zm3 | zm2 | ym2 | xm2 | local[2]
  757.         fmuls   C(vright)+8                     // xm3 | zm3 | zm2 | ym2 | xm2 | local[2]
  758.         fxch    %st(5)                          // local[2] | zm3 | zm2 | ym2 | xm2 | xm3
  759.         fmuls   C(vup)+8                        // ym3 | zm3 | zm2 | ym2 | xm2 | xm3
  760.         fxch    %st(1)                          // zm3 | ym3 | zm2 | ym2 | xm2 | xm3
  761.         faddp   %st(0),%st(2)           // ym3 | zm4 | ym2 | xm2 | xm3
  762.         fxch    %st(4)                          // xm3 | zm4 | ym2 | xm2 | ym3
  763.         faddp   %st(0),%st(3)           // zm4 | ym2 | xm4 | ym3
  764.         fxch    %st(1)                          // ym2 | zm4 | xm4 | ym3
  765.         faddp   %st(0),%st(3)           // zm4 | xm4 | ym4
  766.  
  767.         fcoms   Lfp_near_clip
  768.         fnstsw  %ax
  769.         testb   $1,%ah
  770.         jz              LNoClip
  771.         fstp    %st(0)
  772.         flds    Lfp_near_clip
  773.  
  774. LNoClip:
  775.  
  776.         fdivrs  float_1                         // lzi0 | x | y
  777.         fxch    %st(1)                          // x | lzi0 | y
  778.  
  779. //      // FIXME: build x/yscale into transform?
  780. //              scale = xscale * lzi0;
  781. //              u0 = (xcenter + scale*transformed[0]);
  782.         flds    C(xscale)                       // xscale | x | lzi0 | y
  783.         fmul    %st(2),%st(0)           // scale | x | lzi0 | y
  784.         fmulp   %st(0),%st(1)           // scale*x | lzi0 | y
  785.         fadds   C(xcenter)                      // u0 | lzi0 | y
  786.  
  787. //              if (u0 < r_refdef.fvrectx_adj)
  788. //                      u0 = r_refdef.fvrectx_adj;
  789. //              if (u0 > r_refdef.fvrectright_adj)
  790. //                      u0 = r_refdef.fvrectright_adj;
  791. // FIXME: use integer compares of floats?
  792.         fcoms   C(r_refdef)+rd_fvrectx_adj
  793.         fnstsw  %ax
  794.         testb   $1,%ah
  795.         jz              LClampP0
  796.         fstp    %st(0)
  797.         flds    C(r_refdef)+rd_fvrectx_adj
  798. LClampP0:
  799.         fcoms   C(r_refdef)+rd_fvrectright_adj
  800.         fnstsw  %ax
  801.         testb   $0x45,%ah
  802.         jnz             LClampP1
  803.         fstp    %st(0)
  804.         flds    C(r_refdef)+rd_fvrectright_adj
  805. LClampP1:
  806.  
  807.         fld             %st(1)                          // lzi0 | u0 | lzi0 | y
  808.  
  809. //              scale = yscale * lzi0;
  810. //              v0 = (ycenter - scale*transformed[1]);
  811.         fmuls   C(yscale)                       // scale | u0 | lzi0 | y
  812.         fmulp   %st(0),%st(3)           // u0 | lzi0 | scale*y
  813.         fxch    %st(2)                          // scale*y | lzi0 | u0
  814.         fsubrs  C(ycenter)                      // v0 | lzi0 | u0
  815.  
  816. //              if (v0 < r_refdef.fvrecty_adj)
  817. //                      v0 = r_refdef.fvrecty_adj;
  818. //              if (v0 > r_refdef.fvrectbottom_adj)
  819. //                      v0 = r_refdef.fvrectbottom_adj;
  820. // FIXME: use integer compares of floats?
  821.         fcoms   C(r_refdef)+rd_fvrecty_adj
  822.         fnstsw  %ax
  823.         testb   $1,%ah
  824.         jz              LClampP2
  825.         fstp    %st(0)
  826.         flds    C(r_refdef)+rd_fvrecty_adj
  827. LClampP2:
  828.         fcoms   C(r_refdef)+rd_fvrectbottom_adj
  829.         fnstsw  %ax
  830.         testb   $0x45,%ah
  831.         jnz             LClampP3
  832.         fstp    %st(0)
  833.         flds    C(r_refdef)+rd_fvrectbottom_adj
  834. LClampP3:
  835.         ret
  836.  
  837. #endif  // id386
  838.  
  839.