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