Merge branch 'mesa_7_7_branch'
[mesa.git] / src / mesa / drivers / dri / savage / savagetris.c
1 /* -*- 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 "main/glheader.h"
41 #include "main/mtypes.h"
42 #include "main/colormac.h"
43 #include "main/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 uint32_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 uint32_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 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);
137 GLuint j;
138
139 *(float *)&vb[0] = x - sz;
140 *(float *)&vb[1] = y - sz;
141 EMIT_VERT (j, vb, vertsize, 2, tmp);
142
143 *(float *)&vb[0] = x + sz;
144 *(float *)&vb[1] = y - sz;
145 EMIT_VERT (j, vb, vertsize, 2, tmp);
146
147 *(float *)&vb[0] = x + sz;
148 *(float *)&vb[1] = y + sz;
149 EMIT_VERT (j, vb, vertsize, 2, tmp);
150
151 *(float *)&vb[0] = x + sz;
152 *(float *)&vb[1] = y + sz;
153 EMIT_VERT (j, vb, vertsize, 2, tmp);
154
155 *(float *)&vb[0] = x - sz;
156 *(float *)&vb[1] = y + sz;
157 EMIT_VERT (j, vb, vertsize, 2, tmp);
158
159 *(float *)&vb[0] = x - sz;
160 *(float *)&vb[1] = y - sz;
161 EMIT_VERT (j, vb, vertsize, 2, tmp);
162 }
163
164 static INLINE void savage_draw_line (savageContextPtr imesa,
165 savageVertexPtr v0,
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;
173 GLuint j;
174
175 dx = v0->v.x - v1->v.x;
176 dy = v0->v.y - v1->v.y;
177
178 ix = width * .5; iy = 0;
179 if (dx * dx > dy * dy) {
180 iy = ix; ix = 0;
181 }
182
183 *(float *)&vb[0] = v0->v.x - ix;
184 *(float *)&vb[1] = v0->v.y - iy;
185 EMIT_VERT (j, vb, vertsize, 2, v0);
186
187 *(float *)&vb[0] = v1->v.x + ix;
188 *(float *)&vb[1] = v1->v.y + iy;
189 EMIT_VERT (j, vb, vertsize, 2, v1);
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] = v0->v.x - ix;
196 *(float *)&vb[1] = v0->v.y - iy;
197 EMIT_VERT (j, vb, vertsize, 2, v0);
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 *(float *)&vb[0] = v1->v.x + ix;
204 *(float *)&vb[1] = v1->v.y + iy;
205 EMIT_VERT (j, vb, vertsize, 2, v1);
206 }
207
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. :-/
211 */
212 #define PTEX_VERTEX( j, tmp, vertex_size, start, v) \
213 do { \
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; \
220 } while (0)
221
222 static void INLINE savage_ptex_tri (savageContextPtr imesa,
223 savageVertexPtr v0,
224 savageVertexPtr v1,
225 savageVertexPtr v2) {
226 GLuint vertsize = imesa->HwVertexSize;
227 uint32_t *vb = savageAllocVtxBuf (imesa, 3*vertsize);
228 savageVertex tmp;
229 GLuint j;
230
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);
234 }
235
236 static INLINE void savage_ptex_line (savageContextPtr imesa,
237 savageVertexPtr v0,
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;
246 GLuint j;
247
248 PTEX_VERTEX (j, tmp0, vertsize, 2, v0);
249 PTEX_VERTEX (j, tmp1, vertsize, 2, v1);
250
251 dx = v0->v.x - v1->v.x;
252 dy = v0->v.y - v1->v.y;
253
254 ix = width * .5; iy = 0;
255 if (dx * dx > dy * dy) {
256 iy = ix; ix = 0;
257 }
258
259 *(float *)&vb[0] = v0->v.x - ix;
260 *(float *)&vb[1] = v0->v.y - iy;
261 EMIT_VERT (j, vb, vertsize, 2, &tmp0);
262
263 *(float *)&vb[0] = v1->v.x + ix;
264 *(float *)&vb[1] = v1->v.y + iy;
265 EMIT_VERT (j, vb, vertsize, 2, &tmp1);
266
267 *(float *)&vb[0] = v0->v.x + ix;
268 *(float *)&vb[1] = v0->v.y + iy;
269 EMIT_VERT (j, vb, vertsize, 2, &tmp0);
270
271 *(float *)&vb[0] = v0->v.x - ix;
272 *(float *)&vb[1] = v0->v.y - iy;
273 EMIT_VERT (j, vb, vertsize, 2, &tmp0);
274
275 *(float *)&vb[0] = v1->v.x - ix;
276 *(float *)&vb[1] = v1->v.y - iy;
277 EMIT_VERT (j, vb, vertsize, 2, &tmp1);
278
279 *(float *)&vb[0] = v1->v.x + ix;
280 *(float *)&vb[1] = v1->v.y + iy;
281 EMIT_VERT (j, vb, vertsize, 2, &tmp1);
282 }
283
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);
293 savageVertex tmp;
294 GLuint j;
295
296 PTEX_VERTEX (j, tmp, vertsize, 2, v0);
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 *(float *)&vb[0] = x - sz;
315 *(float *)&vb[1] = y + sz;
316 EMIT_VERT (j, vb, vertsize, 2, &tmp);
317
318 *(float *)&vb[0] = x - sz;
319 *(float *)&vb[1] = y - sz;
320 EMIT_VERT (j, vb, vertsize, 2, &tmp);
321 }
322
323 /***********************************************************************
324 * Macros for t_dd_tritmp.h to draw basic primitives *
325 ***********************************************************************/
326
327 #define TRI( a, b, c ) \
328 do { \
329 if (DO_FALLBACK) \
330 imesa->draw_tri( imesa, a, b, c ); \
331 else \
332 savage_draw_triangle( imesa, a, b, c ); \
333 } while (0)
334
335 #define QUAD( a, b, c, d ) \
336 do { \
337 if (DO_FALLBACK) { \
338 imesa->draw_tri( imesa, a, b, d ); \
339 imesa->draw_tri( imesa, b, c, d ); \
340 } else \
341 savage_draw_quad( imesa, a, b, c, d ); \
342 } while (0)
343
344 #define LINE( v0, v1 ) \
345 do { \
346 if (DO_FALLBACK) \
347 imesa->draw_line( imesa, v0, v1 ); \
348 else \
349 savage_draw_line( imesa, v0, v1 ); \
350 } while (0)
351
352 #define POINT( v0 ) \
353 do { \
354 if (DO_FALLBACK) \
355 imesa->draw_point( imesa, v0 ); \
356 else \
357 savage_draw_point( imesa, v0 ); \
358 } while (0)
359
360
361 /***********************************************************************
362 * Build render functions from dd templates *
363 ***********************************************************************/
364
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
370
371
372 static struct {
373 tnl_points_func points;
374 tnl_line_func line;
375 tnl_triangle_func triangle;
376 tnl_quad_func quad;
377 } rast_tab[SAVAGE_MAX_TRIFUNC];
378
379
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)
384 #define DO_FLAT 0
385 #define DO_TRI 1
386 #define DO_QUAD 1
387 #define DO_LINE 1
388 #define DO_POINTS 1
389 #define DO_FULL_QUAD 1
390
391 #define HAVE_RGBA 1
392 #define HAVE_SPEC 1
393 #define HAVE_BACK_COLORS 0
394 #define HAVE_HW_FLATSHADE 1
395 #define VERTEX savageVertex
396 #define TAB rast_tab
397
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)))
407
408 #define VERT_SET_RGBA( v, c ) \
409 do { \
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]); \
415 } while (0)
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]
419
420 #define VERT_SET_SPEC( v, c ) \
421 do { \
422 if (specoffset) { \
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]); \
427 } \
428 } while (0)
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]
435
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;
445
446 /***********************************************************************
447 * Helpers for rendering unfilled primitives *
448 ***********************************************************************/
449
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
454 #define TAG(x) x
455 #include "tnl_dd/t_dd_unfilled.h"
456 #undef IND
457
458
459 /***********************************************************************
460 * Generate GL render functions *
461 ***********************************************************************/
462
463
464 #define IND (0)
465 #define TAG(x) x
466 #include "tnl_dd/t_dd_tritmp.h"
467
468 #define IND (SAVAGE_OFFSET_BIT)
469 #define TAG(x) x##_offset
470 #include "tnl_dd/t_dd_tritmp.h"
471
472 #define IND (SAVAGE_TWOSIDE_BIT)
473 #define TAG(x) x##_twoside
474 #include "tnl_dd/t_dd_tritmp.h"
475
476 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT)
477 #define TAG(x) x##_twoside_offset
478 #include "tnl_dd/t_dd_tritmp.h"
479
480 #define IND (SAVAGE_UNFILLED_BIT)
481 #define TAG(x) x##_unfilled
482 #include "tnl_dd/t_dd_tritmp.h"
483
484 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
485 #define TAG(x) x##_offset_unfilled
486 #include "tnl_dd/t_dd_tritmp.h"
487
488 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT)
489 #define TAG(x) x##_twoside_unfilled
490 #include "tnl_dd/t_dd_tritmp.h"
491
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"
495
496 #define IND (SAVAGE_FALLBACK_BIT)
497 #define TAG(x) x##_fallback
498 #include "tnl_dd/t_dd_tritmp.h"
499
500 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
501 #define TAG(x) x##_offset_fallback
502 #include "tnl_dd/t_dd_tritmp.h"
503
504 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_FALLBACK_BIT)
505 #define TAG(x) x##_twoside_fallback
506 #include "tnl_dd/t_dd_tritmp.h"
507
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"
511
512 #define IND (SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
513 #define TAG(x) x##_unfilled_fallback
514 #include "tnl_dd/t_dd_tritmp.h"
515
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"
519
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"
523
524 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT| \
525 SAVAGE_FALLBACK_BIT)
526 #define TAG(x) x##_twoside_offset_unfilled_fallback
527 #include "tnl_dd/t_dd_tritmp.h"
528
529
530 static void init_rast_tab( void )
531 {
532 init();
533 init_offset();
534 init_twoside();
535 init_twoside_offset();
536 init_unfilled();
537 init_offset_unfilled();
538 init_twoside_unfilled();
539 init_twoside_offset_unfilled();
540 init_fallback();
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();
548 }
549
550
551
552 /***********************************************************************
553 * Rasterization fallback helpers *
554 ***********************************************************************/
555
556
557 /* This code is hit only when a mix of accelerated and unaccelerated
558 * primitives are being drawn, and only for the unaccelerated
559 * primitives.
560 */
561 static void
562 savage_fallback_tri( savageContextPtr imesa,
563 savageVertexPtr v0,
564 savageVertexPtr v1,
565 savageVertexPtr v2 )
566 {
567 GLcontext *ctx = imesa->glCtx;
568 SWvertex v[3];
569 FLUSH_BATCH(imesa);
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] );
575 }
576
577
578 static void
579 savage_fallback_line( savageContextPtr imesa,
580 savageVertexPtr v0,
581 savageVertexPtr v1 )
582 {
583 GLcontext *ctx = imesa->glCtx;
584 SWvertex v[2];
585 FLUSH_BATCH(imesa);
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] );
590 }
591
592
593 static void
594 savage_fallback_point( savageContextPtr imesa,
595 savageVertexPtr v0 )
596 {
597 GLcontext *ctx = imesa->glCtx;
598 SWvertex v[1];
599 FLUSH_BATCH(imesa);
600 WAIT_IDLE_EMPTY(imesa);
601 _swsetup_Translate( ctx, v0, &v[0] );
602 _swrast_Point( ctx, &v[0] );
603 }
604
605
606
607 /**********************************************************************/
608 /* Render unclipped begin/end objects */
609 /**********************************************************************/
610
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;*/ \
625 } while (0)
626 #undef LOCAL_VARS
627 #define LOCAL_VARS \
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; \
632 (void) elt;
633 #define RESET_STIPPLE
634 #define RESET_OCCLUSION
635 #define PRESERVE_VB_DEFS
636 #define ELT(x) (x)
637 #define TAG(x) savage_##x##_verts
638 #include "tnl/t_vb_rendertmp.h"
639 #undef ELT
640 #undef TAG
641 #define TAG(x) savage_##x##_elts
642 #define ELT(x) elt[x]
643 #include "tnl/t_vb_rendertmp.h"
644
645
646 /**********************************************************************/
647 /* Render clipped primitives */
648 /**********************************************************************/
649
650 static void savageRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
651 GLuint n )
652 {
653 TNLcontext *tnl = TNL_CONTEXT(ctx);
654 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
655
656 /* Render the new vertices as an unclipped polygon.
657 */
658 {
659 GLuint *tmp = VB->Elts;
660 VB->Elts = (GLuint *)elts;
661 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
662 VB->Elts = tmp;
663 }
664 }
665
666 static void savageRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
667 {
668 TNLcontext *tnl = TNL_CONTEXT(ctx);
669 tnl->Driver.Render.Line( ctx, ii, jj );
670 }
671 /*
672 static void savageFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
673 GLuint n )
674 {
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]);
681 int i,j;
682
683 rmesa->num_verts += (n-2) * 3;
684
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]) );
689 }
690 }
691 */
692
693
694
695 /**********************************************************************/
696 /* Choose render functions */
697 /**********************************************************************/
698
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) \
707
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)
714
715
716 static void savageChooseRenderState(GLcontext *ctx)
717 {
718 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
719 GLuint flags = ctx->_TriangleCaps;
720 GLuint index = 0;
721
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.
725 */
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;
732 } else {
733 imesa->draw_point = savage_draw_point;
734 imesa->draw_line = savage_draw_line;
735 imesa->draw_tri = savage_draw_triangle;
736 }
737
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;
743 }
744
745 /* Hook in fallbacks for specific primitives.
746 */
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",
754 ctx->_TriangleCaps);
755 }
756 }
757 }
758
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;
765
766 if (index == 0) {
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*/;
771 } else {
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;
776 }
777
778 imesa->RenderIndex = index;
779 }
780 }
781
782 /**********************************************************************/
783 /* Validate state at pipeline start */
784 /**********************************************************************/
785
786 static void savageRunPipeline( GLcontext *ctx )
787 {
788 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
789
790 if (imesa->no_rast)
791 FALLBACK(ctx, SAVAGE_FALLBACK_NORAST, GL_TRUE);
792
793 if (imesa->new_state)
794 savageDDUpdateHwState( ctx );
795
796 if (!imesa->Fallback) {
797 if (imesa->new_gl_state & _SAVAGE_NEW_RENDER_STATE)
798 savageChooseRenderState( ctx );
799
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;
806 } else {
807 if (imesa->HwPrim != SAVAGE_PRIM_TRILIST)
808 savageFlushVertices(imesa);
809 imesa->HwPrim = SAVAGE_PRIM_TRILIST;
810 }
811
812 imesa->new_gl_state = 0;
813 }
814
815 _tnl_run_pipeline( ctx );
816
817 if (imesa->no_rast)
818 FALLBACK(ctx, SAVAGE_FALLBACK_NORAST, GL_FALSE);
819 }
820
821 /**********************************************************************/
822 /* High level hooks for t_vb_render.c */
823 /**********************************************************************/
824
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.
828 *
829 * As the r128 uses triangles to render lines and points, it is
830 * necessary to turn off hardware culling when rendering these
831 * primitives.
832 */
833
834 static void savageRasterPrimitive( GLcontext *ctx, GLuint prim )
835 {
836 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
837
838 /* Update culling */
839 if (imesa->raster_primitive != prim) {
840 imesa->raster_primitive = prim;
841 imesa->new_state |= SAVAGE_NEW_CULL;
842 savageDDUpdateHwState (ctx);
843 }
844
845 #if 0
846 if (ctx->Polygon.StippleFlag && mmesa->haveHwStipple)
847 {
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;
852 }
853 #endif
854 }
855
856 static void savageRenderPrimitive( GLcontext *ctx, GLenum prim )
857 {
858 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
859 GLuint rprim = reduced_prim[prim];
860
861 imesa->render_primitive = prim;
862
863 if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
864 return;
865
866 if (imesa->raster_primitive != rprim) {
867 savageRasterPrimitive( ctx, rprim );
868 }
869 }
870
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.
874 */
875 static GLboolean savageCheckPTexHack( GLcontext *ctx )
876 {
877 TNLcontext *tnl = TNL_CONTEXT(ctx);
878 struct vertex_buffer *VB = &tnl->vb;
879 DECLARE_RENDERINPUTS(index_bitset);
880
881 RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
882
883 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 ) && VB->AttribPtr[_TNL_ATTRIB_TEX0]->size == 4) {
884 if (!RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_ATTRIB_TEX1, _TNL_LAST_TEX ))
885 return GL_TRUE; /* apply ptex hack */
886 else
887 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
888 }
889 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 ) && VB->AttribPtr[_TNL_ATTRIB_TEX1]->size == 4)
890 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
891
892 return GL_FALSE; /* don't apply ptex hack */
893 }
894
895
896 #define DO_EMIT_ATTR( ATTR, STYLE ) \
897 do { \
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++; \
901 } while (0)
902
903 #define NEED_ATTR( INDEX, SKIP ) \
904 do { \
905 setupIndex |= (INDEX); \
906 skip &= ~(SKIP); \
907 } while (0)
908
909 #define EMIT_ATTR( ATTR, STYLE, INDEX, SKIP ) \
910 do { \
911 NEED_ATTR( INDEX, SKIP ); \
912 DO_EMIT_ATTR( ATTR, STYLE ); \
913 } while (0)
914
915 #define EMIT_PAD( N ) \
916 do { \
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++; \
921 } while (0)
922
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
936
937
938 static INLINE GLuint savageChooseVertexFormat_s3d( GLcontext *ctx )
939 {
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;
945 GLubyte skip;
946
947 RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
948 imesa->vertex_attr_count = 0;
949
950 skip = SAVAGE_SKIP_ALL_S3D;
951 skip &= ~SAVAGE_SKIP_Z; /* all mesa vertices have a z coordinate */
952
953 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
954 * build up a hardware vertex.
955 */
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 );
958 else {
959 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
960 EMIT_PAD( 4 );
961 skip &= ~SAVAGE_SKIP_W;
962 }
963
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 );
966
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 );
969 else
970 EMIT_PAD( 3 );
971 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
972 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 );
973 else
974 EMIT_PAD( 1 );
975 skip &= ~SAVAGE_SKIP_C1;
976
977 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
978 if (imesa->ptexHack)
979 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0);
980 else if (VB->AttribPtr[_TNL_ATTRIB_TEX0]->size == 4)
981 assert (0); /* should be caught by savageCheckPTexHack */
982 else if (VB->AttribPtr[_TNL_ATTRIB_TEX0]->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->AttribPtr[_TNL_ATTRIB_TEX0]->size == 1) {
987 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_1F, SAVAGE_EMIT_S0, SAVAGE_SKIP_S0 );
988 EMIT_PAD( 4 );
989 } else
990 EMIT_PAD( 8 );
991 } else
992 EMIT_PAD( 8 );
993 skip &= ~SAVAGE_SKIP_ST0;
994
995 assert (skip == 0);
996 imesa->skip = skip;
997 return setupIndex;
998 }
999
1000
1001 static INLINE GLuint savageChooseVertexFormat_s4( GLcontext *ctx )
1002 {
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;
1008 GLubyte skip;
1009 GLuint size, mask;
1010
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 */
1014
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 );
1017
1018 /* t_context.c always includes a diffuse color */
1019 NEED_ATTR( SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 );
1020
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 );
1025
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->AttribPtr[_TNL_ATTRIB_TEX0]->size == 4)
1030 assert (0); /* should be caught by savageCheckPTexHack */
1031 else if (VB->AttribPtr[_TNL_ATTRIB_TEX0]->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 );
1035 else
1036 NEED_ATTR( SAVAGE_EMIT_S0, SAVAGE_SKIP_S0 );
1037 }
1038 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) {
1039 if (VB->AttribPtr[_TNL_ATTRIB_TEX1]->size == 4)
1040 /* projective textures are not supported by the hardware */
1041 assert (0); /* should be caught by savageCheckPTexHack */
1042 else if (VB->AttribPtr[_TNL_ATTRIB_TEX1]->size >= 2)
1043 NEED_ATTR( SAVAGE_EMIT_ST1, SAVAGE_SKIP_ST1 );
1044 else
1045 NEED_ATTR( SAVAGE_EMIT_S1, SAVAGE_SKIP_S1 );
1046 }
1047
1048 /* if nothing changed we can skip the rest */
1049 if (setupIndex == imesa->SetupIndex && imesa->vertex_size != 0)
1050 return setupIndex;
1051
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);
1057
1058 while (size < 8) {
1059 if (skip & mask) {
1060 skip &= ~mask;
1061 size++;
1062 }
1063 mask <<= 1;
1064 }
1065 }
1066
1067 imesa->vertex_attr_count = 0;
1068
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 );
1073 else {
1074 DO_EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT );
1075 EMIT_PAD( 4 );
1076 }
1077
1078 DO_EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA );
1079
1080 if (!(skip & SAVAGE_SKIP_C1)) {
1081 if (!(setupIndex & (SAVAGE_EMIT_C1|SAVAGE_EMIT_FOG)))
1082 EMIT_PAD( 4 );
1083 else {
1084 if (setupIndex & SAVAGE_EMIT_C1)
1085 DO_EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR );
1086 else
1087 EMIT_PAD( 3 );
1088 if (setupIndex & SAVAGE_EMIT_FOG)
1089 DO_EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F );
1090 else
1091 EMIT_PAD( 1 );
1092 }
1093 }
1094
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 );
1103 } else {
1104 if (!(skip & SAVAGE_SKIP_S0)) EMIT_PAD( 4 );
1105 if (!(skip & SAVAGE_SKIP_T0)) EMIT_PAD( 4 );
1106 }
1107 }
1108
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 );
1115 } else {
1116 if (!(skip & SAVAGE_SKIP_S1)) EMIT_PAD( 4 );
1117 if (!(skip & SAVAGE_SKIP_T1)) EMIT_PAD( 4 );
1118 }
1119 }
1120
1121 imesa->skip = skip;
1122 return setupIndex;
1123 }
1124
1125
1126 static void savageRenderStart( GLcontext *ctx )
1127 {
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;
1132 GLboolean ptexHack;
1133
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);
1142 }
1143 /* Handle fallback cases identified in savageCheckPTexHack. */
1144 if (SAVAGE_CONTEXT(ctx)->Fallback) {
1145 tnl->Driver.Render.Start(ctx);
1146 return;
1147 }
1148
1149 /* Important:
1150 */
1151 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
1152
1153 if (imesa->savageScreen->chipset < S3_SAVAGE4) {
1154 setupIndex = savageChooseVertexFormat_s3d(ctx);
1155 } else {
1156 setupIndex = savageChooseVertexFormat_s4(ctx);
1157 }
1158
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;
1170
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. */
1179 hwVertexSize--;
1180 assert (imesa->ptexHack);
1181 } else
1182 assert (!imesa->ptexHack);
1183
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;
1194 } else {
1195 if (SAVAGE_DEBUG & DEBUG_DMA)
1196 fprintf (stderr, "Not using DMA, skip=0x%02x\n", imesa->skip);
1197 imesa->vtxBuf = &imesa->clientVtxBuf;
1198 }
1199 imesa->HwVertexSize = hwVertexSize;
1200 }
1201 }
1202 }
1203
1204 static void savageRenderFinish( GLcontext *ctx )
1205 {
1206 /* Flush the last primitive now, before any state is changed. */
1207 savageFlushVertices(SAVAGE_CONTEXT(ctx));
1208
1209 if (SAVAGE_CONTEXT(ctx)->RenderIndex & SAVAGE_FALLBACK_BIT)
1210 _swrast_flush( ctx );
1211 }
1212
1213
1214 /**********************************************************************/
1215 /* Transition to/from hardware rasterization. */
1216 /**********************************************************************/
1217
1218 static const char * const fallbackStrings[] = {
1219 "Texture mode",
1220 "Draw buffer",
1221 "Read buffer",
1222 "Color mask",
1223 "Specular",
1224 "LogicOp",
1225 "glEnable(GL_STENCIL) without hw stencil buffer",
1226 "glRenderMode(selection or feedback)",
1227 "glBlendEquation",
1228 "Hardware rasterization disabled",
1229 "Projective texture",
1230 };
1231
1232 void savageFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
1233 {
1234 TNLcontext *tnl = TNL_CONTEXT(ctx);
1235 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1236 GLuint oldfallback = imesa->Fallback;
1237 GLuint index;
1238 for (index = 0; (1 << index) < bit; ++index);
1239
1240 if (mode) {
1241 imesa->Fallback |= bit;
1242 if (oldfallback == 0) {
1243 /* the first fallback */
1244 _swsetup_Wakeup( ctx );
1245 imesa->RenderIndex = ~0;
1246 }
1247 if (!(oldfallback & bit) && (SAVAGE_DEBUG & DEBUG_FALLBACKS))
1248 fprintf (stderr, "Savage begin fallback: 0x%x %s\n",
1249 bit, fallbackStrings[index]);
1250 }
1251 else {
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;
1259
1260 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1261 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1262 tnl->Driver.Render.Interp = _tnl_interp;
1263
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 );
1270
1271 imesa->new_gl_state |= _SAVAGE_NEW_RENDER_STATE;
1272 }
1273 if ((oldfallback & bit) && (SAVAGE_DEBUG & DEBUG_FALLBACKS))
1274 fprintf (stderr, "Savage end fallback: 0x%x %s\n",
1275 bit, fallbackStrings[index]);
1276 }
1277 }
1278
1279
1280 /**********************************************************************/
1281 /* Initialization. */
1282 /**********************************************************************/
1283
1284 void savageInitTriFuncs( GLcontext *ctx )
1285 {
1286 TNLcontext *tnl = TNL_CONTEXT(ctx);
1287 static int firsttime = 1;
1288
1289 if (firsttime) {
1290 init_rast_tab();
1291 firsttime = 0;
1292 }
1293
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;
1299
1300 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1301 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1302 tnl->Driver.Render.Interp = _tnl_interp;
1303
1304 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
1305 (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
1306
1307 SAVAGE_CONTEXT(ctx)->verts = (char *)tnl->clipspace.vertex_buf;
1308 }