Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[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 "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 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], spec[n]; \
439 GLuint coloroffset = \
440 ((imesa->skip & SAVAGE_SKIP_W) ? 3 : 4); \
441 GLboolean specoffset = \
442 ((imesa->skip & SAVAGE_SKIP_C1) ? 0 : coloroffset+1); \
443 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
444
445 /***********************************************************************
446 * Helpers for rendering unfilled primitives *
447 ***********************************************************************/
448
449 #define RASTERIZE(x) if (imesa->raster_primitive != reduced_prim[x]) \
450 savageRasterPrimitive( ctx, x )
451 #define RENDER_PRIMITIVE imesa->render_primitive
452 #define IND SAVAGE_FALLBACK_BIT
453 #define TAG(x) x
454 #include "tnl_dd/t_dd_unfilled.h"
455 #undef IND
456
457
458 /***********************************************************************
459 * Generate GL render functions *
460 ***********************************************************************/
461
462
463 #define IND (0)
464 #define TAG(x) x
465 #include "tnl_dd/t_dd_tritmp.h"
466
467 #define IND (SAVAGE_OFFSET_BIT)
468 #define TAG(x) x##_offset
469 #include "tnl_dd/t_dd_tritmp.h"
470
471 #define IND (SAVAGE_TWOSIDE_BIT)
472 #define TAG(x) x##_twoside
473 #include "tnl_dd/t_dd_tritmp.h"
474
475 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT)
476 #define TAG(x) x##_twoside_offset
477 #include "tnl_dd/t_dd_tritmp.h"
478
479 #define IND (SAVAGE_UNFILLED_BIT)
480 #define TAG(x) x##_unfilled
481 #include "tnl_dd/t_dd_tritmp.h"
482
483 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
484 #define TAG(x) x##_offset_unfilled
485 #include "tnl_dd/t_dd_tritmp.h"
486
487 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT)
488 #define TAG(x) x##_twoside_unfilled
489 #include "tnl_dd/t_dd_tritmp.h"
490
491 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
492 #define TAG(x) x##_twoside_offset_unfilled
493 #include "tnl_dd/t_dd_tritmp.h"
494
495 #define IND (SAVAGE_FALLBACK_BIT)
496 #define TAG(x) x##_fallback
497 #include "tnl_dd/t_dd_tritmp.h"
498
499 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
500 #define TAG(x) x##_offset_fallback
501 #include "tnl_dd/t_dd_tritmp.h"
502
503 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_FALLBACK_BIT)
504 #define TAG(x) x##_twoside_fallback
505 #include "tnl_dd/t_dd_tritmp.h"
506
507 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
508 #define TAG(x) x##_twoside_offset_fallback
509 #include "tnl_dd/t_dd_tritmp.h"
510
511 #define IND (SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
512 #define TAG(x) x##_unfilled_fallback
513 #include "tnl_dd/t_dd_tritmp.h"
514
515 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
516 #define TAG(x) x##_offset_unfilled_fallback
517 #include "tnl_dd/t_dd_tritmp.h"
518
519 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
520 #define TAG(x) x##_twoside_unfilled_fallback
521 #include "tnl_dd/t_dd_tritmp.h"
522
523 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT| \
524 SAVAGE_FALLBACK_BIT)
525 #define TAG(x) x##_twoside_offset_unfilled_fallback
526 #include "tnl_dd/t_dd_tritmp.h"
527
528
529 static void init_rast_tab( void )
530 {
531 init();
532 init_offset();
533 init_twoside();
534 init_twoside_offset();
535 init_unfilled();
536 init_offset_unfilled();
537 init_twoside_unfilled();
538 init_twoside_offset_unfilled();
539 init_fallback();
540 init_offset_fallback();
541 init_twoside_fallback();
542 init_twoside_offset_fallback();
543 init_unfilled_fallback();
544 init_offset_unfilled_fallback();
545 init_twoside_unfilled_fallback();
546 init_twoside_offset_unfilled_fallback();
547 }
548
549
550
551 /***********************************************************************
552 * Rasterization fallback helpers *
553 ***********************************************************************/
554
555
556 /* This code is hit only when a mix of accelerated and unaccelerated
557 * primitives are being drawn, and only for the unaccelerated
558 * primitives.
559 */
560 static void
561 savage_fallback_tri( savageContextPtr imesa,
562 savageVertexPtr v0,
563 savageVertexPtr v1,
564 savageVertexPtr v2 )
565 {
566 GLcontext *ctx = imesa->glCtx;
567 SWvertex v[3];
568 FLUSH_BATCH(imesa);
569 WAIT_IDLE_EMPTY(imesa);
570 _swsetup_Translate( ctx, v0, &v[0] );
571 _swsetup_Translate( ctx, v1, &v[1] );
572 _swsetup_Translate( ctx, v2, &v[2] );
573 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
574 }
575
576
577 static void
578 savage_fallback_line( savageContextPtr imesa,
579 savageVertexPtr v0,
580 savageVertexPtr v1 )
581 {
582 GLcontext *ctx = imesa->glCtx;
583 SWvertex v[2];
584 FLUSH_BATCH(imesa);
585 WAIT_IDLE_EMPTY(imesa);
586 _swsetup_Translate( ctx, v0, &v[0] );
587 _swsetup_Translate( ctx, v1, &v[1] );
588 _swrast_Line( ctx, &v[0], &v[1] );
589 }
590
591
592 static void
593 savage_fallback_point( savageContextPtr imesa,
594 savageVertexPtr v0 )
595 {
596 GLcontext *ctx = imesa->glCtx;
597 SWvertex v[1];
598 FLUSH_BATCH(imesa);
599 WAIT_IDLE_EMPTY(imesa);
600 _swsetup_Translate( ctx, v0, &v[0] );
601 _swrast_Point( ctx, &v[0] );
602 }
603
604
605
606 /**********************************************************************/
607 /* Render unclipped begin/end objects */
608 /**********************************************************************/
609
610 #define VERT(x) (savageVertexPtr)(savageVerts + (x * vertsize * sizeof(int)))
611 #define RENDER_POINTS( start, count ) \
612 for ( ; start < count ; start++) \
613 savage_draw_point( imesa, VERT(start) )
614 #define RENDER_LINE( v0, v1 ) \
615 savage_draw_line( imesa, VERT(v0), VERT(v1) )
616 #define RENDER_TRI( v0, v1, v2 ) \
617 savage_draw_triangle( imesa, VERT(v0), VERT(v1), VERT(v2) )
618 #define RENDER_QUAD( v0, v1, v2, v3 ) \
619 savage_draw_quad( imesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
620 #define INIT(x) do { \
621 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
622 savageRenderPrimitive( ctx, x ); \
623 /*SAVAGE_CONTEXT(ctx)->render_primitive = x;*/ \
624 } while (0)
625 #undef LOCAL_VARS
626 #define LOCAL_VARS \
627 savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
628 const GLuint vertsize = imesa->vertex_size; \
629 const char *savageVerts = (char *)imesa->verts; \
630 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
631 (void) elt;
632 #define RESET_STIPPLE
633 #define RESET_OCCLUSION
634 #define PRESERVE_VB_DEFS
635 #define ELT(x) (x)
636 #define TAG(x) savage_##x##_verts
637 #include "tnl/t_vb_rendertmp.h"
638 #undef ELT
639 #undef TAG
640 #define TAG(x) savage_##x##_elts
641 #define ELT(x) elt[x]
642 #include "tnl/t_vb_rendertmp.h"
643
644
645 /**********************************************************************/
646 /* Render clipped primitives */
647 /**********************************************************************/
648
649 static void savageRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
650 GLuint n )
651 {
652 TNLcontext *tnl = TNL_CONTEXT(ctx);
653 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
654
655 /* Render the new vertices as an unclipped polygon.
656 */
657 {
658 GLuint *tmp = VB->Elts;
659 VB->Elts = (GLuint *)elts;
660 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
661 VB->Elts = tmp;
662 }
663 }
664
665 static void savageRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
666 {
667 TNLcontext *tnl = TNL_CONTEXT(ctx);
668 tnl->Driver.Render.Line( ctx, ii, jj );
669 }
670 /*
671 static void savageFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
672 GLuint n )
673 {
674 r128ContextPtr rmesa = R128_CONTEXT( ctx );
675 GLuint vertsize = rmesa->vertex_size;
676 GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
677 GLubyte *r128verts = (GLubyte *)rmesa->verts;
678 const GLuint shift = rmesa->vertex_stride_shift;
679 const GLuint *start = (const GLuint *)VERT(elts[0]);
680 int i,j;
681
682 rmesa->num_verts += (n-2) * 3;
683
684 for (i = 2 ; i < n ; i++) {
685 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
686 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
687 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
688 }
689 }
690 */
691
692
693
694 /**********************************************************************/
695 /* Choose render functions */
696 /**********************************************************************/
697
698 #define _SAVAGE_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
699 _DD_NEW_LINE_SMOOTH | \
700 _DD_NEW_POINT_SMOOTH | \
701 _DD_NEW_TRI_STIPPLE | \
702 _DD_NEW_TRI_SMOOTH | \
703 _DD_NEW_TRI_UNFILLED | \
704 _DD_NEW_TRI_LIGHT_TWOSIDE | \
705 _DD_NEW_TRI_OFFSET) \
706
707 /* original driver didn't have DD_POINT_SMOOTH. really needed? */
708 #define POINT_FALLBACK (DD_POINT_SMOOTH)
709 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
710 #define TRI_FALLBACK (DD_TRI_STIPPLE|DD_TRI_SMOOTH)
711 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
712 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
713
714
715 static void savageChooseRenderState(GLcontext *ctx)
716 {
717 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
718 GLuint flags = ctx->_TriangleCaps;
719 GLuint index = 0;
720
721 /* Hook in fallback functions for the ptex hack. Do this first, so
722 * that a real fallback will overwrite them with the respective
723 * savage_fallback_... function.
724 */
725 if (imesa->ptexHack) {
726 /* Do textures make sense with points? */
727 imesa->draw_point = savage_ptex_point;
728 imesa->draw_line = savage_ptex_line;
729 imesa->draw_tri = savage_ptex_tri;
730 index |= SAVAGE_FALLBACK_BIT;
731 } else {
732 imesa->draw_point = savage_draw_point;
733 imesa->draw_line = savage_draw_line;
734 imesa->draw_tri = savage_draw_triangle;
735 }
736
737 if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
738 if (flags & ANY_RASTER_FLAGS) {
739 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= SAVAGE_TWOSIDE_BIT;
740 if (flags & DD_TRI_OFFSET) index |= SAVAGE_OFFSET_BIT;
741 if (flags & DD_TRI_UNFILLED) index |= SAVAGE_UNFILLED_BIT;
742 }
743
744 /* Hook in fallbacks for specific primitives.
745 */
746 if (flags & ANY_FALLBACK_FLAGS) {
747 if (flags & POINT_FALLBACK) imesa->draw_point = savage_fallback_point;
748 if (flags & LINE_FALLBACK) imesa->draw_line = savage_fallback_line;
749 if (flags & TRI_FALLBACK) imesa->draw_tri = savage_fallback_tri;
750 index |= SAVAGE_FALLBACK_BIT;
751 if (SAVAGE_DEBUG & DEBUG_FALLBACKS) {
752 fprintf (stderr, "Per-primitive fallback, TriangleCaps=0x%x\n",
753 ctx->_TriangleCaps);
754 }
755 }
756 }
757
758 if (index != imesa->RenderIndex) {
759 TNLcontext *tnl = TNL_CONTEXT(ctx);
760 tnl->Driver.Render.Points = rast_tab[index].points;
761 tnl->Driver.Render.Line = rast_tab[index].line;
762 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
763 tnl->Driver.Render.Quad = rast_tab[index].quad;
764
765 if (index == 0) {
766 tnl->Driver.Render.PrimTabVerts = savage_render_tab_verts;
767 tnl->Driver.Render.PrimTabElts = savage_render_tab_elts;
768 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
769 tnl->Driver.Render.ClippedPolygon = savageRenderClippedPoly/*r128FastRenderClippedPoly*/;
770 } else {
771 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
772 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
773 tnl->Driver.Render.ClippedLine = savageRenderClippedLine;
774 tnl->Driver.Render.ClippedPolygon = savageRenderClippedPoly;
775 }
776
777 imesa->RenderIndex = index;
778 }
779 }
780
781 /**********************************************************************/
782 /* Validate state at pipeline start */
783 /**********************************************************************/
784
785 static void savageRunPipeline( GLcontext *ctx )
786 {
787 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
788
789 if (imesa->no_rast)
790 FALLBACK(ctx, SAVAGE_FALLBACK_NORAST, GL_TRUE);
791
792 if (imesa->new_state)
793 savageDDUpdateHwState( ctx );
794
795 if (!imesa->Fallback) {
796 if (imesa->new_gl_state & _SAVAGE_NEW_RENDER_STATE)
797 savageChooseRenderState( ctx );
798
799 /* choose the correct primitive type for tnl rendering */
800 if (imesa->savageScreen->chipset < S3_SAVAGE4 &&
801 (ctx->_TriangleCaps & DD_FLATSHADE)) {
802 if (imesa->HwPrim != SAVAGE_PRIM_TRILIST_201)
803 savageFlushVertices(imesa);
804 imesa->HwPrim = SAVAGE_PRIM_TRILIST_201;
805 } else {
806 if (imesa->HwPrim != SAVAGE_PRIM_TRILIST)
807 savageFlushVertices(imesa);
808 imesa->HwPrim = SAVAGE_PRIM_TRILIST;
809 }
810
811 imesa->new_gl_state = 0;
812 }
813
814 _tnl_run_pipeline( ctx );
815
816 if (imesa->no_rast)
817 FALLBACK(ctx, SAVAGE_FALLBACK_NORAST, GL_FALSE);
818 }
819
820 /**********************************************************************/
821 /* High level hooks for t_vb_render.c */
822 /**********************************************************************/
823
824 /* This is called when Mesa switches between rendering triangle
825 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
826 * and lines, points and bitmaps.
827 *
828 * As the r128 uses triangles to render lines and points, it is
829 * necessary to turn off hardware culling when rendering these
830 * primitives.
831 */
832
833 static void savageRasterPrimitive( GLcontext *ctx, GLuint prim )
834 {
835 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
836
837 /* Update culling */
838 if (imesa->raster_primitive != prim) {
839 imesa->raster_primitive = prim;
840 imesa->new_state |= SAVAGE_NEW_CULL;
841 savageDDUpdateHwState (ctx);
842 }
843
844 #if 0
845 if (ctx->Polygon.StippleFlag && mmesa->haveHwStipple)
846 {
847 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
848 mmesa->setup.dwgctl &= ~(0xf<<20);
849 if (mmesa->raster_primitive == GL_TRIANGLES)
850 mmesa->setup.dwgctl |= mmesa->poly_stipple;
851 }
852 #endif
853 }
854
855 static void savageRenderPrimitive( GLcontext *ctx, GLenum prim )
856 {
857 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
858 GLuint rprim = reduced_prim[prim];
859
860 imesa->render_primitive = prim;
861
862 if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
863 return;
864
865 if (imesa->raster_primitive != rprim) {
866 savageRasterPrimitive( ctx, rprim );
867 }
868 }
869
870 /* Check if projective texture coordinates are used and if we can fake
871 * them. Fallback to swrast we can't. Returns GL_TRUE if projective
872 * texture coordinates must be faked, GL_FALSE otherwise.
873 */
874 static GLboolean savageCheckPTexHack( GLcontext *ctx )
875 {
876 TNLcontext *tnl = TNL_CONTEXT(ctx);
877 struct vertex_buffer *VB = &tnl->vb;
878 DECLARE_RENDERINPUTS(index_bitset);
879
880 RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
881
882 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 ) && VB->TexCoordPtr[0]->size == 4) {
883 if (!RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_ATTRIB_TEX1, _TNL_LAST_TEX ))
884 return GL_TRUE; /* apply ptex hack */
885 else
886 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
887 }
888 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 ) && VB->TexCoordPtr[1]->size == 4)
889 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
890
891 return GL_FALSE; /* don't apply ptex hack */
892 }
893
894
895 #define DO_EMIT_ATTR( ATTR, STYLE ) \
896 do { \
897 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = (ATTR); \
898 imesa->vertex_attrs[imesa->vertex_attr_count].format = (STYLE); \
899 imesa->vertex_attr_count++; \
900 } while (0)
901
902 #define NEED_ATTR( INDEX, SKIP ) \
903 do { \
904 setupIndex |= (INDEX); \
905 skip &= ~(SKIP); \
906 } while (0)
907
908 #define EMIT_ATTR( ATTR, STYLE, INDEX, SKIP ) \
909 do { \
910 NEED_ATTR( INDEX, SKIP ); \
911 DO_EMIT_ATTR( ATTR, STYLE ); \
912 } while (0)
913
914 #define EMIT_PAD( N ) \
915 do { \
916 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = 0; \
917 imesa->vertex_attrs[imesa->vertex_attr_count].format = EMIT_PAD; \
918 imesa->vertex_attrs[imesa->vertex_attr_count].offset = (N); \
919 imesa->vertex_attr_count++; \
920 } while (0)
921
922 #define SAVAGE_EMIT_XYZ 0x0001
923 #define SAVAGE_EMIT_W 0x0002
924 #define SAVAGE_EMIT_C0 0x0004
925 #define SAVAGE_EMIT_C1 0x0008
926 #define SAVAGE_EMIT_FOG 0x0010
927 #define SAVAGE_EMIT_S0 0x0020
928 #define SAVAGE_EMIT_T0 0x0040
929 #define SAVAGE_EMIT_Q0 0x0080
930 #define SAVAGE_EMIT_ST0 0x0060
931 #define SAVAGE_EMIT_STQ0 0x00e0
932 #define SAVAGE_EMIT_S1 0x0100
933 #define SAVAGE_EMIT_T1 0x0200
934 #define SAVAGE_EMIT_ST1 0x0300
935
936
937 static __inline__ GLuint savageChooseVertexFormat_s3d( GLcontext *ctx )
938 {
939 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
940 TNLcontext *tnl = TNL_CONTEXT(ctx);
941 struct vertex_buffer *VB = &tnl->vb;
942 DECLARE_RENDERINPUTS(index_bitset);
943 GLuint setupIndex = SAVAGE_EMIT_XYZ;
944 GLubyte skip;
945
946 RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
947 imesa->vertex_attr_count = 0;
948
949 skip = SAVAGE_SKIP_ALL_S3D;
950 skip &= ~SAVAGE_SKIP_Z; /* all mesa vertices have a z coordinate */
951
952 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
953 * build up a hardware vertex.
954 */
955 if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) || !(ctx->_TriangleCaps & DD_FLATSHADE))
956 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, SAVAGE_EMIT_W, SAVAGE_SKIP_W );
957 else {
958 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
959 EMIT_PAD( 4 );
960 skip &= ~SAVAGE_SKIP_W;
961 }
962
963 /* t_context.c always includes a diffuse color */
964 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 );
965
966 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ))
967 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 );
968 else
969 EMIT_PAD( 3 );
970 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
971 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 );
972 else
973 EMIT_PAD( 1 );
974 skip &= ~SAVAGE_SKIP_C1;
975
976 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
977 if (imesa->ptexHack)
978 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0);
979 else if (VB->TexCoordPtr[0]->size == 4)
980 assert (0); /* should be caught by savageCheckPTexHack */
981 else if (VB->TexCoordPtr[0]->size >= 2)
982 /* The chromium menu emits some 3D tex coords even though no
983 * 3D texture is enabled. Ignore the 3rd coordinate. */
984 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, SAVAGE_EMIT_ST0, SAVAGE_SKIP_ST0 );
985 else if (VB->TexCoordPtr[0]->size == 1) {
986 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_1F, SAVAGE_EMIT_S0, SAVAGE_SKIP_S0 );
987 EMIT_PAD( 4 );
988 } else
989 EMIT_PAD( 8 );
990 } else
991 EMIT_PAD( 8 );
992 skip &= ~SAVAGE_SKIP_ST0;
993
994 assert (skip == 0);
995 imesa->skip = skip;
996 return setupIndex;
997 }
998
999
1000 static __inline__ GLuint savageChooseVertexFormat_s4( GLcontext *ctx )
1001 {
1002 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1003 TNLcontext *tnl = TNL_CONTEXT(ctx);
1004 struct vertex_buffer *VB = &tnl->vb;
1005 DECLARE_RENDERINPUTS(index_bitset);
1006 GLuint setupIndex = SAVAGE_EMIT_XYZ;
1007 GLubyte skip;
1008 GLuint size, mask;
1009
1010 RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
1011 skip = SAVAGE_SKIP_ALL_S4;
1012 skip &= ~SAVAGE_SKIP_Z; /* all mesa vertices have a z coordinate */
1013
1014 if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) || !(ctx->_TriangleCaps & DD_FLATSHADE))
1015 NEED_ATTR( SAVAGE_EMIT_W, SAVAGE_SKIP_W );
1016
1017 /* t_context.c always includes a diffuse color */
1018 NEED_ATTR( SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 );
1019
1020 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ))
1021 NEED_ATTR( SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 );
1022 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
1023 NEED_ATTR( SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 );
1024
1025 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
1026 if (imesa->ptexHack)
1027 NEED_ATTR( SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0);
1028 else if (VB->TexCoordPtr[0]->size == 4)
1029 assert (0); /* should be caught by savageCheckPTexHack */
1030 else if (VB->TexCoordPtr[0]->size >= 2)
1031 /* The chromium menu emits some 3D tex coords even though no
1032 * 3D texture is enabled. Ignore the 3rd coordinate. */
1033 NEED_ATTR( SAVAGE_EMIT_ST0, SAVAGE_SKIP_ST0 );
1034 else
1035 NEED_ATTR( SAVAGE_EMIT_S0, SAVAGE_SKIP_S0 );
1036 }
1037 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) {
1038 if (VB->TexCoordPtr[1]->size == 4)
1039 /* projective textures are not supported by the hardware */
1040 assert (0); /* should be caught by savageCheckPTexHack */
1041 else if (VB->TexCoordPtr[1]->size >= 2)
1042 NEED_ATTR( SAVAGE_EMIT_ST1, SAVAGE_SKIP_ST1 );
1043 else
1044 NEED_ATTR( SAVAGE_EMIT_S1, SAVAGE_SKIP_S1 );
1045 }
1046
1047 /* if nothing changed we can skip the rest */
1048 if (setupIndex == imesa->SetupIndex && imesa->vertex_size != 0)
1049 return setupIndex;
1050
1051 if (imesa->enable_vdma) {
1052 mask = SAVAGE_SKIP_W;
1053 size = 10 - (skip & 1) - (skip >> 1 & 1) -
1054 (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
1055 (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
1056
1057 while (size < 8) {
1058 if (skip & mask) {
1059 skip &= ~mask;
1060 size++;
1061 }
1062 mask <<= 1;
1063 }
1064 }
1065
1066 imesa->vertex_attr_count = 0;
1067
1068 if (skip & SAVAGE_SKIP_W)
1069 DO_EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT );
1070 else if (setupIndex & SAVAGE_EMIT_W)
1071 DO_EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT );
1072 else {
1073 DO_EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT );
1074 EMIT_PAD( 4 );
1075 }
1076
1077 DO_EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA );
1078
1079 if (!(skip & SAVAGE_SKIP_C1)) {
1080 if (!(setupIndex & (SAVAGE_EMIT_C1|SAVAGE_EMIT_FOG)))
1081 EMIT_PAD( 4 );
1082 else {
1083 if (setupIndex & SAVAGE_EMIT_C1)
1084 DO_EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR );
1085 else
1086 EMIT_PAD( 3 );
1087 if (setupIndex & SAVAGE_EMIT_FOG)
1088 DO_EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F );
1089 else
1090 EMIT_PAD( 1 );
1091 }
1092 }
1093
1094 if ((skip & SAVAGE_SKIP_ST0) != SAVAGE_SKIP_ST0) {
1095 if ((setupIndex & SAVAGE_EMIT_STQ0) == SAVAGE_EMIT_STQ0)
1096 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW );
1097 else if ((setupIndex & SAVAGE_EMIT_ST0) == SAVAGE_EMIT_ST0)
1098 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F );
1099 else if ((setupIndex & SAVAGE_EMIT_ST0) == SAVAGE_EMIT_S0) {
1100 DO_EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_1F );
1101 if (!(skip & SAVAGE_SKIP_T0)) EMIT_PAD( 4 );
1102 } else {
1103 if (!(skip & SAVAGE_SKIP_S0)) EMIT_PAD( 4 );
1104 if (!(skip & SAVAGE_SKIP_T0)) EMIT_PAD( 4 );
1105 }
1106 }
1107
1108 if ((skip & SAVAGE_SKIP_ST1) != SAVAGE_SKIP_ST1) {
1109 if ((setupIndex & SAVAGE_EMIT_ST1) == SAVAGE_EMIT_ST1)
1110 DO_EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F );
1111 else if ((setupIndex & SAVAGE_EMIT_ST1) == SAVAGE_EMIT_S1) {
1112 DO_EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_1F );
1113 if (!(skip & SAVAGE_SKIP_T1)) EMIT_PAD( 4 );
1114 } else {
1115 if (!(skip & SAVAGE_SKIP_S1)) EMIT_PAD( 4 );
1116 if (!(skip & SAVAGE_SKIP_T1)) EMIT_PAD( 4 );
1117 }
1118 }
1119
1120 imesa->skip = skip;
1121 return setupIndex;
1122 }
1123
1124
1125 static void savageRenderStart( GLcontext *ctx )
1126 {
1127 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1128 TNLcontext *tnl = TNL_CONTEXT(ctx);
1129 struct vertex_buffer *VB = &tnl->vb;
1130 GLuint setupIndex = SAVAGE_EMIT_XYZ;
1131 GLboolean ptexHack;
1132
1133 /* Check if we need to apply the ptex hack. Choose a new render
1134 * state if necessary. (Note: this can't be done in
1135 * savageRunPipeline, since the number of vertex coordinates can
1136 * change in the pipeline. texmat or texgen or both?) */
1137 ptexHack = savageCheckPTexHack( ctx );
1138 if (ptexHack != imesa->ptexHack) {
1139 imesa->ptexHack = ptexHack;
1140 savageChooseRenderState (ctx);
1141 }
1142 /* Handle fallback cases identified in savageCheckPTexHack. */
1143 if (SAVAGE_CONTEXT(ctx)->Fallback) {
1144 tnl->Driver.Render.Start(ctx);
1145 return;
1146 }
1147
1148 /* Important:
1149 */
1150 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
1151
1152 if (imesa->savageScreen->chipset < S3_SAVAGE4) {
1153 setupIndex = savageChooseVertexFormat_s3d(ctx);
1154 } else {
1155 setupIndex = savageChooseVertexFormat_s4(ctx);
1156 }
1157
1158 /* Need to change the vertex emit code if the SetupIndex changed or
1159 * is set for the first time (indicated by vertex_size == 0). */
1160 if (setupIndex != imesa->SetupIndex || imesa->vertex_size == 0) {
1161 GLuint hwVertexSize;
1162 imesa->vertex_size =
1163 _tnl_install_attrs( ctx,
1164 imesa->vertex_attrs,
1165 imesa->vertex_attr_count,
1166 imesa->hw_viewport, 0 );
1167 imesa->vertex_size >>= 2;
1168 imesa->SetupIndex = setupIndex;
1169
1170 hwVertexSize = imesa->vertex_size;
1171 if (setupIndex & SAVAGE_EMIT_Q0) {
1172 /* The vertex setup code emits homogenous texture
1173 * coordinates. They are converted to normal 2D coords by
1174 * savage_ptex_tri/line/point. Now we have two different
1175 * vertex sizes. Functions that emit vertices to the hardware
1176 * need to use HwVertexSize, anything that manipulates the
1177 * vertices generated by t_vertex uses vertex_size. */
1178 hwVertexSize--;
1179 assert (imesa->ptexHack);
1180 } else
1181 assert (!imesa->ptexHack);
1182
1183 if (hwVertexSize != imesa->HwVertexSize) {
1184 /* Changing the vertex size: flush vertex and command buffer and
1185 * discard the DMA buffer, if we were using one. */
1186 savageFlushVertices(imesa);
1187 savageFlushCmdBuf(imesa, GL_TRUE);
1188 if (hwVertexSize == 8 && imesa->enable_vdma) {
1189 if (SAVAGE_DEBUG & DEBUG_DMA)
1190 fprintf (stderr, "Using DMA, skip=0x%02x\n", imesa->skip);
1191 /* we can use vertex dma */
1192 imesa->vtxBuf = &imesa->dmaVtxBuf;
1193 } else {
1194 if (SAVAGE_DEBUG & DEBUG_DMA)
1195 fprintf (stderr, "Not using DMA, skip=0x%02x\n", imesa->skip);
1196 imesa->vtxBuf = &imesa->clientVtxBuf;
1197 }
1198 imesa->HwVertexSize = hwVertexSize;
1199 }
1200 }
1201 }
1202
1203 static void savageRenderFinish( GLcontext *ctx )
1204 {
1205 /* Flush the last primitive now, before any state is changed. */
1206 savageFlushVertices(SAVAGE_CONTEXT(ctx));
1207
1208 if (SAVAGE_CONTEXT(ctx)->RenderIndex & SAVAGE_FALLBACK_BIT)
1209 _swrast_flush( ctx );
1210 }
1211
1212
1213 /**********************************************************************/
1214 /* Transition to/from hardware rasterization. */
1215 /**********************************************************************/
1216
1217 static const char * const fallbackStrings[] = {
1218 "Texture mode",
1219 "Draw buffer",
1220 "Read buffer",
1221 "Color mask",
1222 "Specular",
1223 "LogicOp",
1224 "glEnable(GL_STENCIL) without hw stencil buffer",
1225 "glRenderMode(selection or feedback)",
1226 "glBlendEquation",
1227 "Hardware rasterization disabled",
1228 "Projective texture",
1229 };
1230
1231 void savageFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
1232 {
1233 TNLcontext *tnl = TNL_CONTEXT(ctx);
1234 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1235 GLuint oldfallback = imesa->Fallback;
1236 GLuint index;
1237 for (index = 0; (1 << index) < bit; ++index);
1238
1239 if (mode) {
1240 imesa->Fallback |= bit;
1241 if (oldfallback == 0) {
1242 /* the first fallback */
1243 _swsetup_Wakeup( ctx );
1244 imesa->RenderIndex = ~0;
1245 }
1246 if (!(oldfallback & bit) && (SAVAGE_DEBUG & DEBUG_FALLBACKS))
1247 fprintf (stderr, "Savage begin fallback: 0x%x %s\n",
1248 bit, fallbackStrings[index]);
1249 }
1250 else {
1251 imesa->Fallback &= ~bit;
1252 if (oldfallback == bit) {
1253 /* the last fallback */
1254 _swrast_flush( ctx );
1255 tnl->Driver.Render.Start = savageRenderStart;
1256 tnl->Driver.Render.PrimitiveNotify = savageRenderPrimitive;
1257 tnl->Driver.Render.Finish = savageRenderFinish;
1258
1259 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1260 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1261 tnl->Driver.Render.Interp = _tnl_interp;
1262
1263 _tnl_invalidate_vertex_state( ctx, ~0 );
1264 _tnl_invalidate_vertices( ctx, ~0 );
1265 _tnl_install_attrs( ctx,
1266 imesa->vertex_attrs,
1267 imesa->vertex_attr_count,
1268 imesa->hw_viewport, 0 );
1269
1270 imesa->new_gl_state |= _SAVAGE_NEW_RENDER_STATE;
1271 }
1272 if ((oldfallback & bit) && (SAVAGE_DEBUG & DEBUG_FALLBACKS))
1273 fprintf (stderr, "Savage end fallback: 0x%x %s\n",
1274 bit, fallbackStrings[index]);
1275 }
1276 }
1277
1278
1279 /**********************************************************************/
1280 /* Initialization. */
1281 /**********************************************************************/
1282
1283 void savageInitTriFuncs( GLcontext *ctx )
1284 {
1285 TNLcontext *tnl = TNL_CONTEXT(ctx);
1286 static int firsttime = 1;
1287
1288 if (firsttime) {
1289 init_rast_tab();
1290 firsttime = 0;
1291 }
1292
1293 tnl->Driver.RunPipeline = savageRunPipeline;
1294 tnl->Driver.Render.Start = savageRenderStart;
1295 tnl->Driver.Render.Finish = savageRenderFinish;
1296 tnl->Driver.Render.PrimitiveNotify = savageRenderPrimitive;
1297 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
1298
1299 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1300 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1301 tnl->Driver.Render.Interp = _tnl_interp;
1302
1303 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
1304 (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
1305
1306 SAVAGE_CONTEXT(ctx)->verts = (char *)tnl->clipspace.vertex_buf;
1307 }