Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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