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