(Stephane Marchesin, me) add hyperz support to radeon and r200 drivers. Only fast...
[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->vertex_size;
103 uint32_t *vb = savageAllocDmaLow (imesa, 3*4*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->vertex_size;
117 uint32_t *vb = savageAllocDmaLow (imesa, 6*4*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->vertex_size;
131 uint32_t *vb = savageAllocDmaLow (imesa, 6*4*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->vertex_size;
166 uint32_t *vb = savageAllocDmaLow (imesa, 6*4*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 /***********************************************************************
205 * Macros for t_dd_tritmp.h to draw basic primitives *
206 ***********************************************************************/
207
208 #define TRI( a, b, c ) \
209 do { \
210 if (DO_FALLBACK) \
211 imesa->draw_tri( imesa, a, b, c ); \
212 else \
213 savage_draw_triangle( imesa, a, b, c ); \
214 } while (0)
215
216 #define QUAD( a, b, c, d ) \
217 do { \
218 if (DO_FALLBACK) { \
219 imesa->draw_tri( imesa, a, b, d ); \
220 imesa->draw_tri( imesa, b, c, d ); \
221 } else \
222 savage_draw_quad( imesa, a, b, c, d ); \
223 } while (0)
224
225 #define LINE( v0, v1 ) \
226 do { \
227 if (DO_FALLBACK) \
228 imesa->draw_line( imesa, v0, v1 ); \
229 else \
230 savage_draw_line( imesa, v0, v1 ); \
231 } while (0)
232
233 #define POINT( v0 ) \
234 do { \
235 if (DO_FALLBACK) \
236 imesa->draw_point( imesa, v0 ); \
237 else \
238 savage_draw_point( imesa, v0 ); \
239 } while (0)
240
241
242 /***********************************************************************
243 * Build render functions from dd templates *
244 ***********************************************************************/
245
246 #define SAVAGE_OFFSET_BIT 0x1
247 #define SAVAGE_TWOSIDE_BIT 0x2
248 #define SAVAGE_UNFILLED_BIT 0x4
249 #define SAVAGE_FALLBACK_BIT 0x8
250 #define SAVAGE_MAX_TRIFUNC 0x10
251
252
253 static struct {
254 tnl_points_func points;
255 tnl_line_func line;
256 tnl_triangle_func triangle;
257 tnl_quad_func quad;
258 } rast_tab[SAVAGE_MAX_TRIFUNC];
259
260
261 #define DO_FALLBACK (IND & SAVAGE_FALLBACK_BIT)
262 #define DO_OFFSET (IND & SAVAGE_OFFSET_BIT)
263 #define DO_UNFILLED (IND & SAVAGE_UNFILLED_BIT)
264 #define DO_TWOSIDE (IND & SAVAGE_TWOSIDE_BIT)
265 #define DO_FLAT 0
266 #define DO_TRI 1
267 #define DO_QUAD 1
268 #define DO_LINE 1
269 #define DO_POINTS 1
270 #define DO_FULL_QUAD 1
271
272 #define HAVE_RGBA 1
273 #define HAVE_SPEC 1
274 #define HAVE_BACK_COLORS 0
275 #define HAVE_HW_FLATSHADE 1
276 #define VERTEX savageVertex
277 #define TAB rast_tab
278
279 #define DEPTH_SCALE imesa->depth_scale
280 #define UNFILLED_TRI unfilled_tri
281 #define UNFILLED_QUAD unfilled_quad
282 #define VERT_X(_v) _v->v.x
283 #define VERT_Y(_v) _v->v.y
284 #define VERT_Z(_v) _v->v.z
285 #define AREA_IS_CCW( a ) (a > 0)
286 #define GET_VERTEX(e) (imesa->verts + (e * imesa->vertex_size * sizeof(int)))
287
288 #define VERT_SET_RGBA( v, c ) \
289 do { \
290 savage_color_t *color = (savage_color_t *)&((v)->ub4[coloroffset]); \
291 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
292 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
293 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
294 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
295 } while (0)
296 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
297 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
298 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
299
300 #define VERT_SET_SPEC( v, c ) \
301 do { \
302 if (specoffset) { \
303 savage_color_t *spec = (savage_color_t *)&((v)->ub4[specoffset]); \
304 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
305 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
306 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
307 } \
308 } while (0)
309 #define VERT_COPY_SPEC( v0, v1 ) \
310 if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset])
311 #define VERT_SAVE_SPEC( idx ) \
312 if (specoffset) spec[idx] = v[idx]->ui[specoffset]
313 #define VERT_RESTORE_SPEC( idx ) \
314 if (specoffset) v[idx]->ui[specoffset] = spec[idx]
315
316 #define LOCAL_VARS(n) \
317 savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
318 GLuint color[n], spec[n]; \
319 GLuint coloroffset = \
320 ((imesa->DrawPrimitiveCmd & SAVAGE_HW_NO_W) ? 3 : 4); \
321 GLboolean specoffset = \
322 ((imesa->DrawPrimitiveCmd & SAVAGE_HW_NO_CS) ? 0 : coloroffset+1);\
323 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
324
325 /***********************************************************************
326 * Helpers for rendering unfilled primitives *
327 ***********************************************************************/
328
329 #define RASTERIZE(x) if (imesa->raster_primitive != reduced_prim[x]) \
330 savageRasterPrimitive( ctx, x )
331 #define RENDER_PRIMITIVE imesa->render_primitive
332 #define IND SAVAGE_FALLBACK_BIT
333 #define TAG(x) x
334 #include "tnl_dd/t_dd_unfilled.h"
335 #undef IND
336
337
338 /***********************************************************************
339 * Generate GL render functions *
340 ***********************************************************************/
341
342
343 #define IND (0)
344 #define TAG(x) x
345 #include "tnl_dd/t_dd_tritmp.h"
346
347 #define IND (SAVAGE_OFFSET_BIT)
348 #define TAG(x) x##_offset
349 #include "tnl_dd/t_dd_tritmp.h"
350
351 #define IND (SAVAGE_TWOSIDE_BIT)
352 #define TAG(x) x##_twoside
353 #include "tnl_dd/t_dd_tritmp.h"
354
355 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT)
356 #define TAG(x) x##_twoside_offset
357 #include "tnl_dd/t_dd_tritmp.h"
358
359 #define IND (SAVAGE_UNFILLED_BIT)
360 #define TAG(x) x##_unfilled
361 #include "tnl_dd/t_dd_tritmp.h"
362
363 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
364 #define TAG(x) x##_offset_unfilled
365 #include "tnl_dd/t_dd_tritmp.h"
366
367 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT)
368 #define TAG(x) x##_twoside_unfilled
369 #include "tnl_dd/t_dd_tritmp.h"
370
371 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
372 #define TAG(x) x##_twoside_offset_unfilled
373 #include "tnl_dd/t_dd_tritmp.h"
374
375 #define IND (SAVAGE_FALLBACK_BIT)
376 #define TAG(x) x##_fallback
377 #include "tnl_dd/t_dd_tritmp.h"
378
379 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
380 #define TAG(x) x##_offset_fallback
381 #include "tnl_dd/t_dd_tritmp.h"
382
383 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_FALLBACK_BIT)
384 #define TAG(x) x##_twoside_fallback
385 #include "tnl_dd/t_dd_tritmp.h"
386
387 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
388 #define TAG(x) x##_twoside_offset_fallback
389 #include "tnl_dd/t_dd_tritmp.h"
390
391 #define IND (SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
392 #define TAG(x) x##_unfilled_fallback
393 #include "tnl_dd/t_dd_tritmp.h"
394
395 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
396 #define TAG(x) x##_offset_unfilled_fallback
397 #include "tnl_dd/t_dd_tritmp.h"
398
399 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
400 #define TAG(x) x##_twoside_unfilled_fallback
401 #include "tnl_dd/t_dd_tritmp.h"
402
403 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT| \
404 SAVAGE_FALLBACK_BIT)
405 #define TAG(x) x##_twoside_offset_unfilled_fallback
406 #include "tnl_dd/t_dd_tritmp.h"
407
408
409 static void init_rast_tab( void )
410 {
411 init();
412 init_offset();
413 init_twoside();
414 init_twoside_offset();
415 init_unfilled();
416 init_offset_unfilled();
417 init_twoside_unfilled();
418 init_twoside_offset_unfilled();
419 init_fallback();
420 init_offset_fallback();
421 init_twoside_fallback();
422 init_twoside_offset_fallback();
423 init_unfilled_fallback();
424 init_offset_unfilled_fallback();
425 init_twoside_unfilled_fallback();
426 init_twoside_offset_unfilled_fallback();
427 }
428
429
430
431 /***********************************************************************
432 * Rasterization fallback helpers *
433 ***********************************************************************/
434
435
436 /* This code is hit only when a mix of accelerated and unaccelerated
437 * primitives are being drawn, and only for the unaccelerated
438 * primitives.
439 */
440 static void
441 savage_fallback_tri( savageContextPtr imesa,
442 savageVertexPtr v0,
443 savageVertexPtr v1,
444 savageVertexPtr v2 )
445 {
446 GLcontext *ctx = imesa->glCtx;
447 SWvertex v[3];
448 _swsetup_Translate( ctx, v0, &v[0] );
449 _swsetup_Translate( ctx, v1, &v[1] );
450 _swsetup_Translate( ctx, v2, &v[2] );
451 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
452 }
453
454
455 static void
456 savage_fallback_line( savageContextPtr imesa,
457 savageVertexPtr v0,
458 savageVertexPtr v1 )
459 {
460 GLcontext *ctx = imesa->glCtx;
461 SWvertex v[2];
462 _swsetup_Translate( ctx, v0, &v[0] );
463 _swsetup_Translate( ctx, v1, &v[1] );
464 _swrast_Line( ctx, &v[0], &v[1] );
465 }
466
467
468 static void
469 savage_fallback_point( savageContextPtr imesa,
470 savageVertexPtr v0 )
471 {
472 GLcontext *ctx = imesa->glCtx;
473 SWvertex v[1];
474 _swsetup_Translate( ctx, v0, &v[0] );
475 _swrast_Point( ctx, &v[0] );
476 }
477
478
479
480 /**********************************************************************/
481 /* Render unclipped begin/end objects */
482 /**********************************************************************/
483
484 #define VERT(x) (savageVertexPtr)(savageVerts + (x * vertsize * sizeof(int)))
485 #define RENDER_POINTS( start, count ) \
486 for ( ; start < count ; start++) \
487 savage_draw_point( imesa, VERT(start) )
488 #define RENDER_LINE( v0, v1 ) \
489 savage_draw_line( imesa, VERT(v0), VERT(v1) )
490 #define RENDER_TRI( v0, v1, v2 ) \
491 savage_draw_triangle( imesa, VERT(v0), VERT(v1), VERT(v2) )
492 #define RENDER_QUAD( v0, v1, v2, v3 ) \
493 savage_draw_quad( imesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
494 #define INIT(x) do { \
495 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
496 savageRenderPrimitive( ctx, x ); \
497 /*SAVAGE_CONTEXT(ctx)->render_primitive = x;*/ \
498 } while (0)
499 #undef LOCAL_VARS
500 #define LOCAL_VARS \
501 savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
502 const GLuint vertsize = imesa->vertex_size; \
503 const char *savageVerts = (char *)imesa->verts; \
504 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
505 (void) elt;
506 #define RESET_STIPPLE
507 #define RESET_OCCLUSION
508 #define PRESERVE_VB_DEFS
509 #define ELT(x) (x)
510 #define TAG(x) savage_##x##_verts
511 #include "tnl/t_vb_rendertmp.h"
512 #undef ELT
513 #undef TAG
514 #define TAG(x) savage_##x##_elts
515 #define ELT(x) elt[x]
516 #include "tnl/t_vb_rendertmp.h"
517
518
519 /**********************************************************************/
520 /* Render clipped primitives */
521 /**********************************************************************/
522
523 static void savageRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
524 GLuint n )
525 {
526 TNLcontext *tnl = TNL_CONTEXT(ctx);
527 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
528
529 /* Render the new vertices as an unclipped polygon.
530 */
531 {
532 GLuint *tmp = VB->Elts;
533 VB->Elts = (GLuint *)elts;
534 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
535 VB->Elts = tmp;
536 }
537 }
538
539 static void savageRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
540 {
541 TNLcontext *tnl = TNL_CONTEXT(ctx);
542 tnl->Driver.Render.Line( ctx, ii, jj );
543 }
544 /*
545 static void savageFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
546 GLuint n )
547 {
548 r128ContextPtr rmesa = R128_CONTEXT( ctx );
549 GLuint vertsize = rmesa->vertex_size;
550 GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
551 GLubyte *r128verts = (GLubyte *)rmesa->verts;
552 const GLuint shift = rmesa->vertex_stride_shift;
553 const GLuint *start = (const GLuint *)VERT(elts[0]);
554 int i,j;
555
556 rmesa->num_verts += (n-2) * 3;
557
558 for (i = 2 ; i < n ; i++) {
559 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
560 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
561 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
562 }
563 }
564 */
565
566
567
568 /**********************************************************************/
569 /* Choose render functions */
570 /**********************************************************************/
571
572 #define _SAVAGE_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
573 _DD_NEW_LINE_SMOOTH | \
574 _DD_NEW_POINT_SMOOTH | \
575 _DD_NEW_TRI_SMOOTH | \
576 _DD_NEW_TRI_UNFILLED | \
577 _DD_NEW_TRI_LIGHT_TWOSIDE | \
578 _DD_NEW_TRI_OFFSET) \
579
580 /* original driver didn't have DD_POINT_SMOOTH. really needed? */
581 #define POINT_FALLBACK (DD_POINT_SMOOTH)
582 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
583 #define TRI_FALLBACK (DD_TRI_SMOOTH)
584 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
585 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
586
587
588 static void savageChooseRenderState(GLcontext *ctx)
589 {
590 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
591 GLuint flags = ctx->_TriangleCaps;
592 GLuint index = 0;
593
594 if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
595 imesa->draw_point = savage_draw_point;
596 imesa->draw_line = savage_draw_line;
597 imesa->draw_tri = savage_draw_triangle;
598
599 if (flags & ANY_RASTER_FLAGS) {
600 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= SAVAGE_TWOSIDE_BIT;
601 if (flags & DD_TRI_OFFSET) index |= SAVAGE_OFFSET_BIT;
602 if (flags & DD_TRI_UNFILLED) index |= SAVAGE_UNFILLED_BIT;
603 }
604
605 /* Hook in fallbacks for specific primitives.
606 */
607 if (flags & (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)) {
608 if (flags & POINT_FALLBACK) imesa->draw_point = savage_fallback_point;
609 if (flags & LINE_FALLBACK) imesa->draw_line = savage_fallback_line;
610 if (flags & TRI_FALLBACK) imesa->draw_tri = savage_fallback_tri;
611 index |= SAVAGE_FALLBACK_BIT;
612 }
613 }
614
615 if (index != imesa->RenderIndex) {
616 TNLcontext *tnl = TNL_CONTEXT(ctx);
617 tnl->Driver.Render.Points = rast_tab[index].points;
618 tnl->Driver.Render.Line = rast_tab[index].line;
619 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
620 tnl->Driver.Render.Quad = rast_tab[index].quad;
621
622 if (index == 0) {
623 tnl->Driver.Render.PrimTabVerts = savage_render_tab_verts;
624 tnl->Driver.Render.PrimTabElts = savage_render_tab_elts;
625 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
626 tnl->Driver.Render.ClippedPolygon = savageRenderClippedPoly/*r128FastRenderClippedPoly*/;
627 } else {
628 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
629 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
630 tnl->Driver.Render.ClippedLine = savageRenderClippedLine;
631 tnl->Driver.Render.ClippedPolygon = savageRenderClippedPoly;
632 }
633
634 imesa->RenderIndex = index;
635 }
636 }
637
638 /**********************************************************************/
639 /* Validate state at pipeline start */
640 /**********************************************************************/
641
642 static void savageRunPipeline( GLcontext *ctx )
643 {
644 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
645
646 if (imesa->new_state)
647 savageDDUpdateHwState( ctx );
648
649 if (!imesa->Fallback && imesa->new_gl_state) {
650 if (imesa->new_gl_state & _SAVAGE_NEW_RENDER_STATE)
651 savageChooseRenderState( ctx );
652
653 imesa->new_gl_state = 0;
654 }
655
656 _tnl_run_pipeline( ctx );
657 }
658
659 /**********************************************************************/
660 /* High level hooks for t_vb_render.c */
661 /**********************************************************************/
662
663 /* This is called when Mesa switches between rendering triangle
664 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
665 * and lines, points and bitmaps.
666 *
667 * As the r128 uses triangles to render lines and points, it is
668 * necessary to turn off hardware culling when rendering these
669 * primitives.
670 */
671
672 static void savageRasterPrimitive( GLcontext *ctx, GLuint prim )
673 {
674 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
675
676 /* Update culling */
677 if (imesa->raster_primitive != prim) {
678 imesa->raster_primitive = prim;
679 imesa->new_state |= SAVAGE_NEW_CULL;
680 savageDDUpdateHwState (ctx);
681 }
682
683 #if 0
684 if (ctx->Polygon.StippleFlag && mmesa->haveHwStipple)
685 {
686 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
687 mmesa->setup.dwgctl &= ~(0xf<<20);
688 if (mmesa->raster_primitive == GL_TRIANGLES)
689 mmesa->setup.dwgctl |= mmesa->poly_stipple;
690 }
691 #endif
692 }
693
694 static void savageRenderPrimitive( GLcontext *ctx, GLenum prim )
695 {
696 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
697 GLuint rprim = reduced_prim[prim];
698
699 imesa->render_primitive = prim;
700
701 if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
702 return;
703
704 if (imesa->raster_primitive != rprim) {
705 savageRasterPrimitive( ctx, rprim );
706 }
707 }
708
709
710 #define EMIT_ATTR( ATTR, STYLE, INDEX, SKIP ) \
711 do { \
712 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = (ATTR); \
713 imesa->vertex_attrs[imesa->vertex_attr_count].format = (STYLE); \
714 imesa->vertex_attr_count++; \
715 setupIndex |= (INDEX); \
716 drawCmd &= ~(SKIP); \
717 } while (0)
718
719 #define EMIT_PAD( N ) \
720 do { \
721 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = 0; \
722 imesa->vertex_attrs[imesa->vertex_attr_count].format = EMIT_PAD; \
723 imesa->vertex_attrs[imesa->vertex_attr_count].offset = (N); \
724 imesa->vertex_attr_count++; \
725 } while (0)
726
727 #define SAVAGE_EMIT_XYZ 0x0001
728 #define SAVAGE_EMIT_W 0x0002
729 #define SAVAGE_EMIT_C0 0x0004
730 #define SAVAGE_EMIT_C1 0x0008
731 #define SAVAGE_EMIT_FOG 0x0010
732 #define SAVAGE_EMIT_S0 0x0020
733 #define SAVAGE_EMIT_T0 0x0040
734 #define SAVAGE_EMIT_ST0 0x0060
735 #define SAVAGE_EMIT_S1 0x0080
736 #define SAVAGE_EMIT_T1 0x0100
737 #define SAVAGE_EMIT_ST1 0x0180
738
739
740 static void savageRenderStart( GLcontext *ctx )
741 {
742 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
743 TNLcontext *tnl = TNL_CONTEXT(ctx);
744 struct vertex_buffer *VB = &tnl->vb;
745 GLuint index = tnl->render_inputs;
746 GLuint setupIndex = SAVAGE_EMIT_XYZ;
747 GLuint drawCmd = SAVAGE_HW_SKIPFLAGS;
748 if (imesa->savageScreen->chipset < S3_SAVAGE4)
749 drawCmd &= ~SAVAGE_HW_NO_UV1;
750 drawCmd &= ~SAVAGE_HW_NO_Z; /* all mesa vertices have a z coordinate */
751
752 /* Important:
753 */
754 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
755 imesa->vertex_attr_count = 0;
756
757 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
758 * build up a hardware vertex.
759 */
760 if ((index & _TNL_BITS_TEX_ANY) || !(ctx->_TriangleCaps & DD_FLATSHADE)) {
761 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, SAVAGE_EMIT_W, SAVAGE_HW_NO_W );
762 }
763 else {
764 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
765 }
766
767 /* t_context.c always includes a diffuse color */
768 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, SAVAGE_EMIT_C0, SAVAGE_HW_NO_CD );
769
770 if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
771 if ((index & _TNL_BIT_COLOR1))
772 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, SAVAGE_EMIT_C1, SAVAGE_HW_NO_CS );
773 else
774 EMIT_PAD( 3 );
775 if ((index & _TNL_BIT_FOG))
776 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, SAVAGE_EMIT_FOG, SAVAGE_HW_NO_CS );
777 else
778 EMIT_PAD( 1 );
779 }
780
781 if (index & _TNL_BIT_TEX(0)) {
782 if (VB->TexCoordPtr[0]->size > 2) {
783 /* projective textures are not supported by the hardware */
784 FALLBACK(ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
785 }
786 if (VB->TexCoordPtr[0]->size == 2)
787 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, SAVAGE_EMIT_ST0, SAVAGE_HW_NO_UV0 );
788 else
789 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_1F, SAVAGE_EMIT_S0, SAVAGE_HW_NO_U0 );
790 }
791 if (index & _TNL_BIT_TEX(1)) {
792 if (VB->TexCoordPtr[1]->size > 2) {
793 /* projective textures are not supported by the hardware */
794 FALLBACK(ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
795 }
796 if (VB->TexCoordPtr[1]->size == 2)
797 EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, SAVAGE_EMIT_ST1, SAVAGE_HW_NO_UV1 );
798 else
799 EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_1F, SAVAGE_EMIT_S1, SAVAGE_HW_NO_U1 );
800 }
801
802 /* Need to change the vertex emit code if the SetupIndex changed or
803 * is set for the first time (indicated by vertex_size == 0). */
804 if (setupIndex != imesa->SetupIndex || imesa->vertex_size == 0) {
805 imesa->vertex_size =
806 _tnl_install_attrs( ctx,
807 imesa->vertex_attrs,
808 imesa->vertex_attr_count,
809 imesa->hw_viewport, 0 );
810 imesa->vertex_size >>= 2;
811 imesa->SetupIndex = setupIndex;
812
813 imesa->DrawPrimitiveCmd = drawCmd;
814 }
815
816 if (!SAVAGE_CONTEXT(ctx)->Fallback) {
817 /* Update hardware state and get the lock */
818 savageDDRenderStart( ctx );
819 } else {
820 tnl->Driver.Render.Start(ctx);
821 }
822 }
823
824 static void savageRenderFinish( GLcontext *ctx )
825 {
826 /* Release the lock */
827 savageDDRenderEnd( ctx );
828
829 /* Flush the last primitive now, before any state is changed.
830 * Alternatively state could be emitted in all state-changing
831 * functions in savagestate.c and when changing the vertex format
832 * above. */
833 FLUSH_BATCH(SAVAGE_CONTEXT(ctx));
834
835 if (SAVAGE_CONTEXT(ctx)->RenderIndex & SAVAGE_FALLBACK_BIT)
836 _swrast_flush( ctx );
837 }
838
839
840 /**********************************************************************/
841 /* Transition to/from hardware rasterization. */
842 /**********************************************************************/
843
844 void savageFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
845 {
846 TNLcontext *tnl = TNL_CONTEXT(ctx);
847 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
848 GLuint oldfallback = imesa->Fallback;
849
850 if (mode) {
851 imesa->Fallback |= bit;
852 if (oldfallback == 0) {
853 /* the first fallback */
854 FLUSH_BATCH( imesa );
855 _swsetup_Wakeup( ctx );
856 imesa->RenderIndex = ~0;
857 }
858 }
859 else {
860 imesa->Fallback &= ~bit;
861 if (oldfallback == bit) {
862 /* the last fallback */
863 _swrast_flush( ctx );
864 tnl->Driver.Render.Start = savageRenderStart;
865 tnl->Driver.Render.PrimitiveNotify = savageRenderPrimitive;
866 tnl->Driver.Render.Finish = savageRenderFinish;
867
868 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
869 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
870 tnl->Driver.Render.Interp = _tnl_interp;
871
872 _tnl_invalidate_vertex_state( ctx, ~0 );
873 _tnl_invalidate_vertices( ctx, ~0 );
874 _tnl_install_attrs( ctx,
875 imesa->vertex_attrs,
876 imesa->vertex_attr_count,
877 imesa->hw_viewport, 0 );
878
879 imesa->new_gl_state |= _SAVAGE_NEW_RENDER_STATE;
880 }
881 }
882 }
883
884
885 /**********************************************************************/
886 /* Initialization. */
887 /**********************************************************************/
888
889 void savageInitTriFuncs( GLcontext *ctx )
890 {
891 TNLcontext *tnl = TNL_CONTEXT(ctx);
892 static int firsttime = 1;
893
894 if (firsttime) {
895 init_rast_tab();
896 firsttime = 0;
897 }
898
899 tnl->Driver.RunPipeline = savageRunPipeline;
900 tnl->Driver.Render.Start = savageRenderStart;
901 tnl->Driver.Render.Finish = savageRenderFinish;
902 tnl->Driver.Render.PrimitiveNotify = savageRenderPrimitive;
903 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
904
905 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
906 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
907 tnl->Driver.Render.Interp = _tnl_interp;
908
909 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
910 (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
911
912 SAVAGE_CONTEXT(ctx)->verts = (char *)tnl->clipspace.vertex_buf;
913 }