1 /* -*- c-basic-offset: 3 -*- */
2 /**************************************************************************
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5 VA Linux Systems Inc., Fremont, California.
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the "Software"),
11 to deal in the Software without restriction, including without limitation
12 on the rights to use, copy, modify, merge, publish, distribute, sub
13 license, and/or sell copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the following conditions:
16 The above copyright notice and this permission notice (including the next
17 paragraph) shall be included in all copies or substantial portions of the
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
23 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
24 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
25 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
26 USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
32 * Keith Whitwell <keithw@valinux.com>
33 * Felix Kuehling <fxkuehl@gmx.de>
40 #include "main/glheader.h"
41 #include "main/mtypes.h"
42 #include "main/colormac.h"
43 #include "main/macros.h"
45 #include "swrast/swrast.h"
46 #include "swrast_setup/swrast_setup.h"
48 #include "tnl/t_context.h"
49 #include "tnl/t_pipeline.h"
51 #include "savagetris.h"
52 #include "savagestate.h"
53 #include "savagetex.h"
54 #include "savageioctl.h"
55 #include "savage_bci.h"
57 static void savageRasterPrimitive( GLcontext
*ctx
, GLuint prim
);
58 static void savageRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
61 static GLenum reduced_prim
[GL_POLYGON
+1] = {
75 /***********************************************************************
77 ***********************************************************************/
79 #if defined (USE_X86_ASM)
80 #define EMIT_VERT( j, vb, vertex_size, start, v ) \
83 __asm__ __volatile__( "rep ; movsl" \
84 : "=%c" (j), "=D" (vb), "=S" (__tmp) \
85 : "0" (vertex_size-start), \
87 "S" ((long)&(v)->ui[start])); \
90 #define EMIT_VERT( j, vb, vertex_size, start, v ) \
92 for ( j = start ; j < vertex_size ; j++ ) \
98 static void INLINE
savage_draw_triangle (savageContextPtr imesa
,
101 savageVertexPtr v2
) {
102 GLuint vertsize
= imesa
->HwVertexSize
;
103 uint32_t *vb
= savageAllocVtxBuf (imesa
, 3*vertsize
);
106 EMIT_VERT (j
, vb
, vertsize
, 0, v0
);
107 EMIT_VERT (j
, vb
, vertsize
, 0, v1
);
108 EMIT_VERT (j
, vb
, vertsize
, 0, v2
);
111 static void INLINE
savage_draw_quad (savageContextPtr imesa
,
115 savageVertexPtr v3
) {
116 GLuint vertsize
= imesa
->HwVertexSize
;
117 uint32_t *vb
= savageAllocVtxBuf (imesa
, 6*vertsize
);
120 EMIT_VERT (j
, vb
, vertsize
, 0, v0
);
121 EMIT_VERT (j
, vb
, vertsize
, 0, v1
);
122 EMIT_VERT (j
, vb
, vertsize
, 0, v3
);
123 EMIT_VERT (j
, vb
, vertsize
, 0, v1
);
124 EMIT_VERT (j
, vb
, vertsize
, 0, v2
);
125 EMIT_VERT (j
, vb
, vertsize
, 0, v3
);
128 static INLINE
void savage_draw_point (savageContextPtr imesa
,
129 savageVertexPtr tmp
) {
130 GLuint vertsize
= imesa
->HwVertexSize
;
131 uint32_t *vb
= savageAllocVtxBuf (imesa
, 6*vertsize
);
132 const GLfloat x
= tmp
->v
.x
;
133 const GLfloat y
= tmp
->v
.y
;
134 const GLfloat sz
= 0.5 * CLAMP(imesa
->glCtx
->Point
.Size
,
135 imesa
->glCtx
->Const
.MinPointSize
,
136 imesa
->glCtx
->Const
.MaxPointSize
);
139 *(float *)&vb
[0] = x
- sz
;
140 *(float *)&vb
[1] = y
- sz
;
141 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
143 *(float *)&vb
[0] = x
+ sz
;
144 *(float *)&vb
[1] = y
- sz
;
145 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
147 *(float *)&vb
[0] = x
+ sz
;
148 *(float *)&vb
[1] = y
+ sz
;
149 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
151 *(float *)&vb
[0] = x
+ sz
;
152 *(float *)&vb
[1] = y
+ sz
;
153 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
155 *(float *)&vb
[0] = x
- sz
;
156 *(float *)&vb
[1] = y
+ sz
;
157 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
159 *(float *)&vb
[0] = x
- sz
;
160 *(float *)&vb
[1] = y
- sz
;
161 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
164 static INLINE
void savage_draw_line (savageContextPtr imesa
,
166 savageVertexPtr v1
) {
167 GLuint vertsize
= imesa
->HwVertexSize
;
168 uint32_t *vb
= savageAllocVtxBuf (imesa
, 6*vertsize
);
169 const GLfloat width
= CLAMP(imesa
->glCtx
->Line
.Width
,
170 imesa
->glCtx
->Const
.MinLineWidth
,
171 imesa
->glCtx
->Const
.MaxLineWidth
);
172 GLfloat dx
, dy
, ix
, iy
;
175 dx
= v0
->v
.x
- v1
->v
.x
;
176 dy
= v0
->v
.y
- v1
->v
.y
;
178 ix
= width
* .5; iy
= 0;
179 if (dx
* dx
> dy
* dy
) {
183 *(float *)&vb
[0] = v0
->v
.x
- ix
;
184 *(float *)&vb
[1] = v0
->v
.y
- iy
;
185 EMIT_VERT (j
, vb
, vertsize
, 2, v0
);
187 *(float *)&vb
[0] = v1
->v
.x
+ ix
;
188 *(float *)&vb
[1] = v1
->v
.y
+ iy
;
189 EMIT_VERT (j
, vb
, vertsize
, 2, v1
);
191 *(float *)&vb
[0] = v0
->v
.x
+ ix
;
192 *(float *)&vb
[1] = v0
->v
.y
+ iy
;
193 EMIT_VERT (j
, vb
, vertsize
, 2, v0
);
195 *(float *)&vb
[0] = v0
->v
.x
- ix
;
196 *(float *)&vb
[1] = v0
->v
.y
- iy
;
197 EMIT_VERT (j
, vb
, vertsize
, 2, v0
);
199 *(float *)&vb
[0] = v1
->v
.x
- ix
;
200 *(float *)&vb
[1] = v1
->v
.y
- iy
;
201 EMIT_VERT (j
, vb
, vertsize
, 2, v1
);
203 *(float *)&vb
[0] = v1
->v
.x
+ ix
;
204 *(float *)&vb
[1] = v1
->v
.y
+ iy
;
205 EMIT_VERT (j
, vb
, vertsize
, 2, v1
);
208 /* Fallback drawing functions for the ptex hack. Code duplication
209 * (especially lines and points) isn't beautiful, but I didn't feel
210 * like inventing yet another template. :-/
212 #define PTEX_VERTEX( j, tmp, vertex_size, start, v) \
214 GLfloat rhw = 1.0 / v->f[vertex_size]; \
215 for ( j = start ; j < vertex_size ; j++ ) \
216 tmp.f[j] = v->f[j]; \
217 tmp.f[3] *= v->f[vertex_size]; \
218 tmp.f[vertex_size-2] *= rhw; \
219 tmp.f[vertex_size-1] *= rhw; \
222 static void INLINE
savage_ptex_tri (savageContextPtr imesa
,
225 savageVertexPtr v2
) {
226 GLuint vertsize
= imesa
->HwVertexSize
;
227 uint32_t *vb
= savageAllocVtxBuf (imesa
, 3*vertsize
);
231 PTEX_VERTEX (j
, tmp
, vertsize
, 0, v0
); EMIT_VERT (j
, vb
, vertsize
, 0, &tmp
);
232 PTEX_VERTEX (j
, tmp
, vertsize
, 0, v1
); EMIT_VERT (j
, vb
, vertsize
, 0, &tmp
);
233 PTEX_VERTEX (j
, tmp
, vertsize
, 0, v2
); EMIT_VERT (j
, vb
, vertsize
, 0, &tmp
);
236 static INLINE
void savage_ptex_line (savageContextPtr imesa
,
238 savageVertexPtr v1
) {
239 GLuint vertsize
= imesa
->HwVertexSize
;
240 uint32_t *vb
= savageAllocVtxBuf (imesa
, 6*vertsize
);
241 const GLfloat width
= CLAMP(imesa
->glCtx
->Line
.Width
,
242 imesa
->glCtx
->Const
.MinLineWidth
,
243 imesa
->glCtx
->Const
.MaxLineWidth
);
244 GLfloat dx
, dy
, ix
, iy
;
245 savageVertex tmp0
, tmp1
;
248 PTEX_VERTEX (j
, tmp0
, vertsize
, 2, v0
);
249 PTEX_VERTEX (j
, tmp1
, vertsize
, 2, v1
);
251 dx
= v0
->v
.x
- v1
->v
.x
;
252 dy
= v0
->v
.y
- v1
->v
.y
;
254 ix
= width
* .5; iy
= 0;
255 if (dx
* dx
> dy
* dy
) {
259 *(float *)&vb
[0] = v0
->v
.x
- ix
;
260 *(float *)&vb
[1] = v0
->v
.y
- iy
;
261 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp0
);
263 *(float *)&vb
[0] = v1
->v
.x
+ ix
;
264 *(float *)&vb
[1] = v1
->v
.y
+ iy
;
265 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp1
);
267 *(float *)&vb
[0] = v0
->v
.x
+ ix
;
268 *(float *)&vb
[1] = v0
->v
.y
+ iy
;
269 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp0
);
271 *(float *)&vb
[0] = v0
->v
.x
- ix
;
272 *(float *)&vb
[1] = v0
->v
.y
- iy
;
273 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp0
);
275 *(float *)&vb
[0] = v1
->v
.x
- ix
;
276 *(float *)&vb
[1] = v1
->v
.y
- iy
;
277 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp1
);
279 *(float *)&vb
[0] = v1
->v
.x
+ ix
;
280 *(float *)&vb
[1] = v1
->v
.y
+ iy
;
281 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp1
);
284 static INLINE
void savage_ptex_point (savageContextPtr imesa
,
285 savageVertexPtr v0
) {
286 GLuint vertsize
= imesa
->HwVertexSize
;
287 uint32_t *vb
= savageAllocVtxBuf (imesa
, 6*vertsize
);
288 const GLfloat x
= v0
->v
.x
;
289 const GLfloat y
= v0
->v
.y
;
290 const GLfloat sz
= 0.5 * CLAMP(imesa
->glCtx
->Point
.Size
,
291 imesa
->glCtx
->Const
.MinPointSize
,
292 imesa
->glCtx
->Const
.MaxPointSize
);
296 PTEX_VERTEX (j
, tmp
, vertsize
, 2, v0
);
298 *(float *)&vb
[0] = x
- sz
;
299 *(float *)&vb
[1] = y
- sz
;
300 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp
);
302 *(float *)&vb
[0] = x
+ sz
;
303 *(float *)&vb
[1] = y
- sz
;
304 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp
);
306 *(float *)&vb
[0] = x
+ sz
;
307 *(float *)&vb
[1] = y
+ sz
;
308 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp
);
310 *(float *)&vb
[0] = x
+ sz
;
311 *(float *)&vb
[1] = y
+ sz
;
312 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp
);
314 *(float *)&vb
[0] = x
- sz
;
315 *(float *)&vb
[1] = y
+ sz
;
316 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp
);
318 *(float *)&vb
[0] = x
- sz
;
319 *(float *)&vb
[1] = y
- sz
;
320 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp
);
323 /***********************************************************************
324 * Macros for t_dd_tritmp.h to draw basic primitives *
325 ***********************************************************************/
327 #define TRI( a, b, c ) \
330 imesa->draw_tri( imesa, a, b, c ); \
332 savage_draw_triangle( imesa, a, b, c ); \
335 #define QUAD( a, b, c, d ) \
338 imesa->draw_tri( imesa, a, b, d ); \
339 imesa->draw_tri( imesa, b, c, d ); \
341 savage_draw_quad( imesa, a, b, c, d ); \
344 #define LINE( v0, v1 ) \
347 imesa->draw_line( imesa, v0, v1 ); \
349 savage_draw_line( imesa, v0, v1 ); \
352 #define POINT( v0 ) \
355 imesa->draw_point( imesa, v0 ); \
357 savage_draw_point( imesa, v0 ); \
361 /***********************************************************************
362 * Build render functions from dd templates *
363 ***********************************************************************/
365 #define SAVAGE_OFFSET_BIT 0x1
366 #define SAVAGE_TWOSIDE_BIT 0x2
367 #define SAVAGE_UNFILLED_BIT 0x4
368 #define SAVAGE_FALLBACK_BIT 0x8
369 #define SAVAGE_MAX_TRIFUNC 0x10
373 tnl_points_func points
;
375 tnl_triangle_func triangle
;
377 } rast_tab
[SAVAGE_MAX_TRIFUNC
];
380 #define DO_FALLBACK (IND & SAVAGE_FALLBACK_BIT)
381 #define DO_OFFSET (IND & SAVAGE_OFFSET_BIT)
382 #define DO_UNFILLED (IND & SAVAGE_UNFILLED_BIT)
383 #define DO_TWOSIDE (IND & SAVAGE_TWOSIDE_BIT)
389 #define DO_FULL_QUAD 1
393 #define HAVE_BACK_COLORS 0
394 #define HAVE_HW_FLATSHADE 1
395 #define VERTEX savageVertex
398 #define DEPTH_SCALE imesa->depth_scale
399 #define REVERSE_DEPTH 1
400 #define UNFILLED_TRI unfilled_tri
401 #define UNFILLED_QUAD unfilled_quad
402 #define VERT_X(_v) _v->v.x
403 #define VERT_Y(_v) _v->v.y
404 #define VERT_Z(_v) _v->v.z
405 #define AREA_IS_CCW( a ) (a > 0)
406 #define GET_VERTEX(e) (imesa->verts + (e * imesa->vertex_size * sizeof(int)))
408 #define VERT_SET_RGBA( v, c ) \
410 savage_color_t *color = (savage_color_t *)&((v)->ub4[coloroffset]); \
411 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
412 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
413 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
414 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
416 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
417 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
418 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
420 #define VERT_SET_SPEC( v, c ) \
423 savage_color_t *spec = (savage_color_t *)&((v)->ub4[specoffset]); \
424 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
425 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
426 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
429 #define VERT_COPY_SPEC( v0, v1 ) \
430 if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset])
431 #define VERT_SAVE_SPEC( idx ) \
432 if (specoffset) spec[idx] = v[idx]->ui[specoffset]
433 #define VERT_RESTORE_SPEC( idx ) \
434 if (specoffset) v[idx]->ui[specoffset] = spec[idx]
436 #define LOCAL_VARS(n) \
437 savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
438 GLuint color[n], spec[n]; \
439 GLuint coloroffset = \
440 ((imesa->skip & SAVAGE_SKIP_W) ? 3 : 4); \
441 GLboolean specoffset = \
442 ((imesa->skip & SAVAGE_SKIP_C1) ? 0 : coloroffset+1); \
443 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
445 /***********************************************************************
446 * Helpers for rendering unfilled primitives *
447 ***********************************************************************/
449 #define RASTERIZE(x) if (imesa->raster_primitive != reduced_prim[x]) \
450 savageRasterPrimitive( ctx, x )
451 #define RENDER_PRIMITIVE imesa->render_primitive
452 #define IND SAVAGE_FALLBACK_BIT
454 #include "tnl_dd/t_dd_unfilled.h"
458 /***********************************************************************
459 * Generate GL render functions *
460 ***********************************************************************/
465 #include "tnl_dd/t_dd_tritmp.h"
467 #define IND (SAVAGE_OFFSET_BIT)
468 #define TAG(x) x##_offset
469 #include "tnl_dd/t_dd_tritmp.h"
471 #define IND (SAVAGE_TWOSIDE_BIT)
472 #define TAG(x) x##_twoside
473 #include "tnl_dd/t_dd_tritmp.h"
475 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT)
476 #define TAG(x) x##_twoside_offset
477 #include "tnl_dd/t_dd_tritmp.h"
479 #define IND (SAVAGE_UNFILLED_BIT)
480 #define TAG(x) x##_unfilled
481 #include "tnl_dd/t_dd_tritmp.h"
483 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
484 #define TAG(x) x##_offset_unfilled
485 #include "tnl_dd/t_dd_tritmp.h"
487 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT)
488 #define TAG(x) x##_twoside_unfilled
489 #include "tnl_dd/t_dd_tritmp.h"
491 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
492 #define TAG(x) x##_twoside_offset_unfilled
493 #include "tnl_dd/t_dd_tritmp.h"
495 #define IND (SAVAGE_FALLBACK_BIT)
496 #define TAG(x) x##_fallback
497 #include "tnl_dd/t_dd_tritmp.h"
499 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
500 #define TAG(x) x##_offset_fallback
501 #include "tnl_dd/t_dd_tritmp.h"
503 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_FALLBACK_BIT)
504 #define TAG(x) x##_twoside_fallback
505 #include "tnl_dd/t_dd_tritmp.h"
507 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
508 #define TAG(x) x##_twoside_offset_fallback
509 #include "tnl_dd/t_dd_tritmp.h"
511 #define IND (SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
512 #define TAG(x) x##_unfilled_fallback
513 #include "tnl_dd/t_dd_tritmp.h"
515 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
516 #define TAG(x) x##_offset_unfilled_fallback
517 #include "tnl_dd/t_dd_tritmp.h"
519 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
520 #define TAG(x) x##_twoside_unfilled_fallback
521 #include "tnl_dd/t_dd_tritmp.h"
523 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT| \
525 #define TAG(x) x##_twoside_offset_unfilled_fallback
526 #include "tnl_dd/t_dd_tritmp.h"
529 static void init_rast_tab( void )
534 init_twoside_offset();
536 init_offset_unfilled();
537 init_twoside_unfilled();
538 init_twoside_offset_unfilled();
540 init_offset_fallback();
541 init_twoside_fallback();
542 init_twoside_offset_fallback();
543 init_unfilled_fallback();
544 init_offset_unfilled_fallback();
545 init_twoside_unfilled_fallback();
546 init_twoside_offset_unfilled_fallback();
551 /***********************************************************************
552 * Rasterization fallback helpers *
553 ***********************************************************************/
556 /* This code is hit only when a mix of accelerated and unaccelerated
557 * primitives are being drawn, and only for the unaccelerated
561 savage_fallback_tri( savageContextPtr imesa
,
566 GLcontext
*ctx
= imesa
->glCtx
;
569 WAIT_IDLE_EMPTY(imesa
);
570 _swsetup_Translate( ctx
, v0
, &v
[0] );
571 _swsetup_Translate( ctx
, v1
, &v
[1] );
572 _swsetup_Translate( ctx
, v2
, &v
[2] );
573 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
578 savage_fallback_line( savageContextPtr imesa
,
582 GLcontext
*ctx
= imesa
->glCtx
;
585 WAIT_IDLE_EMPTY(imesa
);
586 _swsetup_Translate( ctx
, v0
, &v
[0] );
587 _swsetup_Translate( ctx
, v1
, &v
[1] );
588 _swrast_Line( ctx
, &v
[0], &v
[1] );
593 savage_fallback_point( savageContextPtr imesa
,
596 GLcontext
*ctx
= imesa
->glCtx
;
599 WAIT_IDLE_EMPTY(imesa
);
600 _swsetup_Translate( ctx
, v0
, &v
[0] );
601 _swrast_Point( ctx
, &v
[0] );
606 /**********************************************************************/
607 /* Render unclipped begin/end objects */
608 /**********************************************************************/
610 #define VERT(x) (savageVertexPtr)(savageVerts + (x * vertsize * sizeof(int)))
611 #define RENDER_POINTS( start, count ) \
612 for ( ; start < count ; start++) \
613 savage_draw_point( imesa, VERT(start) )
614 #define RENDER_LINE( v0, v1 ) \
615 savage_draw_line( imesa, VERT(v0), VERT(v1) )
616 #define RENDER_TRI( v0, v1, v2 ) \
617 savage_draw_triangle( imesa, VERT(v0), VERT(v1), VERT(v2) )
618 #define RENDER_QUAD( v0, v1, v2, v3 ) \
619 savage_draw_quad( imesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
620 #define INIT(x) do { \
621 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
622 savageRenderPrimitive( ctx, x ); \
623 /*SAVAGE_CONTEXT(ctx)->render_primitive = x;*/ \
627 savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
628 const GLuint vertsize = imesa->vertex_size; \
629 const char *savageVerts = (char *)imesa->verts; \
630 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
632 #define RESET_STIPPLE
633 #define RESET_OCCLUSION
634 #define PRESERVE_VB_DEFS
636 #define TAG(x) savage_##x##_verts
637 #include "tnl/t_vb_rendertmp.h"
640 #define TAG(x) savage_##x##_elts
641 #define ELT(x) elt[x]
642 #include "tnl/t_vb_rendertmp.h"
645 /**********************************************************************/
646 /* Render clipped primitives */
647 /**********************************************************************/
649 static void savageRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
652 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
653 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
655 /* Render the new vertices as an unclipped polygon.
658 GLuint
*tmp
= VB
->Elts
;
659 VB
->Elts
= (GLuint
*)elts
;
660 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
, PRIM_BEGIN
|PRIM_END
);
665 static void savageRenderClippedLine( GLcontext
*ctx
, GLuint ii
, GLuint jj
)
667 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
668 tnl
->Driver
.Render
.Line( ctx
, ii
, jj
);
671 static void savageFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
674 r128ContextPtr rmesa = R128_CONTEXT( ctx );
675 GLuint vertsize = rmesa->vertex_size;
676 GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
677 GLubyte *r128verts = (GLubyte *)rmesa->verts;
678 const GLuint shift = rmesa->vertex_stride_shift;
679 const GLuint *start = (const GLuint *)VERT(elts[0]);
682 rmesa->num_verts += (n-2) * 3;
684 for (i = 2 ; i < n ; i++) {
685 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
686 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
687 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
694 /**********************************************************************/
695 /* Choose render functions */
696 /**********************************************************************/
698 #define _SAVAGE_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
699 _DD_NEW_LINE_SMOOTH | \
700 _DD_NEW_POINT_SMOOTH | \
701 _DD_NEW_TRI_STIPPLE | \
702 _DD_NEW_TRI_SMOOTH | \
703 _DD_NEW_TRI_UNFILLED | \
704 _DD_NEW_TRI_LIGHT_TWOSIDE | \
705 _DD_NEW_TRI_OFFSET) \
707 /* original driver didn't have DD_POINT_SMOOTH. really needed? */
708 #define POINT_FALLBACK (DD_POINT_SMOOTH)
709 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
710 #define TRI_FALLBACK (DD_TRI_STIPPLE|DD_TRI_SMOOTH)
711 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
712 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
715 static void savageChooseRenderState(GLcontext
*ctx
)
717 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
718 GLuint flags
= ctx
->_TriangleCaps
;
721 /* Hook in fallback functions for the ptex hack. Do this first, so
722 * that a real fallback will overwrite them with the respective
723 * savage_fallback_... function.
725 if (imesa
->ptexHack
) {
726 /* Do textures make sense with points? */
727 imesa
->draw_point
= savage_ptex_point
;
728 imesa
->draw_line
= savage_ptex_line
;
729 imesa
->draw_tri
= savage_ptex_tri
;
730 index
|= SAVAGE_FALLBACK_BIT
;
732 imesa
->draw_point
= savage_draw_point
;
733 imesa
->draw_line
= savage_draw_line
;
734 imesa
->draw_tri
= savage_draw_triangle
;
737 if (flags
& (ANY_RASTER_FLAGS
|ANY_FALLBACK_FLAGS
)) {
738 if (flags
& ANY_RASTER_FLAGS
) {
739 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= SAVAGE_TWOSIDE_BIT
;
740 if (flags
& DD_TRI_OFFSET
) index
|= SAVAGE_OFFSET_BIT
;
741 if (flags
& DD_TRI_UNFILLED
) index
|= SAVAGE_UNFILLED_BIT
;
744 /* Hook in fallbacks for specific primitives.
746 if (flags
& ANY_FALLBACK_FLAGS
) {
747 if (flags
& POINT_FALLBACK
) imesa
->draw_point
= savage_fallback_point
;
748 if (flags
& LINE_FALLBACK
) imesa
->draw_line
= savage_fallback_line
;
749 if (flags
& TRI_FALLBACK
) imesa
->draw_tri
= savage_fallback_tri
;
750 index
|= SAVAGE_FALLBACK_BIT
;
751 if (SAVAGE_DEBUG
& DEBUG_FALLBACKS
) {
752 fprintf (stderr
, "Per-primitive fallback, TriangleCaps=0x%x\n",
758 if (index
!= imesa
->RenderIndex
) {
759 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
760 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
761 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
762 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
763 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
766 tnl
->Driver
.Render
.PrimTabVerts
= savage_render_tab_verts
;
767 tnl
->Driver
.Render
.PrimTabElts
= savage_render_tab_elts
;
768 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
769 tnl
->Driver
.Render
.ClippedPolygon
= savageRenderClippedPoly
/*r128FastRenderClippedPoly*/;
771 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
772 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
773 tnl
->Driver
.Render
.ClippedLine
= savageRenderClippedLine
;
774 tnl
->Driver
.Render
.ClippedPolygon
= savageRenderClippedPoly
;
777 imesa
->RenderIndex
= index
;
781 /**********************************************************************/
782 /* Validate state at pipeline start */
783 /**********************************************************************/
785 static void savageRunPipeline( GLcontext
*ctx
)
787 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
790 FALLBACK(ctx
, SAVAGE_FALLBACK_NORAST
, GL_TRUE
);
792 if (imesa
->new_state
)
793 savageDDUpdateHwState( ctx
);
795 if (!imesa
->Fallback
) {
796 if (imesa
->new_gl_state
& _SAVAGE_NEW_RENDER_STATE
)
797 savageChooseRenderState( ctx
);
799 /* choose the correct primitive type for tnl rendering */
800 if (imesa
->savageScreen
->chipset
< S3_SAVAGE4
&&
801 (ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
802 if (imesa
->HwPrim
!= SAVAGE_PRIM_TRILIST_201
)
803 savageFlushVertices(imesa
);
804 imesa
->HwPrim
= SAVAGE_PRIM_TRILIST_201
;
806 if (imesa
->HwPrim
!= SAVAGE_PRIM_TRILIST
)
807 savageFlushVertices(imesa
);
808 imesa
->HwPrim
= SAVAGE_PRIM_TRILIST
;
811 imesa
->new_gl_state
= 0;
814 _tnl_run_pipeline( ctx
);
817 FALLBACK(ctx
, SAVAGE_FALLBACK_NORAST
, GL_FALSE
);
820 /**********************************************************************/
821 /* High level hooks for t_vb_render.c */
822 /**********************************************************************/
824 /* This is called when Mesa switches between rendering triangle
825 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
826 * and lines, points and bitmaps.
828 * As the r128 uses triangles to render lines and points, it is
829 * necessary to turn off hardware culling when rendering these
833 static void savageRasterPrimitive( GLcontext
*ctx
, GLuint prim
)
835 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
838 if (imesa
->raster_primitive
!= prim
) {
839 imesa
->raster_primitive
= prim
;
840 imesa
->new_state
|= SAVAGE_NEW_CULL
;
841 savageDDUpdateHwState (ctx
);
845 if (ctx
->Polygon
.StippleFlag
&& mmesa
->haveHwStipple
)
847 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
848 mmesa
->setup
.dwgctl
&= ~(0xf<<20);
849 if (mmesa
->raster_primitive
== GL_TRIANGLES
)
850 mmesa
->setup
.dwgctl
|= mmesa
->poly_stipple
;
855 static void savageRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
857 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
858 GLuint rprim
= reduced_prim
[prim
];
860 imesa
->render_primitive
= prim
;
862 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
865 if (imesa
->raster_primitive
!= rprim
) {
866 savageRasterPrimitive( ctx
, rprim
);
870 /* Check if projective texture coordinates are used and if we can fake
871 * them. Fallback to swrast we can't. Returns GL_TRUE if projective
872 * texture coordinates must be faked, GL_FALSE otherwise.
874 static GLboolean
savageCheckPTexHack( GLcontext
*ctx
)
876 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
877 struct vertex_buffer
*VB
= &tnl
->vb
;
878 DECLARE_RENDERINPUTS(index_bitset
);
880 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
882 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX0
) && VB
->TexCoordPtr
[0]->size
== 4) {
883 if (!RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_ATTRIB_TEX1
, _TNL_LAST_TEX
))
884 return GL_TRUE
; /* apply ptex hack */
886 FALLBACK(ctx
, SAVAGE_FALLBACK_PROJ_TEXTURE
, GL_TRUE
);
888 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX1
) && VB
->TexCoordPtr
[1]->size
== 4)
889 FALLBACK(ctx
, SAVAGE_FALLBACK_PROJ_TEXTURE
, GL_TRUE
);
891 return GL_FALSE
; /* don't apply ptex hack */
895 #define DO_EMIT_ATTR( ATTR, STYLE ) \
897 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = (ATTR); \
898 imesa->vertex_attrs[imesa->vertex_attr_count].format = (STYLE); \
899 imesa->vertex_attr_count++; \
902 #define NEED_ATTR( INDEX, SKIP ) \
904 setupIndex |= (INDEX); \
908 #define EMIT_ATTR( ATTR, STYLE, INDEX, SKIP ) \
910 NEED_ATTR( INDEX, SKIP ); \
911 DO_EMIT_ATTR( ATTR, STYLE ); \
914 #define EMIT_PAD( N ) \
916 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = 0; \
917 imesa->vertex_attrs[imesa->vertex_attr_count].format = EMIT_PAD; \
918 imesa->vertex_attrs[imesa->vertex_attr_count].offset = (N); \
919 imesa->vertex_attr_count++; \
922 #define SAVAGE_EMIT_XYZ 0x0001
923 #define SAVAGE_EMIT_W 0x0002
924 #define SAVAGE_EMIT_C0 0x0004
925 #define SAVAGE_EMIT_C1 0x0008
926 #define SAVAGE_EMIT_FOG 0x0010
927 #define SAVAGE_EMIT_S0 0x0020
928 #define SAVAGE_EMIT_T0 0x0040
929 #define SAVAGE_EMIT_Q0 0x0080
930 #define SAVAGE_EMIT_ST0 0x0060
931 #define SAVAGE_EMIT_STQ0 0x00e0
932 #define SAVAGE_EMIT_S1 0x0100
933 #define SAVAGE_EMIT_T1 0x0200
934 #define SAVAGE_EMIT_ST1 0x0300
937 static INLINE GLuint
savageChooseVertexFormat_s3d( GLcontext
*ctx
)
939 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
940 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
941 struct vertex_buffer
*VB
= &tnl
->vb
;
942 DECLARE_RENDERINPUTS(index_bitset
);
943 GLuint setupIndex
= SAVAGE_EMIT_XYZ
;
946 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
947 imesa
->vertex_attr_count
= 0;
949 skip
= SAVAGE_SKIP_ALL_S3D
;
950 skip
&= ~SAVAGE_SKIP_Z
; /* all mesa vertices have a z coordinate */
952 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
953 * build up a hardware vertex.
955 if (RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
) || !(ctx
->_TriangleCaps
& DD_FLATSHADE
))
956 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
, SAVAGE_EMIT_W
, SAVAGE_SKIP_W
);
958 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
, 0, 0 );
960 skip
&= ~SAVAGE_SKIP_W
;
963 /* t_context.c always includes a diffuse color */
964 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
, SAVAGE_EMIT_C0
, SAVAGE_SKIP_C0
);
966 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
))
967 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
, SAVAGE_EMIT_C1
, SAVAGE_SKIP_C1
);
970 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
))
971 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, SAVAGE_EMIT_FOG
, SAVAGE_SKIP_C1
);
974 skip
&= ~SAVAGE_SKIP_C1
;
976 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX0
)) {
978 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_3F_XYW
, SAVAGE_EMIT_STQ0
, SAVAGE_SKIP_ST0
);
979 else if (VB
->TexCoordPtr
[0]->size
== 4)
980 assert (0); /* should be caught by savageCheckPTexHack */
981 else if (VB
->TexCoordPtr
[0]->size
>= 2)
982 /* The chromium menu emits some 3D tex coords even though no
983 * 3D texture is enabled. Ignore the 3rd coordinate. */
984 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_2F
, SAVAGE_EMIT_ST0
, SAVAGE_SKIP_ST0
);
985 else if (VB
->TexCoordPtr
[0]->size
== 1) {
986 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_1F
, SAVAGE_EMIT_S0
, SAVAGE_SKIP_S0
);
992 skip
&= ~SAVAGE_SKIP_ST0
;
1000 static INLINE GLuint
savageChooseVertexFormat_s4( GLcontext
*ctx
)
1002 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1003 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1004 struct vertex_buffer
*VB
= &tnl
->vb
;
1005 DECLARE_RENDERINPUTS(index_bitset
);
1006 GLuint setupIndex
= SAVAGE_EMIT_XYZ
;
1010 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
1011 skip
= SAVAGE_SKIP_ALL_S4
;
1012 skip
&= ~SAVAGE_SKIP_Z
; /* all mesa vertices have a z coordinate */
1014 if (RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
) || !(ctx
->_TriangleCaps
& DD_FLATSHADE
))
1015 NEED_ATTR( SAVAGE_EMIT_W
, SAVAGE_SKIP_W
);
1017 /* t_context.c always includes a diffuse color */
1018 NEED_ATTR( SAVAGE_EMIT_C0
, SAVAGE_SKIP_C0
);
1020 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
))
1021 NEED_ATTR( SAVAGE_EMIT_C1
, SAVAGE_SKIP_C1
);
1022 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
))
1023 NEED_ATTR( SAVAGE_EMIT_FOG
, SAVAGE_SKIP_C1
);
1025 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX0
)) {
1026 if (imesa
->ptexHack
)
1027 NEED_ATTR( SAVAGE_EMIT_STQ0
, SAVAGE_SKIP_ST0
);
1028 else if (VB
->TexCoordPtr
[0]->size
== 4)
1029 assert (0); /* should be caught by savageCheckPTexHack */
1030 else if (VB
->TexCoordPtr
[0]->size
>= 2)
1031 /* The chromium menu emits some 3D tex coords even though no
1032 * 3D texture is enabled. Ignore the 3rd coordinate. */
1033 NEED_ATTR( SAVAGE_EMIT_ST0
, SAVAGE_SKIP_ST0
);
1035 NEED_ATTR( SAVAGE_EMIT_S0
, SAVAGE_SKIP_S0
);
1037 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX1
)) {
1038 if (VB
->TexCoordPtr
[1]->size
== 4)
1039 /* projective textures are not supported by the hardware */
1040 assert (0); /* should be caught by savageCheckPTexHack */
1041 else if (VB
->TexCoordPtr
[1]->size
>= 2)
1042 NEED_ATTR( SAVAGE_EMIT_ST1
, SAVAGE_SKIP_ST1
);
1044 NEED_ATTR( SAVAGE_EMIT_S1
, SAVAGE_SKIP_S1
);
1047 /* if nothing changed we can skip the rest */
1048 if (setupIndex
== imesa
->SetupIndex
&& imesa
->vertex_size
!= 0)
1051 if (imesa
->enable_vdma
) {
1052 mask
= SAVAGE_SKIP_W
;
1053 size
= 10 - (skip
& 1) - (skip
>> 1 & 1) -
1054 (skip
>> 2 & 1) - (skip
>> 3 & 1) - (skip
>> 4 & 1) -
1055 (skip
>> 5 & 1) - (skip
>> 6 & 1) - (skip
>> 7 & 1);
1066 imesa
->vertex_attr_count
= 0;
1068 if (skip
& SAVAGE_SKIP_W
)
1069 DO_EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
);
1070 else if (setupIndex
& SAVAGE_EMIT_W
)
1071 DO_EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
);
1073 DO_EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
);
1077 DO_EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
);
1079 if (!(skip
& SAVAGE_SKIP_C1
)) {
1080 if (!(setupIndex
& (SAVAGE_EMIT_C1
|SAVAGE_EMIT_FOG
)))
1083 if (setupIndex
& SAVAGE_EMIT_C1
)
1084 DO_EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
);
1087 if (setupIndex
& SAVAGE_EMIT_FOG
)
1088 DO_EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
);
1094 if ((skip
& SAVAGE_SKIP_ST0
) != SAVAGE_SKIP_ST0
) {
1095 if ((setupIndex
& SAVAGE_EMIT_STQ0
) == SAVAGE_EMIT_STQ0
)
1096 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_3F_XYW
);
1097 else if ((setupIndex
& SAVAGE_EMIT_ST0
) == SAVAGE_EMIT_ST0
)
1098 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_2F
);
1099 else if ((setupIndex
& SAVAGE_EMIT_ST0
) == SAVAGE_EMIT_S0
) {
1100 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_1F
);
1101 if (!(skip
& SAVAGE_SKIP_T0
)) EMIT_PAD( 4 );
1103 if (!(skip
& SAVAGE_SKIP_S0
)) EMIT_PAD( 4 );
1104 if (!(skip
& SAVAGE_SKIP_T0
)) EMIT_PAD( 4 );
1108 if ((skip
& SAVAGE_SKIP_ST1
) != SAVAGE_SKIP_ST1
) {
1109 if ((setupIndex
& SAVAGE_EMIT_ST1
) == SAVAGE_EMIT_ST1
)
1110 DO_EMIT_ATTR( _TNL_ATTRIB_TEX1
, EMIT_2F
);
1111 else if ((setupIndex
& SAVAGE_EMIT_ST1
) == SAVAGE_EMIT_S1
) {
1112 DO_EMIT_ATTR( _TNL_ATTRIB_TEX1
, EMIT_1F
);
1113 if (!(skip
& SAVAGE_SKIP_T1
)) EMIT_PAD( 4 );
1115 if (!(skip
& SAVAGE_SKIP_S1
)) EMIT_PAD( 4 );
1116 if (!(skip
& SAVAGE_SKIP_T1
)) EMIT_PAD( 4 );
1125 static void savageRenderStart( GLcontext
*ctx
)
1127 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1128 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1129 struct vertex_buffer
*VB
= &tnl
->vb
;
1130 GLuint setupIndex
= SAVAGE_EMIT_XYZ
;
1133 /* Check if we need to apply the ptex hack. Choose a new render
1134 * state if necessary. (Note: this can't be done in
1135 * savageRunPipeline, since the number of vertex coordinates can
1136 * change in the pipeline. texmat or texgen or both?) */
1137 ptexHack
= savageCheckPTexHack( ctx
);
1138 if (ptexHack
!= imesa
->ptexHack
) {
1139 imesa
->ptexHack
= ptexHack
;
1140 savageChooseRenderState (ctx
);
1142 /* Handle fallback cases identified in savageCheckPTexHack. */
1143 if (SAVAGE_CONTEXT(ctx
)->Fallback
) {
1144 tnl
->Driver
.Render
.Start(ctx
);
1150 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
1152 if (imesa
->savageScreen
->chipset
< S3_SAVAGE4
) {
1153 setupIndex
= savageChooseVertexFormat_s3d(ctx
);
1155 setupIndex
= savageChooseVertexFormat_s4(ctx
);
1158 /* Need to change the vertex emit code if the SetupIndex changed or
1159 * is set for the first time (indicated by vertex_size == 0). */
1160 if (setupIndex
!= imesa
->SetupIndex
|| imesa
->vertex_size
== 0) {
1161 GLuint hwVertexSize
;
1162 imesa
->vertex_size
=
1163 _tnl_install_attrs( ctx
,
1164 imesa
->vertex_attrs
,
1165 imesa
->vertex_attr_count
,
1166 imesa
->hw_viewport
, 0 );
1167 imesa
->vertex_size
>>= 2;
1168 imesa
->SetupIndex
= setupIndex
;
1170 hwVertexSize
= imesa
->vertex_size
;
1171 if (setupIndex
& SAVAGE_EMIT_Q0
) {
1172 /* The vertex setup code emits homogenous texture
1173 * coordinates. They are converted to normal 2D coords by
1174 * savage_ptex_tri/line/point. Now we have two different
1175 * vertex sizes. Functions that emit vertices to the hardware
1176 * need to use HwVertexSize, anything that manipulates the
1177 * vertices generated by t_vertex uses vertex_size. */
1179 assert (imesa
->ptexHack
);
1181 assert (!imesa
->ptexHack
);
1183 if (hwVertexSize
!= imesa
->HwVertexSize
) {
1184 /* Changing the vertex size: flush vertex and command buffer and
1185 * discard the DMA buffer, if we were using one. */
1186 savageFlushVertices(imesa
);
1187 savageFlushCmdBuf(imesa
, GL_TRUE
);
1188 if (hwVertexSize
== 8 && imesa
->enable_vdma
) {
1189 if (SAVAGE_DEBUG
& DEBUG_DMA
)
1190 fprintf (stderr
, "Using DMA, skip=0x%02x\n", imesa
->skip
);
1191 /* we can use vertex dma */
1192 imesa
->vtxBuf
= &imesa
->dmaVtxBuf
;
1194 if (SAVAGE_DEBUG
& DEBUG_DMA
)
1195 fprintf (stderr
, "Not using DMA, skip=0x%02x\n", imesa
->skip
);
1196 imesa
->vtxBuf
= &imesa
->clientVtxBuf
;
1198 imesa
->HwVertexSize
= hwVertexSize
;
1203 static void savageRenderFinish( GLcontext
*ctx
)
1205 /* Flush the last primitive now, before any state is changed. */
1206 savageFlushVertices(SAVAGE_CONTEXT(ctx
));
1208 if (SAVAGE_CONTEXT(ctx
)->RenderIndex
& SAVAGE_FALLBACK_BIT
)
1209 _swrast_flush( ctx
);
1213 /**********************************************************************/
1214 /* Transition to/from hardware rasterization. */
1215 /**********************************************************************/
1217 static const char * const fallbackStrings
[] = {
1224 "glEnable(GL_STENCIL) without hw stencil buffer",
1225 "glRenderMode(selection or feedback)",
1227 "Hardware rasterization disabled",
1228 "Projective texture",
1231 void savageFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
1233 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1234 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1235 GLuint oldfallback
= imesa
->Fallback
;
1237 for (index
= 0; (1 << index
) < bit
; ++index
);
1240 imesa
->Fallback
|= bit
;
1241 if (oldfallback
== 0) {
1242 /* the first fallback */
1243 _swsetup_Wakeup( ctx
);
1244 imesa
->RenderIndex
= ~0;
1246 if (!(oldfallback
& bit
) && (SAVAGE_DEBUG
& DEBUG_FALLBACKS
))
1247 fprintf (stderr
, "Savage begin fallback: 0x%x %s\n",
1248 bit
, fallbackStrings
[index
]);
1251 imesa
->Fallback
&= ~bit
;
1252 if (oldfallback
== bit
) {
1253 /* the last fallback */
1254 _swrast_flush( ctx
);
1255 tnl
->Driver
.Render
.Start
= savageRenderStart
;
1256 tnl
->Driver
.Render
.PrimitiveNotify
= savageRenderPrimitive
;
1257 tnl
->Driver
.Render
.Finish
= savageRenderFinish
;
1259 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1260 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1261 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1263 _tnl_invalidate_vertex_state( ctx
, ~0 );
1264 _tnl_invalidate_vertices( ctx
, ~0 );
1265 _tnl_install_attrs( ctx
,
1266 imesa
->vertex_attrs
,
1267 imesa
->vertex_attr_count
,
1268 imesa
->hw_viewport
, 0 );
1270 imesa
->new_gl_state
|= _SAVAGE_NEW_RENDER_STATE
;
1272 if ((oldfallback
& bit
) && (SAVAGE_DEBUG
& DEBUG_FALLBACKS
))
1273 fprintf (stderr
, "Savage end fallback: 0x%x %s\n",
1274 bit
, fallbackStrings
[index
]);
1279 /**********************************************************************/
1280 /* Initialization. */
1281 /**********************************************************************/
1283 void savageInitTriFuncs( GLcontext
*ctx
)
1285 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1286 static int firsttime
= 1;
1293 tnl
->Driver
.RunPipeline
= savageRunPipeline
;
1294 tnl
->Driver
.Render
.Start
= savageRenderStart
;
1295 tnl
->Driver
.Render
.Finish
= savageRenderFinish
;
1296 tnl
->Driver
.Render
.PrimitiveNotify
= savageRenderPrimitive
;
1297 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1299 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1300 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1301 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1303 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
1304 (6 + 2*ctx
->Const
.MaxTextureUnits
) * sizeof(GLfloat
) );
1306 SAVAGE_CONTEXT(ctx
)->verts
= (char *)tnl
->clipspace
.vertex_buf
;