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
28 * Daniel Borca <dborca@users.sourceforge.net>, 19 Jul 2004
31 * Keith Whitwell <keith@tungstengraphics.com>
34 #include "main/glheader.h"
35 #include "main/mtypes.h"
36 #include "main/macros.h"
37 #include "main/colormac.h"
39 #include "swrast/swrast.h"
40 #include "swrast_setup/swrast_setup.h"
41 #include "swrast_setup/ss_context.h"
42 #include "tnl/t_context.h"
43 #include "tnl/t_pipeline.h"
45 #include "tdfx_tris.h"
46 #include "tdfx_state.h"
48 #include "tdfx_lock.h"
49 #include "tdfx_render.h"
52 static void tdfxRasterPrimitive( GLcontext
*ctx
, GLenum prim
);
53 static void tdfxRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
55 static GLenum reduced_prim
[GL_POLYGON
+1] = {
68 /***********************************************************************
69 * Macros for t_dd_tritmp.h to draw basic primitives *
70 ***********************************************************************/
72 #define TRI( a, b, c ) \
75 fxMesa->draw_triangle( fxMesa, a, b, c ); \
77 fxMesa->Glide.grDrawTriangle( a, b, c ); \
80 #define QUAD( a, b, c, d ) \
83 fxMesa->draw_triangle( fxMesa, a, b, d ); \
84 fxMesa->draw_triangle( fxMesa, b, c, d ); \
91 fxMesa->Glide.grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
92 /*fxMesa->Glide.grDrawTriangle( a, b, d );*/\
93 /*fxMesa->Glide.grDrawTriangle( b, c, d );*/\
97 #define LINE( v0, v1 ) \
100 fxMesa->draw_line( fxMesa, v0, v1 ); \
102 v0->x += LINE_X_OFFSET - TRI_X_OFFSET; \
103 v0->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
104 v1->x += LINE_X_OFFSET - TRI_X_OFFSET; \
105 v1->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
106 fxMesa->Glide.grDrawLine( v0, v1 ); \
107 v0->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
108 v0->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
109 v1->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
110 v1->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
114 #define POINT( v0 ) \
117 fxMesa->draw_point( fxMesa, v0 ); \
119 v0->x += PNT_X_OFFSET - TRI_X_OFFSET; \
120 v0->y += PNT_Y_OFFSET - TRI_Y_OFFSET; \
121 fxMesa->Glide.grDrawPoint( v0 ); \
122 v0->x -= PNT_X_OFFSET - TRI_X_OFFSET; \
123 v0->y -= PNT_Y_OFFSET - TRI_Y_OFFSET; \
128 /***********************************************************************
129 * Fallback to swrast for basic primitives *
130 ***********************************************************************/
132 /* Build an SWvertex from a hardware vertex.
134 * This code is hit only when a mix of accelerated and unaccelerated
135 * primitives are being drawn, and only for the unaccelerated
139 tdfx_translate_vertex( GLcontext
*ctx
, const tdfxVertex
*src
, SWvertex
*dst
)
141 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
143 if (fxMesa
->vertexFormat
== TDFX_LAYOUT_TINY
) {
144 dst
->attrib
[FRAG_ATTRIB_WPOS
][0] = src
->x
- fxMesa
->x_offset
;
145 dst
->attrib
[FRAG_ATTRIB_WPOS
][1] = src
->y
- (fxMesa
->screen_height
- fxMesa
->height
- fxMesa
->y_offset
);
146 dst
->attrib
[FRAG_ATTRIB_WPOS
][2] = src
->z
;
147 dst
->attrib
[FRAG_ATTRIB_WPOS
][3] = 1.0;
149 dst
->color
[0] = src
->color
[2];
150 dst
->color
[1] = src
->color
[1];
151 dst
->color
[2] = src
->color
[0];
152 dst
->color
[3] = src
->color
[3];
155 GLfloat w
= 1.0 / src
->rhw
;
157 dst
->attrib
[FRAG_ATTRIB_WPOS
][0] = src
->x
- fxMesa
->x_offset
;
158 dst
->attrib
[FRAG_ATTRIB_WPOS
][1] = src
->y
- (fxMesa
->screen_height
- fxMesa
->height
- fxMesa
->y_offset
);
159 dst
->attrib
[FRAG_ATTRIB_WPOS
][2] = src
->z
;
160 dst
->attrib
[FRAG_ATTRIB_WPOS
][3] = src
->rhw
;
162 dst
->color
[0] = src
->color
[2];
163 dst
->color
[1] = src
->color
[1];
164 dst
->color
[2] = src
->color
[0];
165 dst
->color
[3] = src
->color
[3];
167 dst
->attrib
[FRAG_ATTRIB_TEX0
][0] = 1.0 / fxMesa
->sScale0
* w
* src
->tu0
;
168 dst
->attrib
[FRAG_ATTRIB_TEX0
][1] = 1.0 / fxMesa
->tScale0
* w
* src
->tv0
;
169 if (fxMesa
->vertexFormat
== TDFX_LAYOUT_PROJ1
|| fxMesa
->vertexFormat
== TDFX_LAYOUT_PROJ2
) {
170 dst
->attrib
[FRAG_ATTRIB_TEX0
][3] = w
* src
->tq0
;
172 dst
->attrib
[FRAG_ATTRIB_TEX0
][3] = 1.0;
175 if (fxMesa
->SetupIndex
& TDFX_TEX1_BIT
) {
176 dst
->attrib
[FRAG_ATTRIB_TEX1
][0] = 1.0 / fxMesa
->sScale1
* w
* src
->tu1
;
177 dst
->attrib
[FRAG_ATTRIB_TEX1
][1] = 1.0 / fxMesa
->tScale1
* w
* src
->tv1
;
178 if (fxMesa
->vertexFormat
== TDFX_LAYOUT_PROJ2
) {
179 dst
->attrib
[FRAG_ATTRIB_TEX1
][3] = w
* src
->tq1
;
181 dst
->attrib
[FRAG_ATTRIB_TEX1
][3] = 1.0;
186 dst
->pointSize
= ctx
->Point
.Size
;
191 tdfx_fallback_tri( tdfxContextPtr fxMesa
,
196 GLcontext
*ctx
= fxMesa
->glCtx
;
198 tdfx_translate_vertex( ctx
, v0
, &v
[0] );
199 tdfx_translate_vertex( ctx
, v1
, &v
[1] );
200 tdfx_translate_vertex( ctx
, v2
, &v
[2] );
201 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
206 tdfx_fallback_line( tdfxContextPtr fxMesa
,
210 GLcontext
*ctx
= fxMesa
->glCtx
;
212 tdfx_translate_vertex( ctx
, v0
, &v
[0] );
213 tdfx_translate_vertex( ctx
, v1
, &v
[1] );
214 _swrast_Line( ctx
, &v
[0], &v
[1] );
219 tdfx_fallback_point( tdfxContextPtr fxMesa
,
222 GLcontext
*ctx
= fxMesa
->glCtx
;
224 tdfx_translate_vertex( ctx
, v0
, &v
[0] );
225 _swrast_Point( ctx
, &v
[0] );
228 /***********************************************************************
229 * Functions to draw basic primitives *
230 ***********************************************************************/
232 static void tdfx_print_vertex( GLcontext
*ctx
, const tdfxVertex
*v
)
234 tdfxContextPtr tmesa
= TDFX_CONTEXT( ctx
);
236 fprintf(stderr
, "vertex at %p\n", (void *)v
);
238 if (tmesa
->vertexFormat
== TDFX_LAYOUT_TINY
) {
239 fprintf(stderr
, "x %f y %f z %f\n", v
->x
, v
->y
, v
->z
);
242 fprintf(stderr
, "x %f y %f z %f oow %f\n",
243 v
->x
, v
->y
, v
->z
, v
->rhw
);
245 fprintf(stderr
, "r %d g %d b %d a %d\n",
251 fprintf(stderr
, "\n");
254 #define DO_FALLBACK 0
256 /* Need to do clip loop at each triangle when mixing swrast and hw
257 * rendering. These functions are only used when mixed-mode rendering
260 static void tdfx_draw_triangle( tdfxContextPtr fxMesa
,
265 /* fprintf(stderr, "%s\n", __FUNCTION__); */
266 /* tdfx_print_vertex( fxMesa->glCtx, v0 ); */
267 /* tdfx_print_vertex( fxMesa->glCtx, v1 ); */
268 /* tdfx_print_vertex( fxMesa->glCtx, v2 ); */
269 BEGIN_CLIP_LOOP_LOCKED(fxMesa
) {
271 } END_CLIP_LOOP_LOCKED(fxMesa
);
274 static void tdfx_draw_line( tdfxContextPtr fxMesa
,
278 /* No support for wide lines (avoid wide/aa line fallback).
280 BEGIN_CLIP_LOOP_LOCKED(fxMesa
) {
282 } END_CLIP_LOOP_LOCKED(fxMesa
);
285 static void tdfx_draw_point( tdfxContextPtr fxMesa
,
288 /* No support for wide points.
290 BEGIN_CLIP_LOOP_LOCKED(fxMesa
) {
292 } END_CLIP_LOOP_LOCKED(fxMesa
);
298 #define TDFX_UNFILLED_BIT 0x1
299 #define TDFX_OFFSET_BIT 0x2
300 #define TDFX_TWOSIDE_BIT 0x4
301 #define TDFX_FLAT_BIT 0x8
302 #define TDFX_FALLBACK_BIT 0x10
303 #define TDFX_MAX_TRIFUNC 0x20
306 tnl_points_func points
;
308 tnl_triangle_func triangle
;
310 } rast_tab
[TDFX_MAX_TRIFUNC
];
312 #define DO_FALLBACK (IND & TDFX_FALLBACK_BIT)
313 #define DO_OFFSET (IND & TDFX_OFFSET_BIT)
314 #define DO_UNFILLED (IND & TDFX_UNFILLED_BIT)
315 #define DO_TWOSIDE (IND & TDFX_TWOSIDE_BIT)
316 #define DO_FLAT (IND & TDFX_FLAT_BIT)
321 #define DO_FULL_QUAD 1
325 #define HAVE_HW_FLATSHADE 0
326 #define HAVE_BACK_COLORS 0
327 #define VERTEX tdfxVertex
330 #define DEPTH_SCALE 1.0
331 #define UNFILLED_TRI unfilled_tri
332 #define UNFILLED_QUAD unfilled_quad
333 #define VERT_X(_v) _v->x
334 #define VERT_Y(_v) _v->y
335 #define VERT_Z(_v) _v->z
336 #define AREA_IS_CCW( a ) (a < 0)
337 #define GET_VERTEX(e) (fxMesa->verts + (e))
339 #define VERT_SET_RGBA( dst, f ) \
341 UNCLAMPED_FLOAT_TO_UBYTE(dst->color[2], f[0]);\
342 UNCLAMPED_FLOAT_TO_UBYTE(dst->color[1], f[1]);\
343 UNCLAMPED_FLOAT_TO_UBYTE(dst->color[0], f[2]);\
344 UNCLAMPED_FLOAT_TO_UBYTE(dst->color[3], f[3]);\
347 #define VERT_COPY_RGBA( v0, v1 ) \
348 *(GLuint *)&v0->color = *(GLuint *)&v1->color
350 #define VERT_SAVE_RGBA( idx ) \
351 *(GLuint *)&color[idx] = *(GLuint *)&v[idx]->color
353 #define VERT_RESTORE_RGBA( idx ) \
354 *(GLuint *)&v[idx]->color = *(GLuint *)&color[idx]
356 #define LOCAL_VARS(n) \
357 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); \
358 GLubyte color[n][4]; \
363 /***********************************************************************
364 * Functions to draw basic unfilled primitives *
365 ***********************************************************************/
367 #define RASTERIZE(x) if (fxMesa->raster_primitive != reduced_prim[x]) \
368 tdfxRasterPrimitive( ctx, reduced_prim[x] )
369 #define RENDER_PRIMITIVE fxMesa->render_primitive
370 #define IND TDFX_FALLBACK_BIT
372 #include "tnl_dd/t_dd_unfilled.h"
375 /***********************************************************************
376 * Functions to draw GL primitives *
377 ***********************************************************************/
381 #include "tnl_dd/t_dd_tritmp.h"
383 #define IND (TDFX_OFFSET_BIT)
384 #define TAG(x) x##_offset
385 #include "tnl_dd/t_dd_tritmp.h"
387 #define IND (TDFX_TWOSIDE_BIT)
388 #define TAG(x) x##_twoside
389 #include "tnl_dd/t_dd_tritmp.h"
391 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT)
392 #define TAG(x) x##_twoside_offset
393 #include "tnl_dd/t_dd_tritmp.h"
395 #define IND (TDFX_UNFILLED_BIT)
396 #define TAG(x) x##_unfilled
397 #include "tnl_dd/t_dd_tritmp.h"
399 #define IND (TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT)
400 #define TAG(x) x##_offset_unfilled
401 #include "tnl_dd/t_dd_tritmp.h"
403 #define IND (TDFX_TWOSIDE_BIT|TDFX_UNFILLED_BIT)
404 #define TAG(x) x##_twoside_unfilled
405 #include "tnl_dd/t_dd_tritmp.h"
407 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT)
408 #define TAG(x) x##_twoside_offset_unfilled
409 #include "tnl_dd/t_dd_tritmp.h"
411 #define IND (TDFX_FALLBACK_BIT)
412 #define TAG(x) x##_fallback
413 #include "tnl_dd/t_dd_tritmp.h"
415 #define IND (TDFX_OFFSET_BIT|TDFX_FALLBACK_BIT)
416 #define TAG(x) x##_offset_fallback
417 #include "tnl_dd/t_dd_tritmp.h"
419 #define IND (TDFX_TWOSIDE_BIT|TDFX_FALLBACK_BIT)
420 #define TAG(x) x##_twoside_fallback
421 #include "tnl_dd/t_dd_tritmp.h"
423 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_FALLBACK_BIT)
424 #define TAG(x) x##_twoside_offset_fallback
425 #include "tnl_dd/t_dd_tritmp.h"
427 #define IND (TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT)
428 #define TAG(x) x##_unfilled_fallback
429 #include "tnl_dd/t_dd_tritmp.h"
431 #define IND (TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT)
432 #define TAG(x) x##_offset_unfilled_fallback
433 #include "tnl_dd/t_dd_tritmp.h"
435 #define IND (TDFX_TWOSIDE_BIT|TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT)
436 #define TAG(x) x##_twoside_unfilled_fallback
437 #include "tnl_dd/t_dd_tritmp.h"
439 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT| \
441 #define TAG(x) x##_twoside_offset_unfilled_fallback
442 #include "tnl_dd/t_dd_tritmp.h"
445 /* Tdfx doesn't support provoking-vertex flat-shading?
447 #define IND (TDFX_FLAT_BIT)
448 #define TAG(x) x##_flat
449 #include "tnl_dd/t_dd_tritmp.h"
451 #define IND (TDFX_OFFSET_BIT|TDFX_FLAT_BIT)
452 #define TAG(x) x##_offset_flat
453 #include "tnl_dd/t_dd_tritmp.h"
455 #define IND (TDFX_TWOSIDE_BIT|TDFX_FLAT_BIT)
456 #define TAG(x) x##_twoside_flat
457 #include "tnl_dd/t_dd_tritmp.h"
459 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_FLAT_BIT)
460 #define TAG(x) x##_twoside_offset_flat
461 #include "tnl_dd/t_dd_tritmp.h"
463 #define IND (TDFX_UNFILLED_BIT|TDFX_FLAT_BIT)
464 #define TAG(x) x##_unfilled_flat
465 #include "tnl_dd/t_dd_tritmp.h"
467 #define IND (TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT|TDFX_FLAT_BIT)
468 #define TAG(x) x##_offset_unfilled_flat
469 #include "tnl_dd/t_dd_tritmp.h"
471 #define IND (TDFX_TWOSIDE_BIT|TDFX_UNFILLED_BIT|TDFX_FLAT_BIT)
472 #define TAG(x) x##_twoside_unfilled_flat
473 #include "tnl_dd/t_dd_tritmp.h"
475 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT|TDFX_FLAT_BIT)
476 #define TAG(x) x##_twoside_offset_unfilled_flat
477 #include "tnl_dd/t_dd_tritmp.h"
479 #define IND (TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
480 #define TAG(x) x##_fallback_flat
481 #include "tnl_dd/t_dd_tritmp.h"
483 #define IND (TDFX_OFFSET_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
484 #define TAG(x) x##_offset_fallback_flat
485 #include "tnl_dd/t_dd_tritmp.h"
487 #define IND (TDFX_TWOSIDE_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
488 #define TAG(x) x##_twoside_fallback_flat
489 #include "tnl_dd/t_dd_tritmp.h"
491 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
492 #define TAG(x) x##_twoside_offset_fallback_flat
493 #include "tnl_dd/t_dd_tritmp.h"
495 #define IND (TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
496 #define TAG(x) x##_unfilled_fallback_flat
497 #include "tnl_dd/t_dd_tritmp.h"
499 #define IND (TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
500 #define TAG(x) x##_offset_unfilled_fallback_flat
501 #include "tnl_dd/t_dd_tritmp.h"
503 #define IND (TDFX_TWOSIDE_BIT|TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
504 #define TAG(x) x##_twoside_unfilled_fallback_flat
505 #include "tnl_dd/t_dd_tritmp.h"
507 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT| \
508 TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
509 #define TAG(x) x##_twoside_offset_unfilled_fallback_flat
510 #include "tnl_dd/t_dd_tritmp.h"
513 static void init_rast_tab( void )
518 init_twoside_offset();
520 init_offset_unfilled();
521 init_twoside_unfilled();
522 init_twoside_offset_unfilled();
524 init_offset_fallback();
525 init_twoside_fallback();
526 init_twoside_offset_fallback();
527 init_unfilled_fallback();
528 init_offset_unfilled_fallback();
529 init_twoside_unfilled_fallback();
530 init_twoside_offset_unfilled_fallback();
535 init_twoside_offset_flat();
536 init_unfilled_flat();
537 init_offset_unfilled_flat();
538 init_twoside_unfilled_flat();
539 init_twoside_offset_unfilled_flat();
540 init_fallback_flat();
541 init_offset_fallback_flat();
542 init_twoside_fallback_flat();
543 init_twoside_offset_fallback_flat();
544 init_unfilled_fallback_flat();
545 init_offset_unfilled_fallback_flat();
546 init_twoside_unfilled_fallback_flat();
547 init_twoside_offset_unfilled_fallback_flat();
551 /**********************************************************************/
552 /* Render whole begin/end objects */
553 /**********************************************************************/
556 /* Accelerate vertex buffer rendering when renderindex == 0 and
557 * there is no clipping.
559 #define INIT(x) tdfxRenderPrimitive( ctx, x )
561 static void tdfx_render_vb_points( GLcontext
*ctx
,
566 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
567 tdfxVertex
*fxVB
= fxMesa
->verts
;
573 /* Adjust point coords */
574 for (i
= start
; i
< count
; i
++) {
575 fxVB
[i
].x
+= PNT_X_OFFSET
- TRI_X_OFFSET
;
576 fxVB
[i
].y
+= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
579 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_POINTS
, count
-start
,
580 fxVB
+ start
, sizeof(tdfxVertex
));
581 /* restore point coords */
582 for (i
= start
; i
< count
; i
++) {
583 fxVB
[i
].x
-= PNT_X_OFFSET
- TRI_X_OFFSET
;
584 fxVB
[i
].y
-= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
588 static void tdfx_render_vb_line_strip( GLcontext
*ctx
,
593 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
594 tdfxVertex
*fxVB
= fxMesa
->verts
;
600 /* adjust line coords */
601 for (i
= start
; i
< count
; i
++) {
602 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
603 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
606 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-start
,
607 fxVB
+ start
, sizeof(tdfxVertex
) );
609 /* restore line coords */
610 for (i
= start
; i
< count
; i
++) {
611 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
612 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
616 static void tdfx_render_vb_line_loop( GLcontext
*ctx
,
621 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
622 tdfxVertex
*fxVB
= fxMesa
->verts
;
629 if (!(flags
& PRIM_BEGIN
)) {
633 /* adjust line coords */
634 for (i
= start
; i
< count
; i
++) {
635 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
636 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
639 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-j
,
640 fxVB
+ j
, sizeof(tdfxVertex
));
642 if (flags
& PRIM_END
)
643 fxMesa
->Glide
.grDrawLine( fxVB
+ (count
- 1),
646 /* restore line coords */
647 for (i
= start
; i
< count
; i
++) {
648 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
649 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
653 static void tdfx_render_vb_lines( GLcontext
*ctx
,
658 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
659 tdfxVertex
*fxVB
= fxMesa
->verts
;
665 /* adjust line coords */
666 for (i
= start
; i
< count
; i
++) {
667 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
668 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
671 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_LINES
, count
-start
,
672 fxVB
+ start
, sizeof(tdfxVertex
));
674 /* restore line coords */
675 for (i
= start
; i
< count
; i
++) {
676 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
677 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
681 static void tdfx_render_vb_triangles( GLcontext
*ctx
,
686 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
687 tdfxVertex
*fxVB
= fxMesa
->verts
;
694 * apparently, this causes troubles with some programs (GLExcess);
695 * might be a bug in Glide... However, "grDrawVertexArrayContiguous"
696 * eventually calls "grDrawTriangle" for GR_TRIANGLES, so we're better
697 * off doing it by hand...
699 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_TRIANGLES
, count
-start
,
700 fxVB
+ start
, sizeof(tdfxVertex
));
704 for (j
=start
+2; j
<count
; j
+=3) {
705 fxMesa
->Glide
.grDrawTriangle(fxVB
+ (j
-2), fxVB
+ (j
-1), fxVB
+ j
);
712 static void tdfx_render_vb_tri_strip( GLcontext
*ctx
,
717 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
718 tdfxVertex
*fxVB
= fxMesa
->verts
;
722 INIT(GL_TRIANGLE_STRIP
);
724 /* fprintf(stderr, "%s/%d\n", __FUNCTION__, 1<<shift); */
725 /* if(!prevLockLine) abort(); */
727 mode
= GR_TRIANGLE_STRIP
;
729 fxMesa
->Glide
.grDrawVertexArrayContiguous( mode
, count
-start
,
730 fxVB
+ start
, sizeof(tdfxVertex
));
734 static void tdfx_render_vb_tri_fan( GLcontext
*ctx
,
739 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
740 tdfxVertex
*fxVB
= fxMesa
->verts
;
743 INIT(GL_TRIANGLE_FAN
);
745 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_TRIANGLE_FAN
, count
-start
,
746 fxVB
+ start
, sizeof(tdfxVertex
) );
749 static void tdfx_render_vb_quads( GLcontext
*ctx
,
754 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
755 tdfxVertex
*fxVB
= fxMesa
->verts
;
761 for (i
= start
+ 3 ; i
< count
; i
+= 4 ) {
762 #define VERT(x) (fxVB + (x))
768 fxMesa
->Glide
.grDrawVertexArray(GR_TRIANGLE_FAN
, 4, _v_
);
769 /*fxMesa->Glide.grDrawTriangle( VERT(i-3), VERT(i-2), VERT(i) );*/
770 /*fxMesa->Glide.grDrawTriangle( VERT(i-2), VERT(i-1), VERT(i) );*/
775 static void tdfx_render_vb_quad_strip( GLcontext
*ctx
,
780 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
781 tdfxVertex
*fxVB
= fxMesa
->verts
;
786 count
-= (count
-start
)&1;
788 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP
,
789 count
-start
, fxVB
+ start
, sizeof(tdfxVertex
));
792 static void tdfx_render_vb_poly( GLcontext
*ctx
,
797 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
798 tdfxVertex
*fxVB
= fxMesa
->verts
;
803 fxMesa
->Glide
.grDrawVertexArrayContiguous( GR_POLYGON
, count
-start
,
804 fxVB
+ start
, sizeof(tdfxVertex
));
807 static void tdfx_render_vb_noop( GLcontext
*ctx
,
812 (void) (ctx
&& start
&& count
&& flags
);
815 static void (*tdfx_render_tab_verts
[GL_POLYGON
+2])(GLcontext
*,
820 tdfx_render_vb_points
,
821 tdfx_render_vb_lines
,
822 tdfx_render_vb_line_loop
,
823 tdfx_render_vb_line_strip
,
824 tdfx_render_vb_triangles
,
825 tdfx_render_vb_tri_strip
,
826 tdfx_render_vb_tri_fan
,
827 tdfx_render_vb_quads
,
828 tdfx_render_vb_quad_strip
,
835 /**********************************************************************/
836 /* Render whole (indexed) begin/end objects */
837 /**********************************************************************/
840 #define VERT(x) (tdfxVertex *)(vertptr + (x))
842 #define RENDER_POINTS( start, count ) \
843 for ( ; start < count ; start++) \
844 fxMesa->Glide.grDrawPoint( VERT(ELT(start)) );
846 #define RENDER_LINE( v0, v1 ) \
847 fxMesa->Glide.grDrawLine( VERT(v0), VERT(v1) )
849 #define RENDER_TRI( v0, v1, v2 ) \
850 fxMesa->Glide.grDrawTriangle( VERT(v0), VERT(v1), VERT(v2) )
852 #define RENDER_QUAD( v0, v1, v2, v3 ) \
854 tdfxVertex *_v_[4]; \
859 fxMesa->Glide.grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
860 /*fxMesa->Glide.grDrawTriangle( VERT(v0), VERT(v1), VERT(v3) );*/\
861 /*fxMesa->Glide.grDrawTriangle( VERT(v1), VERT(v2), VERT(v3) );*/\
864 #define INIT(x) tdfxRenderPrimitive( ctx, x )
868 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); \
869 tdfxVertex *vertptr = fxMesa->verts; \
870 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
873 #define RESET_STIPPLE
874 #define RESET_OCCLUSION
875 #define PRESERVE_VB_DEFS
877 /* Elts, no clipping.
881 #define TAG(x) tdfx_##x##_elts
882 #define ELT(x) elt[x]
883 #include "tnl_dd/t_dd_rendertmp.h"
885 /* Verts, no clipping.
889 #define TAG(x) tdfx_##x##_verts
891 /*#include "tnl_dd/t_dd_rendertmp.h"*/
895 /**********************************************************************/
896 /* Render clipped primitives */
897 /**********************************************************************/
901 static void tdfxRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
904 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
905 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
906 struct vertex_buffer
*VB
= &tnl
->vb
;
907 GLuint prim
= fxMesa
->render_primitive
;
909 /* Render the new vertices as an unclipped polygon.
912 GLuint
*tmp
= VB
->Elts
;
913 VB
->Elts
= (GLuint
*)elts
;
914 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
, PRIM_BEGIN
|PRIM_END
);
918 /* Restore the render primitive
920 if (prim
!= GL_POLYGON
)
921 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
924 static void tdfxRenderClippedLine( GLcontext
*ctx
, GLuint ii
, GLuint jj
)
926 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
927 tnl
->Driver
.Render
.Line( ctx
, ii
, jj
);
930 static void tdfxFastRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
934 tdfxContextPtr fxMesa
= TDFX_CONTEXT( ctx
);
935 tdfxVertex
*vertptr
= fxMesa
->verts
;
937 fxMesa
->Glide
.grDrawTriangle( VERT(elts
[0]), VERT(elts
[1]), VERT(elts
[2]) );
938 } else if (n
<= 32) {
939 tdfxVertex
*newvptr
[32];
940 for (i
= 0 ; i
< n
; i
++) {
941 newvptr
[i
] = VERT(elts
[i
]);
943 fxMesa
->Glide
.grDrawVertexArray(GR_TRIANGLE_FAN
, n
, newvptr
);
945 const tdfxVertex
*start
= VERT(elts
[0]);
946 for (i
= 2 ; i
< n
; i
++) {
947 fxMesa
->Glide
.grDrawTriangle( start
, VERT(elts
[i
-1]), VERT(elts
[i
]) );
952 /**********************************************************************/
953 /* Choose render functions */
954 /**********************************************************************/
957 #define POINT_FALLBACK (DD_POINT_SMOOTH)
958 #define LINE_FALLBACK (DD_LINE_STIPPLE)
959 #define TRI_FALLBACK (DD_TRI_SMOOTH)
960 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|DD_TRI_STIPPLE)
961 #define ANY_RASTER_FLAGS (DD_FLATSHADE|DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET| \
965 /* All state referenced below:
967 #define _TDFX_NEW_RENDERSTATE (_DD_NEW_POINT_SMOOTH | \
968 _DD_NEW_LINE_STIPPLE | \
969 _DD_NEW_TRI_SMOOTH | \
970 _DD_NEW_FLATSHADE | \
971 _DD_NEW_TRI_UNFILLED | \
972 _DD_NEW_TRI_LIGHT_TWOSIDE | \
973 _DD_NEW_TRI_OFFSET | \
974 _DD_NEW_TRI_STIPPLE | \
978 static void tdfxChooseRenderState(GLcontext
*ctx
)
980 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
981 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
982 GLuint flags
= ctx
->_TriangleCaps
;
986 fxMesa
->draw_point
= tdfx_draw_point
;
987 fxMesa
->draw_line
= tdfx_draw_line
;
988 fxMesa
->draw_triangle
= tdfx_draw_triangle
;
989 index
|= TDFX_FALLBACK_BIT
;
992 if (flags
& (ANY_FALLBACK_FLAGS
|ANY_RASTER_FLAGS
)) {
993 if (flags
& ANY_RASTER_FLAGS
) {
994 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= TDFX_TWOSIDE_BIT
;
995 if (flags
& DD_TRI_OFFSET
) index
|= TDFX_OFFSET_BIT
;
996 if (flags
& DD_TRI_UNFILLED
) index
|= TDFX_UNFILLED_BIT
;
997 if (flags
& DD_FLATSHADE
) index
|= TDFX_FLAT_BIT
;
1000 fxMesa
->draw_point
= tdfx_draw_point
;
1001 fxMesa
->draw_line
= tdfx_draw_line
;
1002 fxMesa
->draw_triangle
= tdfx_draw_triangle
;
1004 /* Hook in fallbacks for specific primitives.
1006 * DD_TRI_UNFILLED is here because the unfilled_tri functions use
1007 * fxMesa->draw_tri *always*, and thus can't use the multipass
1008 * approach to cliprects.
1011 if (flags
& (POINT_FALLBACK
|
1017 if (flags
& POINT_FALLBACK
)
1018 fxMesa
->draw_point
= tdfx_fallback_point
;
1020 if (flags
& LINE_FALLBACK
)
1021 fxMesa
->draw_line
= tdfx_fallback_line
;
1023 if (flags
& TRI_FALLBACK
)
1024 fxMesa
->draw_triangle
= tdfx_fallback_tri
;
1026 if ((flags
& DD_TRI_STIPPLE
) && !fxMesa
->haveHwStipple
)
1027 fxMesa
->draw_triangle
= tdfx_fallback_tri
;
1029 index
|= TDFX_FALLBACK_BIT
;
1033 if (fxMesa
->RenderIndex
!= index
) {
1034 fxMesa
->RenderIndex
= index
;
1036 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
1037 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
1038 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
1039 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
1042 tnl
->Driver
.Render
.PrimTabVerts
= tdfx_render_tab_verts
;
1043 tnl
->Driver
.Render
.PrimTabElts
= tdfx_render_tab_elts
;
1044 tnl
->Driver
.Render
.ClippedLine
= line
; /* from tritmp.h */
1045 tnl
->Driver
.Render
.ClippedPolygon
= tdfxFastRenderClippedPoly
;
1047 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1048 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1049 tnl
->Driver
.Render
.ClippedLine
= tdfxRenderClippedLine
;
1050 tnl
->Driver
.Render
.ClippedPolygon
= tdfxRenderClippedPoly
;
1055 /**********************************************************************/
1056 /* Use multipass rendering for cliprects */
1057 /**********************************************************************/
1061 /* TODO: Benchmark this.
1062 * TODO: Use single back-buffer cliprect where possible.
1063 * NOTE: <pass> starts at 1, not zero!
1065 static GLboolean
multipass_cliprect( GLcontext
*ctx
, GLuint pass
)
1067 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1068 if (pass
>= fxMesa
->numClipRects
)
1071 fxMesa
->Glide
.grClipWindow(fxMesa
->pClipRects
[pass
].x1
,
1072 fxMesa
->screen_height
- fxMesa
->pClipRects
[pass
].y2
,
1073 fxMesa
->pClipRects
[pass
].x2
,
1074 fxMesa
->screen_height
- fxMesa
->pClipRects
[pass
].y1
);
1081 /**********************************************************************/
1082 /* Runtime render state and callbacks */
1083 /**********************************************************************/
1085 static void tdfxRunPipeline( GLcontext
*ctx
)
1087 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1089 if (fxMesa
->new_state
) {
1090 tdfxDDUpdateHwState( ctx
);
1093 if (!fxMesa
->Fallback
&& fxMesa
->new_gl_state
) {
1094 if (fxMesa
->new_gl_state
& _TDFX_NEW_RASTERSETUP
)
1095 tdfxChooseVertexState( ctx
);
1097 if (fxMesa
->new_gl_state
& _TDFX_NEW_RENDERSTATE
)
1098 tdfxChooseRenderState( ctx
);
1100 fxMesa
->new_gl_state
= 0;
1103 _tnl_run_pipeline( ctx
);
1107 static void tdfxRenderStart( GLcontext
*ctx
)
1109 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1110 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1112 tdfxCheckTexSizes( ctx
);
1114 LOCK_HARDWARE(fxMesa
);
1116 /* Make sure vertex format changes get uploaded before we start
1117 * sending triangles.
1119 if (fxMesa
->dirty
) {
1120 tdfxEmitHwStateLocked( fxMesa
);
1123 if (fxMesa
->numClipRects
&& !(fxMesa
->RenderIndex
& TDFX_FALLBACK_BIT
)) {
1124 fxMesa
->Glide
.grClipWindow(fxMesa
->pClipRects
[0].x1
,
1125 fxMesa
->screen_height
- fxMesa
->pClipRects
[0].y2
,
1126 fxMesa
->pClipRects
[0].x2
,
1127 fxMesa
->screen_height
- fxMesa
->pClipRects
[0].y1
);
1128 if (fxMesa
->numClipRects
> 1)
1129 tnl
->Driver
.Render
.Multipass
= multipass_cliprect
;
1131 tnl
->Driver
.Render
.Multipass
= NULL
;
1134 tnl
->Driver
.Render
.Multipass
= NULL
;
1139 /* Always called between RenderStart and RenderFinish --> We already
1142 static void tdfxRasterPrimitive( GLcontext
*ctx
, GLenum prim
)
1144 tdfxContextPtr fxMesa
= TDFX_CONTEXT( ctx
);
1146 FLUSH_BATCH( fxMesa
);
1148 fxMesa
->raster_primitive
= prim
;
1150 tdfxUpdateCull(ctx
);
1151 if ( fxMesa
->dirty
& TDFX_UPLOAD_CULL
) {
1152 fxMesa
->Glide
.grCullMode( fxMesa
->CullMode
);
1153 fxMesa
->dirty
&= ~TDFX_UPLOAD_CULL
;
1156 tdfxUpdateStipple(ctx
);
1157 if ( fxMesa
->dirty
& TDFX_UPLOAD_STIPPLE
) {
1158 fxMesa
->Glide
.grStipplePattern ( fxMesa
->Stipple
.Pattern
);
1159 fxMesa
->Glide
.grStippleMode ( fxMesa
->Stipple
.Mode
);
1160 fxMesa
->dirty
&= ~TDFX_UPLOAD_STIPPLE
;
1166 /* Determine the rasterized primitive when not drawing unfilled
1169 * Used only for the default render stage which always decomposes
1170 * primitives to trianges/lines/points. For the accelerated stage,
1171 * which renders strips as strips, the equivalent calculations are
1172 * performed in tdfx_render.c.
1174 static void tdfxRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
1176 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1177 GLuint rprim
= reduced_prim
[prim
];
1179 fxMesa
->render_primitive
= prim
;
1181 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
1184 if (fxMesa
->raster_primitive
!= rprim
) {
1185 tdfxRasterPrimitive( ctx
, rprim
);
1189 static void tdfxRenderFinish( GLcontext
*ctx
)
1191 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1193 if (fxMesa
->RenderIndex
& TDFX_FALLBACK_BIT
)
1194 _swrast_flush( ctx
);
1196 UNLOCK_HARDWARE(fxMesa
);
1200 /**********************************************************************/
1201 /* Manage total rasterization fallbacks */
1202 /**********************************************************************/
1204 static char *fallbackStrings
[] = {
1205 "3D/Rect/Cube Texture map",
1206 "glDrawBuffer(GL_FRONT_AND_BACK)",
1207 "Separate specular color",
1208 "glEnable/Disable(GL_STENCIL_TEST)",
1209 "glRenderMode(selection or feedback)",
1216 "Rasterization disable"
1220 static char *getFallbackString(GLuint bit
)
1227 return fallbackStrings
[i
];
1231 void tdfxFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
1233 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1234 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1235 GLuint oldfallback
= fxMesa
->Fallback
;
1238 fxMesa
->Fallback
|= bit
;
1239 if (oldfallback
== 0) {
1240 /*printf("Go to software rendering, bit = 0x%x\n", bit);*/
1241 FLUSH_BATCH(fxMesa
);
1242 _swsetup_Wakeup( ctx
);
1243 fxMesa
->RenderIndex
= ~0;
1244 if (TDFX_DEBUG
& DEBUG_VERBOSE_FALL
) {
1245 fprintf(stderr
, "Tdfx begin software fallback: 0x%x %s\n",
1246 bit
, getFallbackString(bit
));
1251 fxMesa
->Fallback
&= ~bit
;
1252 if (oldfallback
== bit
) {
1253 /*printf("Go to hardware rendering, bit = 0x%x\n", bit);*/
1254 _swrast_flush( ctx
);
1255 tnl
->Driver
.Render
.Start
= tdfxRenderStart
;
1256 tnl
->Driver
.Render
.PrimitiveNotify
= tdfxRenderPrimitive
;
1257 tnl
->Driver
.Render
.Finish
= tdfxRenderFinish
;
1258 tnl
->Driver
.Render
.BuildVertices
= tdfxBuildVertices
;
1259 fxMesa
->new_gl_state
|= (_TDFX_NEW_RENDERSTATE
|
1260 _TDFX_NEW_RASTERSETUP
);
1261 if (TDFX_DEBUG
& DEBUG_VERBOSE_FALL
) {
1262 fprintf(stderr
, "Tdfx end software fallback: 0x%x %s\n",
1263 bit
, getFallbackString(bit
));
1270 void tdfxDDInitTriFuncs( GLcontext
*ctx
)
1272 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1273 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1274 static int firsttime
= 1;
1281 fxMesa
->RenderIndex
= ~0;
1283 tnl
->Driver
.RunPipeline
= tdfxRunPipeline
;
1284 tnl
->Driver
.Render
.Start
= tdfxRenderStart
;
1285 tnl
->Driver
.Render
.Finish
= tdfxRenderFinish
;
1286 tnl
->Driver
.Render
.PrimitiveNotify
= tdfxRenderPrimitive
;
1287 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1288 tnl
->Driver
.Render
.BuildVertices
= tdfxBuildVertices
;
1289 tnl
->Driver
.Render
.Multipass
= NULL
;
1291 (void) tdfx_print_vertex
;