mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 14:20:59 +00:00
3103f400fd
r_refdef is really meant for holding the various screen "constants" for the software renderer rather than the more generic scene stuff. All the fields referenced by the low level rendering code (especially assembly) have been moved to the beginning of the struct (and nicely fit within 64 bytes). The other fields should be moved elsewhere, but not this commit. On top of that, R_ViewChanged is much easier to read, and there are fewer static globals.
852 lines
19 KiB
ArmAsm
852 lines
19 KiB
ArmAsm
/*
|
|
r_drawa.S
|
|
|
|
x86 assembly-language edge clipping and emission code
|
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to:
|
|
|
|
Free Software Foundation, Inc.
|
|
59 Temple Place - Suite 330
|
|
Boston, MA 02111-1307, USA
|
|
|
|
$Id$
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
#include "asm_i386.h"
|
|
#include "quakeasm.h"
|
|
#include "asm_draw.h"
|
|
#include "d_ifacea.h"
|
|
|
|
#ifdef PIC
|
|
#undef USE_INTEL_ASM //XXX asm pic hack
|
|
#endif
|
|
|
|
#ifdef USE_INTEL_ASM
|
|
|
|
// !!! if these are changed, they must be changed in r_draw.c too !!!
|
|
#define FULLY_CLIPPED_CACHED 0x80000000
|
|
#define FRAMECOUNT_MASK 0x7FFFFFFF
|
|
|
|
.data
|
|
|
|
Ld0: .single 0.0
|
|
Ld1: .single 0.0
|
|
Lstack: .long 0
|
|
Lfp_near_clip: .single NEAR_CLIP
|
|
Lceilv0: .long 0
|
|
Lv: .long 0
|
|
Lu0: .long 0
|
|
Lv0: .long 0
|
|
Lzi0: .long 0
|
|
|
|
.text
|
|
|
|
//----------------------------------------------------------------------
|
|
// edge clipping code
|
|
//----------------------------------------------------------------------
|
|
|
|
#define pv0 4+12
|
|
#define pv1 8+12
|
|
#define clip 12+12
|
|
|
|
.align 4
|
|
.globl C(R_ClipEdge)
|
|
C(R_ClipEdge):
|
|
pushl %esi // preserve register variables
|
|
pushl %edi
|
|
pushl %ebx
|
|
movl %esp,Lstack // for clearing the stack later
|
|
|
|
// float d0, d1, f;
|
|
// mvertex_t clipvert;
|
|
|
|
movl clip(%esp),%ebx
|
|
movl pv0(%esp),%esi
|
|
movl pv1(%esp),%edx
|
|
|
|
// if (clip)
|
|
// {
|
|
testl %ebx,%ebx
|
|
jz Lemit
|
|
|
|
// do
|
|
// {
|
|
|
|
Lcliploop:
|
|
|
|
// d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
|
|
// d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
|
|
flds mv_position+0(%esi)
|
|
fmuls cp_normal+0(%ebx)
|
|
flds mv_position+4(%esi)
|
|
fmuls cp_normal+4(%ebx)
|
|
flds mv_position+8(%esi)
|
|
fmuls cp_normal+8(%ebx)
|
|
fxch %st(1)
|
|
faddp %st(0),%st(2) // d0mul2 | d0add0
|
|
|
|
flds mv_position+0(%edx)
|
|
fmuls cp_normal+0(%ebx)
|
|
flds mv_position+4(%edx)
|
|
fmuls cp_normal+4(%ebx)
|
|
flds mv_position+8(%edx)
|
|
fmuls cp_normal+8(%ebx)
|
|
fxch %st(1)
|
|
faddp %st(0),%st(2) // d1mul2 | d1add0 | d0mul2 | d0add0
|
|
fxch %st(3) // d0add0 | d1add0 | d0mul2 | d1mul2
|
|
|
|
faddp %st(0),%st(2) // d1add0 | dot0 | d1mul2
|
|
faddp %st(0),%st(2) // dot0 | dot1
|
|
|
|
fsubs cp_dist(%ebx) // d0 | dot1
|
|
fxch %st(1) // dot1 | d0
|
|
fsubs cp_dist(%ebx) // d1 | d0
|
|
fxch %st(1)
|
|
fstps Ld0
|
|
fstps Ld1
|
|
|
|
// if (d0 >= 0)
|
|
// {
|
|
movl Ld0,%eax
|
|
movl Ld1,%ecx
|
|
orl %eax,%ecx
|
|
js Lp2
|
|
|
|
// both points are unclipped
|
|
|
|
Lcontinue:
|
|
|
|
//
|
|
// R_ClipEdge (&clipvert, pv1, clip->next);
|
|
// return;
|
|
// }
|
|
// } while ((clip = clip->next) != NULL);
|
|
movl cp_next(%ebx),%ebx
|
|
testl %ebx,%ebx
|
|
jnz Lcliploop
|
|
|
|
// }
|
|
|
|
//// add the edge
|
|
// R_EmitEdge (pv0, pv1);
|
|
Lemit:
|
|
|
|
//
|
|
// set integer rounding to ceil mode, set to single precision
|
|
//
|
|
// FIXME: do away with by manually extracting integers from floats?
|
|
// FIXME: set less often
|
|
fldcw C(r_ceil_cw)
|
|
|
|
// edge_t *edge, *pcheck;
|
|
// int u_check;
|
|
// float u, u_step;
|
|
// vec3_t local, transformed;
|
|
// float *world;
|
|
// int v, v2, ceilv0;
|
|
// float scale, lzi0, u0, v0;
|
|
// int side;
|
|
|
|
// if (r_lastvertvalid)
|
|
// {
|
|
cmpl $0,C(r_lastvertvalid)
|
|
jz LCalcFirst
|
|
|
|
// u0 = r_u1;
|
|
// v0 = r_v1;
|
|
// lzi0 = r_lzi1;
|
|
// ceilv0 = r_ceilv1;
|
|
movl C(r_lzi1),%eax
|
|
movl C(r_u1),%ecx
|
|
movl %eax,Lzi0
|
|
movl %ecx,Lu0
|
|
movl C(r_v1),%ecx
|
|
movl C(r_ceilv1),%eax
|
|
movl %ecx,Lv0
|
|
movl %eax,Lceilv0
|
|
jmp LCalcSecond
|
|
|
|
// }
|
|
|
|
LCalcFirst:
|
|
|
|
// else
|
|
// {
|
|
// world = &pv0->position[0];
|
|
|
|
call LTransformAndProject // v0 | lzi0 | u0
|
|
|
|
fsts Lv0
|
|
fxch %st(2) // u0 | lzi0 | v0
|
|
fstps Lu0 // lzi0 | v0
|
|
fstps Lzi0 // v0
|
|
|
|
// ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
|
|
fistpl Lceilv0
|
|
|
|
// }
|
|
|
|
LCalcSecond:
|
|
|
|
// world = &pv1->position[0];
|
|
movl %edx,%esi
|
|
|
|
call LTransformAndProject // v1 | lzi1 | u1
|
|
|
|
flds Lu0 // u0 | v1 | lzi1 | u1
|
|
fxch %st(3) // u1 | v1 | lzi1 | u0
|
|
flds Lzi0 // lzi0 | u1 | v1 | lzi1 | u0
|
|
fxch %st(3) // lzi1 | u1 | v1 | lzi0 | u0
|
|
flds Lv0 // v0 | lzi1 | u1 | v1 | lzi0 | u0
|
|
fxch %st(3) // v1 | lzi1 | u1 | v0 | lzi0 | u0
|
|
|
|
// r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
|
|
fistl C(r_ceilv1)
|
|
|
|
fldcw C(r_single_cw) // put back normal floating-point state
|
|
|
|
fsts C(r_v1)
|
|
fxch %st(4) // lzi0 | lzi1 | u1 | v0 | v1 | u0
|
|
|
|
// if (r_lzi1 > lzi0)
|
|
// lzi0 = r_lzi1;
|
|
fcom %st(1)
|
|
fnstsw %ax
|
|
testb $1,%ah
|
|
jz LP0
|
|
fstp %st(0)
|
|
fld %st(0)
|
|
LP0:
|
|
|
|
fxch %st(1) // lzi1 | lzi0 | u1 | v0 | v1 | u0
|
|
fstps C(r_lzi1) // lzi0 | u1 | v0 | v1 | u0
|
|
fxch %st(1)
|
|
fsts C(r_u1)
|
|
fxch %st(1)
|
|
|
|
// if (lzi0 > r_nearzi) // for mipmap finding
|
|
// r_nearzi = lzi0;
|
|
fcoms C(r_nearzi)
|
|
fnstsw %ax
|
|
testb $0x45,%ah
|
|
jnz LP1
|
|
fsts C(r_nearzi)
|
|
LP1:
|
|
|
|
// // for right edges, all we want is the effect on 1/z
|
|
// if (r_nearzionly)
|
|
// return;
|
|
movl C(r_nearzionly),%eax
|
|
testl %eax,%eax
|
|
jz LP2
|
|
LPop5AndDone:
|
|
movl C(cacheoffset),%eax
|
|
movl C(r_framecount),%edx
|
|
cmpl $0x7FFFFFFF,%eax
|
|
jz LDoPop
|
|
andl $(FRAMECOUNT_MASK),%edx
|
|
orl $(FULLY_CLIPPED_CACHED),%edx
|
|
movl %edx,C(cacheoffset)
|
|
|
|
LDoPop:
|
|
fstp %st(0) // u1 | v0 | v1 | u0
|
|
fstp %st(0) // v0 | v1 | u0
|
|
fstp %st(0) // v1 | u0
|
|
fstp %st(0) // u0
|
|
fstp %st(0)
|
|
jmp Ldone
|
|
|
|
LP2:
|
|
|
|
// // create the edge
|
|
// if (ceilv0 == r_ceilv1)
|
|
// return; // horizontal edge
|
|
movl Lceilv0,%ebx
|
|
movl C(edge_p),%edi
|
|
movl C(r_ceilv1),%ecx
|
|
movl %edi,%edx
|
|
movl C(r_pedge),%esi
|
|
addl $(et_size),%edx
|
|
cmpl %ecx,%ebx
|
|
jz LPop5AndDone
|
|
|
|
movl C(r_pedge),%eax
|
|
movl %eax,et_owner(%edi)
|
|
|
|
// side = ceilv0 > r_ceilv1;
|
|
//
|
|
// edge->nearzi = lzi0;
|
|
fstps et_nearzi(%edi) // u1 | v0 | v1 | u0
|
|
|
|
// if (side == 1)
|
|
// {
|
|
jc LSide0
|
|
|
|
LSide1:
|
|
|
|
// // leading edge (go from p2 to p1)
|
|
|
|
// u_step = ((u0 - r_u1) / (v0 - r_v1));
|
|
fsubrp %st(0),%st(3) // v0 | v1 | u0-u1
|
|
fsub %st(1),%st(0) // v0-v1 | v1 | u0-u1
|
|
fdivrp %st(0),%st(2) // v1 | ustep
|
|
|
|
// r_emitted = 1;
|
|
movl $1,C(r_emitted)
|
|
|
|
// edge = edge_p++;
|
|
movl %edx,C(edge_p)
|
|
|
|
// pretouch next edge
|
|
movl (%edx),%eax
|
|
|
|
// v2 = ceilv0 - 1;
|
|
// v = r_ceilv1;
|
|
movl %ecx,%eax
|
|
leal -1(%ebx),%ecx
|
|
movl %eax,%ebx
|
|
|
|
// edge->surfs[0] = 0;
|
|
// edge->surfs[1] = surface_p - surfaces;
|
|
movl C(surface_p),%eax
|
|
movl C(surfaces),%esi
|
|
subl %edx,%edx
|
|
subl %esi,%eax
|
|
shrl $(SURF_T_SHIFT),%eax
|
|
movl %edx,et_surfs(%edi)
|
|
movl %eax,et_surfs+2(%edi)
|
|
|
|
subl %esi,%esi
|
|
|
|
// u = r_u1 + ((float)v - r_v1) * u_step;
|
|
movl %ebx,Lv
|
|
fildl Lv // v | v1 | ustep
|
|
fsubp %st(0),%st(1) // v-v1 | ustep
|
|
fmul %st(1),%st(0) // (v-v1)*ustep | ustep
|
|
fadds C(r_u1) // u | ustep
|
|
|
|
jmp LSideDone
|
|
|
|
// }
|
|
|
|
LSide0:
|
|
|
|
// else
|
|
// {
|
|
// // trailing edge (go from p1 to p2)
|
|
|
|
// u_step = ((r_u1 - u0) / (r_v1 - v0));
|
|
fsub %st(3),%st(0) // u1-u0 | v0 | v1 | u0
|
|
fxch %st(2) // v1 | v0 | u1-u0 | u0
|
|
fsub %st(1),%st(0) // v1-v0 | v0 | u1-u0 | u0
|
|
fdivrp %st(0),%st(2) // v0 | ustep | u0
|
|
|
|
// r_emitted = 1;
|
|
movl $1,C(r_emitted)
|
|
|
|
// edge = edge_p++;
|
|
movl %edx,C(edge_p)
|
|
|
|
// pretouch next edge
|
|
movl (%edx),%eax
|
|
|
|
// v = ceilv0;
|
|
// v2 = r_ceilv1 - 1;
|
|
decl %ecx
|
|
|
|
// edge->surfs[0] = surface_p - surfaces;
|
|
// edge->surfs[1] = 0;
|
|
movl C(surface_p),%eax
|
|
movl C(surfaces),%esi
|
|
subl %edx,%edx
|
|
subl %esi,%eax
|
|
shrl $(SURF_T_SHIFT),%eax
|
|
movl %edx,et_surfs+2(%edi)
|
|
movl %eax,et_surfs(%edi)
|
|
|
|
movl $1,%esi
|
|
|
|
// u = u0 + ((float)v - v0) * u_step;
|
|
movl %ebx,Lv
|
|
fildl Lv // v | v0 | ustep | u0
|
|
fsubp %st(0),%st(1) // v-v0 | ustep | u0
|
|
fmul %st(1),%st(0) // (v-v0)*ustep | ustep | u0
|
|
faddp %st(0),%st(2) // ustep | u
|
|
fxch %st(1) // u | ustep
|
|
|
|
// }
|
|
|
|
LSideDone:
|
|
|
|
// edge->u_step = u_step*0x100000;
|
|
// edge->u = u*0x100000 + 0xFFFFF;
|
|
|
|
fmuls C(fp_1m) // u*0x100000 | ustep
|
|
fxch %st(1) // ustep | u*0x100000
|
|
fmuls C(fp_1m) // ustep*0x100000 | u*0x100000
|
|
fxch %st(1) // u*0x100000 | ustep*0x100000
|
|
fadds C(fp_1m_minus_1) // u*0x100000 + 0xFFFFF | ustep*0x100000
|
|
fxch %st(1) // ustep*0x100000 | u*0x100000 + 0xFFFFF
|
|
fistpl et_u_step(%edi) // u*0x100000 + 0xFFFFF
|
|
fistpl et_u(%edi)
|
|
|
|
// // we need to do this to avoid stepping off the edges if a very nearly
|
|
// // horizontal edge is less than epsilon above a scan, and numeric error
|
|
// // causes it to incorrectly extend to the scan, and the extension of the
|
|
// // line goes off the edge of the screen
|
|
// // FIXME: is this actually needed?
|
|
// if (edge->u < r_refdef.vrectx_adj_shift20)
|
|
// edge->u = r_refdef.vrectx_adj_shift20;
|
|
// if (edge->u > r_refdef.vrectright_adj_shift20)
|
|
// edge->u = r_refdef.vrectright_adj_shift20;
|
|
movl et_u(%edi),%eax
|
|
movl C(r_refdef)+rd_vrectx_adj_shift20,%edx
|
|
cmpl %edx,%eax
|
|
jl LP4
|
|
movl C(r_refdef)+rd_vrectright_adj_shift20,%edx
|
|
cmpl %edx,%eax
|
|
jng LP5
|
|
LP4:
|
|
movl %edx,et_u(%edi)
|
|
movl %edx,%eax
|
|
LP5:
|
|
|
|
// // sort the edge in normally
|
|
// u_check = edge->u;
|
|
//
|
|
// if (edge->surfs[0])
|
|
// u_check++; // sort trailers after leaders
|
|
addl %esi,%eax
|
|
|
|
// if (!newedges[v] || newedges[v]->u >= u_check)
|
|
// {
|
|
movl C(newedges)(,%ebx,4),%esi
|
|
testl %esi,%esi
|
|
jz LDoFirst
|
|
cmpl %eax,et_u(%esi)
|
|
jl LNotFirst
|
|
LDoFirst:
|
|
|
|
// edge->next = newedges[v];
|
|
// newedges[v] = edge;
|
|
movl %esi,et_next(%edi)
|
|
movl %edi,C(newedges)(,%ebx,4)
|
|
|
|
jmp LSetRemove
|
|
|
|
// }
|
|
|
|
LNotFirst:
|
|
|
|
// else
|
|
// {
|
|
// pcheck = newedges[v];
|
|
//
|
|
// while (pcheck->next && pcheck->next->u < u_check)
|
|
// pcheck = pcheck->next;
|
|
LFindInsertLoop:
|
|
movl %esi,%edx
|
|
movl et_next(%esi),%esi
|
|
testl %esi,%esi
|
|
jz LInsertFound
|
|
cmpl %eax,et_u(%esi)
|
|
jl LFindInsertLoop
|
|
|
|
LInsertFound:
|
|
|
|
// edge->next = pcheck->next;
|
|
// pcheck->next = edge;
|
|
movl %esi,et_next(%edi)
|
|
movl %edi,et_next(%edx)
|
|
|
|
// }
|
|
|
|
LSetRemove:
|
|
|
|
// edge->nextremove = removeedges[v2];
|
|
// removeedges[v2] = edge;
|
|
movl C(removeedges)(,%ecx,4),%eax
|
|
movl %edi,C(removeedges)(,%ecx,4)
|
|
movl %eax,et_nextremove(%edi)
|
|
|
|
Ldone:
|
|
movl Lstack,%esp // clear temporary variables from stack
|
|
|
|
popl %ebx // restore register variables
|
|
popl %edi
|
|
popl %esi
|
|
ret
|
|
|
|
// at least one point is clipped
|
|
|
|
Lp2:
|
|
testl %eax,%eax
|
|
jns Lp1
|
|
|
|
// else
|
|
// {
|
|
// // point 0 is clipped
|
|
|
|
// if (d1 < 0)
|
|
// {
|
|
movl Ld1,%eax
|
|
testl %eax,%eax
|
|
jns Lp3
|
|
|
|
// // both points are clipped
|
|
// // we do cache fully clipped edges
|
|
// if (!leftclipped)
|
|
movl C(r_leftclipped),%eax
|
|
movl C(r_pedge),%ecx
|
|
testl %eax,%eax
|
|
jnz Ldone
|
|
|
|
// r_pedge->framecount = r_framecount;
|
|
movl C(r_framecount),%eax
|
|
andl $(FRAMECOUNT_MASK),%eax
|
|
orl $(FULLY_CLIPPED_CACHED),%eax
|
|
movl %eax,C(cacheoffset)
|
|
|
|
// return;
|
|
jmp Ldone
|
|
|
|
// }
|
|
|
|
Lp1:
|
|
|
|
// // point 0 is unclipped
|
|
// if (d1 >= 0)
|
|
// {
|
|
// // both points are unclipped
|
|
// continue;
|
|
|
|
// // only point 1 is clipped
|
|
|
|
// f = d0 / (d0 - d1);
|
|
flds Ld0
|
|
flds Ld1
|
|
fsubr %st(1),%st(0)
|
|
|
|
// // we don't cache partially clipped edges
|
|
movl $0x7FFFFFFF,C(cacheoffset)
|
|
|
|
fdivrp %st(0),%st(1)
|
|
|
|
subl $(mv_size),%esp // allocate space for clipvert
|
|
|
|
// clipvert.position[0] = pv0->position[0] +
|
|
// f * (pv1->position[0] - pv0->position[0]);
|
|
// clipvert.position[1] = pv0->position[1] +
|
|
// f * (pv1->position[1] - pv0->position[1]);
|
|
// clipvert.position[2] = pv0->position[2] +
|
|
// f * (pv1->position[2] - pv0->position[2]);
|
|
flds mv_position+8(%edx)
|
|
fsubs mv_position+8(%esi)
|
|
flds mv_position+4(%edx)
|
|
fsubs mv_position+4(%esi)
|
|
flds mv_position+0(%edx)
|
|
fsubs mv_position+0(%esi) // 0 | 1 | 2
|
|
|
|
// replace pv1 with the clip point
|
|
movl %esp,%edx
|
|
movl cp_leftedge(%ebx),%eax
|
|
testb %al,%al
|
|
|
|
fmul %st(3),%st(0)
|
|
fxch %st(1) // 1 | 0 | 2
|
|
fmul %st(3),%st(0)
|
|
fxch %st(2) // 2 | 0 | 1
|
|
fmulp %st(0),%st(3) // 0 | 1 | 2
|
|
fadds mv_position+0(%esi)
|
|
fxch %st(1) // 1 | 0 | 2
|
|
fadds mv_position+4(%esi)
|
|
fxch %st(2) // 2 | 0 | 1
|
|
fadds mv_position+8(%esi)
|
|
fxch %st(1) // 0 | 2 | 1
|
|
fstps mv_position+0(%esp) // 2 | 1
|
|
fstps mv_position+8(%esp) // 1
|
|
fstps mv_position+4(%esp)
|
|
|
|
// if (clip->leftedge)
|
|
// {
|
|
jz Ltestright
|
|
|
|
// r_leftclipped = true;
|
|
// r_leftexit = clipvert;
|
|
movl $1,C(r_leftclipped)
|
|
movl mv_position+0(%esp),%eax
|
|
movl %eax,C(r_leftexit)+mv_position+0
|
|
movl mv_position+4(%esp),%eax
|
|
movl %eax,C(r_leftexit)+mv_position+4
|
|
movl mv_position+8(%esp),%eax
|
|
movl %eax,C(r_leftexit)+mv_position+8
|
|
|
|
jmp Lcontinue
|
|
|
|
// }
|
|
|
|
Ltestright:
|
|
// else if (clip->rightedge)
|
|
// {
|
|
testb %ah,%ah
|
|
jz Lcontinue
|
|
|
|
// r_rightclipped = true;
|
|
// r_rightexit = clipvert;
|
|
movl $1,C(r_rightclipped)
|
|
movl mv_position+0(%esp),%eax
|
|
movl %eax,C(r_rightexit)+mv_position+0
|
|
movl mv_position+4(%esp),%eax
|
|
movl %eax,C(r_rightexit)+mv_position+4
|
|
movl mv_position+8(%esp),%eax
|
|
movl %eax,C(r_rightexit)+mv_position+8
|
|
|
|
// }
|
|
//
|
|
// R_ClipEdge (pv0, &clipvert, clip->next);
|
|
// return;
|
|
// }
|
|
jmp Lcontinue
|
|
|
|
// }
|
|
|
|
Lp3:
|
|
|
|
// // only point 0 is clipped
|
|
// r_lastvertvalid = false;
|
|
|
|
movl $0,C(r_lastvertvalid)
|
|
|
|
// f = d0 / (d0 - d1);
|
|
flds Ld0
|
|
flds Ld1
|
|
fsubr %st(1),%st(0)
|
|
|
|
// // we don't cache partially clipped edges
|
|
movl $0x7FFFFFFF,C(cacheoffset)
|
|
|
|
fdivrp %st(0),%st(1)
|
|
|
|
subl $(mv_size),%esp // allocate space for clipvert
|
|
|
|
// clipvert.position[0] = pv0->position[0] +
|
|
// f * (pv1->position[0] - pv0->position[0]);
|
|
// clipvert.position[1] = pv0->position[1] +
|
|
// f * (pv1->position[1] - pv0->position[1]);
|
|
// clipvert.position[2] = pv0->position[2] +
|
|
// f * (pv1->position[2] - pv0->position[2]);
|
|
flds mv_position+8(%edx)
|
|
fsubs mv_position+8(%esi)
|
|
flds mv_position+4(%edx)
|
|
fsubs mv_position+4(%esi)
|
|
flds mv_position+0(%edx)
|
|
fsubs mv_position+0(%esi) // 0 | 1 | 2
|
|
|
|
movl cp_leftedge(%ebx),%eax
|
|
testb %al,%al
|
|
|
|
fmul %st(3),%st(0)
|
|
fxch %st(1) // 1 | 0 | 2
|
|
fmul %st(3),%st(0)
|
|
fxch %st(2) // 2 | 0 | 1
|
|
fmulp %st(0),%st(3) // 0 | 1 | 2
|
|
fadds mv_position+0(%esi)
|
|
fxch %st(1) // 1 | 0 | 2
|
|
fadds mv_position+4(%esi)
|
|
fxch %st(2) // 2 | 0 | 1
|
|
fadds mv_position+8(%esi)
|
|
fxch %st(1) // 0 | 2 | 1
|
|
fstps mv_position+0(%esp) // 2 | 1
|
|
fstps mv_position+8(%esp) // 1
|
|
fstps mv_position+4(%esp)
|
|
|
|
// replace pv0 with the clip point
|
|
movl %esp,%esi
|
|
|
|
// if (clip->leftedge)
|
|
// {
|
|
jz Ltestright2
|
|
|
|
// r_leftclipped = true;
|
|
// r_leftenter = clipvert;
|
|
movl $1,C(r_leftclipped)
|
|
movl mv_position+0(%esp),%eax
|
|
movl %eax,C(r_leftenter)+mv_position+0
|
|
movl mv_position+4(%esp),%eax
|
|
movl %eax,C(r_leftenter)+mv_position+4
|
|
movl mv_position+8(%esp),%eax
|
|
movl %eax,C(r_leftenter)+mv_position+8
|
|
|
|
jmp Lcontinue
|
|
|
|
// }
|
|
|
|
Ltestright2:
|
|
// else if (clip->rightedge)
|
|
// {
|
|
testb %ah,%ah
|
|
jz Lcontinue
|
|
|
|
// r_rightclipped = true;
|
|
// r_rightenter = clipvert;
|
|
movl $1,C(r_rightclipped)
|
|
movl mv_position+0(%esp),%eax
|
|
movl %eax,C(r_rightenter)+mv_position+0
|
|
movl mv_position+4(%esp),%eax
|
|
movl %eax,C(r_rightenter)+mv_position+4
|
|
movl mv_position+8(%esp),%eax
|
|
movl %eax,C(r_rightenter)+mv_position+8
|
|
|
|
// }
|
|
jmp Lcontinue
|
|
|
|
// %esi = vec3_t point to transform and project
|
|
// %edx preserved
|
|
LTransformAndProject:
|
|
|
|
// // transform and project
|
|
// VectorSubtract (world, modelorg, local);
|
|
flds mv_position+0(%esi)
|
|
fsubs C(modelorg)+0
|
|
flds mv_position+4(%esi)
|
|
fsubs C(modelorg)+4
|
|
flds mv_position+8(%esi)
|
|
fsubs C(modelorg)+8
|
|
fxch %st(2) // local[0] | local[1] | local[2]
|
|
|
|
// TransformVector (local, transformed);
|
|
//
|
|
// if (transformed[2] < NEAR_CLIP)
|
|
// transformed[2] = NEAR_CLIP;
|
|
//
|
|
// lzi0 = 1.0 / transformed[2];
|
|
fld %st(0) // local[0] | local[0] | local[1] | local[2]
|
|
fmuls C(vfwd)+0 // zm0 | local[0] | local[1] | local[2]
|
|
fld %st(1) // local[0] | zm0 | local[0] | local[1] |
|
|
// local[2]
|
|
fmuls C(vright)+0 // xm0 | zm0 | local[0] | local[1] | local[2]
|
|
fxch %st(2) // local[0] | zm0 | xm0 | local[1] | local[2]
|
|
fmuls C(vup)+0 // ym0 | zm0 | xm0 | local[1] | local[2]
|
|
fld %st(3) // local[1] | ym0 | zm0 | xm0 | local[1] |
|
|
// local[2]
|
|
fmuls C(vfwd)+4 // zm1 | ym0 | zm0 | xm0 | local[1] |
|
|
// local[2]
|
|
fld %st(4) // local[1] | zm1 | ym0 | zm0 | xm0 |
|
|
// local[1] | local[2]
|
|
fmuls C(vright)+4 // xm1 | zm1 | ym0 | zm0 | xm0 |
|
|
// local[1] | local[2]
|
|
fxch %st(5) // local[1] | zm1 | ym0 | zm0 | xm0 |
|
|
// xm1 | local[2]
|
|
fmuls C(vup)+4 // ym1 | zm1 | ym0 | zm0 | xm0 |
|
|
// xm1 | local[2]
|
|
fxch %st(1) // zm1 | ym1 | ym0 | zm0 | xm0 |
|
|
// xm1 | local[2]
|
|
faddp %st(0),%st(3) // ym1 | ym0 | zm2 | xm0 | xm1 | local[2]
|
|
fxch %st(3) // xm0 | ym0 | zm2 | ym1 | xm1 | local[2]
|
|
faddp %st(0),%st(4) // ym0 | zm2 | ym1 | xm2 | local[2]
|
|
faddp %st(0),%st(2) // zm2 | ym2 | xm2 | local[2]
|
|
fld %st(3) // local[2] | zm2 | ym2 | xm2 | local[2]
|
|
fmuls C(vfwd)+8 // zm3 | zm2 | ym2 | xm2 | local[2]
|
|
fld %st(4) // local[2] | zm3 | zm2 | ym2 | xm2 | local[2]
|
|
fmuls C(vright)+8 // xm3 | zm3 | zm2 | ym2 | xm2 | local[2]
|
|
fxch %st(5) // local[2] | zm3 | zm2 | ym2 | xm2 | xm3
|
|
fmuls C(vup)+8 // ym3 | zm3 | zm2 | ym2 | xm2 | xm3
|
|
fxch %st(1) // zm3 | ym3 | zm2 | ym2 | xm2 | xm3
|
|
faddp %st(0),%st(2) // ym3 | zm4 | ym2 | xm2 | xm3
|
|
fxch %st(4) // xm3 | zm4 | ym2 | xm2 | ym3
|
|
faddp %st(0),%st(3) // zm4 | ym2 | xm4 | ym3
|
|
fxch %st(1) // ym2 | zm4 | xm4 | ym3
|
|
faddp %st(0),%st(3) // zm4 | xm4 | ym4
|
|
|
|
fcoms Lfp_near_clip
|
|
fnstsw %ax
|
|
testb $1,%ah
|
|
jz LNoClip
|
|
fstp %st(0)
|
|
flds Lfp_near_clip
|
|
|
|
LNoClip:
|
|
|
|
fdivrs C(float_1) // lzi0 | x | y
|
|
fxch %st(1) // x | lzi0 | y
|
|
|
|
// // FIXME: build x/yscale into transform?
|
|
// scale = xscale * lzi0;
|
|
// u0 = (xcenter + scale*transformed[0]);
|
|
flds C(xscale) // xscale | x | lzi0 | y
|
|
fmul %st(2),%st(0) // scale | x | lzi0 | y
|
|
fmulp %st(0),%st(1) // scale*x | lzi0 | y
|
|
fadds C(xcenter) // u0 | lzi0 | y
|
|
|
|
// if (u0 < r_refdef.fvrectx_adj)
|
|
// u0 = r_refdef.fvrectx_adj;
|
|
// if (u0 > r_refdef.fvrectright_adj)
|
|
// u0 = r_refdef.fvrectright_adj;
|
|
// FIXME: use integer compares of floats?
|
|
fcoms C(r_refdef)+rd_fvrectx_adj
|
|
fnstsw %ax
|
|
testb $1,%ah
|
|
jz LClampP0
|
|
fstp %st(0)
|
|
flds C(r_refdef)+rd_fvrectx_adj
|
|
LClampP0:
|
|
fcoms C(r_refdef)+rd_fvrectright_adj
|
|
fnstsw %ax
|
|
testb $0x45,%ah
|
|
jnz LClampP1
|
|
fstp %st(0)
|
|
flds C(r_refdef)+rd_fvrectright_adj
|
|
LClampP1:
|
|
|
|
fld %st(1) // lzi0 | u0 | lzi0 | y
|
|
|
|
// scale = yscale * lzi0;
|
|
// v0 = (ycenter - scale*transformed[1]);
|
|
fmuls C(yscale) // scale | u0 | lzi0 | y
|
|
fmulp %st(0),%st(3) // u0 | lzi0 | scale*y
|
|
fxch %st(2) // scale*y | lzi0 | u0
|
|
fsubrs C(ycenter) // v0 | lzi0 | u0
|
|
|
|
// if (v0 < r_refdef.fvrecty_adj)
|
|
// v0 = r_refdef.fvrecty_adj;
|
|
// if (v0 > r_refdef.fvrectbottom_adj)
|
|
// v0 = r_refdef.fvrectbottom_adj;
|
|
// FIXME: use integer compares of floats?
|
|
fcoms C(r_refdef)+rd_fvrecty_adj
|
|
fnstsw %ax
|
|
testb $1,%ah
|
|
jz LClampP2
|
|
fstp %st(0)
|
|
flds C(r_refdef)+rd_fvrecty_adj
|
|
LClampP2:
|
|
fcoms C(r_refdef)+rd_fvrectbottom_adj
|
|
fnstsw %ax
|
|
testb $0x45,%ah
|
|
jnz LClampP3
|
|
fstp %st(0)
|
|
flds C(r_refdef)+rd_fvrectbottom_adj
|
|
LClampP3:
|
|
ret
|
|
|
|
#endif // USE_INTEL_ASM
|
|
|
|
#if defined(__linux__) && defined(__ELF__)
|
|
.section .note.GNU-stack,"",%progbits
|
|
#endif
|