Fixed some suspicious pointer casts that caused lots of
[mesa.git] / src / mesa / drivers / dri / savage / savagetris.c
1 /* $XFree86$ */ /* -*- c-basic-offset: 3 -*- */
2 /**************************************************************************
3
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5 VA Linux Systems Inc., Fremont, California.
6
7 All Rights Reserved.
8
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:
15
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
18 Software.
19
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.
27
28 **************************************************************************/
29
30 /*
31 * Authors:
32 * Keith Whitwell <keithw@valinux.com>
33 * Felix Kuehling <fxkuehl@gmx.de>
34 *
35 */
36
37 #include <stdio.h>
38 #include <math.h>
39
40 #include "glheader.h"
41 #include "mtypes.h"
42 #include "colormac.h"
43 #include "macros.h"
44
45 #include "swrast/swrast.h"
46 #include "swrast_setup/swrast_setup.h"
47 #include "tnl/tnl.h"
48 #include "tnl/t_context.h"
49 #include "tnl/t_pipeline.h"
50
51 #include "savagetris.h"
52 #include "savagestate.h"
53 #include "savagetex.h"
54 #include "savageioctl.h"
55 #include "savage_bci.h"
56
57 static void savageRasterPrimitive( GLcontext *ctx, GLuint prim );
58 static void savageRenderPrimitive( GLcontext *ctx, GLenum prim );
59
60
61 static GLenum reduced_prim[GL_POLYGON+1] = {
62 GL_POINTS,
63 GL_LINES,
64 GL_LINES,
65 GL_LINES,
66 GL_TRIANGLES,
67 GL_TRIANGLES,
68 GL_TRIANGLES,
69 GL_TRIANGLES,
70 GL_TRIANGLES,
71 GL_TRIANGLES
72 };
73
74
75 /***********************************************************************
76 * Emit primitives *
77 ***********************************************************************/
78
79 #if defined (USE_X86_ASM)
80 #define EMIT_VERT( j, vb, vertex_size, start, v ) \
81 do { int __tmp; \
82 vb += start; \
83 __asm__ __volatile__( "rep ; movsl" \
84 : "=%c" (j), "=D" (vb), "=S" (__tmp) \
85 : "0" (vertex_size-start), \
86 "D" ((long)vb), \
87 "S" ((long)&(v)->ui[start])); \
88 } while (0)
89 #else
90 #define EMIT_VERT( j, vb, vertex_size, start, v ) \
91 do { \
92 for ( j = start ; j < vertex_size ; j++ ) \
93 vb[j] = (v)->ui[j]; \
94 vb += vertex_size; \
95 } while (0)
96 #endif
97
98 static void __inline__ savage_draw_triangle (savageContextPtr imesa,
99 savageVertexPtr v0,
100 savageVertexPtr v1,
101 savageVertexPtr v2) {
102 GLuint vertsize = imesa->HwVertexSize;
103 u_int32_t *vb = savageAllocVtxBuf (imesa, 3*vertsize);
104 GLuint j;
105
106 EMIT_VERT (j, vb, vertsize, 0, v0);
107 EMIT_VERT (j, vb, vertsize, 0, v1);
108 EMIT_VERT (j, vb, vertsize, 0, v2);
109 }
110
111 static void __inline__ savage_draw_quad (savageContextPtr imesa,
112 savageVertexPtr v0,
113 savageVertexPtr v1,
114 savageVertexPtr v2,
115 savageVertexPtr v3) {
116 GLuint vertsize = imesa->HwVertexSize;
117 u_int32_t *vb = savageAllocVtxBuf (imesa, 6*vertsize);
118 GLuint j;
119
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);
126 }
127
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;
135 GLuint j;
136
137 *(float *)&vb[0] = x - sz;
138 *(float *)&vb[1] = y - sz;
139 EMIT_VERT (j, vb, vertsize, 2, tmp);
140
141 *(float *)&vb[0] = x + sz;
142 *(float *)&vb[1] = y - sz;
143 EMIT_VERT (j, vb, vertsize, 2, tmp);
144
145 *(float *)&vb[0] = x + sz;
146 *(float *)&vb[1] = y + sz;
147 EMIT_VERT (j, vb, vertsize, 2, tmp);
148
149 *(float *)&vb[0] = x + sz;
150 *(float *)&vb[1] = y + sz;
151 EMIT_VERT (j, vb, vertsize, 2, tmp);
152
153 *(float *)&vb[0] = x - sz;
154 *(float *)&vb[1] = y + sz;
155 EMIT_VERT (j, vb, vertsize, 2, tmp);
156
157 *(float *)&vb[0] = x - sz;
158 *(float *)&vb[1] = y - sz;
159 EMIT_VERT (j, vb, vertsize, 2, tmp);
160 }
161
162 static __inline__ void savage_draw_line (savageContextPtr imesa,
163 savageVertexPtr v0,
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;
169 GLuint j;
170
171 dx = v0->v.x - v1->v.x;
172 dy = v0->v.y - v1->v.y;
173
174 ix = width * .5; iy = 0;
175 if (dx * dx > dy * dy) {
176 iy = ix; ix = 0;
177 }
178
179 *(float *)&vb[0] = v0->v.x - ix;
180 *(float *)&vb[1] = v0->v.y - iy;
181 EMIT_VERT (j, vb, vertsize, 2, v0);
182
183 *(float *)&vb[0] = v1->v.x + ix;
184 *(float *)&vb[1] = v1->v.y + iy;
185 EMIT_VERT (j, vb, vertsize, 2, v1);
186
187 *(float *)&vb[0] = v0->v.x + ix;
188 *(float *)&vb[1] = v0->v.y + iy;
189 EMIT_VERT (j, vb, vertsize, 2, v0);
190
191 *(float *)&vb[0] = v0->v.x - ix;
192 *(float *)&vb[1] = v0->v.y - iy;
193 EMIT_VERT (j, vb, vertsize, 2, v0);
194
195 *(float *)&vb[0] = v1->v.x - ix;
196 *(float *)&vb[1] = v1->v.y - iy;
197 EMIT_VERT (j, vb, vertsize, 2, v1);
198
199 *(float *)&vb[0] = v1->v.x + ix;
200 *(float *)&vb[1] = v1->v.y + iy;
201 EMIT_VERT (j, vb, vertsize, 2, v1);
202 }
203
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. :-/
207 */
208 #define PTEX_VERTEX( j, tmp, vertex_size, start, v) \
209 do { \
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; \
216 } while (0)
217
218 static void __inline__ savage_ptex_tri (savageContextPtr imesa,
219 savageVertexPtr v0,
220 savageVertexPtr v1,
221 savageVertexPtr v2) {
222 GLuint vertsize = imesa->HwVertexSize;
223 u_int32_t *vb = savageAllocVtxBuf (imesa, 3*vertsize);
224 savageVertex tmp;
225 GLuint j;
226
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);
230 }
231
232 static __inline__ void savage_ptex_line (savageContextPtr imesa,
233 savageVertexPtr v0,
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;
240 GLuint j;
241
242 PTEX_VERTEX (j, tmp0, vertsize, 2, v0);
243 PTEX_VERTEX (j, tmp1, vertsize, 2, v1);
244
245 dx = v0->v.x - v1->v.x;
246 dy = v0->v.y - v1->v.y;
247
248 ix = width * .5; iy = 0;
249 if (dx * dx > dy * dy) {
250 iy = ix; ix = 0;
251 }
252
253 *(float *)&vb[0] = v0->v.x - ix;
254 *(float *)&vb[1] = v0->v.y - iy;
255 EMIT_VERT (j, vb, vertsize, 2, &tmp0);
256
257 *(float *)&vb[0] = v1->v.x + ix;
258 *(float *)&vb[1] = v1->v.y + iy;
259 EMIT_VERT (j, vb, vertsize, 2, &tmp1);
260
261 *(float *)&vb[0] = v0->v.x + ix;
262 *(float *)&vb[1] = v0->v.y + iy;
263 EMIT_VERT (j, vb, vertsize, 2, &tmp0);
264
265 *(float *)&vb[0] = v0->v.x - ix;
266 *(float *)&vb[1] = v0->v.y - iy;
267 EMIT_VERT (j, vb, vertsize, 2, &tmp0);
268
269 *(float *)&vb[0] = v1->v.x - ix;
270 *(float *)&vb[1] = v1->v.y - iy;
271 EMIT_VERT (j, vb, vertsize, 2, &tmp1);
272
273 *(float *)&vb[0] = v1->v.x + ix;
274 *(float *)&vb[1] = v1->v.y + iy;
275 EMIT_VERT (j, vb, vertsize, 2, &tmp1);
276 }
277
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;
285 savageVertex tmp;
286 GLuint j;
287
288 PTEX_VERTEX (j, tmp, vertsize, 2, v0);
289
290 *(float *)&vb[0] = x - sz;
291 *(float *)&vb[1] = y - sz;
292 EMIT_VERT (j, vb, vertsize, 2, &tmp);
293
294 *(float *)&vb[0] = x + sz;
295 *(float *)&vb[1] = y - sz;
296 EMIT_VERT (j, vb, vertsize, 2, &tmp);
297
298 *(float *)&vb[0] = x + sz;
299 *(float *)&vb[1] = y + sz;
300 EMIT_VERT (j, vb, vertsize, 2, &tmp);
301
302 *(float *)&vb[0] = x + sz;
303 *(float *)&vb[1] = y + sz;
304 EMIT_VERT (j, vb, vertsize, 2, &tmp);
305
306 *(float *)&vb[0] = x - sz;
307 *(float *)&vb[1] = y + sz;
308 EMIT_VERT (j, vb, vertsize, 2, &tmp);
309
310 *(float *)&vb[0] = x - sz;
311 *(float *)&vb[1] = y - sz;
312 EMIT_VERT (j, vb, vertsize, 2, &tmp);
313 }
314
315 /***********************************************************************
316 * Macros for t_dd_tritmp.h to draw basic primitives *
317 ***********************************************************************/
318
319 #define TRI( a, b, c ) \
320 do { \
321 if (DO_FALLBACK) \
322 imesa->draw_tri( imesa, a, b, c ); \
323 else \
324 savage_draw_triangle( imesa, a, b, c ); \
325 } while (0)
326
327 #define QUAD( a, b, c, d ) \
328 do { \
329 if (DO_FALLBACK) { \
330 imesa->draw_tri( imesa, a, b, d ); \
331 imesa->draw_tri( imesa, b, c, d ); \
332 } else \
333 savage_draw_quad( imesa, a, b, c, d ); \
334 } while (0)
335
336 #define LINE( v0, v1 ) \
337 do { \
338 if (DO_FALLBACK) \
339 imesa->draw_line( imesa, v0, v1 ); \
340 else \
341 savage_draw_line( imesa, v0, v1 ); \
342 } while (0)
343
344 #define POINT( v0 ) \
345 do { \
346 if (DO_FALLBACK) \
347 imesa->draw_point( imesa, v0 ); \
348 else \
349 savage_draw_point( imesa, v0 ); \
350 } while (0)
351
352
353 /***********************************************************************
354 * Build render functions from dd templates *
355 ***********************************************************************/
356
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
362
363
364 static struct {
365 tnl_points_func points;
366 tnl_line_func line;
367 tnl_triangle_func triangle;
368 tnl_quad_func quad;
369 } rast_tab[SAVAGE_MAX_TRIFUNC];
370
371
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)
376 #define DO_FLAT 0
377 #define DO_TRI 1
378 #define DO_QUAD 1
379 #define DO_LINE 1
380 #define DO_POINTS 1
381 #define DO_FULL_QUAD 1
382
383 #define HAVE_RGBA 1
384 #define HAVE_SPEC 1
385 #define HAVE_BACK_COLORS 0
386 #define HAVE_HW_FLATSHADE 1
387 #define VERTEX savageVertex
388 #define TAB rast_tab
389
390 #define DEPTH_SCALE imesa->depth_scale
391 #define REVERSE_DEPTH 1
392 #define UNFILLED_TRI unfilled_tri
393 #define UNFILLED_QUAD unfilled_quad
394 #define VERT_X(_v) _v->v.x
395 #define VERT_Y(_v) _v->v.y
396 #define VERT_Z(_v) _v->v.z
397 #define AREA_IS_CCW( a ) (a > 0)
398 #define GET_VERTEX(e) (imesa->verts + (e * imesa->vertex_size * sizeof(int)))
399
400 #define VERT_SET_RGBA( v, c ) \
401 do { \
402 savage_color_t *color = (savage_color_t *)&((v)->ub4[coloroffset]); \
403 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
404 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
405 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
406 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
407 } while (0)
408 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
409 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
410 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
411
412 #define VERT_SET_SPEC( v, c ) \
413 do { \
414 if (specoffset) { \
415 savage_color_t *spec = (savage_color_t *)&((v)->ub4[specoffset]); \
416 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
417 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
418 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
419 } \
420 } while (0)
421 #define VERT_COPY_SPEC( v0, v1 ) \
422 if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset])
423 #define VERT_SAVE_SPEC( idx ) \
424 if (specoffset) spec[idx] = v[idx]->ui[specoffset]
425 #define VERT_RESTORE_SPEC( idx ) \
426 if (specoffset) v[idx]->ui[specoffset] = spec[idx]
427
428 #define LOCAL_VARS(n) \
429 savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
430 GLuint color[n], spec[n]; \
431 GLuint coloroffset = \
432 ((imesa->skip & SAVAGE_SKIP_W) ? 3 : 4); \
433 GLboolean specoffset = \
434 ((imesa->skip & SAVAGE_SKIP_C1) ? 0 : coloroffset+1); \
435 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
436
437 /***********************************************************************
438 * Helpers for rendering unfilled primitives *
439 ***********************************************************************/
440
441 #define RASTERIZE(x) if (imesa->raster_primitive != reduced_prim[x]) \
442 savageRasterPrimitive( ctx, x )
443 #define RENDER_PRIMITIVE imesa->render_primitive
444 #define IND SAVAGE_FALLBACK_BIT
445 #define TAG(x) x
446 #include "tnl_dd/t_dd_unfilled.h"
447 #undef IND
448
449
450 /***********************************************************************
451 * Generate GL render functions *
452 ***********************************************************************/
453
454
455 #define IND (0)
456 #define TAG(x) x
457 #include "tnl_dd/t_dd_tritmp.h"
458
459 #define IND (SAVAGE_OFFSET_BIT)
460 #define TAG(x) x##_offset
461 #include "tnl_dd/t_dd_tritmp.h"
462
463 #define IND (SAVAGE_TWOSIDE_BIT)
464 #define TAG(x) x##_twoside
465 #include "tnl_dd/t_dd_tritmp.h"
466
467 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT)
468 #define TAG(x) x##_twoside_offset
469 #include "tnl_dd/t_dd_tritmp.h"
470
471 #define IND (SAVAGE_UNFILLED_BIT)
472 #define TAG(x) x##_unfilled
473 #include "tnl_dd/t_dd_tritmp.h"
474
475 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
476 #define TAG(x) x##_offset_unfilled
477 #include "tnl_dd/t_dd_tritmp.h"
478
479 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT)
480 #define TAG(x) x##_twoside_unfilled
481 #include "tnl_dd/t_dd_tritmp.h"
482
483 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
484 #define TAG(x) x##_twoside_offset_unfilled
485 #include "tnl_dd/t_dd_tritmp.h"
486
487 #define IND (SAVAGE_FALLBACK_BIT)
488 #define TAG(x) x##_fallback
489 #include "tnl_dd/t_dd_tritmp.h"
490
491 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
492 #define TAG(x) x##_offset_fallback
493 #include "tnl_dd/t_dd_tritmp.h"
494
495 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_FALLBACK_BIT)
496 #define TAG(x) x##_twoside_fallback
497 #include "tnl_dd/t_dd_tritmp.h"
498
499 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
500 #define TAG(x) x##_twoside_offset_fallback
501 #include "tnl_dd/t_dd_tritmp.h"
502
503 #define IND (SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
504 #define TAG(x) x##_unfilled_fallback
505 #include "tnl_dd/t_dd_tritmp.h"
506
507 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
508 #define TAG(x) x##_offset_unfilled_fallback
509 #include "tnl_dd/t_dd_tritmp.h"
510
511 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
512 #define TAG(x) x##_twoside_unfilled_fallback
513 #include "tnl_dd/t_dd_tritmp.h"
514
515 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT| \
516 SAVAGE_FALLBACK_BIT)
517 #define TAG(x) x##_twoside_offset_unfilled_fallback
518 #include "tnl_dd/t_dd_tritmp.h"
519
520
521 static void init_rast_tab( void )
522 {
523 init();
524 init_offset();
525 init_twoside();
526 init_twoside_offset();
527 init_unfilled();
528 init_offset_unfilled();
529 init_twoside_unfilled();
530 init_twoside_offset_unfilled();
531 init_fallback();
532 init_offset_fallback();
533 init_twoside_fallback();
534 init_twoside_offset_fallback();
535 init_unfilled_fallback();
536 init_offset_unfilled_fallback();
537 init_twoside_unfilled_fallback();
538 init_twoside_offset_unfilled_fallback();
539 }
540
541
542
543 /***********************************************************************
544 * Rasterization fallback helpers *
545 ***********************************************************************/
546
547
548 /* This code is hit only when a mix of accelerated and unaccelerated
549 * primitives are being drawn, and only for the unaccelerated
550 * primitives.
551 */
552 static void
553 savage_fallback_tri( savageContextPtr imesa,
554 savageVertexPtr v0,
555 savageVertexPtr v1,
556 savageVertexPtr v2 )
557 {
558 GLcontext *ctx = imesa->glCtx;
559 SWvertex v[3];
560 FLUSH_BATCH(imesa);
561 WAIT_IDLE_EMPTY(imesa);
562 _swsetup_Translate( ctx, v0, &v[0] );
563 _swsetup_Translate( ctx, v1, &v[1] );
564 _swsetup_Translate( ctx, v2, &v[2] );
565 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
566 }
567
568
569 static void
570 savage_fallback_line( savageContextPtr imesa,
571 savageVertexPtr v0,
572 savageVertexPtr v1 )
573 {
574 GLcontext *ctx = imesa->glCtx;
575 SWvertex v[2];
576 FLUSH_BATCH(imesa);
577 WAIT_IDLE_EMPTY(imesa);
578 _swsetup_Translate( ctx, v0, &v[0] );
579 _swsetup_Translate( ctx, v1, &v[1] );
580 _swrast_Line( ctx, &v[0], &v[1] );
581 }
582
583
584 static void
585 savage_fallback_point( savageContextPtr imesa,
586 savageVertexPtr v0 )
587 {
588 GLcontext *ctx = imesa->glCtx;
589 SWvertex v[1];
590 FLUSH_BATCH(imesa);
591 WAIT_IDLE_EMPTY(imesa);
592 _swsetup_Translate( ctx, v0, &v[0] );
593 _swrast_Point( ctx, &v[0] );
594 }
595
596
597
598 /**********************************************************************/
599 /* Render unclipped begin/end objects */
600 /**********************************************************************/
601
602 #define VERT(x) (savageVertexPtr)(savageVerts + (x * vertsize * sizeof(int)))
603 #define RENDER_POINTS( start, count ) \
604 for ( ; start < count ; start++) \
605 savage_draw_point( imesa, VERT(start) )
606 #define RENDER_LINE( v0, v1 ) \
607 savage_draw_line( imesa, VERT(v0), VERT(v1) )
608 #define RENDER_TRI( v0, v1, v2 ) \
609 savage_draw_triangle( imesa, VERT(v0), VERT(v1), VERT(v2) )
610 #define RENDER_QUAD( v0, v1, v2, v3 ) \
611 savage_draw_quad( imesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
612 #define INIT(x) do { \
613 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
614 savageRenderPrimitive( ctx, x ); \
615 /*SAVAGE_CONTEXT(ctx)->render_primitive = x;*/ \
616 } while (0)
617 #undef LOCAL_VARS
618 #define LOCAL_VARS \
619 savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
620 const GLuint vertsize = imesa->vertex_size; \
621 const char *savageVerts = (char *)imesa->verts; \
622 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
623 (void) elt;
624 #define RESET_STIPPLE
625 #define RESET_OCCLUSION
626 #define PRESERVE_VB_DEFS
627 #define ELT(x) (x)
628 #define TAG(x) savage_##x##_verts
629 #include "tnl/t_vb_rendertmp.h"
630 #undef ELT
631 #undef TAG
632 #define TAG(x) savage_##x##_elts
633 #define ELT(x) elt[x]
634 #include "tnl/t_vb_rendertmp.h"
635
636
637 /**********************************************************************/
638 /* Render clipped primitives */
639 /**********************************************************************/
640
641 static void savageRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
642 GLuint n )
643 {
644 TNLcontext *tnl = TNL_CONTEXT(ctx);
645 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
646
647 /* Render the new vertices as an unclipped polygon.
648 */
649 {
650 GLuint *tmp = VB->Elts;
651 VB->Elts = (GLuint *)elts;
652 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
653 VB->Elts = tmp;
654 }
655 }
656
657 static void savageRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
658 {
659 TNLcontext *tnl = TNL_CONTEXT(ctx);
660 tnl->Driver.Render.Line( ctx, ii, jj );
661 }
662 /*
663 static void savageFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
664 GLuint n )
665 {
666 r128ContextPtr rmesa = R128_CONTEXT( ctx );
667 GLuint vertsize = rmesa->vertex_size;
668 GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
669 GLubyte *r128verts = (GLubyte *)rmesa->verts;
670 const GLuint shift = rmesa->vertex_stride_shift;
671 const GLuint *start = (const GLuint *)VERT(elts[0]);
672 int i,j;
673
674 rmesa->num_verts += (n-2) * 3;
675
676 for (i = 2 ; i < n ; i++) {
677 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
678 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
679 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
680 }
681 }
682 */
683
684
685
686 /**********************************************************************/
687 /* Choose render functions */
688 /**********************************************************************/
689
690 #define _SAVAGE_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
691 _DD_NEW_LINE_SMOOTH | \
692 _DD_NEW_POINT_SMOOTH | \
693 _DD_NEW_TRI_STIPPLE | \
694 _DD_NEW_TRI_SMOOTH | \
695 _DD_NEW_TRI_UNFILLED | \
696 _DD_NEW_TRI_LIGHT_TWOSIDE | \
697 _DD_NEW_TRI_OFFSET) \
698
699 /* original driver didn't have DD_POINT_SMOOTH. really needed? */
700 #define POINT_FALLBACK (DD_POINT_SMOOTH)
701 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
702 #define TRI_FALLBACK (DD_TRI_STIPPLE|DD_TRI_SMOOTH)
703 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
704 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
705
706
707 static void savageChooseRenderState(GLcontext *ctx)
708 {
709 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
710 GLuint flags = ctx->_TriangleCaps;
711 GLuint index = 0;
712
713 /* Hook in fallback functions for the ptex hack. Do this first, so
714 * that a real fallback will overwrite them with the respective
715 * savage_fallback_... function.
716 */
717 if (imesa->ptexHack) {
718 /* Do textures make sense with points? */
719 imesa->draw_point = savage_ptex_point;
720 imesa->draw_line = savage_ptex_line;
721 imesa->draw_tri = savage_ptex_tri;
722 index |= SAVAGE_FALLBACK_BIT;
723 } else {
724 imesa->draw_point = savage_draw_point;
725 imesa->draw_line = savage_draw_line;
726 imesa->draw_tri = savage_draw_triangle;
727 }
728
729 if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
730 if (flags & ANY_RASTER_FLAGS) {
731 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= SAVAGE_TWOSIDE_BIT;
732 if (flags & DD_TRI_OFFSET) index |= SAVAGE_OFFSET_BIT;
733 if (flags & DD_TRI_UNFILLED) index |= SAVAGE_UNFILLED_BIT;
734 }
735
736 /* Hook in fallbacks for specific primitives.
737 */
738 if (flags & ANY_FALLBACK_FLAGS) {
739 if (flags & POINT_FALLBACK) imesa->draw_point = savage_fallback_point;
740 if (flags & LINE_FALLBACK) imesa->draw_line = savage_fallback_line;
741 if (flags & TRI_FALLBACK) imesa->draw_tri = savage_fallback_tri;
742 index |= SAVAGE_FALLBACK_BIT;
743 if (SAVAGE_DEBUG & DEBUG_FALLBACKS) {
744 fprintf (stderr, "Per-primitive fallback, TriangleCaps=0x%x\n",
745 ctx->_TriangleCaps);
746 }
747 }
748 }
749
750 if (index != imesa->RenderIndex) {
751 TNLcontext *tnl = TNL_CONTEXT(ctx);
752 tnl->Driver.Render.Points = rast_tab[index].points;
753 tnl->Driver.Render.Line = rast_tab[index].line;
754 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
755 tnl->Driver.Render.Quad = rast_tab[index].quad;
756
757 if (index == 0) {
758 tnl->Driver.Render.PrimTabVerts = savage_render_tab_verts;
759 tnl->Driver.Render.PrimTabElts = savage_render_tab_elts;
760 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
761 tnl->Driver.Render.ClippedPolygon = savageRenderClippedPoly/*r128FastRenderClippedPoly*/;
762 } else {
763 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
764 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
765 tnl->Driver.Render.ClippedLine = savageRenderClippedLine;
766 tnl->Driver.Render.ClippedPolygon = savageRenderClippedPoly;
767 }
768
769 imesa->RenderIndex = index;
770 }
771 }
772
773 /**********************************************************************/
774 /* Validate state at pipeline start */
775 /**********************************************************************/
776
777 static void savageRunPipeline( GLcontext *ctx )
778 {
779 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
780
781 if (imesa->no_rast)
782 FALLBACK(ctx, SAVAGE_FALLBACK_NORAST, GL_TRUE);
783
784 if (imesa->new_state)
785 savageDDUpdateHwState( ctx );
786
787 if (!imesa->Fallback) {
788 if (imesa->new_gl_state & _SAVAGE_NEW_RENDER_STATE)
789 savageChooseRenderState( ctx );
790
791 /* choose the correct primitive type for tnl rendering */
792 if (imesa->savageScreen->chipset < S3_SAVAGE4 &&
793 (ctx->_TriangleCaps & DD_FLATSHADE)) {
794 if (imesa->HwPrim != SAVAGE_PRIM_TRILIST_201)
795 savageFlushVertices(imesa);
796 imesa->HwPrim = SAVAGE_PRIM_TRILIST_201;
797 } else {
798 if (imesa->HwPrim != SAVAGE_PRIM_TRILIST)
799 savageFlushVertices(imesa);
800 imesa->HwPrim = SAVAGE_PRIM_TRILIST;
801 }
802
803 imesa->new_gl_state = 0;
804 }
805
806 _tnl_run_pipeline( ctx );
807
808 if (imesa->no_rast)
809 FALLBACK(ctx, SAVAGE_FALLBACK_NORAST, GL_FALSE);
810 }
811
812 /**********************************************************************/
813 /* High level hooks for t_vb_render.c */
814 /**********************************************************************/
815
816 /* This is called when Mesa switches between rendering triangle
817 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
818 * and lines, points and bitmaps.
819 *
820 * As the r128 uses triangles to render lines and points, it is
821 * necessary to turn off hardware culling when rendering these
822 * primitives.
823 */
824
825 static void savageRasterPrimitive( GLcontext *ctx, GLuint prim )
826 {
827 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
828
829 /* Update culling */
830 if (imesa->raster_primitive != prim) {
831 imesa->raster_primitive = prim;
832 imesa->new_state |= SAVAGE_NEW_CULL;
833 savageDDUpdateHwState (ctx);
834 }
835
836 #if 0
837 if (ctx->Polygon.StippleFlag && mmesa->haveHwStipple)
838 {
839 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
840 mmesa->setup.dwgctl &= ~(0xf<<20);
841 if (mmesa->raster_primitive == GL_TRIANGLES)
842 mmesa->setup.dwgctl |= mmesa->poly_stipple;
843 }
844 #endif
845 }
846
847 static void savageRenderPrimitive( GLcontext *ctx, GLenum prim )
848 {
849 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
850 GLuint rprim = reduced_prim[prim];
851
852 imesa->render_primitive = prim;
853
854 if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
855 return;
856
857 if (imesa->raster_primitive != rprim) {
858 savageRasterPrimitive( ctx, rprim );
859 }
860 }
861
862 /* Check if projective texture coordinates are used and if we can fake
863 * them. Fallback to swrast we can't. Returns GL_TRUE if projective
864 * texture coordinates must be faked, GL_FALSE otherwise.
865 */
866 static GLboolean savageCheckPTexHack( GLcontext *ctx )
867 {
868 TNLcontext *tnl = TNL_CONTEXT(ctx);
869 struct vertex_buffer *VB = &tnl->vb;
870 GLuint index = tnl->render_inputs;
871
872 if (index & _TNL_BIT_TEX(0) && VB->TexCoordPtr[0]->size == 4) {
873 if ((index & _TNL_BITS_TEX_ANY) == _TNL_BIT_TEX(0))
874 return GL_TRUE; /* apply ptex hack */
875 else
876 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
877 }
878 if ((index & _TNL_BIT_TEX(1)) && VB->TexCoordPtr[1]->size == 4)
879 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
880
881 return GL_FALSE; /* don't apply ptex hack */
882 }
883
884
885 #define DO_EMIT_ATTR( ATTR, STYLE ) \
886 do { \
887 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = (ATTR); \
888 imesa->vertex_attrs[imesa->vertex_attr_count].format = (STYLE); \
889 imesa->vertex_attr_count++; \
890 } while (0)
891
892 #define NEED_ATTR( INDEX, SKIP ) \
893 do { \
894 setupIndex |= (INDEX); \
895 skip &= ~(SKIP); \
896 } while (0)
897
898 #define EMIT_ATTR( ATTR, STYLE, INDEX, SKIP ) \
899 do { \
900 NEED_ATTR( INDEX, SKIP ); \
901 DO_EMIT_ATTR( ATTR, STYLE ); \
902 } while (0)
903
904 #define EMIT_PAD( N ) \
905 do { \
906 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = 0; \
907 imesa->vertex_attrs[imesa->vertex_attr_count].format = EMIT_PAD; \
908 imesa->vertex_attrs[imesa->vertex_attr_count].offset = (N); \
909 imesa->vertex_attr_count++; \
910 } while (0)
911
912 #define SAVAGE_EMIT_XYZ 0x0001
913 #define SAVAGE_EMIT_W 0x0002
914 #define SAVAGE_EMIT_C0 0x0004
915 #define SAVAGE_EMIT_C1 0x0008
916 #define SAVAGE_EMIT_FOG 0x0010
917 #define SAVAGE_EMIT_S0 0x0020
918 #define SAVAGE_EMIT_T0 0x0040
919 #define SAVAGE_EMIT_Q0 0x0080
920 #define SAVAGE_EMIT_ST0 0x0060
921 #define SAVAGE_EMIT_STQ0 0x00e0
922 #define SAVAGE_EMIT_S1 0x0100
923 #define SAVAGE_EMIT_T1 0x0200
924 #define SAVAGE_EMIT_ST1 0x0300
925
926
927 static __inline__ GLuint savageChooseVertexFormat_s3d( GLcontext *ctx )
928 {
929 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
930 TNLcontext *tnl = TNL_CONTEXT(ctx);
931 struct vertex_buffer *VB = &tnl->vb;
932 GLuint index = tnl->render_inputs;
933 GLuint setupIndex = SAVAGE_EMIT_XYZ;
934 GLubyte skip;
935
936 imesa->vertex_attr_count = 0;
937
938 skip = SAVAGE_SKIP_ALL_S3D;
939 skip &= ~SAVAGE_SKIP_Z; /* all mesa vertices have a z coordinate */
940
941 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
942 * build up a hardware vertex.
943 */
944 if ((index & _TNL_BITS_TEX_ANY) || !(ctx->_TriangleCaps & DD_FLATSHADE))
945 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, SAVAGE_EMIT_W, SAVAGE_SKIP_W );
946 else {
947 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
948 EMIT_PAD( 4 );
949 skip &= ~SAVAGE_SKIP_W;
950 }
951
952 /* t_context.c always includes a diffuse color */
953 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 );
954
955 if ((index & _TNL_BIT_COLOR1))
956 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 );
957 else
958 EMIT_PAD( 3 );
959 if ((index & _TNL_BIT_FOG))
960 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 );
961 else
962 EMIT_PAD( 1 );
963 skip &= ~SAVAGE_SKIP_C1;
964
965 if (index & _TNL_BIT_TEX(0)) {
966 if (imesa->ptexHack)
967 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0);
968 else if (VB->TexCoordPtr[0]->size == 4)
969 assert (0); /* should be caught by savageCheckPTexHack */
970 else if (VB->TexCoordPtr[0]->size >= 2)
971 /* The chromium menu emits some 3D tex coords even though no
972 * 3D texture is enabled. Ignore the 3rd coordinate. */
973 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, SAVAGE_EMIT_ST0, SAVAGE_SKIP_ST0 );
974 else if (VB->TexCoordPtr[0]->size == 1) {
975 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_1F, SAVAGE_EMIT_S0, SAVAGE_SKIP_S0 );
976 EMIT_PAD( 4 );
977 } else
978 EMIT_PAD( 8 );
979 } else
980 EMIT_PAD( 8 );
981 skip &= ~SAVAGE_SKIP_ST0;
982
983 assert (skip == 0);
984 imesa->skip = skip;
985 return setupIndex;
986 }
987
988
989 static __inline__ GLuint savageChooseVertexFormat_s4( GLcontext *ctx )
990 {
991 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
992 TNLcontext *tnl = TNL_CONTEXT(ctx);
993 struct vertex_buffer *VB = &tnl->vb;
994 GLuint index = tnl->render_inputs;
995 GLuint setupIndex = SAVAGE_EMIT_XYZ;
996 GLubyte skip;
997 GLuint size, mask;
998
999 skip = SAVAGE_SKIP_ALL_S4;
1000 skip &= ~SAVAGE_SKIP_Z; /* all mesa vertices have a z coordinate */
1001
1002 if ((index & _TNL_BITS_TEX_ANY) || !(ctx->_TriangleCaps & DD_FLATSHADE))
1003 NEED_ATTR( SAVAGE_EMIT_W, SAVAGE_SKIP_W );
1004
1005 /* t_context.c always includes a diffuse color */
1006 NEED_ATTR( SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 );
1007
1008 if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
1009 if ((index & _TNL_BIT_COLOR1))
1010 NEED_ATTR( SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 );
1011 if ((index & _TNL_BIT_FOG))
1012 NEED_ATTR( SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 );
1013 }
1014
1015 if (index & _TNL_BIT_TEX(0)) {
1016 if (imesa->ptexHack)
1017 NEED_ATTR( SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0);
1018 else if (VB->TexCoordPtr[0]->size == 4)
1019 assert (0); /* should be caught by savageCheckPTexHack */
1020 else if (VB->TexCoordPtr[0]->size >= 2)
1021 /* The chromium menu emits some 3D tex coords even though no
1022 * 3D texture is enabled. Ignore the 3rd coordinate. */
1023 NEED_ATTR( SAVAGE_EMIT_ST0, SAVAGE_SKIP_ST0 );
1024 else
1025 NEED_ATTR( SAVAGE_EMIT_S0, SAVAGE_SKIP_S0 );
1026 }
1027 if (index & _TNL_BIT_TEX(1)) {
1028 if (VB->TexCoordPtr[1]->size == 4)
1029 /* projective textures are not supported by the hardware */
1030 assert (0); /* should be caught by savageCheckPTexHack */
1031 else if (VB->TexCoordPtr[1]->size >= 2)
1032 NEED_ATTR( SAVAGE_EMIT_ST1, SAVAGE_SKIP_ST1 );
1033 else
1034 NEED_ATTR( SAVAGE_EMIT_S1, SAVAGE_SKIP_S1 );
1035 }
1036
1037 /* if nothing changed we can skip the rest */
1038 if (setupIndex == imesa->SetupIndex && imesa->vertex_size != 0)
1039 return setupIndex;
1040
1041 if (imesa->enable_vdma) {
1042 mask = SAVAGE_SKIP_W;
1043 size = 10 - (skip & 1) - (skip >> 1 & 1) -
1044 (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
1045 (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
1046
1047 while (size < 8) {
1048 if (skip & mask) {
1049 skip &= ~mask;
1050 size++;
1051 }
1052 mask <<= 1;
1053 }
1054 }
1055
1056 imesa->vertex_attr_count = 0;
1057
1058 if (skip & SAVAGE_SKIP_W)
1059 DO_EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT );
1060 else if (setupIndex & SAVAGE_EMIT_W)
1061 DO_EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT );
1062 else {
1063 DO_EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT );
1064 EMIT_PAD( 4 );
1065 }
1066
1067 DO_EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA );
1068
1069 if (!(skip & SAVAGE_SKIP_C1)) {
1070 if (!(setupIndex & (SAVAGE_EMIT_C1|SAVAGE_EMIT_FOG)))
1071 EMIT_PAD( 4 );
1072 else {
1073 if (setupIndex & SAVAGE_EMIT_C1)
1074 DO_EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR );
1075 else
1076 EMIT_PAD( 3 );
1077 if (setupIndex & SAVAGE_EMIT_FOG)
1078 DO_EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F );
1079 else
1080 EMIT_PAD( 1 );
1081 }
1082 }
1083
1084 if ((skip & SAVAGE_SKIP_ST0) != SAVAGE_SKIP_ST0) {
1085 if ((setupIndex & SAVAGE_EMIT_STQ0) == SAVAGE_EMIT_STQ0)
1086 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW );
1087 else if ((setupIndex & SAVAGE_EMIT_ST0) == SAVAGE_EMIT_ST0)
1088 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F );
1089 else if ((setupIndex & SAVAGE_EMIT_ST0) == SAVAGE_EMIT_S0) {
1090 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_1F );
1091 if (!(skip & SAVAGE_SKIP_T0)) EMIT_PAD( 4 );
1092 } else {
1093 if (!(skip & SAVAGE_SKIP_S0)) EMIT_PAD( 4 );
1094 if (!(skip & SAVAGE_SKIP_T0)) EMIT_PAD( 4 );
1095 }
1096 }
1097
1098 if ((skip & SAVAGE_SKIP_ST1) != SAVAGE_SKIP_ST1) {
1099 if ((setupIndex & SAVAGE_EMIT_ST1) == SAVAGE_EMIT_ST1)
1100 DO_EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F );
1101 else if ((setupIndex & SAVAGE_EMIT_ST1) == SAVAGE_EMIT_S1) {
1102 DO_EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_1F );
1103 if (!(skip & SAVAGE_SKIP_T1)) EMIT_PAD( 4 );
1104 } else {
1105 if (!(skip & SAVAGE_SKIP_S1)) EMIT_PAD( 4 );
1106 if (!(skip & SAVAGE_SKIP_T1)) EMIT_PAD( 4 );
1107 }
1108 }
1109
1110 imesa->skip = skip;
1111 return setupIndex;
1112 }
1113
1114
1115 static void savageRenderStart( GLcontext *ctx )
1116 {
1117 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1118 TNLcontext *tnl = TNL_CONTEXT(ctx);
1119 struct vertex_buffer *VB = &tnl->vb;
1120 GLuint setupIndex = SAVAGE_EMIT_XYZ;
1121 GLboolean ptexHack;
1122
1123 /* Check if we need to apply the ptex hack. Choose a new render
1124 * state if necessary. (Note: this can't be done in
1125 * savageRunPipeline, since the number of vertex coordinates can
1126 * change in the pipeline. texmat or texgen or both?) */
1127 ptexHack = savageCheckPTexHack( ctx );
1128 if (ptexHack != imesa->ptexHack) {
1129 imesa->ptexHack = ptexHack;
1130 savageChooseRenderState (ctx);
1131 }
1132 /* Handle fallback cases identified in savageCheckPTexHack. */
1133 if (SAVAGE_CONTEXT(ctx)->Fallback) {
1134 tnl->Driver.Render.Start(ctx);
1135 return;
1136 }
1137
1138 /* Important:
1139 */
1140 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
1141
1142 if (imesa->savageScreen->chipset < S3_SAVAGE4) {
1143 setupIndex = savageChooseVertexFormat_s3d(ctx);
1144 } else {
1145 setupIndex = savageChooseVertexFormat_s4(ctx);
1146 }
1147
1148 /* Need to change the vertex emit code if the SetupIndex changed or
1149 * is set for the first time (indicated by vertex_size == 0). */
1150 if (setupIndex != imesa->SetupIndex || imesa->vertex_size == 0) {
1151 GLuint hwVertexSize;
1152 imesa->vertex_size =
1153 _tnl_install_attrs( ctx,
1154 imesa->vertex_attrs,
1155 imesa->vertex_attr_count,
1156 imesa->hw_viewport, 0 );
1157 imesa->vertex_size >>= 2;
1158 imesa->SetupIndex = setupIndex;
1159
1160 hwVertexSize = imesa->vertex_size;
1161 if (setupIndex & SAVAGE_EMIT_Q0) {
1162 /* The vertex setup code emits homogenous texture
1163 * coordinates. They are converted to normal 2D coords by
1164 * savage_ptex_tri/line/point. Now we have two different
1165 * vertex sizes. Functions that emit vertices to the hardware
1166 * need to use HwVertexSize, anything that manipulates the
1167 * vertices generated by t_vertex uses vertex_size. */
1168 hwVertexSize--;
1169 assert (imesa->ptexHack);
1170 } else
1171 assert (!imesa->ptexHack);
1172
1173 if (hwVertexSize != imesa->HwVertexSize) {
1174 /* Changing the vertex size: flush vertex and command buffer and
1175 * discard the DMA buffer, if we were using one. */
1176 savageFlushVertices(imesa);
1177 savageFlushCmdBuf(imesa, GL_TRUE);
1178 if (hwVertexSize == 8 && imesa->enable_vdma) {
1179 if (SAVAGE_DEBUG & DEBUG_DMA)
1180 fprintf (stderr, "Using DMA, skip=0x%02x\n", imesa->skip);
1181 /* we can use vertex dma */
1182 imesa->vtxBuf = &imesa->dmaVtxBuf;
1183 } else {
1184 if (SAVAGE_DEBUG & DEBUG_DMA)
1185 fprintf (stderr, "Not using DMA, skip=0x%02x\n", imesa->skip);
1186 imesa->vtxBuf = &imesa->clientVtxBuf;
1187 }
1188 imesa->HwVertexSize = hwVertexSize;
1189 }
1190 }
1191 }
1192
1193 static void savageRenderFinish( GLcontext *ctx )
1194 {
1195 /* Flush the last primitive now, before any state is changed. */
1196 savageFlushVertices(SAVAGE_CONTEXT(ctx));
1197
1198 if (SAVAGE_CONTEXT(ctx)->RenderIndex & SAVAGE_FALLBACK_BIT)
1199 _swrast_flush( ctx );
1200 }
1201
1202
1203 /**********************************************************************/
1204 /* Transition to/from hardware rasterization. */
1205 /**********************************************************************/
1206
1207 static const char * const fallbackStrings[] = {
1208 "Texture mode",
1209 "Draw buffer",
1210 "Read buffer",
1211 "Color mask",
1212 "Specular",
1213 "LogicOp",
1214 "glEnable(GL_STENCIL) without hw stencil buffer",
1215 "glRenderMode(selection or feedback)",
1216 "glBlendEquation",
1217 "Hardware rasterization disabled",
1218 "Projective texture",
1219 };
1220
1221 void savageFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
1222 {
1223 TNLcontext *tnl = TNL_CONTEXT(ctx);
1224 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1225 GLuint oldfallback = imesa->Fallback;
1226 GLuint index;
1227 for (index = 0; (1 << index) < bit; ++index);
1228
1229 if (mode) {
1230 imesa->Fallback |= bit;
1231 if (oldfallback == 0) {
1232 /* the first fallback */
1233 _swsetup_Wakeup( ctx );
1234 imesa->RenderIndex = ~0;
1235 }
1236 if (!(oldfallback & bit) && (SAVAGE_DEBUG & DEBUG_FALLBACKS))
1237 fprintf (stderr, "Savage begin fallback: 0x%x %s\n",
1238 bit, fallbackStrings[index]);
1239 }
1240 else {
1241 imesa->Fallback &= ~bit;
1242 if (oldfallback == bit) {
1243 /* the last fallback */
1244 _swrast_flush( ctx );
1245 tnl->Driver.Render.Start = savageRenderStart;
1246 tnl->Driver.Render.PrimitiveNotify = savageRenderPrimitive;
1247 tnl->Driver.Render.Finish = savageRenderFinish;
1248
1249 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1250 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1251 tnl->Driver.Render.Interp = _tnl_interp;
1252
1253 _tnl_invalidate_vertex_state( ctx, ~0 );
1254 _tnl_invalidate_vertices( ctx, ~0 );
1255 _tnl_install_attrs( ctx,
1256 imesa->vertex_attrs,
1257 imesa->vertex_attr_count,
1258 imesa->hw_viewport, 0 );
1259
1260 imesa->new_gl_state |= _SAVAGE_NEW_RENDER_STATE;
1261 }
1262 if ((oldfallback & bit) && (SAVAGE_DEBUG & DEBUG_FALLBACKS))
1263 fprintf (stderr, "Savage end fallback: 0x%x %s\n",
1264 bit, fallbackStrings[index]);
1265 }
1266 }
1267
1268
1269 /**********************************************************************/
1270 /* Initialization. */
1271 /**********************************************************************/
1272
1273 void savageInitTriFuncs( GLcontext *ctx )
1274 {
1275 TNLcontext *tnl = TNL_CONTEXT(ctx);
1276 static int firsttime = 1;
1277
1278 if (firsttime) {
1279 init_rast_tab();
1280 firsttime = 0;
1281 }
1282
1283 tnl->Driver.RunPipeline = savageRunPipeline;
1284 tnl->Driver.Render.Start = savageRenderStart;
1285 tnl->Driver.Render.Finish = savageRenderFinish;
1286 tnl->Driver.Render.PrimitiveNotify = savageRenderPrimitive;
1287 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
1288
1289 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1290 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1291 tnl->Driver.Render.Interp = _tnl_interp;
1292
1293 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
1294 (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
1295
1296 SAVAGE_CONTEXT(ctx)->verts = (char *)tnl->clipspace.vertex_buf;
1297 }