1 /* -*- mode: c; c-basic-offset: 3 -*-
3 * Copyright 2000 VA Linux Systems Inc., Fremont, California.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 /* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_tris.c,v 1.4 2002/10/30 12:52:01 alanh Exp $ */
29 * Daniel Borca <dborca@users.sourceforge.net>, 19 Jul 2004
32 * Keith Whitwell <keith@tungstengraphics.com>
35 #include "main/glheader.h"
36 #include "main/mtypes.h"
37 #include "main/macros.h"
38 #include "main/colormac.h"
40 #include "swrast/swrast.h"
41 #include "swrast_setup/swrast_setup.h"
42 #include "swrast_setup/ss_context.h"
43 #include "tnl/t_context.h"
44 #include "tnl/t_pipeline.h"
46 #include "tdfx_tris.h"
47 #include "tdfx_state.h"
49 #include "tdfx_lock.h"
50 #include "tdfx_render.h"
53 static void tdfxRasterPrimitive( GLcontext
*ctx
, GLenum prim
);
54 static void tdfxRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
56 static GLenum reduced_prim
[GL_POLYGON
+1] = {
69 /***********************************************************************
70 * Macros for t_dd_tritmp.h to draw basic primitives *
71 ***********************************************************************/
73 #define TRI( a, b, c ) \
76 fxMesa->draw_triangle( fxMesa, a, b, c ); \
78 fxMesa->Glide.grDrawTriangle( a, b, c ); \
81 #define QUAD( a, b, c, d ) \
84 fxMesa->draw_triangle( fxMesa, a, b, d ); \
85 fxMesa->draw_triangle( fxMesa, b, c, d ); \
92 fxMesa->Glide.grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
93 /*fxMesa->Glide.grDrawTriangle( a, b, d );*/\
94 /*fxMesa->Glide.grDrawTriangle( b, c, d );*/\
98 #define LINE( v0, v1 ) \
101 fxMesa->draw_line( fxMesa, v0, v1 ); \
103 v0->x += LINE_X_OFFSET - TRI_X_OFFSET; \
104 v0->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
105 v1->x += LINE_X_OFFSET - TRI_X_OFFSET; \
106 v1->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
107 fxMesa->Glide.grDrawLine( v0, v1 ); \
108 v0->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
109 v0->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
110 v1->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
111 v1->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
115 #define POINT( v0 ) \
118 fxMesa->draw_point( fxMesa, v0 ); \
120 v0->x += PNT_X_OFFSET - TRI_X_OFFSET; \
121 v0->y += PNT_Y_OFFSET - TRI_Y_OFFSET; \
122 fxMesa->Glide.grDrawPoint( v0 ); \
123 v0->x -= PNT_X_OFFSET - TRI_X_OFFSET; \
124 v0->y -= PNT_Y_OFFSET - TRI_Y_OFFSET; \
129 /***********************************************************************
130 * Fallback to swrast for basic primitives *
131 ***********************************************************************/
133 /* Build an SWvertex from a hardware vertex.
135 * This code is hit only when a mix of accelerated and unaccelerated
136 * primitives are being drawn, and only for the unaccelerated
140 tdfx_translate_vertex( GLcontext
*ctx
, const tdfxVertex
*src
, SWvertex
*dst
)
142 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
144 if (fxMesa
->vertexFormat
== TDFX_LAYOUT_TINY
) {
145 dst
->attrib
[FRAG_ATTRIB_WPOS
][0] = src
->x
- fxMesa
->x_offset
;
146 dst
->attrib
[FRAG_ATTRIB_WPOS
][1] = src
->y
- (fxMesa
->screen_height
- fxMesa
->height
- fxMesa
->y_offset
);
147 dst
->attrib
[FRAG_ATTRIB_WPOS
][2] = src
->z
;
148 dst
->attrib
[FRAG_ATTRIB_WPOS
][3] = 1.0;
150 dst
->color
[0] = src
->color
[2];
151 dst
->color
[1] = src
->color
[1];
152 dst
->color
[2] = src
->color
[0];
153 dst
->color
[3] = src
->color
[3];
156 GLfloat w
= 1.0 / src
->rhw
;
158 dst
->attrib
[FRAG_ATTRIB_WPOS
][0] = src
->x
- fxMesa
->x_offset
;
159 dst
->attrib
[FRAG_ATTRIB_WPOS
][1] = src
->y
- (fxMesa
->screen_height
- fxMesa
->height
- fxMesa
->y_offset
);
160 dst
->attrib
[FRAG_ATTRIB_WPOS
][2] = src
->z
;
161 dst
->attrib
[FRAG_ATTRIB_WPOS
][3] = src
->rhw
;
163 dst
->color
[0] = src
->color
[2];
164 dst
->color
[1] = src
->color
[1];
165 dst
->color
[2] = src
->color
[0];
166 dst
->color
[3] = src
->color
[3];
168 dst
->attrib
[FRAG_ATTRIB_TEX0
][0] = 1.0 / fxMesa
->sScale0
* w
* src
->tu0
;
169 dst
->attrib
[FRAG_ATTRIB_TEX0
][1] = 1.0 / fxMesa
->tScale0
* w
* src
->tv0
;
170 if (fxMesa
->vertexFormat
== TDFX_LAYOUT_PROJ1
|| fxMesa
->vertexFormat
== TDFX_LAYOUT_PROJ2
) {
171 dst
->attrib
[FRAG_ATTRIB_TEX0
][3] = w
* src
->tq0
;
173 dst
->attrib
[FRAG_ATTRIB_TEX0
][3] = 1.0;
176 if (fxMesa
->SetupIndex
& TDFX_TEX1_BIT
) {
177 dst
->attrib
[FRAG_ATTRIB_TEX1
][0] = 1.0 / fxMesa
->sScale1
* w
* src
->tu1
;
178 dst
->attrib
[FRAG_ATTRIB_TEX1
][1] = 1.0 / fxMesa
->tScale1
* w
* src
->tv1
;
179 if (fxMesa
->vertexFormat
== TDFX_LAYOUT_PROJ2
) {
180 dst
->attrib
[FRAG_ATTRIB_TEX1
][3] = w
* src
->tq1
;
182 dst
->attrib
[FRAG_ATTRIB_TEX1
][3] = 1.0;
187 dst
->pointSize
= ctx
->Point
.Size
;
192 tdfx_fallback_tri( tdfxContextPtr fxMesa
,
197 GLcontext
*ctx
= fxMesa
->glCtx
;
199 tdfx_translate_vertex( ctx
, v0
, &v
[0] );
200 tdfx_translate_vertex( ctx
, v1
, &v
[1] );
201 tdfx_translate_vertex( ctx
, v2
, &v
[2] );
202 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
207 tdfx_fallback_line( tdfxContextPtr fxMesa
,
211 GLcontext
*ctx
= fxMesa
->glCtx
;
213 tdfx_translate_vertex( ctx
, v0
, &v
[0] );
214 tdfx_translate_vertex( ctx
, v1
, &v
[1] );
215 _swrast_Line( ctx
, &v
[0], &v
[1] );
220 tdfx_fallback_point( tdfxContextPtr fxMesa
,
223 GLcontext
*ctx
= fxMesa
->glCtx
;
225 tdfx_translate_vertex( ctx
, v0
, &v
[0] );
226 _swrast_Point( ctx
, &v
[0] );
229 /***********************************************************************
230 * Functions to draw basic primitives *
231 ***********************************************************************/
233 static void tdfx_print_vertex( GLcontext
*ctx
, const tdfxVertex
*v
)
235 tdfxContextPtr tmesa
= TDFX_CONTEXT( ctx
);
237 fprintf(stderr
, "vertex at %p\n", (void *)v
);
239 if (tmesa
->vertexFormat
== TDFX_LAYOUT_TINY
) {
240 fprintf(stderr
, "x %f y %f z %f\n", v
->x
, v
->y
, v
->z
);
243 fprintf(stderr
, "x %f y %f z %f oow %f\n",
244 v
->x
, v
->y
, v
->z
, v
->rhw
);
246 fprintf(stderr
, "r %d g %d b %d a %d\n",
252 fprintf(stderr
, "\n");
255 #define DO_FALLBACK 0
257 /* Need to do clip loop at each triangle when mixing swrast and hw
258 * rendering. These functions are only used when mixed-mode rendering
261 static void tdfx_draw_triangle( tdfxContextPtr fxMesa
,
266 /* fprintf(stderr, "%s\n", __FUNCTION__); */
267 /* tdfx_print_vertex( fxMesa->glCtx, v0 ); */
268 /* tdfx_print_vertex( fxMesa->glCtx, v1 ); */
269 /* tdfx_print_vertex( fxMesa->glCtx, v2 ); */
270 BEGIN_CLIP_LOOP_LOCKED(fxMesa
) {
272 } END_CLIP_LOOP_LOCKED(fxMesa
);
275 static void tdfx_draw_line( tdfxContextPtr fxMesa
,
279 /* No support for wide lines (avoid wide/aa line fallback).
281 BEGIN_CLIP_LOOP_LOCKED(fxMesa
) {
283 } END_CLIP_LOOP_LOCKED(fxMesa
);
286 static void tdfx_draw_point( tdfxContextPtr fxMesa
,
289 /* No support for wide points.
291 BEGIN_CLIP_LOOP_LOCKED(fxMesa
) {
293 } END_CLIP_LOOP_LOCKED(fxMesa
);
299 #define TDFX_UNFILLED_BIT 0x1
300 #define TDFX_OFFSET_BIT 0x2
301 #define TDFX_TWOSIDE_BIT 0x4
302 #define TDFX_FLAT_BIT 0x8
303 #define TDFX_FALLBACK_BIT 0x10
304 #define TDFX_MAX_TRIFUNC 0x20
307 tnl_points_func points
;
309 tnl_triangle_func triangle
;
311 } rast_tab
[TDFX_MAX_TRIFUNC
];
313 #define DO_FALLBACK (IND & TDFX_FALLBACK_BIT)
314 #define DO_OFFSET (IND & TDFX_OFFSET_BIT)
315 #define DO_UNFILLED (IND & TDFX_UNFILLED_BIT)
316 #define DO_TWOSIDE (IND & TDFX_TWOSIDE_BIT)
317 #define DO_FLAT (IND & TDFX_FLAT_BIT)
322 #define DO_FULL_QUAD 1
326 #define HAVE_HW_FLATSHADE 0
327 #define HAVE_BACK_COLORS 0
328 #define VERTEX tdfxVertex
331 #define DEPTH_SCALE 1.0
332 #define UNFILLED_TRI unfilled_tri
333 #define UNFILLED_QUAD unfilled_quad
334 #define VERT_X(_v) _v->x
335 #define VERT_Y(_v) _v->y
336 #define VERT_Z(_v) _v->z
337 #define AREA_IS_CCW( a ) (a < 0)
338 #define GET_VERTEX(e) (fxMesa->verts + (e))
340 #define VERT_SET_RGBA( dst, f ) \
342 UNCLAMPED_FLOAT_TO_UBYTE(dst->color[2], f[0]);\
343 UNCLAMPED_FLOAT_TO_UBYTE(dst->color[1], f[1]);\
344 UNCLAMPED_FLOAT_TO_UBYTE(dst->color[0], f[2]);\
345 UNCLAMPED_FLOAT_TO_UBYTE(dst->color[3], f[3]);\
348 #define VERT_COPY_RGBA( v0, v1 ) \
349 *(GLuint *)&v0->color = *(GLuint *)&v1->color
351 #define VERT_SAVE_RGBA( idx ) \
352 *(GLuint *)&color[idx] = *(GLuint *)&v[idx]->color
354 #define VERT_RESTORE_RGBA( idx ) \
355 *(GLuint *)&v[idx]->color = *(GLuint *)&color[idx]
357 #define LOCAL_VARS(n) \
358 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); \
359 GLubyte color[n][4]; \
364 /***********************************************************************
365 * Functions to draw basic unfilled primitives *
366 ***********************************************************************/
368 #define RASTERIZE(x) if (fxMesa->raster_primitive != reduced_prim[x]) \
369 tdfxRasterPrimitive( ctx, reduced_prim[x] )
370 #define RENDER_PRIMITIVE fxMesa->render_primitive
371 #define IND TDFX_FALLBACK_BIT
373 #include "tnl_dd/t_dd_unfilled.h"
376 /***********************************************************************
377 * Functions to draw GL primitives *
378 ***********************************************************************/
382 #include "tnl_dd/t_dd_tritmp.h"
384 #define IND (TDFX_OFFSET_BIT)
385 #define TAG(x) x##_offset
386 #include "tnl_dd/t_dd_tritmp.h"
388 #define IND (TDFX_TWOSIDE_BIT)
389 #define TAG(x) x##_twoside
390 #include "tnl_dd/t_dd_tritmp.h"
392 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT)
393 #define TAG(x) x##_twoside_offset
394 #include "tnl_dd/t_dd_tritmp.h"
396 #define IND (TDFX_UNFILLED_BIT)
397 #define TAG(x) x##_unfilled
398 #include "tnl_dd/t_dd_tritmp.h"
400 #define IND (TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT)
401 #define TAG(x) x##_offset_unfilled
402 #include "tnl_dd/t_dd_tritmp.h"
404 #define IND (TDFX_TWOSIDE_BIT|TDFX_UNFILLED_BIT)
405 #define TAG(x) x##_twoside_unfilled
406 #include "tnl_dd/t_dd_tritmp.h"
408 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT)
409 #define TAG(x) x##_twoside_offset_unfilled
410 #include "tnl_dd/t_dd_tritmp.h"
412 #define IND (TDFX_FALLBACK_BIT)
413 #define TAG(x) x##_fallback
414 #include "tnl_dd/t_dd_tritmp.h"
416 #define IND (TDFX_OFFSET_BIT|TDFX_FALLBACK_BIT)
417 #define TAG(x) x##_offset_fallback
418 #include "tnl_dd/t_dd_tritmp.h"
420 #define IND (TDFX_TWOSIDE_BIT|TDFX_FALLBACK_BIT)
421 #define TAG(x) x##_twoside_fallback
422 #include "tnl_dd/t_dd_tritmp.h"
424 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_FALLBACK_BIT)
425 #define TAG(x) x##_twoside_offset_fallback
426 #include "tnl_dd/t_dd_tritmp.h"
428 #define IND (TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT)
429 #define TAG(x) x##_unfilled_fallback
430 #include "tnl_dd/t_dd_tritmp.h"
432 #define IND (TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT)
433 #define TAG(x) x##_offset_unfilled_fallback
434 #include "tnl_dd/t_dd_tritmp.h"
436 #define IND (TDFX_TWOSIDE_BIT|TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT)
437 #define TAG(x) x##_twoside_unfilled_fallback
438 #include "tnl_dd/t_dd_tritmp.h"
440 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT| \
442 #define TAG(x) x##_twoside_offset_unfilled_fallback
443 #include "tnl_dd/t_dd_tritmp.h"
446 /* Tdfx doesn't support provoking-vertex flat-shading?
448 #define IND (TDFX_FLAT_BIT)
449 #define TAG(x) x##_flat
450 #include "tnl_dd/t_dd_tritmp.h"
452 #define IND (TDFX_OFFSET_BIT|TDFX_FLAT_BIT)
453 #define TAG(x) x##_offset_flat
454 #include "tnl_dd/t_dd_tritmp.h"
456 #define IND (TDFX_TWOSIDE_BIT|TDFX_FLAT_BIT)
457 #define TAG(x) x##_twoside_flat
458 #include "tnl_dd/t_dd_tritmp.h"
460 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_FLAT_BIT)
461 #define TAG(x) x##_twoside_offset_flat
462 #include "tnl_dd/t_dd_tritmp.h"
464 #define IND (TDFX_UNFILLED_BIT|TDFX_FLAT_BIT)
465 #define TAG(x) x##_unfilled_flat
466 #include "tnl_dd/t_dd_tritmp.h"
468 #define IND (TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT|TDFX_FLAT_BIT)
469 #define TAG(x) x##_offset_unfilled_flat
470 #include "tnl_dd/t_dd_tritmp.h"
472 #define IND (TDFX_TWOSIDE_BIT|TDFX_UNFILLED_BIT|TDFX_FLAT_BIT)
473 #define TAG(x) x##_twoside_unfilled_flat
474 #include "tnl_dd/t_dd_tritmp.h"
476 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT|TDFX_FLAT_BIT)
477 #define TAG(x) x##_twoside_offset_unfilled_flat
478 #include "tnl_dd/t_dd_tritmp.h"
480 #define IND (TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
481 #define TAG(x) x##_fallback_flat
482 #include "tnl_dd/t_dd_tritmp.h"
484 #define IND (TDFX_OFFSET_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
485 #define TAG(x) x##_offset_fallback_flat
486 #include "tnl_dd/t_dd_tritmp.h"
488 #define IND (TDFX_TWOSIDE_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
489 #define TAG(x) x##_twoside_fallback_flat
490 #include "tnl_dd/t_dd_tritmp.h"
492 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
493 #define TAG(x) x##_twoside_offset_fallback_flat
494 #include "tnl_dd/t_dd_tritmp.h"
496 #define IND (TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
497 #define TAG(x) x##_unfilled_fallback_flat
498 #include "tnl_dd/t_dd_tritmp.h"
500 #define IND (TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
501 #define TAG(x) x##_offset_unfilled_fallback_flat
502 #include "tnl_dd/t_dd_tritmp.h"
504 #define IND (TDFX_TWOSIDE_BIT|TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
505 #define TAG(x) x##_twoside_unfilled_fallback_flat
506 #include "tnl_dd/t_dd_tritmp.h"
508 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT| \
509 TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
510 #define TAG(x) x##_twoside_offset_unfilled_fallback_flat
511 #include "tnl_dd/t_dd_tritmp.h"
514 static void init_rast_tab( void )
519 init_twoside_offset();
521 init_offset_unfilled();
522 init_twoside_unfilled();
523 init_twoside_offset_unfilled();
525 init_offset_fallback();
526 init_twoside_fallback();
527 init_twoside_offset_fallback();
528 init_unfilled_fallback();
529 init_offset_unfilled_fallback();
530 init_twoside_unfilled_fallback();
531 init_twoside_offset_unfilled_fallback();
536 init_twoside_offset_flat();
537 init_unfilled_flat();
538 init_offset_unfilled_flat();
539 init_twoside_unfilled_flat();
540 init_twoside_offset_unfilled_flat();
541 init_fallback_flat();
542 init_offset_fallback_flat();
543 init_twoside_fallback_flat();
544 init_twoside_offset_fallback_flat();
545 init_unfilled_fallback_flat();
546 init_offset_unfilled_fallback_flat();
547 init_twoside_unfilled_fallback_flat();
548 init_twoside_offset_unfilled_fallback_flat();
552 /**********************************************************************/
553 /* Render whole begin/end objects */
554 /**********************************************************************/
557 /* Accelerate vertex buffer rendering when renderindex == 0 and
558 * there is no clipping.
560 #define INIT(x) tdfxRenderPrimitive( ctx, x )
562 static void tdfx_render_vb_points( GLcontext
*ctx
,
567 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
568 tdfxVertex
*fxVB
= fxMesa
->verts
;
574 /* Adjust point coords */
575 for (i
= start
; i
< count
; i
++) {
576 fxVB
[i
].x
+= PNT_X_OFFSET
- TRI_X_OFFSET
;
577 fxVB
[i
].y
+= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
580 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_POINTS
, count
-start
,
581 fxVB
+ start
, sizeof(tdfxVertex
));
582 /* restore point coords */
583 for (i
= start
; i
< count
; i
++) {
584 fxVB
[i
].x
-= PNT_X_OFFSET
- TRI_X_OFFSET
;
585 fxVB
[i
].y
-= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
589 static void tdfx_render_vb_line_strip( GLcontext
*ctx
,
594 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
595 tdfxVertex
*fxVB
= fxMesa
->verts
;
601 /* adjust line coords */
602 for (i
= start
; i
< count
; i
++) {
603 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
604 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
607 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-start
,
608 fxVB
+ start
, sizeof(tdfxVertex
) );
610 /* restore line coords */
611 for (i
= start
; i
< count
; i
++) {
612 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
613 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
617 static void tdfx_render_vb_line_loop( GLcontext
*ctx
,
622 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
623 tdfxVertex
*fxVB
= fxMesa
->verts
;
630 if (!(flags
& PRIM_BEGIN
)) {
634 /* adjust line coords */
635 for (i
= start
; i
< count
; i
++) {
636 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
637 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
640 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-j
,
641 fxVB
+ j
, sizeof(tdfxVertex
));
643 if (flags
& PRIM_END
)
644 fxMesa
->Glide
.grDrawLine( fxVB
+ (count
- 1),
647 /* restore line coords */
648 for (i
= start
; i
< count
; i
++) {
649 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
650 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
654 static void tdfx_render_vb_lines( GLcontext
*ctx
,
659 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
660 tdfxVertex
*fxVB
= fxMesa
->verts
;
666 /* adjust line coords */
667 for (i
= start
; i
< count
; i
++) {
668 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
669 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
672 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_LINES
, count
-start
,
673 fxVB
+ start
, sizeof(tdfxVertex
));
675 /* restore line coords */
676 for (i
= start
; i
< count
; i
++) {
677 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
678 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
682 static void tdfx_render_vb_triangles( GLcontext
*ctx
,
687 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
688 tdfxVertex
*fxVB
= fxMesa
->verts
;
695 * apparently, this causes troubles with some programs (GLExcess);
696 * might be a bug in Glide... However, "grDrawVertexArrayContiguous"
697 * eventually calls "grDrawTriangle" for GR_TRIANGLES, so we're better
698 * off doing it by hand...
700 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_TRIANGLES
, count
-start
,
701 fxVB
+ start
, sizeof(tdfxVertex
));
705 for (j
=start
+2; j
<count
; j
+=3) {
706 fxMesa
->Glide
.grDrawTriangle(fxVB
+ (j
-2), fxVB
+ (j
-1), fxVB
+ j
);
713 static void tdfx_render_vb_tri_strip( GLcontext
*ctx
,
718 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
719 tdfxVertex
*fxVB
= fxMesa
->verts
;
723 INIT(GL_TRIANGLE_STRIP
);
725 /* fprintf(stderr, "%s/%d\n", __FUNCTION__, 1<<shift); */
726 /* if(!prevLockLine) abort(); */
728 mode
= GR_TRIANGLE_STRIP
;
730 fxMesa
->Glide
.grDrawVertexArrayContiguous( mode
, count
-start
,
731 fxVB
+ start
, sizeof(tdfxVertex
));
735 static void tdfx_render_vb_tri_fan( GLcontext
*ctx
,
740 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
741 tdfxVertex
*fxVB
= fxMesa
->verts
;
744 INIT(GL_TRIANGLE_FAN
);
746 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_TRIANGLE_FAN
, count
-start
,
747 fxVB
+ start
, sizeof(tdfxVertex
) );
750 static void tdfx_render_vb_quads( GLcontext
*ctx
,
755 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
756 tdfxVertex
*fxVB
= fxMesa
->verts
;
762 for (i
= start
+ 3 ; i
< count
; i
+= 4 ) {
763 #define VERT(x) (fxVB + (x))
769 fxMesa
->Glide
.grDrawVertexArray(GR_TRIANGLE_FAN
, 4, _v_
);
770 /*fxMesa->Glide.grDrawTriangle( VERT(i-3), VERT(i-2), VERT(i) );*/
771 /*fxMesa->Glide.grDrawTriangle( VERT(i-2), VERT(i-1), VERT(i) );*/
776 static void tdfx_render_vb_quad_strip( GLcontext
*ctx
,
781 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
782 tdfxVertex
*fxVB
= fxMesa
->verts
;
787 count
-= (count
-start
)&1;
789 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP
,
790 count
-start
, fxVB
+ start
, sizeof(tdfxVertex
));
793 static void tdfx_render_vb_poly( GLcontext
*ctx
,
798 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
799 tdfxVertex
*fxVB
= fxMesa
->verts
;
804 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_POLYGON
, count
-start
,
805 fxVB
+ start
, sizeof(tdfxVertex
));
808 static void tdfx_render_vb_noop( GLcontext
*ctx
,
813 (void) (ctx
&& start
&& count
&& flags
);
816 static void (*tdfx_render_tab_verts
[GL_POLYGON
+2])(GLcontext
*,
821 tdfx_render_vb_points
,
822 tdfx_render_vb_lines
,
823 tdfx_render_vb_line_loop
,
824 tdfx_render_vb_line_strip
,
825 tdfx_render_vb_triangles
,
826 tdfx_render_vb_tri_strip
,
827 tdfx_render_vb_tri_fan
,
828 tdfx_render_vb_quads
,
829 tdfx_render_vb_quad_strip
,
836 /**********************************************************************/
837 /* Render whole (indexed) begin/end objects */
838 /**********************************************************************/
841 #define VERT(x) (tdfxVertex *)(vertptr + (x))
843 #define RENDER_POINTS( start, count ) \
844 for ( ; start < count ; start++) \
845 fxMesa->Glide.grDrawPoint( VERT(ELT(start)) );
847 #define RENDER_LINE( v0, v1 ) \
848 fxMesa->Glide.grDrawLine( VERT(v0), VERT(v1) )
850 #define RENDER_TRI( v0, v1, v2 ) \
851 fxMesa->Glide.grDrawTriangle( VERT(v0), VERT(v1), VERT(v2) )
853 #define RENDER_QUAD( v0, v1, v2, v3 ) \
855 tdfxVertex *_v_[4]; \
860 fxMesa->Glide.grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
861 /*fxMesa->Glide.grDrawTriangle( VERT(v0), VERT(v1), VERT(v3) );*/\
862 /*fxMesa->Glide.grDrawTriangle( VERT(v1), VERT(v2), VERT(v3) );*/\
865 #define INIT(x) tdfxRenderPrimitive( ctx, x )
869 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); \
870 tdfxVertex *vertptr = fxMesa->verts; \
871 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
874 #define RESET_STIPPLE
875 #define RESET_OCCLUSION
876 #define PRESERVE_VB_DEFS
878 /* Elts, no clipping.
882 #define TAG(x) tdfx_##x##_elts
883 #define ELT(x) elt[x]
884 #include "tnl_dd/t_dd_rendertmp.h"
886 /* Verts, no clipping.
890 #define TAG(x) tdfx_##x##_verts
892 /*#include "tnl_dd/t_dd_rendertmp.h"*/
896 /**********************************************************************/
897 /* Render clipped primitives */
898 /**********************************************************************/
902 static void tdfxRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
905 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
906 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
907 struct vertex_buffer
*VB
= &tnl
->vb
;
908 GLuint prim
= fxMesa
->render_primitive
;
910 /* Render the new vertices as an unclipped polygon.
913 GLuint
*tmp
= VB
->Elts
;
914 VB
->Elts
= (GLuint
*)elts
;
915 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
, PRIM_BEGIN
|PRIM_END
);
919 /* Restore the render primitive
921 if (prim
!= GL_POLYGON
)
922 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
925 static void tdfxRenderClippedLine( GLcontext
*ctx
, GLuint ii
, GLuint jj
)
927 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
928 tnl
->Driver
.Render
.Line( ctx
, ii
, jj
);
931 static void tdfxFastRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
935 tdfxContextPtr fxMesa
= TDFX_CONTEXT( ctx
);
936 tdfxVertex
*vertptr
= fxMesa
->verts
;
938 fxMesa
->Glide
.grDrawTriangle( VERT(elts
[0]), VERT(elts
[1]), VERT(elts
[2]) );
939 } else if (n
<= 32) {
940 tdfxVertex
*newvptr
[32];
941 for (i
= 0 ; i
< n
; i
++) {
942 newvptr
[i
] = VERT(elts
[i
]);
944 fxMesa
->Glide
.grDrawVertexArray(GR_TRIANGLE_FAN
, n
, newvptr
);
946 const tdfxVertex
*start
= VERT(elts
[0]);
947 for (i
= 2 ; i
< n
; i
++) {
948 fxMesa
->Glide
.grDrawTriangle( start
, VERT(elts
[i
-1]), VERT(elts
[i
]) );
953 /**********************************************************************/
954 /* Choose render functions */
955 /**********************************************************************/
958 #define POINT_FALLBACK (DD_POINT_SMOOTH)
959 #define LINE_FALLBACK (DD_LINE_STIPPLE)
960 #define TRI_FALLBACK (DD_TRI_SMOOTH)
961 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|DD_TRI_STIPPLE)
962 #define ANY_RASTER_FLAGS (DD_FLATSHADE|DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET| \
966 /* All state referenced below:
968 #define _TDFX_NEW_RENDERSTATE (_DD_NEW_POINT_SMOOTH | \
969 _DD_NEW_LINE_STIPPLE | \
970 _DD_NEW_TRI_SMOOTH | \
971 _DD_NEW_FLATSHADE | \
972 _DD_NEW_TRI_UNFILLED | \
973 _DD_NEW_TRI_LIGHT_TWOSIDE | \
974 _DD_NEW_TRI_OFFSET | \
975 _DD_NEW_TRI_STIPPLE | \
979 static void tdfxChooseRenderState(GLcontext
*ctx
)
981 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
982 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
983 GLuint flags
= ctx
->_TriangleCaps
;
987 fxMesa
->draw_point
= tdfx_draw_point
;
988 fxMesa
->draw_line
= tdfx_draw_line
;
989 fxMesa
->draw_triangle
= tdfx_draw_triangle
;
990 index
|= TDFX_FALLBACK_BIT
;
993 if (flags
& (ANY_FALLBACK_FLAGS
|ANY_RASTER_FLAGS
)) {
994 if (flags
& ANY_RASTER_FLAGS
) {
995 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= TDFX_TWOSIDE_BIT
;
996 if (flags
& DD_TRI_OFFSET
) index
|= TDFX_OFFSET_BIT
;
997 if (flags
& DD_TRI_UNFILLED
) index
|= TDFX_UNFILLED_BIT
;
998 if (flags
& DD_FLATSHADE
) index
|= TDFX_FLAT_BIT
;
1001 fxMesa
->draw_point
= tdfx_draw_point
;
1002 fxMesa
->draw_line
= tdfx_draw_line
;
1003 fxMesa
->draw_triangle
= tdfx_draw_triangle
;
1005 /* Hook in fallbacks for specific primitives.
1007 * DD_TRI_UNFILLED is here because the unfilled_tri functions use
1008 * fxMesa->draw_tri *always*, and thus can't use the multipass
1009 * approach to cliprects.
1012 if (flags
& (POINT_FALLBACK
|
1018 if (flags
& POINT_FALLBACK
)
1019 fxMesa
->draw_point
= tdfx_fallback_point
;
1021 if (flags
& LINE_FALLBACK
)
1022 fxMesa
->draw_line
= tdfx_fallback_line
;
1024 if (flags
& TRI_FALLBACK
)
1025 fxMesa
->draw_triangle
= tdfx_fallback_tri
;
1027 if ((flags
& DD_TRI_STIPPLE
) && !fxMesa
->haveHwStipple
)
1028 fxMesa
->draw_triangle
= tdfx_fallback_tri
;
1030 index
|= TDFX_FALLBACK_BIT
;
1034 if (fxMesa
->RenderIndex
!= index
) {
1035 fxMesa
->RenderIndex
= index
;
1037 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
1038 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
1039 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
1040 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
1043 tnl
->Driver
.Render
.PrimTabVerts
= tdfx_render_tab_verts
;
1044 tnl
->Driver
.Render
.PrimTabElts
= tdfx_render_tab_elts
;
1045 tnl
->Driver
.Render
.ClippedLine
= line
; /* from tritmp.h */
1046 tnl
->Driver
.Render
.ClippedPolygon
= tdfxFastRenderClippedPoly
;
1048 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1049 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1050 tnl
->Driver
.Render
.ClippedLine
= tdfxRenderClippedLine
;
1051 tnl
->Driver
.Render
.ClippedPolygon
= tdfxRenderClippedPoly
;
1056 /**********************************************************************/
1057 /* Use multipass rendering for cliprects */
1058 /**********************************************************************/
1062 /* TODO: Benchmark this.
1063 * TODO: Use single back-buffer cliprect where possible.
1064 * NOTE: <pass> starts at 1, not zero!
1066 static GLboolean
multipass_cliprect( GLcontext
*ctx
, GLuint pass
)
1068 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1069 if (pass
>= fxMesa
->numClipRects
)
1072 fxMesa
->Glide
.grClipWindow(fxMesa
->pClipRects
[pass
].x1
,
1073 fxMesa
->screen_height
- fxMesa
->pClipRects
[pass
].y2
,
1074 fxMesa
->pClipRects
[pass
].x2
,
1075 fxMesa
->screen_height
- fxMesa
->pClipRects
[pass
].y1
);
1082 /**********************************************************************/
1083 /* Runtime render state and callbacks */
1084 /**********************************************************************/
1086 static void tdfxRunPipeline( GLcontext
*ctx
)
1088 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1090 if (fxMesa
->new_state
) {
1091 tdfxDDUpdateHwState( ctx
);
1094 if (!fxMesa
->Fallback
&& fxMesa
->new_gl_state
) {
1095 if (fxMesa
->new_gl_state
& _TDFX_NEW_RASTERSETUP
)
1096 tdfxChooseVertexState( ctx
);
1098 if (fxMesa
->new_gl_state
& _TDFX_NEW_RENDERSTATE
)
1099 tdfxChooseRenderState( ctx
);
1101 fxMesa
->new_gl_state
= 0;
1104 _tnl_run_pipeline( ctx
);
1108 static void tdfxRenderStart( GLcontext
*ctx
)
1110 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1111 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1113 tdfxCheckTexSizes( ctx
);
1115 LOCK_HARDWARE(fxMesa
);
1117 /* Make sure vertex format changes get uploaded before we start
1118 * sending triangles.
1120 if (fxMesa
->dirty
) {
1121 tdfxEmitHwStateLocked( fxMesa
);
1124 if (fxMesa
->numClipRects
&& !(fxMesa
->RenderIndex
& TDFX_FALLBACK_BIT
)) {
1125 fxMesa
->Glide
.grClipWindow(fxMesa
->pClipRects
[0].x1
,
1126 fxMesa
->screen_height
- fxMesa
->pClipRects
[0].y2
,
1127 fxMesa
->pClipRects
[0].x2
,
1128 fxMesa
->screen_height
- fxMesa
->pClipRects
[0].y1
);
1129 if (fxMesa
->numClipRects
> 1)
1130 tnl
->Driver
.Render
.Multipass
= multipass_cliprect
;
1132 tnl
->Driver
.Render
.Multipass
= NULL
;
1135 tnl
->Driver
.Render
.Multipass
= NULL
;
1140 /* Always called between RenderStart and RenderFinish --> We already
1143 static void tdfxRasterPrimitive( GLcontext
*ctx
, GLenum prim
)
1145 tdfxContextPtr fxMesa
= TDFX_CONTEXT( ctx
);
1147 FLUSH_BATCH( fxMesa
);
1149 fxMesa
->raster_primitive
= prim
;
1151 tdfxUpdateCull(ctx
);
1152 if ( fxMesa
->dirty
& TDFX_UPLOAD_CULL
) {
1153 fxMesa
->Glide
.grCullMode( fxMesa
->CullMode
);
1154 fxMesa
->dirty
&= ~TDFX_UPLOAD_CULL
;
1157 tdfxUpdateStipple(ctx
);
1158 if ( fxMesa
->dirty
& TDFX_UPLOAD_STIPPLE
) {
1159 fxMesa
->Glide
.grStipplePattern ( fxMesa
->Stipple
.Pattern
);
1160 fxMesa
->Glide
.grStippleMode ( fxMesa
->Stipple
.Mode
);
1161 fxMesa
->dirty
&= ~TDFX_UPLOAD_STIPPLE
;
1167 /* Determine the rasterized primitive when not drawing unfilled
1170 * Used only for the default render stage which always decomposes
1171 * primitives to trianges/lines/points. For the accelerated stage,
1172 * which renders strips as strips, the equivalent calculations are
1173 * performed in tdfx_render.c.
1175 static void tdfxRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
1177 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1178 GLuint rprim
= reduced_prim
[prim
];
1180 fxMesa
->render_primitive
= prim
;
1182 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
1185 if (fxMesa
->raster_primitive
!= rprim
) {
1186 tdfxRasterPrimitive( ctx
, rprim
);
1190 static void tdfxRenderFinish( GLcontext
*ctx
)
1192 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1194 if (fxMesa
->RenderIndex
& TDFX_FALLBACK_BIT
)
1195 _swrast_flush( ctx
);
1197 UNLOCK_HARDWARE(fxMesa
);
1201 /**********************************************************************/
1202 /* Manage total rasterization fallbacks */
1203 /**********************************************************************/
1205 static char *fallbackStrings
[] = {
1206 "3D/Rect/Cube Texture map",
1207 "glDrawBuffer(GL_FRONT_AND_BACK)",
1208 "Separate specular color",
1209 "glEnable/Disable(GL_STENCIL_TEST)",
1210 "glRenderMode(selection or feedback)",
1217 "Rasterization disable"
1221 static char *getFallbackString(GLuint bit
)
1228 return fallbackStrings
[i
];
1232 void tdfxFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
1234 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1235 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1236 GLuint oldfallback
= fxMesa
->Fallback
;
1239 fxMesa
->Fallback
|= bit
;
1240 if (oldfallback
== 0) {
1241 /*printf("Go to software rendering, bit = 0x%x\n", bit);*/
1242 FLUSH_BATCH(fxMesa
);
1243 _swsetup_Wakeup( ctx
);
1244 fxMesa
->RenderIndex
= ~0;
1245 if (TDFX_DEBUG
& DEBUG_VERBOSE_FALL
) {
1246 fprintf(stderr
, "Tdfx begin software fallback: 0x%x %s\n",
1247 bit
, getFallbackString(bit
));
1252 fxMesa
->Fallback
&= ~bit
;
1253 if (oldfallback
== bit
) {
1254 /*printf("Go to hardware rendering, bit = 0x%x\n", bit);*/
1255 _swrast_flush( ctx
);
1256 tnl
->Driver
.Render
.Start
= tdfxRenderStart
;
1257 tnl
->Driver
.Render
.PrimitiveNotify
= tdfxRenderPrimitive
;
1258 tnl
->Driver
.Render
.Finish
= tdfxRenderFinish
;
1259 tnl
->Driver
.Render
.BuildVertices
= tdfxBuildVertices
;
1260 fxMesa
->new_gl_state
|= (_TDFX_NEW_RENDERSTATE
|
1261 _TDFX_NEW_RASTERSETUP
);
1262 if (TDFX_DEBUG
& DEBUG_VERBOSE_FALL
) {
1263 fprintf(stderr
, "Tdfx end software fallback: 0x%x %s\n",
1264 bit
, getFallbackString(bit
));
1271 void tdfxDDInitTriFuncs( GLcontext
*ctx
)
1273 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1274 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1275 static int firsttime
= 1;
1282 fxMesa
->RenderIndex
= ~0;
1284 tnl
->Driver
.RunPipeline
= tdfxRunPipeline
;
1285 tnl
->Driver
.Render
.Start
= tdfxRenderStart
;
1286 tnl
->Driver
.Render
.Finish
= tdfxRenderFinish
;
1287 tnl
->Driver
.Render
.PrimitiveNotify
= tdfxRenderPrimitive
;
1288 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1289 tnl
->Driver
.Render
.BuildVertices
= tdfxBuildVertices
;
1290 tnl
->Driver
.Render
.Multipass
= NULL
;
1292 (void) tdfx_print_vertex
;