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] = { 0 }; \
439 GLuint spec[n] = { 0 }; \
440 GLuint coloroffset = \
441 ((imesa->skip & SAVAGE_SKIP_W) ? 3 : 4); \
442 GLboolean specoffset = \
443 ((imesa->skip & SAVAGE_SKIP_C1) ? 0 : coloroffset+1); \
444 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
446 /***********************************************************************
447 * Helpers for rendering unfilled primitives *
448 ***********************************************************************/
450 #define RASTERIZE(x) if (imesa->raster_primitive != reduced_prim[x]) \
451 savageRasterPrimitive( ctx, x )
452 #define RENDER_PRIMITIVE imesa->render_primitive
453 #define IND SAVAGE_FALLBACK_BIT
455 #include "tnl_dd/t_dd_unfilled.h"
459 /***********************************************************************
460 * Generate GL render functions *
461 ***********************************************************************/
466 #include "tnl_dd/t_dd_tritmp.h"
468 #define IND (SAVAGE_OFFSET_BIT)
469 #define TAG(x) x##_offset
470 #include "tnl_dd/t_dd_tritmp.h"
472 #define IND (SAVAGE_TWOSIDE_BIT)
473 #define TAG(x) x##_twoside
474 #include "tnl_dd/t_dd_tritmp.h"
476 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT)
477 #define TAG(x) x##_twoside_offset
478 #include "tnl_dd/t_dd_tritmp.h"
480 #define IND (SAVAGE_UNFILLED_BIT)
481 #define TAG(x) x##_unfilled
482 #include "tnl_dd/t_dd_tritmp.h"
484 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
485 #define TAG(x) x##_offset_unfilled
486 #include "tnl_dd/t_dd_tritmp.h"
488 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT)
489 #define TAG(x) x##_twoside_unfilled
490 #include "tnl_dd/t_dd_tritmp.h"
492 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
493 #define TAG(x) x##_twoside_offset_unfilled
494 #include "tnl_dd/t_dd_tritmp.h"
496 #define IND (SAVAGE_FALLBACK_BIT)
497 #define TAG(x) x##_fallback
498 #include "tnl_dd/t_dd_tritmp.h"
500 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
501 #define TAG(x) x##_offset_fallback
502 #include "tnl_dd/t_dd_tritmp.h"
504 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_FALLBACK_BIT)
505 #define TAG(x) x##_twoside_fallback
506 #include "tnl_dd/t_dd_tritmp.h"
508 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
509 #define TAG(x) x##_twoside_offset_fallback
510 #include "tnl_dd/t_dd_tritmp.h"
512 #define IND (SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
513 #define TAG(x) x##_unfilled_fallback
514 #include "tnl_dd/t_dd_tritmp.h"
516 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
517 #define TAG(x) x##_offset_unfilled_fallback
518 #include "tnl_dd/t_dd_tritmp.h"
520 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
521 #define TAG(x) x##_twoside_unfilled_fallback
522 #include "tnl_dd/t_dd_tritmp.h"
524 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT| \
526 #define TAG(x) x##_twoside_offset_unfilled_fallback
527 #include "tnl_dd/t_dd_tritmp.h"
530 static void init_rast_tab( void )
535 init_twoside_offset();
537 init_offset_unfilled();
538 init_twoside_unfilled();
539 init_twoside_offset_unfilled();
541 init_offset_fallback();
542 init_twoside_fallback();
543 init_twoside_offset_fallback();
544 init_unfilled_fallback();
545 init_offset_unfilled_fallback();
546 init_twoside_unfilled_fallback();
547 init_twoside_offset_unfilled_fallback();
552 /***********************************************************************
553 * Rasterization fallback helpers *
554 ***********************************************************************/
557 /* This code is hit only when a mix of accelerated and unaccelerated
558 * primitives are being drawn, and only for the unaccelerated
562 savage_fallback_tri( savageContextPtr imesa
,
567 GLcontext
*ctx
= imesa
->glCtx
;
570 WAIT_IDLE_EMPTY(imesa
);
571 _swsetup_Translate( ctx
, v0
, &v
[0] );
572 _swsetup_Translate( ctx
, v1
, &v
[1] );
573 _swsetup_Translate( ctx
, v2
, &v
[2] );
574 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
579 savage_fallback_line( savageContextPtr imesa
,
583 GLcontext
*ctx
= imesa
->glCtx
;
586 WAIT_IDLE_EMPTY(imesa
);
587 _swsetup_Translate( ctx
, v0
, &v
[0] );
588 _swsetup_Translate( ctx
, v1
, &v
[1] );
589 _swrast_Line( ctx
, &v
[0], &v
[1] );
594 savage_fallback_point( savageContextPtr imesa
,
597 GLcontext
*ctx
= imesa
->glCtx
;
600 WAIT_IDLE_EMPTY(imesa
);
601 _swsetup_Translate( ctx
, v0
, &v
[0] );
602 _swrast_Point( ctx
, &v
[0] );
607 /**********************************************************************/
608 /* Render unclipped begin/end objects */
609 /**********************************************************************/
611 #define VERT(x) (savageVertexPtr)(savageVerts + (x * vertsize * sizeof(int)))
612 #define RENDER_POINTS( start, count ) \
613 for ( ; start < count ; start++) \
614 savage_draw_point( imesa, VERT(start) )
615 #define RENDER_LINE( v0, v1 ) \
616 savage_draw_line( imesa, VERT(v0), VERT(v1) )
617 #define RENDER_TRI( v0, v1, v2 ) \
618 savage_draw_triangle( imesa, VERT(v0), VERT(v1), VERT(v2) )
619 #define RENDER_QUAD( v0, v1, v2, v3 ) \
620 savage_draw_quad( imesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
621 #define INIT(x) do { \
622 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
623 savageRenderPrimitive( ctx, x ); \
624 /*SAVAGE_CONTEXT(ctx)->render_primitive = x;*/ \
628 savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
629 const GLuint vertsize = imesa->vertex_size; \
630 const char *savageVerts = (char *)imesa->verts; \
631 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
633 #define RESET_STIPPLE
634 #define RESET_OCCLUSION
635 #define PRESERVE_VB_DEFS
637 #define TAG(x) savage_##x##_verts
638 #include "tnl/t_vb_rendertmp.h"
641 #define TAG(x) savage_##x##_elts
642 #define ELT(x) elt[x]
643 #include "tnl/t_vb_rendertmp.h"
646 /**********************************************************************/
647 /* Render clipped primitives */
648 /**********************************************************************/
650 static void savageRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
653 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
654 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
656 /* Render the new vertices as an unclipped polygon.
659 GLuint
*tmp
= VB
->Elts
;
660 VB
->Elts
= (GLuint
*)elts
;
661 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
, PRIM_BEGIN
|PRIM_END
);
666 static void savageRenderClippedLine( GLcontext
*ctx
, GLuint ii
, GLuint jj
)
668 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
669 tnl
->Driver
.Render
.Line( ctx
, ii
, jj
);
672 static void savageFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
675 r128ContextPtr rmesa = R128_CONTEXT( ctx );
676 GLuint vertsize = rmesa->vertex_size;
677 GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
678 GLubyte *r128verts = (GLubyte *)rmesa->verts;
679 const GLuint shift = rmesa->vertex_stride_shift;
680 const GLuint *start = (const GLuint *)VERT(elts[0]);
683 rmesa->num_verts += (n-2) * 3;
685 for (i = 2 ; i < n ; i++) {
686 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
687 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
688 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
695 /**********************************************************************/
696 /* Choose render functions */
697 /**********************************************************************/
699 #define _SAVAGE_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
700 _DD_NEW_LINE_SMOOTH | \
701 _DD_NEW_POINT_SMOOTH | \
702 _DD_NEW_TRI_STIPPLE | \
703 _DD_NEW_TRI_SMOOTH | \
704 _DD_NEW_TRI_UNFILLED | \
705 _DD_NEW_TRI_LIGHT_TWOSIDE | \
706 _DD_NEW_TRI_OFFSET) \
708 /* original driver didn't have DD_POINT_SMOOTH. really needed? */
709 #define POINT_FALLBACK (DD_POINT_SMOOTH)
710 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
711 #define TRI_FALLBACK (DD_TRI_STIPPLE|DD_TRI_SMOOTH)
712 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
713 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
716 static void savageChooseRenderState(GLcontext
*ctx
)
718 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
719 GLuint flags
= ctx
->_TriangleCaps
;
722 /* Hook in fallback functions for the ptex hack. Do this first, so
723 * that a real fallback will overwrite them with the respective
724 * savage_fallback_... function.
726 if (imesa
->ptexHack
) {
727 /* Do textures make sense with points? */
728 imesa
->draw_point
= savage_ptex_point
;
729 imesa
->draw_line
= savage_ptex_line
;
730 imesa
->draw_tri
= savage_ptex_tri
;
731 index
|= SAVAGE_FALLBACK_BIT
;
733 imesa
->draw_point
= savage_draw_point
;
734 imesa
->draw_line
= savage_draw_line
;
735 imesa
->draw_tri
= savage_draw_triangle
;
738 if (flags
& (ANY_RASTER_FLAGS
|ANY_FALLBACK_FLAGS
)) {
739 if (flags
& ANY_RASTER_FLAGS
) {
740 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= SAVAGE_TWOSIDE_BIT
;
741 if (flags
& DD_TRI_OFFSET
) index
|= SAVAGE_OFFSET_BIT
;
742 if (flags
& DD_TRI_UNFILLED
) index
|= SAVAGE_UNFILLED_BIT
;
745 /* Hook in fallbacks for specific primitives.
747 if (flags
& ANY_FALLBACK_FLAGS
) {
748 if (flags
& POINT_FALLBACK
) imesa
->draw_point
= savage_fallback_point
;
749 if (flags
& LINE_FALLBACK
) imesa
->draw_line
= savage_fallback_line
;
750 if (flags
& TRI_FALLBACK
) imesa
->draw_tri
= savage_fallback_tri
;
751 index
|= SAVAGE_FALLBACK_BIT
;
752 if (SAVAGE_DEBUG
& DEBUG_FALLBACKS
) {
753 fprintf (stderr
, "Per-primitive fallback, TriangleCaps=0x%x\n",
759 if (index
!= imesa
->RenderIndex
) {
760 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
761 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
762 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
763 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
764 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
767 tnl
->Driver
.Render
.PrimTabVerts
= savage_render_tab_verts
;
768 tnl
->Driver
.Render
.PrimTabElts
= savage_render_tab_elts
;
769 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
770 tnl
->Driver
.Render
.ClippedPolygon
= savageRenderClippedPoly
/*r128FastRenderClippedPoly*/;
772 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
773 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
774 tnl
->Driver
.Render
.ClippedLine
= savageRenderClippedLine
;
775 tnl
->Driver
.Render
.ClippedPolygon
= savageRenderClippedPoly
;
778 imesa
->RenderIndex
= index
;
782 /**********************************************************************/
783 /* Validate state at pipeline start */
784 /**********************************************************************/
786 static void savageRunPipeline( GLcontext
*ctx
)
788 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
791 FALLBACK(ctx
, SAVAGE_FALLBACK_NORAST
, GL_TRUE
);
793 if (imesa
->new_state
)
794 savageDDUpdateHwState( ctx
);
796 if (!imesa
->Fallback
) {
797 if (imesa
->new_gl_state
& _SAVAGE_NEW_RENDER_STATE
)
798 savageChooseRenderState( ctx
);
800 /* choose the correct primitive type for tnl rendering */
801 if (imesa
->savageScreen
->chipset
< S3_SAVAGE4
&&
802 (ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
803 if (imesa
->HwPrim
!= SAVAGE_PRIM_TRILIST_201
)
804 savageFlushVertices(imesa
);
805 imesa
->HwPrim
= SAVAGE_PRIM_TRILIST_201
;
807 if (imesa
->HwPrim
!= SAVAGE_PRIM_TRILIST
)
808 savageFlushVertices(imesa
);
809 imesa
->HwPrim
= SAVAGE_PRIM_TRILIST
;
812 imesa
->new_gl_state
= 0;
815 _tnl_run_pipeline( ctx
);
818 FALLBACK(ctx
, SAVAGE_FALLBACK_NORAST
, GL_FALSE
);
821 /**********************************************************************/
822 /* High level hooks for t_vb_render.c */
823 /**********************************************************************/
825 /* This is called when Mesa switches between rendering triangle
826 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
827 * and lines, points and bitmaps.
829 * As the r128 uses triangles to render lines and points, it is
830 * necessary to turn off hardware culling when rendering these
834 static void savageRasterPrimitive( GLcontext
*ctx
, GLuint prim
)
836 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
839 if (imesa
->raster_primitive
!= prim
) {
840 imesa
->raster_primitive
= prim
;
841 imesa
->new_state
|= SAVAGE_NEW_CULL
;
842 savageDDUpdateHwState (ctx
);
846 if (ctx
->Polygon
.StippleFlag
&& mmesa
->haveHwStipple
)
848 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
849 mmesa
->setup
.dwgctl
&= ~(0xf<<20);
850 if (mmesa
->raster_primitive
== GL_TRIANGLES
)
851 mmesa
->setup
.dwgctl
|= mmesa
->poly_stipple
;
856 static void savageRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
858 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
859 GLuint rprim
= reduced_prim
[prim
];
861 imesa
->render_primitive
= prim
;
863 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
866 if (imesa
->raster_primitive
!= rprim
) {
867 savageRasterPrimitive( ctx
, rprim
);
871 /* Check if projective texture coordinates are used and if we can fake
872 * them. Fallback to swrast we can't. Returns GL_TRUE if projective
873 * texture coordinates must be faked, GL_FALSE otherwise.
875 static GLboolean
savageCheckPTexHack( GLcontext
*ctx
)
877 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
878 struct vertex_buffer
*VB
= &tnl
->vb
;
879 DECLARE_RENDERINPUTS(index_bitset
);
881 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
883 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX0
) && VB
->TexCoordPtr
[0]->size
== 4) {
884 if (!RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_ATTRIB_TEX1
, _TNL_LAST_TEX
))
885 return GL_TRUE
; /* apply ptex hack */
887 FALLBACK(ctx
, SAVAGE_FALLBACK_PROJ_TEXTURE
, GL_TRUE
);
889 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX1
) && VB
->TexCoordPtr
[1]->size
== 4)
890 FALLBACK(ctx
, SAVAGE_FALLBACK_PROJ_TEXTURE
, GL_TRUE
);
892 return GL_FALSE
; /* don't apply ptex hack */
896 #define DO_EMIT_ATTR( ATTR, STYLE ) \
898 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = (ATTR); \
899 imesa->vertex_attrs[imesa->vertex_attr_count].format = (STYLE); \
900 imesa->vertex_attr_count++; \
903 #define NEED_ATTR( INDEX, SKIP ) \
905 setupIndex |= (INDEX); \
909 #define EMIT_ATTR( ATTR, STYLE, INDEX, SKIP ) \
911 NEED_ATTR( INDEX, SKIP ); \
912 DO_EMIT_ATTR( ATTR, STYLE ); \
915 #define EMIT_PAD( N ) \
917 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = 0; \
918 imesa->vertex_attrs[imesa->vertex_attr_count].format = EMIT_PAD; \
919 imesa->vertex_attrs[imesa->vertex_attr_count].offset = (N); \
920 imesa->vertex_attr_count++; \
923 #define SAVAGE_EMIT_XYZ 0x0001
924 #define SAVAGE_EMIT_W 0x0002
925 #define SAVAGE_EMIT_C0 0x0004
926 #define SAVAGE_EMIT_C1 0x0008
927 #define SAVAGE_EMIT_FOG 0x0010
928 #define SAVAGE_EMIT_S0 0x0020
929 #define SAVAGE_EMIT_T0 0x0040
930 #define SAVAGE_EMIT_Q0 0x0080
931 #define SAVAGE_EMIT_ST0 0x0060
932 #define SAVAGE_EMIT_STQ0 0x00e0
933 #define SAVAGE_EMIT_S1 0x0100
934 #define SAVAGE_EMIT_T1 0x0200
935 #define SAVAGE_EMIT_ST1 0x0300
938 static INLINE GLuint
savageChooseVertexFormat_s3d( GLcontext
*ctx
)
940 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
941 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
942 struct vertex_buffer
*VB
= &tnl
->vb
;
943 DECLARE_RENDERINPUTS(index_bitset
);
944 GLuint setupIndex
= SAVAGE_EMIT_XYZ
;
947 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
948 imesa
->vertex_attr_count
= 0;
950 skip
= SAVAGE_SKIP_ALL_S3D
;
951 skip
&= ~SAVAGE_SKIP_Z
; /* all mesa vertices have a z coordinate */
953 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
954 * build up a hardware vertex.
956 if (RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
) || !(ctx
->_TriangleCaps
& DD_FLATSHADE
))
957 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
, SAVAGE_EMIT_W
, SAVAGE_SKIP_W
);
959 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
, 0, 0 );
961 skip
&= ~SAVAGE_SKIP_W
;
964 /* t_context.c always includes a diffuse color */
965 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
, SAVAGE_EMIT_C0
, SAVAGE_SKIP_C0
);
967 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
))
968 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
, SAVAGE_EMIT_C1
, SAVAGE_SKIP_C1
);
971 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
))
972 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, SAVAGE_EMIT_FOG
, SAVAGE_SKIP_C1
);
975 skip
&= ~SAVAGE_SKIP_C1
;
977 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX0
)) {
979 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_3F_XYW
, SAVAGE_EMIT_STQ0
, SAVAGE_SKIP_ST0
);
980 else if (VB
->TexCoordPtr
[0]->size
== 4)
981 assert (0); /* should be caught by savageCheckPTexHack */
982 else if (VB
->TexCoordPtr
[0]->size
>= 2)
983 /* The chromium menu emits some 3D tex coords even though no
984 * 3D texture is enabled. Ignore the 3rd coordinate. */
985 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_2F
, SAVAGE_EMIT_ST0
, SAVAGE_SKIP_ST0
);
986 else if (VB
->TexCoordPtr
[0]->size
== 1) {
987 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_1F
, SAVAGE_EMIT_S0
, SAVAGE_SKIP_S0
);
993 skip
&= ~SAVAGE_SKIP_ST0
;
1001 static INLINE GLuint
savageChooseVertexFormat_s4( GLcontext
*ctx
)
1003 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1004 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1005 struct vertex_buffer
*VB
= &tnl
->vb
;
1006 DECLARE_RENDERINPUTS(index_bitset
);
1007 GLuint setupIndex
= SAVAGE_EMIT_XYZ
;
1011 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
1012 skip
= SAVAGE_SKIP_ALL_S4
;
1013 skip
&= ~SAVAGE_SKIP_Z
; /* all mesa vertices have a z coordinate */
1015 if (RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
) || !(ctx
->_TriangleCaps
& DD_FLATSHADE
))
1016 NEED_ATTR( SAVAGE_EMIT_W
, SAVAGE_SKIP_W
);
1018 /* t_context.c always includes a diffuse color */
1019 NEED_ATTR( SAVAGE_EMIT_C0
, SAVAGE_SKIP_C0
);
1021 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
))
1022 NEED_ATTR( SAVAGE_EMIT_C1
, SAVAGE_SKIP_C1
);
1023 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
))
1024 NEED_ATTR( SAVAGE_EMIT_FOG
, SAVAGE_SKIP_C1
);
1026 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX0
)) {
1027 if (imesa
->ptexHack
)
1028 NEED_ATTR( SAVAGE_EMIT_STQ0
, SAVAGE_SKIP_ST0
);
1029 else if (VB
->TexCoordPtr
[0]->size
== 4)
1030 assert (0); /* should be caught by savageCheckPTexHack */
1031 else if (VB
->TexCoordPtr
[0]->size
>= 2)
1032 /* The chromium menu emits some 3D tex coords even though no
1033 * 3D texture is enabled. Ignore the 3rd coordinate. */
1034 NEED_ATTR( SAVAGE_EMIT_ST0
, SAVAGE_SKIP_ST0
);
1036 NEED_ATTR( SAVAGE_EMIT_S0
, SAVAGE_SKIP_S0
);
1038 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX1
)) {
1039 if (VB
->TexCoordPtr
[1]->size
== 4)
1040 /* projective textures are not supported by the hardware */
1041 assert (0); /* should be caught by savageCheckPTexHack */
1042 else if (VB
->TexCoordPtr
[1]->size
>= 2)
1043 NEED_ATTR( SAVAGE_EMIT_ST1
, SAVAGE_SKIP_ST1
);
1045 NEED_ATTR( SAVAGE_EMIT_S1
, SAVAGE_SKIP_S1
);
1048 /* if nothing changed we can skip the rest */
1049 if (setupIndex
== imesa
->SetupIndex
&& imesa
->vertex_size
!= 0)
1052 if (imesa
->enable_vdma
) {
1053 mask
= SAVAGE_SKIP_W
;
1054 size
= 10 - (skip
& 1) - (skip
>> 1 & 1) -
1055 (skip
>> 2 & 1) - (skip
>> 3 & 1) - (skip
>> 4 & 1) -
1056 (skip
>> 5 & 1) - (skip
>> 6 & 1) - (skip
>> 7 & 1);
1067 imesa
->vertex_attr_count
= 0;
1069 if (skip
& SAVAGE_SKIP_W
)
1070 DO_EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
);
1071 else if (setupIndex
& SAVAGE_EMIT_W
)
1072 DO_EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
);
1074 DO_EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
);
1078 DO_EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
);
1080 if (!(skip
& SAVAGE_SKIP_C1
)) {
1081 if (!(setupIndex
& (SAVAGE_EMIT_C1
|SAVAGE_EMIT_FOG
)))
1084 if (setupIndex
& SAVAGE_EMIT_C1
)
1085 DO_EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
);
1088 if (setupIndex
& SAVAGE_EMIT_FOG
)
1089 DO_EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
);
1095 if ((skip
& SAVAGE_SKIP_ST0
) != SAVAGE_SKIP_ST0
) {
1096 if ((setupIndex
& SAVAGE_EMIT_STQ0
) == SAVAGE_EMIT_STQ0
)
1097 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_3F_XYW
);
1098 else if ((setupIndex
& SAVAGE_EMIT_ST0
) == SAVAGE_EMIT_ST0
)
1099 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_2F
);
1100 else if ((setupIndex
& SAVAGE_EMIT_ST0
) == SAVAGE_EMIT_S0
) {
1101 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_1F
);
1102 if (!(skip
& SAVAGE_SKIP_T0
)) EMIT_PAD( 4 );
1104 if (!(skip
& SAVAGE_SKIP_S0
)) EMIT_PAD( 4 );
1105 if (!(skip
& SAVAGE_SKIP_T0
)) EMIT_PAD( 4 );
1109 if ((skip
& SAVAGE_SKIP_ST1
) != SAVAGE_SKIP_ST1
) {
1110 if ((setupIndex
& SAVAGE_EMIT_ST1
) == SAVAGE_EMIT_ST1
)
1111 DO_EMIT_ATTR( _TNL_ATTRIB_TEX1
, EMIT_2F
);
1112 else if ((setupIndex
& SAVAGE_EMIT_ST1
) == SAVAGE_EMIT_S1
) {
1113 DO_EMIT_ATTR( _TNL_ATTRIB_TEX1
, EMIT_1F
);
1114 if (!(skip
& SAVAGE_SKIP_T1
)) EMIT_PAD( 4 );
1116 if (!(skip
& SAVAGE_SKIP_S1
)) EMIT_PAD( 4 );
1117 if (!(skip
& SAVAGE_SKIP_T1
)) EMIT_PAD( 4 );
1126 static void savageRenderStart( GLcontext
*ctx
)
1128 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1129 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1130 struct vertex_buffer
*VB
= &tnl
->vb
;
1131 GLuint setupIndex
= SAVAGE_EMIT_XYZ
;
1134 /* Check if we need to apply the ptex hack. Choose a new render
1135 * state if necessary. (Note: this can't be done in
1136 * savageRunPipeline, since the number of vertex coordinates can
1137 * change in the pipeline. texmat or texgen or both?) */
1138 ptexHack
= savageCheckPTexHack( ctx
);
1139 if (ptexHack
!= imesa
->ptexHack
) {
1140 imesa
->ptexHack
= ptexHack
;
1141 savageChooseRenderState (ctx
);
1143 /* Handle fallback cases identified in savageCheckPTexHack. */
1144 if (SAVAGE_CONTEXT(ctx
)->Fallback
) {
1145 tnl
->Driver
.Render
.Start(ctx
);
1151 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
1153 if (imesa
->savageScreen
->chipset
< S3_SAVAGE4
) {
1154 setupIndex
= savageChooseVertexFormat_s3d(ctx
);
1156 setupIndex
= savageChooseVertexFormat_s4(ctx
);
1159 /* Need to change the vertex emit code if the SetupIndex changed or
1160 * is set for the first time (indicated by vertex_size == 0). */
1161 if (setupIndex
!= imesa
->SetupIndex
|| imesa
->vertex_size
== 0) {
1162 GLuint hwVertexSize
;
1163 imesa
->vertex_size
=
1164 _tnl_install_attrs( ctx
,
1165 imesa
->vertex_attrs
,
1166 imesa
->vertex_attr_count
,
1167 imesa
->hw_viewport
, 0 );
1168 imesa
->vertex_size
>>= 2;
1169 imesa
->SetupIndex
= setupIndex
;
1171 hwVertexSize
= imesa
->vertex_size
;
1172 if (setupIndex
& SAVAGE_EMIT_Q0
) {
1173 /* The vertex setup code emits homogenous texture
1174 * coordinates. They are converted to normal 2D coords by
1175 * savage_ptex_tri/line/point. Now we have two different
1176 * vertex sizes. Functions that emit vertices to the hardware
1177 * need to use HwVertexSize, anything that manipulates the
1178 * vertices generated by t_vertex uses vertex_size. */
1180 assert (imesa
->ptexHack
);
1182 assert (!imesa
->ptexHack
);
1184 if (hwVertexSize
!= imesa
->HwVertexSize
) {
1185 /* Changing the vertex size: flush vertex and command buffer and
1186 * discard the DMA buffer, if we were using one. */
1187 savageFlushVertices(imesa
);
1188 savageFlushCmdBuf(imesa
, GL_TRUE
);
1189 if (hwVertexSize
== 8 && imesa
->enable_vdma
) {
1190 if (SAVAGE_DEBUG
& DEBUG_DMA
)
1191 fprintf (stderr
, "Using DMA, skip=0x%02x\n", imesa
->skip
);
1192 /* we can use vertex dma */
1193 imesa
->vtxBuf
= &imesa
->dmaVtxBuf
;
1195 if (SAVAGE_DEBUG
& DEBUG_DMA
)
1196 fprintf (stderr
, "Not using DMA, skip=0x%02x\n", imesa
->skip
);
1197 imesa
->vtxBuf
= &imesa
->clientVtxBuf
;
1199 imesa
->HwVertexSize
= hwVertexSize
;
1204 static void savageRenderFinish( GLcontext
*ctx
)
1206 /* Flush the last primitive now, before any state is changed. */
1207 savageFlushVertices(SAVAGE_CONTEXT(ctx
));
1209 if (SAVAGE_CONTEXT(ctx
)->RenderIndex
& SAVAGE_FALLBACK_BIT
)
1210 _swrast_flush( ctx
);
1214 /**********************************************************************/
1215 /* Transition to/from hardware rasterization. */
1216 /**********************************************************************/
1218 static const char * const fallbackStrings
[] = {
1225 "glEnable(GL_STENCIL) without hw stencil buffer",
1226 "glRenderMode(selection or feedback)",
1228 "Hardware rasterization disabled",
1229 "Projective texture",
1232 void savageFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
1234 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1235 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1236 GLuint oldfallback
= imesa
->Fallback
;
1238 for (index
= 0; (1 << index
) < bit
; ++index
);
1241 imesa
->Fallback
|= bit
;
1242 if (oldfallback
== 0) {
1243 /* the first fallback */
1244 _swsetup_Wakeup( ctx
);
1245 imesa
->RenderIndex
= ~0;
1247 if (!(oldfallback
& bit
) && (SAVAGE_DEBUG
& DEBUG_FALLBACKS
))
1248 fprintf (stderr
, "Savage begin fallback: 0x%x %s\n",
1249 bit
, fallbackStrings
[index
]);
1252 imesa
->Fallback
&= ~bit
;
1253 if (oldfallback
== bit
) {
1254 /* the last fallback */
1255 _swrast_flush( ctx
);
1256 tnl
->Driver
.Render
.Start
= savageRenderStart
;
1257 tnl
->Driver
.Render
.PrimitiveNotify
= savageRenderPrimitive
;
1258 tnl
->Driver
.Render
.Finish
= savageRenderFinish
;
1260 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1261 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1262 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1264 _tnl_invalidate_vertex_state( ctx
, ~0 );
1265 _tnl_invalidate_vertices( ctx
, ~0 );
1266 _tnl_install_attrs( ctx
,
1267 imesa
->vertex_attrs
,
1268 imesa
->vertex_attr_count
,
1269 imesa
->hw_viewport
, 0 );
1271 imesa
->new_gl_state
|= _SAVAGE_NEW_RENDER_STATE
;
1273 if ((oldfallback
& bit
) && (SAVAGE_DEBUG
& DEBUG_FALLBACKS
))
1274 fprintf (stderr
, "Savage end fallback: 0x%x %s\n",
1275 bit
, fallbackStrings
[index
]);
1280 /**********************************************************************/
1281 /* Initialization. */
1282 /**********************************************************************/
1284 void savageInitTriFuncs( GLcontext
*ctx
)
1286 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1287 static int firsttime
= 1;
1294 tnl
->Driver
.RunPipeline
= savageRunPipeline
;
1295 tnl
->Driver
.Render
.Start
= savageRenderStart
;
1296 tnl
->Driver
.Render
.Finish
= savageRenderFinish
;
1297 tnl
->Driver
.Render
.PrimitiveNotify
= savageRenderPrimitive
;
1298 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1300 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1301 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1302 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1304 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
1305 (6 + 2*ctx
->Const
.MaxTextureUnits
) * sizeof(GLfloat
) );
1307 SAVAGE_CONTEXT(ctx
)->verts
= (char *)tnl
->clipspace
.vertex_buf
;