Fix several conformance problems. Hack solution to line stipple problem.
[mesa.git] / src / mesa / drivers / glide / fxtris.c
1
2
3 #ifdef HAVE_CONFIG_H
4 #include "conf.h"
5 #endif
6
7 #if defined(FX)
8
9 #include "mmath.h"
10 #include "swrast/swrast.h"
11 #include "swrast_setup/swrast_setup.h"
12
13 #include "tnl/t_context.h"
14 #include "tnl/t_pipeline.h"
15
16 #include "fxdrv.h"
17 #include "fxglidew.h"
18
19
20
21
22
23
24
25
26 static void
27 fx_draw_point( GLcontext *ctx, const fxVertex *v )
28 {
29 GLfloat sz = ctx->Point._Size;
30
31 if ( sz <= 1.0 )
32 {
33 grDrawPoint( &(v->v) );
34 }
35 else
36 {
37 GrVertex verts[4];
38
39 sz *= .5;
40
41 verts[0] = v->v;
42 verts[1] = v->v;
43 verts[2] = v->v;
44 verts[3] = v->v;
45
46 verts[0].x = v->v.x - sz;
47 verts[0].y = v->v.y - sz;
48
49 verts[1].x = v->v.x + sz;
50 verts[1].y = v->v.y - sz;
51
52 verts[2].x = v->v.x + sz;
53 verts[2].y = v->v.y + sz;
54
55 verts[3].x = v->v.x - sz;
56 verts[3].y = v->v.y + sz;
57
58 grDrawTriangle( &verts[0], &verts[1], &verts[3] );
59 grDrawTriangle( &verts[1], &verts[2], &verts[3] );
60 }
61 }
62
63
64 static void
65 fx_draw_line( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1 )
66 {
67 float width = ctx->Line.Width;
68
69 if ( width <= 1.0 )
70 {
71 grDrawLine( &(v0->v), &(v1->v) );
72 }
73 else
74 {
75 GrVertex verts[4];
76 float dx, dy, ix, iy;
77
78 dx = v0->v.x - v1->v.x;
79 dy = v0->v.y - v1->v.y;
80
81 if (dx * dx > dy * dy) {
82 iy = width * .5;
83 ix = 0;
84 } else {
85 iy = 0;
86 ix = width * .5;
87 }
88
89
90 verts[0] = v0->v;
91 verts[0].x -= ix;
92 verts[0].y -= iy;
93
94 verts[1] = v0->v;
95 verts[1].x += ix;
96 verts[1].y += iy;
97
98 verts[2] = v1->v;
99 verts[2].x += ix;
100 verts[2].y += iy;
101
102 verts[3] = v1->v;
103 verts[3].x -= ix;
104 verts[3].y -= iy;
105
106 grDrawTriangle( &verts[0], &verts[1], &verts[3] );
107 grDrawTriangle( &verts[1], &verts[2], &verts[3] );
108 }
109 }
110
111 static void
112 fx_draw_tri( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1,
113 const fxVertex *v2 )
114 {
115 grDrawTriangle( &(v0->v), &(v1->v), &(v2->v) );
116 }
117
118
119
120 #define FX_COLOR(vert, c) { \
121 GLubyte *col = c; \
122 vert->v.r=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]); \
123 vert->v.g=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]); \
124 vert->v.b=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]); \
125 vert->v.a=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]); \
126 }
127
128 #define FX_COPY_COLOR( dst, src ) { \
129 dst->v.r = src->v.r; \
130 dst->v.g = src->v.g; \
131 dst->v.b = src->v.b; \
132 dst->v.a = src->v.a; \
133 }
134
135
136
137 #define FX_FLAT_BIT 0x01
138 #define FX_OFFSET_BIT 0x02
139 #define FX_TWOSIDE_BIT 0x04
140 #define FX_UNFILLED_BIT 0x10
141 #define FX_FALLBACK_BIT 0x20
142 #define FX_MAX_TRIFUNC 0x40
143
144 static struct {
145 points_func points;
146 line_func line;
147 triangle_func triangle;
148 quad_func quad;
149 } rast_tab[FX_MAX_TRIFUNC];
150
151
152 #define IND (0)
153 #define TAG(x) x
154 #include "fxtritmp.h"
155
156 #define IND (FX_FLAT_BIT)
157 #define TAG(x) x##_flat
158 #include "fxtritmp.h"
159
160 #define IND (FX_OFFSET_BIT)
161 #define TAG(x) x##_offset
162 #include "fxtritmp.h"
163
164 #define IND (FX_OFFSET_BIT | FX_FLAT_BIT)
165 #define TAG(x) x##_offset_flat
166 #include "fxtritmp.h"
167
168 #define IND (FX_TWOSIDE_BIT)
169 #define TAG(x) x##_twoside
170 #include "fxtritmp.h"
171
172 #define IND (FX_TWOSIDE_BIT | FX_FLAT_BIT)
173 #define TAG(x) x##_twoside_flat
174 #include "fxtritmp.h"
175
176 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT)
177 #define TAG(x) x##_twoside_offset
178 #include "fxtritmp.h"
179
180 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FLAT_BIT)
181 #define TAG(x) x##_twoside_offset_flat
182 #include "fxtritmp.h"
183
184 #define IND (FX_FALLBACK_BIT)
185 #define TAG(x) x##_fallback
186 #include "fxtritmp.h"
187
188 #define IND (FX_FLAT_BIT | FX_FALLBACK_BIT)
189 #define TAG(x) x##_flat_fallback
190 #include "fxtritmp.h"
191
192 #define IND (FX_OFFSET_BIT | FX_FALLBACK_BIT)
193 #define TAG(x) x##_offset_fallback
194 #include "fxtritmp.h"
195
196 #define IND (FX_OFFSET_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT)
197 #define TAG(x) x##_offset_flat_fallback
198 #include "fxtritmp.h"
199
200 #define IND (FX_TWOSIDE_BIT | FX_FALLBACK_BIT)
201 #define TAG(x) x##_twoside_fallback
202 #include "fxtritmp.h"
203
204 #define IND (FX_TWOSIDE_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT)
205 #define TAG(x) x##_twoside_flat_fallback
206 #include "fxtritmp.h"
207
208 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FALLBACK_BIT)
209 #define TAG(x) x##_twoside_offset_fallback
210 #include "fxtritmp.h"
211
212 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT)
213 #define TAG(x) x##_twoside_offset_flat_fallback
214 #include "fxtritmp.h"
215
216 #define IND (FX_UNFILLED_BIT)
217 #define TAG(x) x##_unfilled
218 #include "fxtritmp.h"
219
220 #define IND (FX_FLAT_BIT | FX_UNFILLED_BIT)
221 #define TAG(x) x##_flat_unfilled
222 #include "fxtritmp.h"
223
224 #define IND (FX_OFFSET_BIT | FX_UNFILLED_BIT)
225 #define TAG(x) x##_offset_unfilled
226 #include "fxtritmp.h"
227
228 #define IND (FX_OFFSET_BIT | FX_FLAT_BIT | FX_UNFILLED_BIT)
229 #define TAG(x) x##_offset_flat_unfilled
230 #include "fxtritmp.h"
231
232 #define IND (FX_TWOSIDE_BIT | FX_UNFILLED_BIT)
233 #define TAG(x) x##_twoside_unfilled
234 #include "fxtritmp.h"
235
236 #define IND (FX_TWOSIDE_BIT | FX_FLAT_BIT | FX_UNFILLED_BIT)
237 #define TAG(x) x##_twoside_flat_unfilled
238 #include "fxtritmp.h"
239
240 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_UNFILLED_BIT)
241 #define TAG(x) x##_twoside_offset_unfilled
242 #include "fxtritmp.h"
243
244 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FLAT_BIT | FX_UNFILLED_BIT)
245 #define TAG(x) x##_twoside_offset_flat_unfilled
246 #include "fxtritmp.h"
247
248 #define IND (FX_FALLBACK_BIT | FX_UNFILLED_BIT)
249 #define TAG(x) x##_fallback_unfilled
250 #include "fxtritmp.h"
251
252 #define IND (FX_FLAT_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
253 #define TAG(x) x##_flat_fallback_unfilled
254 #include "fxtritmp.h"
255
256 #define IND (FX_OFFSET_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
257 #define TAG(x) x##_offset_fallback_unfilled
258 #include "fxtritmp.h"
259
260 #define IND (FX_OFFSET_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
261 #define TAG(x) x##_offset_flat_fallback_unfilled
262 #include "fxtritmp.h"
263
264 #define IND (FX_TWOSIDE_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
265 #define TAG(x) x##_twoside_fallback_unfilled
266 #include "fxtritmp.h"
267
268 #define IND (FX_TWOSIDE_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
269 #define TAG(x) x##_twoside_flat_fallback_unfilled
270 #include "fxtritmp.h"
271
272 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
273 #define TAG(x) x##_twoside_offset_fallback_unfilled
274 #include "fxtritmp.h"
275
276 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
277 #define TAG(x) x##_twoside_offset_flat_fallback_unfilled
278 #include "fxtritmp.h"
279
280
281
282
283
284
285 void fxDDTrifuncInit( void )
286 {
287 init();
288 init_flat();
289 init_offset();
290 init_offset_flat();
291 init_twoside();
292 init_twoside_flat();
293 init_twoside_offset();
294 init_twoside_offset_flat();
295 init_fallback();
296 init_flat_fallback();
297 init_offset_fallback();
298 init_offset_flat_fallback();
299 init_twoside_fallback();
300 init_twoside_flat_fallback();
301 init_twoside_offset_fallback();
302 init_twoside_offset_flat_fallback();
303
304 init_unfilled();
305 init_flat_unfilled();
306 init_offset_unfilled();
307 init_offset_flat_unfilled();
308 init_twoside_unfilled();
309 init_twoside_flat_unfilled();
310 init_twoside_offset_unfilled();
311 init_twoside_offset_flat_unfilled();
312 init_fallback_unfilled();
313 init_flat_fallback_unfilled();
314 init_offset_fallback_unfilled();
315 init_offset_flat_fallback_unfilled();
316 init_twoside_fallback_unfilled();
317 init_twoside_flat_fallback_unfilled();
318 init_twoside_offset_fallback_unfilled();
319 init_twoside_offset_flat_fallback_unfilled();
320 }
321
322
323 /* Build an SWvertex from a GrVertex. This is workable because in
324 * states where the GrVertex is insufficent (eg seperate-specular),
325 * the driver initiates a total fallback, and builds SWvertices
326 * directly -- it recognizes that it will never have use for the
327 * GrVertex.
328 *
329 * This code is hit only when a mix of accelerated and unaccelerated
330 * primitives are being drawn, and only for the unaccelerated
331 * primitives.
332 */
333 static void
334 fx_translate_vertex(GLcontext *ctx, const fxVertex *src, SWvertex *dst)
335 {
336 fxMesaContext fxMesa = FX_CONTEXT( ctx );
337 GLuint ts0 = fxMesa->tmu_source[0];
338 GLuint ts1 = fxMesa->tmu_source[1];
339 GLfloat w = 1.0 / src->v.oow;
340
341 dst->win[0] = src->v.x;
342 dst->win[1] = src->v.y;
343 dst->win[2] = src->v.ooz;
344 dst->win[3] = src->v.oow;
345
346 dst->color[0] = (GLubyte) src->v.r;
347 dst->color[1] = (GLubyte) src->v.g;
348 dst->color[2] = (GLubyte) src->v.b;
349 dst->color[3] = (GLubyte) src->v.a;
350
351 dst->texcoord[ts0][0] = fxMesa->inv_s0scale * src->v.tmuvtx[0].sow * w;
352 dst->texcoord[ts0][1] = fxMesa->inv_t0scale * src->v.tmuvtx[0].tow * w;
353
354 if (fxMesa->stw_hint_state & GR_STWHINT_W_DIFF_TMU0)
355 dst->texcoord[ts0][3] = src->v.tmuvtx[0].oow * w;
356 else
357 dst->texcoord[ts0][3] = 1.0;
358
359 dst->texcoord[ts1][0] = fxMesa->inv_s1scale * src->v.tmuvtx[1].sow * w;
360 dst->texcoord[ts1][1] = fxMesa->inv_t1scale * src->v.tmuvtx[1].tow * w;
361
362 if (fxMesa->stw_hint_state & GR_STWHINT_W_DIFF_TMU1)
363 dst->texcoord[ts1][3] = src->v.tmuvtx[1].oow * w;
364 else
365 dst->texcoord[ts1][3] = 1.0;
366 }
367
368
369 static void
370 fx_fallback_tri( GLcontext *ctx,
371 const fxVertex *v0, const fxVertex *v1, const fxVertex *v2 )
372 {
373 SWvertex v[3];
374 fx_translate_vertex( ctx, v0, &v[0] );
375 fx_translate_vertex( ctx, v1, &v[1] );
376 fx_translate_vertex( ctx, v2, &v[2] );
377 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
378 }
379
380
381 static void
382 fx_fallback_line( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1 )
383 {
384 SWvertex v[2];
385 fx_translate_vertex( ctx, v0, &v[0] );
386 fx_translate_vertex( ctx, v1, &v[1] );
387 _swrast_Line( ctx, &v[0], &v[1] );
388 }
389
390
391 static void
392 fx_fallback_point( GLcontext *ctx, const fxVertex *v0 )
393 {
394 SWvertex v[1];
395 fx_translate_vertex( ctx, v0, &v[0] );
396 _swrast_Point( ctx, &v[0] );
397 }
398
399
400 /* System to turn culling off for rasterized lines and points, and
401 * back on for rasterized triangles.
402 */
403 static void
404 fx_cull_draw_tri( GLcontext *ctx,
405 const fxVertex *v0, const fxVertex *v1, const fxVertex *v2 )
406 {
407 fxMesaContext fxMesa = FX_CONTEXT( ctx );
408
409 FX_grCullMode(fxMesa->cullMode);
410
411 fxMesa->draw_line = fxMesa->initial_line;
412 fxMesa->draw_point = fxMesa->initial_point;
413 fxMesa->draw_tri = fxMesa->subsequent_tri;
414
415 fxMesa->draw_tri( ctx, v0, v1, v2 );
416 }
417
418
419 static void
420 fx_cull_draw_line( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1 )
421 {
422 fxMesaContext fxMesa = FX_CONTEXT( ctx );
423
424 FX_grCullMode( GR_CULL_DISABLE );
425
426 fxMesa->draw_point = fxMesa->initial_point;
427 fxMesa->draw_tri = fxMesa->initial_tri;
428 fxMesa->draw_line = fxMesa->subsequent_line;
429
430 fxMesa->draw_line( ctx, v0, v1 );
431 }
432
433
434 static void
435 fx_cull_draw_point( GLcontext *ctx, const fxVertex *v0 )
436 {
437 fxMesaContext fxMesa = FX_CONTEXT( ctx );
438
439 FX_grCullMode(GR_CULL_DISABLE);
440
441 fxMesa->draw_line = fxMesa->initial_line;
442 fxMesa->draw_tri = fxMesa->initial_tri;
443 fxMesa->draw_point = fxMesa->subsequent_point;
444
445 fxMesa->draw_point( ctx, v0 );
446 }
447
448
449 static void
450 fx_null_tri( GLcontext *ctx,
451 const fxVertex *v0, const fxVertex *v1, const fxVertex *v2 )
452 {
453 (void) v0;
454 (void) v1;
455 (void) v2;
456 }
457
458
459
460
461 /**********************************************************************/
462 /* Render whole begin/end objects */
463 /**********************************************************************/
464
465
466 /* Vertices, no clipping.
467 */
468 #define RENDER_POINTS( start, count ) \
469 for ( ; start < count ; start++) \
470 grDrawPoint( &v[ELT(start)].v );
471
472 #define RENDER_LINE( i1, i ) \
473 grDrawLine( &v[i1].v, &v[i].v )
474
475 #define RENDER_TRI( i2, i1, i ) \
476 grDrawTriangle( &v[i2].v, &v[i1].v, &v[i].v )
477
478 #define RENDER_QUAD( i3, i2, i1, i ) \
479 grDrawTriangle( &v[i3].v, &v[i2].v, &v[i].v ); \
480 grDrawTriangle( &v[i2].v, &v[i1].v, &v[i].v )
481
482 #define TAG(x) fx_##x##_verts
483 #define LOCAL_VARS \
484 fxVertex *v = FX_CONTEXT(ctx)->verts; \
485 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
486 (void) elt;
487
488 /* Verts, no clipping.
489 */
490 #define ELT(x) x
491 #define RESET_STIPPLE
492 #define RESET_OCCLUSION
493 #define PRESERVE_VB_DEFS
494 #include "tnl/t_vb_rendertmp.h"
495
496
497 /* Elts, no clipping.
498 */
499 #undef ELT
500 #undef TAG
501 #define TAG(x) fx_##x##_elts
502 #define ELT(x) elt[x]
503 #include "tnl/t_vb_rendertmp.h"
504
505
506 /**********************************************************************/
507 /* Choose render functions */
508 /**********************************************************************/
509
510
511
512
513 #define POINT_FALLBACK (DD_POINT_SMOOTH )
514 #define LINE_FALLBACK (DD_LINE_STIPPLE)
515 #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE )
516 #define ANY_FALLBACK (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)
517
518
519 #define ANY_RENDER_FLAGS (DD_FLATSHADE | \
520 DD_TRI_LIGHT_TWOSIDE | \
521 DD_TRI_OFFSET | \
522 DD_TRI_UNFILLED)
523
524
525
526 /* Setup the Point, Line, Triangle and Quad functions based on the
527 * current rendering state. Wherever possible, use the hardware to
528 * render the primitive. Otherwise, fallback to software rendering.
529 */
530 void fxDDChooseRenderState( GLcontext *ctx )
531 {
532 fxMesaContext fxMesa = FX_CONTEXT( ctx );
533 GLuint flags = ctx->_TriangleCaps;
534 GLuint index = 0;
535
536 if ( !fxMesa->is_in_hardware ) {
537 /* Build software vertices directly. No acceleration is
538 * possible. GrVertices may be insufficient for this mode.
539 */
540 ctx->Driver.PointsFunc = _swsetup_Points;
541 ctx->Driver.LineFunc = _swsetup_Line;
542 ctx->Driver.TriangleFunc = _swsetup_Triangle;
543 ctx->Driver.QuadFunc = _swsetup_Quad;
544 ctx->Driver.RenderTabVerts = _tnl_render_tab_verts;
545 ctx->Driver.RenderTabElts = _tnl_render_tab_elts;
546
547 fxMesa->render_index = FX_FALLBACK_BIT;
548 return;
549 }
550
551 if ( flags & ANY_RENDER_FLAGS ) {
552 if ( flags & DD_FLATSHADE ) index |= FX_FLAT_BIT;
553 if ( flags & DD_TRI_LIGHT_TWOSIDE ) index |= FX_TWOSIDE_BIT;
554 if ( flags & DD_TRI_OFFSET ) index |= FX_OFFSET_BIT;
555 if ( flags & DD_TRI_UNFILLED ) index |= FX_UNFILLED_BIT;
556 }
557
558 if ( flags & (ANY_FALLBACK|
559 DD_LINE_WIDTH|
560 DD_POINT_SIZE|
561 DD_TRI_CULL_FRONT_BACK) ) {
562
563 /* Hook in fallbacks for specific primitives.
564 *
565 * Set up a system to turn culling on/off for wide points and
566 * lines. Alternately: figure out what tris to send so that
567 * culling isn't a problem.
568 *
569 * This replaces the ReducedPrimitiveChange mechanism.
570 */
571 index |= FX_FALLBACK_BIT;
572 fxMesa->initial_point = fx_cull_draw_point;
573 fxMesa->initial_line = fx_cull_draw_line;
574 fxMesa->initial_tri = fx_cull_draw_tri;
575
576 fxMesa->subsequent_point = fx_draw_point;
577 fxMesa->subsequent_line = fx_draw_line;
578 fxMesa->subsequent_tri = fx_draw_tri;
579
580 if ( flags & POINT_FALLBACK )
581 fxMesa->initial_point = fx_fallback_point;
582
583 if ( flags & LINE_FALLBACK )
584 fxMesa->initial_line = fx_fallback_line;
585
586 if ((flags & DD_LINE_SMOOTH) && ctx->Line.Width != 1.0)
587 fxMesa->initial_line = fx_fallback_line;
588
589 if ( flags & TRI_FALLBACK )
590 fxMesa->initial_tri = fx_fallback_tri;
591
592 if ( flags & DD_TRI_CULL_FRONT_BACK )
593 fxMesa->initial_tri = fx_null_tri;
594
595 fxMesa->draw_point = fxMesa->initial_point;
596 fxMesa->draw_line = fxMesa->initial_line;
597 fxMesa->draw_tri = fxMesa->initial_tri;
598 }
599 else if (fxMesa->render_index & FX_FALLBACK_BIT) {
600 FX_grCullMode(fxMesa->cullMode);
601 }
602
603 ctx->Driver.PointsFunc = rast_tab[index].points;
604 ctx->Driver.LineFunc = rast_tab[index].line;
605 ctx->Driver.TriangleFunc = rast_tab[index].triangle;
606 ctx->Driver.QuadFunc = rast_tab[index].quad;
607 fxMesa->render_index = index;
608
609 if (fxMesa->render_index == 0) {
610 ctx->Driver.RenderTabVerts = fx_render_tab_verts;
611 ctx->Driver.RenderTabElts = fx_render_tab_elts;
612 } else {
613 ctx->Driver.RenderTabVerts = _tnl_render_tab_verts;
614 ctx->Driver.RenderTabElts = _tnl_render_tab_elts;
615 }
616 }
617
618
619
620
621 #else
622
623
624 /*
625 * Need this to provide at least one external definition.
626 */
627
628 extern int gl_fx_dummy_function_trifuncs(void);
629 int gl_fx_dummy_function_trifuncs(void)
630 {
631 return 0;
632 }
633
634 #endif /* FX */