r_drawa.s 18 KB

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