1 /* $XFree86$ */ /* -*- 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>
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 u_int32_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 u_int32_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 u_int32_t
*vb
= savageAllocVtxBuf (imesa
, 6*vertsize
);
132 const GLfloat x
= tmp
->v
.x
;
133 const GLfloat y
= tmp
->v
.y
;
134 const GLfloat sz
= imesa
->glCtx
->Point
._Size
* .5;
137 *(float *)&vb
[0] = x
- sz
;
138 *(float *)&vb
[1] = y
- sz
;
139 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
141 *(float *)&vb
[0] = x
+ sz
;
142 *(float *)&vb
[1] = y
- sz
;
143 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
145 *(float *)&vb
[0] = x
+ sz
;
146 *(float *)&vb
[1] = y
+ sz
;
147 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
149 *(float *)&vb
[0] = x
+ sz
;
150 *(float *)&vb
[1] = y
+ sz
;
151 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
153 *(float *)&vb
[0] = x
- sz
;
154 *(float *)&vb
[1] = y
+ sz
;
155 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
157 *(float *)&vb
[0] = x
- sz
;
158 *(float *)&vb
[1] = y
- sz
;
159 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
162 static __inline__
void savage_draw_line (savageContextPtr imesa
,
164 savageVertexPtr v1
) {
165 GLuint vertsize
= imesa
->HwVertexSize
;
166 u_int32_t
*vb
= savageAllocVtxBuf (imesa
, 6*vertsize
);
167 GLfloat width
= imesa
->glCtx
->Line
._Width
;
168 GLfloat dx
, dy
, ix
, iy
;
171 dx
= v0
->v
.x
- v1
->v
.x
;
172 dy
= v0
->v
.y
- v1
->v
.y
;
174 ix
= width
* .5; iy
= 0;
175 if (dx
* dx
> dy
* dy
) {
179 *(float *)&vb
[0] = v0
->v
.x
- ix
;
180 *(float *)&vb
[1] = v0
->v
.y
- iy
;
181 EMIT_VERT (j
, vb
, vertsize
, 2, v0
);
183 *(float *)&vb
[0] = v1
->v
.x
+ ix
;
184 *(float *)&vb
[1] = v1
->v
.y
+ iy
;
185 EMIT_VERT (j
, vb
, vertsize
, 2, v1
);
187 *(float *)&vb
[0] = v0
->v
.x
+ ix
;
188 *(float *)&vb
[1] = v0
->v
.y
+ iy
;
189 EMIT_VERT (j
, vb
, vertsize
, 2, v0
);
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] = v1
->v
.x
- ix
;
196 *(float *)&vb
[1] = v1
->v
.y
- iy
;
197 EMIT_VERT (j
, vb
, vertsize
, 2, v1
);
199 *(float *)&vb
[0] = v1
->v
.x
+ ix
;
200 *(float *)&vb
[1] = v1
->v
.y
+ iy
;
201 EMIT_VERT (j
, vb
, vertsize
, 2, v1
);
204 /* Fallback drawing functions for the ptex hack. Code duplication
205 * (especially lines and points) isn't beautiful, but I didn't feel
206 * like inventing yet another template. :-/
208 #define PTEX_VERTEX( j, tmp, vertex_size, start, v) \
210 GLfloat rhw = 1.0 / v->f[vertex_size]; \
211 for ( j = start ; j < vertex_size ; j++ ) \
212 tmp.f[j] = v->f[j]; \
213 tmp.f[3] *= v->f[vertex_size]; \
214 tmp.f[vertex_size-2] *= rhw; \
215 tmp.f[vertex_size-1] *= rhw; \
218 static void __inline__
savage_ptex_tri (savageContextPtr imesa
,
221 savageVertexPtr v2
) {
222 GLuint vertsize
= imesa
->HwVertexSize
;
223 u_int32_t
*vb
= savageAllocVtxBuf (imesa
, 3*vertsize
);
227 PTEX_VERTEX (j
, tmp
, vertsize
, 0, v0
); EMIT_VERT (j
, vb
, vertsize
, 0, &tmp
);
228 PTEX_VERTEX (j
, tmp
, vertsize
, 0, v1
); EMIT_VERT (j
, vb
, vertsize
, 0, &tmp
);
229 PTEX_VERTEX (j
, tmp
, vertsize
, 0, v2
); EMIT_VERT (j
, vb
, vertsize
, 0, &tmp
);
232 static __inline__
void savage_ptex_line (savageContextPtr imesa
,
234 savageVertexPtr v1
) {
235 GLuint vertsize
= imesa
->HwVertexSize
;
236 u_int32_t
*vb
= savageAllocVtxBuf (imesa
, 6*vertsize
);
237 GLfloat width
= imesa
->glCtx
->Line
._Width
;
238 GLfloat dx
, dy
, ix
, iy
;
239 savageVertex tmp0
, tmp1
;
242 PTEX_VERTEX (j
, tmp0
, vertsize
, 2, v0
);
243 PTEX_VERTEX (j
, tmp1
, vertsize
, 2, v1
);
245 dx
= v0
->v
.x
- v1
->v
.x
;
246 dy
= v0
->v
.y
- v1
->v
.y
;
248 ix
= width
* .5; iy
= 0;
249 if (dx
* dx
> dy
* dy
) {
253 *(float *)&vb
[0] = v0
->v
.x
- ix
;
254 *(float *)&vb
[1] = v0
->v
.y
- iy
;
255 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp0
);
257 *(float *)&vb
[0] = v1
->v
.x
+ ix
;
258 *(float *)&vb
[1] = v1
->v
.y
+ iy
;
259 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp1
);
261 *(float *)&vb
[0] = v0
->v
.x
+ ix
;
262 *(float *)&vb
[1] = v0
->v
.y
+ iy
;
263 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp0
);
265 *(float *)&vb
[0] = v0
->v
.x
- ix
;
266 *(float *)&vb
[1] = v0
->v
.y
- iy
;
267 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp0
);
269 *(float *)&vb
[0] = v1
->v
.x
- ix
;
270 *(float *)&vb
[1] = v1
->v
.y
- iy
;
271 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp1
);
273 *(float *)&vb
[0] = v1
->v
.x
+ ix
;
274 *(float *)&vb
[1] = v1
->v
.y
+ iy
;
275 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp1
);
278 static __inline__
void savage_ptex_point (savageContextPtr imesa
,
279 savageVertexPtr v0
) {
280 GLuint vertsize
= imesa
->HwVertexSize
;
281 u_int32_t
*vb
= savageAllocVtxBuf (imesa
, 6*vertsize
);
282 const GLfloat x
= v0
->v
.x
;
283 const GLfloat y
= v0
->v
.y
;
284 const GLfloat sz
= imesa
->glCtx
->Point
._Size
* .5;
288 PTEX_VERTEX (j
, tmp
, vertsize
, 2, v0
);
290 *(float *)&vb
[0] = x
- sz
;
291 *(float *)&vb
[1] = y
- sz
;
292 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp
);
294 *(float *)&vb
[0] = x
+ sz
;
295 *(float *)&vb
[1] = y
- sz
;
296 EMIT_VERT (j
, vb
, vertsize
, 2, &tmp
);
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
);
315 /***********************************************************************
316 * Macros for t_dd_tritmp.h to draw basic primitives *
317 ***********************************************************************/
319 #define TRI( a, b, c ) \
322 imesa->draw_tri( imesa, a, b, c ); \
324 savage_draw_triangle( imesa, a, b, c ); \
327 #define QUAD( a, b, c, d ) \
330 imesa->draw_tri( imesa, a, b, d ); \
331 imesa->draw_tri( imesa, b, c, d ); \
333 savage_draw_quad( imesa, a, b, c, d ); \
336 #define LINE( v0, v1 ) \
339 imesa->draw_line( imesa, v0, v1 ); \
341 savage_draw_line( imesa, v0, v1 ); \
344 #define POINT( v0 ) \
347 imesa->draw_point( imesa, v0 ); \
349 savage_draw_point( imesa, v0 ); \
353 /***********************************************************************
354 * Build render functions from dd templates *
355 ***********************************************************************/
357 #define SAVAGE_OFFSET_BIT 0x1
358 #define SAVAGE_TWOSIDE_BIT 0x2
359 #define SAVAGE_UNFILLED_BIT 0x4
360 #define SAVAGE_FALLBACK_BIT 0x8
361 #define SAVAGE_MAX_TRIFUNC 0x10
365 tnl_points_func points
;
367 tnl_triangle_func triangle
;
369 } rast_tab
[SAVAGE_MAX_TRIFUNC
];
372 #define DO_FALLBACK (IND & SAVAGE_FALLBACK_BIT)
373 #define DO_OFFSET (IND & SAVAGE_OFFSET_BIT)
374 #define DO_UNFILLED (IND & SAVAGE_UNFILLED_BIT)
375 #define DO_TWOSIDE (IND & SAVAGE_TWOSIDE_BIT)
381 #define DO_FULL_QUAD 1
385 #define HAVE_BACK_COLORS 0
386 #define HAVE_HW_FLATSHADE 1
387 #define VERTEX savageVertex
390 #define DEPTH_SCALE imesa->depth_scale
391 #define UNFILLED_TRI unfilled_tri
392 #define UNFILLED_QUAD unfilled_quad
393 #define VERT_X(_v) _v->v.x
394 #define VERT_Y(_v) _v->v.y
395 #define VERT_Z(_v) _v->v.z
396 #define AREA_IS_CCW( a ) (a > 0)
397 #define GET_VERTEX(e) (imesa->verts + (e * imesa->vertex_size * sizeof(int)))
399 #define VERT_SET_RGBA( v, c ) \
401 savage_color_t *color = (savage_color_t *)&((v)->ub4[coloroffset]); \
402 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
403 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
404 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
405 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
407 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
408 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
409 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
411 #define VERT_SET_SPEC( v, c ) \
414 savage_color_t *spec = (savage_color_t *)&((v)->ub4[specoffset]); \
415 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
416 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
417 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
420 #define VERT_COPY_SPEC( v0, v1 ) \
421 if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset])
422 #define VERT_SAVE_SPEC( idx ) \
423 if (specoffset) spec[idx] = v[idx]->ui[specoffset]
424 #define VERT_RESTORE_SPEC( idx ) \
425 if (specoffset) v[idx]->ui[specoffset] = spec[idx]
427 #define LOCAL_VARS(n) \
428 savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
429 GLuint color[n], spec[n]; \
430 GLuint coloroffset = \
431 ((imesa->skip & SAVAGE_SKIP_W) ? 3 : 4); \
432 GLboolean specoffset = \
433 ((imesa->skip & SAVAGE_SKIP_C1) ? 0 : coloroffset+1); \
434 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
436 /***********************************************************************
437 * Helpers for rendering unfilled primitives *
438 ***********************************************************************/
440 #define RASTERIZE(x) if (imesa->raster_primitive != reduced_prim[x]) \
441 savageRasterPrimitive( ctx, x )
442 #define RENDER_PRIMITIVE imesa->render_primitive
443 #define IND SAVAGE_FALLBACK_BIT
445 #include "tnl_dd/t_dd_unfilled.h"
449 /***********************************************************************
450 * Generate GL render functions *
451 ***********************************************************************/
456 #include "tnl_dd/t_dd_tritmp.h"
458 #define IND (SAVAGE_OFFSET_BIT)
459 #define TAG(x) x##_offset
460 #include "tnl_dd/t_dd_tritmp.h"
462 #define IND (SAVAGE_TWOSIDE_BIT)
463 #define TAG(x) x##_twoside
464 #include "tnl_dd/t_dd_tritmp.h"
466 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT)
467 #define TAG(x) x##_twoside_offset
468 #include "tnl_dd/t_dd_tritmp.h"
470 #define IND (SAVAGE_UNFILLED_BIT)
471 #define TAG(x) x##_unfilled
472 #include "tnl_dd/t_dd_tritmp.h"
474 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
475 #define TAG(x) x##_offset_unfilled
476 #include "tnl_dd/t_dd_tritmp.h"
478 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT)
479 #define TAG(x) x##_twoside_unfilled
480 #include "tnl_dd/t_dd_tritmp.h"
482 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
483 #define TAG(x) x##_twoside_offset_unfilled
484 #include "tnl_dd/t_dd_tritmp.h"
486 #define IND (SAVAGE_FALLBACK_BIT)
487 #define TAG(x) x##_fallback
488 #include "tnl_dd/t_dd_tritmp.h"
490 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
491 #define TAG(x) x##_offset_fallback
492 #include "tnl_dd/t_dd_tritmp.h"
494 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_FALLBACK_BIT)
495 #define TAG(x) x##_twoside_fallback
496 #include "tnl_dd/t_dd_tritmp.h"
498 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
499 #define TAG(x) x##_twoside_offset_fallback
500 #include "tnl_dd/t_dd_tritmp.h"
502 #define IND (SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
503 #define TAG(x) x##_unfilled_fallback
504 #include "tnl_dd/t_dd_tritmp.h"
506 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
507 #define TAG(x) x##_offset_unfilled_fallback
508 #include "tnl_dd/t_dd_tritmp.h"
510 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
511 #define TAG(x) x##_twoside_unfilled_fallback
512 #include "tnl_dd/t_dd_tritmp.h"
514 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT| \
516 #define TAG(x) x##_twoside_offset_unfilled_fallback
517 #include "tnl_dd/t_dd_tritmp.h"
520 static void init_rast_tab( void )
525 init_twoside_offset();
527 init_offset_unfilled();
528 init_twoside_unfilled();
529 init_twoside_offset_unfilled();
531 init_offset_fallback();
532 init_twoside_fallback();
533 init_twoside_offset_fallback();
534 init_unfilled_fallback();
535 init_offset_unfilled_fallback();
536 init_twoside_unfilled_fallback();
537 init_twoside_offset_unfilled_fallback();
542 /***********************************************************************
543 * Rasterization fallback helpers *
544 ***********************************************************************/
547 /* This code is hit only when a mix of accelerated and unaccelerated
548 * primitives are being drawn, and only for the unaccelerated
552 savage_fallback_tri( savageContextPtr imesa
,
557 GLcontext
*ctx
= imesa
->glCtx
;
561 _swsetup_Translate( ctx
, v0
, &v
[0] );
562 _swsetup_Translate( ctx
, v1
, &v
[1] );
563 _swsetup_Translate( ctx
, v2
, &v
[2] );
564 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
569 savage_fallback_line( savageContextPtr imesa
,
573 GLcontext
*ctx
= imesa
->glCtx
;
577 _swsetup_Translate( ctx
, v0
, &v
[0] );
578 _swsetup_Translate( ctx
, v1
, &v
[1] );
579 _swrast_Line( ctx
, &v
[0], &v
[1] );
584 savage_fallback_point( savageContextPtr imesa
,
587 GLcontext
*ctx
= imesa
->glCtx
;
591 _swsetup_Translate( ctx
, v0
, &v
[0] );
592 _swrast_Point( ctx
, &v
[0] );
597 /**********************************************************************/
598 /* Render unclipped begin/end objects */
599 /**********************************************************************/
601 #define VERT(x) (savageVertexPtr)(savageVerts + (x * vertsize * sizeof(int)))
602 #define RENDER_POINTS( start, count ) \
603 for ( ; start < count ; start++) \
604 savage_draw_point( imesa, VERT(start) )
605 #define RENDER_LINE( v0, v1 ) \
606 savage_draw_line( imesa, VERT(v0), VERT(v1) )
607 #define RENDER_TRI( v0, v1, v2 ) \
608 savage_draw_triangle( imesa, VERT(v0), VERT(v1), VERT(v2) )
609 #define RENDER_QUAD( v0, v1, v2, v3 ) \
610 savage_draw_quad( imesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
611 #define INIT(x) do { \
612 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
613 savageRenderPrimitive( ctx, x ); \
614 /*SAVAGE_CONTEXT(ctx)->render_primitive = x;*/ \
618 savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
619 const GLuint vertsize = imesa->vertex_size; \
620 const char *savageVerts = (char *)imesa->verts; \
621 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
623 #define RESET_STIPPLE
624 #define RESET_OCCLUSION
625 #define PRESERVE_VB_DEFS
627 #define TAG(x) savage_##x##_verts
628 #include "tnl/t_vb_rendertmp.h"
631 #define TAG(x) savage_##x##_elts
632 #define ELT(x) elt[x]
633 #include "tnl/t_vb_rendertmp.h"
636 /**********************************************************************/
637 /* Render clipped primitives */
638 /**********************************************************************/
640 static void savageRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
643 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
644 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
646 /* Render the new vertices as an unclipped polygon.
649 GLuint
*tmp
= VB
->Elts
;
650 VB
->Elts
= (GLuint
*)elts
;
651 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
, PRIM_BEGIN
|PRIM_END
);
656 static void savageRenderClippedLine( GLcontext
*ctx
, GLuint ii
, GLuint jj
)
658 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
659 tnl
->Driver
.Render
.Line( ctx
, ii
, jj
);
662 static void savageFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
665 r128ContextPtr rmesa = R128_CONTEXT( ctx );
666 GLuint vertsize = rmesa->vertex_size;
667 GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
668 GLubyte *r128verts = (GLubyte *)rmesa->verts;
669 const GLuint shift = rmesa->vertex_stride_shift;
670 const GLuint *start = (const GLuint *)VERT(elts[0]);
673 rmesa->num_verts += (n-2) * 3;
675 for (i = 2 ; i < n ; i++) {
676 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
677 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
678 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
685 /**********************************************************************/
686 /* Choose render functions */
687 /**********************************************************************/
689 #define _SAVAGE_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
690 _DD_NEW_LINE_SMOOTH | \
691 _DD_NEW_POINT_SMOOTH | \
692 _DD_NEW_TRI_SMOOTH | \
693 _DD_NEW_TRI_UNFILLED | \
694 _DD_NEW_TRI_LIGHT_TWOSIDE | \
695 _DD_NEW_TRI_OFFSET) \
697 /* original driver didn't have DD_POINT_SMOOTH. really needed? */
698 #define POINT_FALLBACK (DD_POINT_SMOOTH)
699 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
700 #define TRI_FALLBACK (DD_TRI_SMOOTH)
701 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
702 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
705 static void savageChooseRenderState(GLcontext
*ctx
)
707 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
708 GLuint flags
= ctx
->_TriangleCaps
;
711 /* Hook in fallback functions for the ptex hack. Do this first, so
712 * that a real fallback will overwrite them with the respective
713 * savage_fallback_... function.
715 if (imesa
->ptexHack
) {
716 /* Do textures make sense with points? */
717 imesa
->draw_point
= savage_ptex_point
;
718 imesa
->draw_line
= savage_ptex_line
;
719 imesa
->draw_tri
= savage_ptex_tri
;
720 index
|= SAVAGE_FALLBACK_BIT
;
722 imesa
->draw_point
= savage_draw_point
;
723 imesa
->draw_line
= savage_draw_line
;
724 imesa
->draw_tri
= savage_draw_triangle
;
727 if (flags
& (ANY_RASTER_FLAGS
|ANY_FALLBACK_FLAGS
)) {
728 if (flags
& ANY_RASTER_FLAGS
) {
729 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= SAVAGE_TWOSIDE_BIT
;
730 if (flags
& DD_TRI_OFFSET
) index
|= SAVAGE_OFFSET_BIT
;
731 if (flags
& DD_TRI_UNFILLED
) index
|= SAVAGE_UNFILLED_BIT
;
734 /* Hook in fallbacks for specific primitives.
736 if (flags
& ANY_FALLBACK_FLAGS
) {
737 if (flags
& POINT_FALLBACK
) imesa
->draw_point
= savage_fallback_point
;
738 if (flags
& LINE_FALLBACK
) imesa
->draw_line
= savage_fallback_line
;
739 if (flags
& TRI_FALLBACK
) imesa
->draw_tri
= savage_fallback_tri
;
740 index
|= SAVAGE_FALLBACK_BIT
;
744 if (index
!= imesa
->RenderIndex
) {
745 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
746 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
747 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
748 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
749 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
752 tnl
->Driver
.Render
.PrimTabVerts
= savage_render_tab_verts
;
753 tnl
->Driver
.Render
.PrimTabElts
= savage_render_tab_elts
;
754 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
755 tnl
->Driver
.Render
.ClippedPolygon
= savageRenderClippedPoly
/*r128FastRenderClippedPoly*/;
757 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
758 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
759 tnl
->Driver
.Render
.ClippedLine
= savageRenderClippedLine
;
760 tnl
->Driver
.Render
.ClippedPolygon
= savageRenderClippedPoly
;
763 imesa
->RenderIndex
= index
;
767 /**********************************************************************/
768 /* Validate state at pipeline start */
769 /**********************************************************************/
771 static void savageRunPipeline( GLcontext
*ctx
)
773 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
776 FALLBACK(ctx
, SAVAGE_FALLBACK_NORAST
, GL_TRUE
);
778 if (imesa
->new_state
)
779 savageDDUpdateHwState( ctx
);
781 if (!imesa
->Fallback
) {
782 if (imesa
->new_gl_state
& _SAVAGE_NEW_RENDER_STATE
)
783 savageChooseRenderState( ctx
);
785 /* choose the correct primitive type for tnl rendering */
786 if (imesa
->savageScreen
->chipset
< S3_SAVAGE4
&&
787 (ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
788 if (imesa
->HwPrim
!= SAVAGE_PRIM_TRILIST_201
)
789 savageFlushVertices(imesa
);
790 imesa
->HwPrim
= SAVAGE_PRIM_TRILIST_201
;
792 if (imesa
->HwPrim
!= SAVAGE_PRIM_TRILIST
)
793 savageFlushVertices(imesa
);
794 imesa
->HwPrim
= SAVAGE_PRIM_TRILIST
;
797 imesa
->new_gl_state
= 0;
800 _tnl_run_pipeline( ctx
);
803 FALLBACK(ctx
, SAVAGE_FALLBACK_NORAST
, GL_FALSE
);
806 /**********************************************************************/
807 /* High level hooks for t_vb_render.c */
808 /**********************************************************************/
810 /* This is called when Mesa switches between rendering triangle
811 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
812 * and lines, points and bitmaps.
814 * As the r128 uses triangles to render lines and points, it is
815 * necessary to turn off hardware culling when rendering these
819 static void savageRasterPrimitive( GLcontext
*ctx
, GLuint prim
)
821 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
824 if (imesa
->raster_primitive
!= prim
) {
825 imesa
->raster_primitive
= prim
;
826 imesa
->new_state
|= SAVAGE_NEW_CULL
;
827 savageDDUpdateHwState (ctx
);
831 if (ctx
->Polygon
.StippleFlag
&& mmesa
->haveHwStipple
)
833 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
834 mmesa
->setup
.dwgctl
&= ~(0xf<<20);
835 if (mmesa
->raster_primitive
== GL_TRIANGLES
)
836 mmesa
->setup
.dwgctl
|= mmesa
->poly_stipple
;
841 static void savageRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
843 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
844 GLuint rprim
= reduced_prim
[prim
];
846 imesa
->render_primitive
= prim
;
848 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
851 if (imesa
->raster_primitive
!= rprim
) {
852 savageRasterPrimitive( ctx
, rprim
);
856 /* Check if projective texture coordinates are used and if we can fake
857 * them. Fallback to swrast we can't. Returns GL_TRUE if projective
858 * texture coordinates must be faked, GL_FALSE otherwise.
860 static GLboolean
savageCheckPTexHack( GLcontext
*ctx
)
862 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
863 struct vertex_buffer
*VB
= &tnl
->vb
;
864 GLuint index
= tnl
->render_inputs
;
866 if (index
& _TNL_BIT_TEX(0) && VB
->TexCoordPtr
[0]->size
== 4) {
867 if ((index
& _TNL_BITS_TEX_ANY
) == _TNL_BIT_TEX(0))
868 return GL_TRUE
; /* apply ptex hack */
870 FALLBACK(ctx
, SAVAGE_FALLBACK_PROJ_TEXTURE
, GL_TRUE
);
872 if ((index
& _TNL_BIT_TEX(1)) && VB
->TexCoordPtr
[1]->size
== 4)
873 FALLBACK(ctx
, SAVAGE_FALLBACK_PROJ_TEXTURE
, GL_TRUE
);
875 return GL_FALSE
; /* don't apply ptex hack */
879 #define DO_EMIT_ATTR( ATTR, STYLE ) \
881 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = (ATTR); \
882 imesa->vertex_attrs[imesa->vertex_attr_count].format = (STYLE); \
883 imesa->vertex_attr_count++; \
886 #define NEED_ATTR( INDEX, SKIP ) \
888 setupIndex |= (INDEX); \
892 #define EMIT_ATTR( ATTR, STYLE, INDEX, SKIP ) \
894 NEED_ATTR( INDEX, SKIP ); \
895 DO_EMIT_ATTR( ATTR, STYLE ); \
898 #define EMIT_PAD( N ) \
900 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = 0; \
901 imesa->vertex_attrs[imesa->vertex_attr_count].format = EMIT_PAD; \
902 imesa->vertex_attrs[imesa->vertex_attr_count].offset = (N); \
903 imesa->vertex_attr_count++; \
906 #define SAVAGE_EMIT_XYZ 0x0001
907 #define SAVAGE_EMIT_W 0x0002
908 #define SAVAGE_EMIT_C0 0x0004
909 #define SAVAGE_EMIT_C1 0x0008
910 #define SAVAGE_EMIT_FOG 0x0010
911 #define SAVAGE_EMIT_S0 0x0020
912 #define SAVAGE_EMIT_T0 0x0040
913 #define SAVAGE_EMIT_Q0 0x0080
914 #define SAVAGE_EMIT_ST0 0x0060
915 #define SAVAGE_EMIT_STQ0 0x00e0
916 #define SAVAGE_EMIT_S1 0x0100
917 #define SAVAGE_EMIT_T1 0x0200
918 #define SAVAGE_EMIT_ST1 0x0300
921 static __inline__ GLuint
savageChooseVertexFormat_s3d( GLcontext
*ctx
)
923 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
924 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
925 struct vertex_buffer
*VB
= &tnl
->vb
;
926 GLuint index
= tnl
->render_inputs
;
927 GLuint setupIndex
= SAVAGE_EMIT_XYZ
;
930 imesa
->vertex_attr_count
= 0;
932 skip
= SAVAGE_SKIP_ALL_S3D
;
933 skip
&= ~SAVAGE_SKIP_Z
; /* all mesa vertices have a z coordinate */
935 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
936 * build up a hardware vertex.
938 if ((index
& _TNL_BITS_TEX_ANY
) || !(ctx
->_TriangleCaps
& DD_FLATSHADE
))
939 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
, SAVAGE_EMIT_W
, SAVAGE_SKIP_W
);
941 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
, 0, 0 );
943 skip
&= ~SAVAGE_SKIP_W
;
946 /* t_context.c always includes a diffuse color */
947 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
, SAVAGE_EMIT_C0
, SAVAGE_SKIP_C0
);
949 if ((index
& _TNL_BIT_COLOR1
))
950 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
, SAVAGE_EMIT_C1
, SAVAGE_SKIP_C1
);
953 if ((index
& _TNL_BIT_FOG
))
954 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, SAVAGE_EMIT_FOG
, SAVAGE_SKIP_C1
);
957 skip
&= ~SAVAGE_SKIP_C1
;
959 if (index
& _TNL_BIT_TEX(0)) {
961 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_3F_XYW
, SAVAGE_EMIT_STQ0
, SAVAGE_SKIP_ST0
);
962 else if (VB
->TexCoordPtr
[0]->size
== 4)
963 assert (0); /* should be caught by savageCheckPTexHack */
964 else if (VB
->TexCoordPtr
[0]->size
>= 2)
965 /* The chromium menu emits some 3D tex coords even though no
966 * 3D texture is enabled. Ignore the 3rd coordinate. */
967 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_2F
, SAVAGE_EMIT_ST0
, SAVAGE_SKIP_ST0
);
968 else if (VB
->TexCoordPtr
[0]->size
== 1) {
969 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_1F
, SAVAGE_EMIT_S0
, SAVAGE_SKIP_S0
);
975 skip
&= ~SAVAGE_SKIP_ST0
;
983 static __inline__ GLuint
savageChooseVertexFormat_s4( GLcontext
*ctx
)
985 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
986 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
987 struct vertex_buffer
*VB
= &tnl
->vb
;
988 GLuint index
= tnl
->render_inputs
;
989 GLuint setupIndex
= SAVAGE_EMIT_XYZ
;
993 skip
= SAVAGE_SKIP_ALL_S4
;
994 skip
&= ~SAVAGE_SKIP_Z
; /* all mesa vertices have a z coordinate */
996 if ((index
& _TNL_BITS_TEX_ANY
) || !(ctx
->_TriangleCaps
& DD_FLATSHADE
))
997 NEED_ATTR( SAVAGE_EMIT_W
, SAVAGE_SKIP_W
);
999 /* t_context.c always includes a diffuse color */
1000 NEED_ATTR( SAVAGE_EMIT_C0
, SAVAGE_SKIP_C0
);
1002 if (index
& (_TNL_BIT_COLOR1
|_TNL_BIT_FOG
)) {
1003 if ((index
& _TNL_BIT_COLOR1
))
1004 NEED_ATTR( SAVAGE_EMIT_C1
, SAVAGE_SKIP_C1
);
1005 if ((index
& _TNL_BIT_FOG
))
1006 NEED_ATTR( SAVAGE_EMIT_FOG
, SAVAGE_SKIP_C1
);
1009 if (index
& _TNL_BIT_TEX(0)) {
1010 if (imesa
->ptexHack
)
1011 NEED_ATTR( SAVAGE_EMIT_STQ0
, SAVAGE_SKIP_ST0
);
1012 else if (VB
->TexCoordPtr
[0]->size
== 4)
1013 assert (0); /* should be caught by savageCheckPTexHack */
1014 else if (VB
->TexCoordPtr
[0]->size
>= 2)
1015 /* The chromium menu emits some 3D tex coords even though no
1016 * 3D texture is enabled. Ignore the 3rd coordinate. */
1017 NEED_ATTR( SAVAGE_EMIT_ST0
, SAVAGE_SKIP_ST0
);
1019 NEED_ATTR( SAVAGE_EMIT_S0
, SAVAGE_SKIP_S0
);
1021 if (index
& _TNL_BIT_TEX(1)) {
1022 if (VB
->TexCoordPtr
[1]->size
== 4)
1023 /* projective textures are not supported by the hardware */
1024 assert (0); /* should be caught by savageCheckPTexHack */
1025 else if (VB
->TexCoordPtr
[1]->size
>= 2)
1026 NEED_ATTR( SAVAGE_EMIT_ST1
, SAVAGE_SKIP_ST1
);
1028 NEED_ATTR( SAVAGE_EMIT_S1
, SAVAGE_SKIP_S1
);
1031 /* if nothing changed we can skip the rest */
1032 if (setupIndex
== imesa
->SetupIndex
&& imesa
->vertex_size
!= 0)
1035 mask
= SAVAGE_SKIP_W
;
1036 size
= 10 - (skip
& 1) - (skip
>> 1 & 1) -
1037 (skip
>> 2 & 1) - (skip
>> 3 & 1) - (skip
>> 4 & 1) -
1038 (skip
>> 5 & 1) - (skip
>> 6 & 1) - (skip
>> 7 & 1);
1048 imesa
->vertex_attr_count
= 0;
1050 if (skip
& SAVAGE_SKIP_W
)
1051 DO_EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
);
1052 else if (setupIndex
& SAVAGE_EMIT_W
)
1053 DO_EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
);
1055 DO_EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
);
1059 DO_EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
);
1061 if (!(skip
& SAVAGE_SKIP_C1
)) {
1062 if (!(setupIndex
& (SAVAGE_EMIT_C1
|SAVAGE_EMIT_FOG
)))
1065 if (setupIndex
& SAVAGE_EMIT_C1
)
1066 DO_EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
);
1069 if (setupIndex
& SAVAGE_EMIT_FOG
)
1070 DO_EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
);
1076 if ((skip
& SAVAGE_SKIP_ST0
) != SAVAGE_SKIP_ST0
) {
1077 if ((setupIndex
& SAVAGE_EMIT_STQ0
) == SAVAGE_EMIT_STQ0
)
1078 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_3F_XYW
);
1079 else if ((setupIndex
& SAVAGE_EMIT_ST0
) == SAVAGE_EMIT_ST0
)
1080 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_2F
);
1081 else if ((setupIndex
& SAVAGE_EMIT_ST0
) == SAVAGE_EMIT_S0
) {
1082 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_1F
);
1083 if (!(skip
& SAVAGE_SKIP_T0
)) EMIT_PAD( 4 );
1085 if (!(skip
& SAVAGE_SKIP_S0
)) EMIT_PAD( 4 );
1086 if (!(skip
& SAVAGE_SKIP_T0
)) EMIT_PAD( 4 );
1090 if ((skip
& SAVAGE_SKIP_ST1
) != SAVAGE_SKIP_ST1
) {
1091 if ((setupIndex
& SAVAGE_EMIT_ST1
) == SAVAGE_EMIT_ST1
)
1092 DO_EMIT_ATTR( _TNL_ATTRIB_TEX1
, EMIT_2F
);
1093 else if ((setupIndex
& SAVAGE_EMIT_ST1
) == SAVAGE_EMIT_S1
) {
1094 DO_EMIT_ATTR( _TNL_ATTRIB_TEX1
, EMIT_1F
);
1095 if (!(skip
& SAVAGE_SKIP_T1
)) EMIT_PAD( 4 );
1097 if (!(skip
& SAVAGE_SKIP_S1
)) EMIT_PAD( 4 );
1098 if (!(skip
& SAVAGE_SKIP_T1
)) EMIT_PAD( 4 );
1107 static void savageRenderStart( GLcontext
*ctx
)
1109 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1110 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1111 struct vertex_buffer
*VB
= &tnl
->vb
;
1112 GLuint setupIndex
= SAVAGE_EMIT_XYZ
;
1115 /* Check if we need to apply the ptex hack. Choose a new render
1116 * state if necessary. (Note: this can't be done in
1117 * savageRunPipeline, since the number of vertex coordinates can
1118 * change in the pipeline. texmat or texgen or both?) */
1119 ptexHack
= savageCheckPTexHack( ctx
);
1120 if (ptexHack
!= imesa
->ptexHack
) {
1121 imesa
->ptexHack
= ptexHack
;
1122 savageChooseRenderState (ctx
);
1124 /* Handle fallback cases identified in savageCheckPTexHack. */
1125 if (SAVAGE_CONTEXT(ctx
)->Fallback
) {
1126 tnl
->Driver
.Render
.Start(ctx
);
1132 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
1134 if (imesa
->savageScreen
->chipset
< S3_SAVAGE4
) {
1135 setupIndex
= savageChooseVertexFormat_s3d(ctx
);
1137 setupIndex
= savageChooseVertexFormat_s4(ctx
);
1140 /* Need to change the vertex emit code if the SetupIndex changed or
1141 * is set for the first time (indicated by vertex_size == 0). */
1142 if (setupIndex
!= imesa
->SetupIndex
|| imesa
->vertex_size
== 0) {
1143 GLuint hwVertexSize
;
1144 imesa
->vertex_size
=
1145 _tnl_install_attrs( ctx
,
1146 imesa
->vertex_attrs
,
1147 imesa
->vertex_attr_count
,
1148 imesa
->hw_viewport
, 0 );
1149 imesa
->vertex_size
>>= 2;
1150 imesa
->SetupIndex
= setupIndex
;
1152 hwVertexSize
= imesa
->vertex_size
;
1153 if (setupIndex
& SAVAGE_EMIT_Q0
) {
1154 /* The vertex setup code emits homogenous texture
1155 * coordinates. They are converted to normal 2D coords by
1156 * savage_ptex_tri/line/point. Now we have two different
1157 * vertex sizes. Functions that emit vertices to the hardware
1158 * need to use HwVertexSize, anything that manipulates the
1159 * vertices generated by t_vertex uses vertex_size. */
1161 assert (imesa
->ptexHack
);
1163 assert (!imesa
->ptexHack
);
1165 if (hwVertexSize
!= imesa
->HwVertexSize
) {
1166 /* Changing the vertex size: flush vertex and command buffer and
1167 * discard the DMA buffer, if we were using one. */
1168 savageFlushVertices(imesa
);
1169 savageFlushCmdBuf(imesa
, GL_TRUE
);
1170 if (hwVertexSize
== 8) {
1171 if (SAVAGE_DEBUG
& DEBUG_DMA
)
1172 fprintf (stderr
, "Using DMA, skip=0x%02x\n", imesa
->skip
);
1173 /* we can use vertex dma */
1174 imesa
->vtxBuf
= &imesa
->dmaVtxBuf
;
1176 if (SAVAGE_DEBUG
& DEBUG_DMA
)
1177 fprintf (stderr
, "Not using DMA, skip=0x%02x\n", imesa
->skip
);
1178 imesa
->vtxBuf
= &imesa
->clientVtxBuf
;
1180 imesa
->HwVertexSize
= hwVertexSize
;
1185 static void savageRenderFinish( GLcontext
*ctx
)
1187 /* Flush the last primitive now, before any state is changed.
1188 * Alternatively state could be emitted in all state-changing
1189 * functions in savagestate.c and when changing the vertex format
1191 FLUSH_BATCH(SAVAGE_CONTEXT(ctx
));
1193 if (SAVAGE_CONTEXT(ctx
)->RenderIndex
& SAVAGE_FALLBACK_BIT
)
1194 _swrast_flush( ctx
);
1198 /**********************************************************************/
1199 /* Transition to/from hardware rasterization. */
1200 /**********************************************************************/
1202 static const char * const fallbackStrings
[] = {
1209 "glEnable(GL_STENCIL) without hw stencil buffer",
1210 "glRenderMode(selection or feedback)",
1212 "Hardware rasterization disabled",
1213 "Projective texture",
1216 void savageFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
1218 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1219 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1220 GLuint oldfallback
= imesa
->Fallback
;
1222 for (index
= 0; (1 << index
) < bit
; ++index
);
1225 imesa
->Fallback
|= bit
;
1226 if (oldfallback
== 0) {
1227 /* the first fallback */
1228 _swsetup_Wakeup( ctx
);
1229 imesa
->RenderIndex
= ~0;
1231 if (!(oldfallback
& bit
) && (SAVAGE_DEBUG
& DEBUG_FALLBACKS
))
1232 fprintf (stderr
, "Savage begin fallback: 0x%x %s\n",
1233 bit
, fallbackStrings
[index
]);
1236 imesa
->Fallback
&= ~bit
;
1237 if (oldfallback
== bit
) {
1238 /* the last fallback */
1239 _swrast_flush( ctx
);
1240 tnl
->Driver
.Render
.Start
= savageRenderStart
;
1241 tnl
->Driver
.Render
.PrimitiveNotify
= savageRenderPrimitive
;
1242 tnl
->Driver
.Render
.Finish
= savageRenderFinish
;
1244 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1245 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1246 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1248 _tnl_invalidate_vertex_state( ctx
, ~0 );
1249 _tnl_invalidate_vertices( ctx
, ~0 );
1250 _tnl_install_attrs( ctx
,
1251 imesa
->vertex_attrs
,
1252 imesa
->vertex_attr_count
,
1253 imesa
->hw_viewport
, 0 );
1255 imesa
->new_gl_state
|= _SAVAGE_NEW_RENDER_STATE
;
1257 if ((oldfallback
& bit
) && (SAVAGE_DEBUG
& DEBUG_FALLBACKS
))
1258 fprintf (stderr
, "Savage end fallback: 0x%x %s\n",
1259 bit
, fallbackStrings
[index
]);
1264 /**********************************************************************/
1265 /* Initialization. */
1266 /**********************************************************************/
1268 void savageInitTriFuncs( GLcontext
*ctx
)
1270 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1271 static int firsttime
= 1;
1278 tnl
->Driver
.RunPipeline
= savageRunPipeline
;
1279 tnl
->Driver
.Render
.Start
= savageRenderStart
;
1280 tnl
->Driver
.Render
.Finish
= savageRenderFinish
;
1281 tnl
->Driver
.Render
.PrimitiveNotify
= savageRenderPrimitive
;
1282 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1284 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1285 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1286 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1288 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
1289 (6 + 2*ctx
->Const
.MaxTextureUnits
) * sizeof(GLfloat
) );
1291 SAVAGE_CONTEXT(ctx
)->verts
= (char *)tnl
->clipspace
.vertex_buf
;