used indent to clean-up the code
[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 grDrawPoint(&(v->v));
33 }
34 else {
35 GrVertex verts[4];
36
37 sz *= .5;
38
39 verts[0] = v->v;
40 verts[1] = v->v;
41 verts[2] = v->v;
42 verts[3] = v->v;
43
44 verts[0].x = v->v.x - sz;
45 verts[0].y = v->v.y - sz;
46
47 verts[1].x = v->v.x + sz;
48 verts[1].y = v->v.y - sz;
49
50 verts[2].x = v->v.x + sz;
51 verts[2].y = v->v.y + sz;
52
53 verts[3].x = v->v.x - sz;
54 verts[3].y = v->v.y + sz;
55
56 grDrawTriangle(&verts[0], &verts[1], &verts[3]);
57 grDrawTriangle(&verts[1], &verts[2], &verts[3]);
58 }
59 }
60
61
62 static void
63 fx_draw_line(GLcontext * ctx, const fxVertex * v0, const fxVertex * v1)
64 {
65 float width = ctx->Line.Width;
66
67 if (width <= 1.0) {
68 grDrawLine(&(v0->v), &(v1->v));
69 }
70 else {
71 GrVertex verts[4];
72 float dx, dy, ix, iy;
73
74 dx = v0->v.x - v1->v.x;
75 dy = v0->v.y - v1->v.y;
76
77 if (dx * dx > dy * dy) {
78 iy = width * .5;
79 ix = 0;
80 }
81 else {
82 iy = 0;
83 ix = width * .5;
84 }
85
86
87 verts[0] = v0->v;
88 verts[0].x -= ix;
89 verts[0].y -= iy;
90
91 verts[1] = v0->v;
92 verts[1].x += ix;
93 verts[1].y += iy;
94
95 verts[2] = v1->v;
96 verts[2].x += ix;
97 verts[2].y += iy;
98
99 verts[3] = v1->v;
100 verts[3].x -= ix;
101 verts[3].y -= iy;
102
103 grDrawTriangle(&verts[0], &verts[1], &verts[3]);
104 grDrawTriangle(&verts[1], &verts[2], &verts[3]);
105 }
106 }
107
108 static void
109 fx_draw_tri(GLcontext * ctx, const fxVertex * v0, const fxVertex * v1,
110 const fxVertex * v2)
111 {
112 grDrawTriangle(&(v0->v), &(v1->v), &(v2->v));
113 }
114
115
116
117 #define FX_COLOR(vert, c) { \
118 GLubyte *col = c; \
119 vert->v.r=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]); \
120 vert->v.g=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]); \
121 vert->v.b=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]); \
122 vert->v.a=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]); \
123 }
124
125 #define FX_COPY_COLOR( dst, src ) { \
126 dst->v.r = src->v.r; \
127 dst->v.g = src->v.g; \
128 dst->v.b = src->v.b; \
129 dst->v.a = src->v.a; \
130 }
131
132
133
134 #define FX_FLAT_BIT 0x01
135 #define FX_OFFSET_BIT 0x02
136 #define FX_TWOSIDE_BIT 0x04
137 #define FX_UNFILLED_BIT 0x10
138 #define FX_FALLBACK_BIT 0x20
139 #define FX_MAX_TRIFUNC 0x40
140
141 static struct
142 {
143 points_func points;
144 line_func line;
145 triangle_func triangle;
146 quad_func quad;
147 }
148 rast_tab[FX_MAX_TRIFUNC];
149
150
151 #define IND (0)
152 #define TAG(x) x
153 #include "fxtritmp.h"
154
155 #define IND (FX_FLAT_BIT)
156 #define TAG(x) x##_flat
157 #include "fxtritmp.h"
158
159 #define IND (FX_OFFSET_BIT)
160 #define TAG(x) x##_offset
161 #include "fxtritmp.h"
162
163 #define IND (FX_OFFSET_BIT | FX_FLAT_BIT)
164 #define TAG(x) x##_offset_flat
165 #include "fxtritmp.h"
166
167 #define IND (FX_TWOSIDE_BIT)
168 #define TAG(x) x##_twoside
169 #include "fxtritmp.h"
170
171 #define IND (FX_TWOSIDE_BIT | FX_FLAT_BIT)
172 #define TAG(x) x##_twoside_flat
173 #include "fxtritmp.h"
174
175 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT)
176 #define TAG(x) x##_twoside_offset
177 #include "fxtritmp.h"
178
179 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FLAT_BIT)
180 #define TAG(x) x##_twoside_offset_flat
181 #include "fxtritmp.h"
182
183 #define IND (FX_FALLBACK_BIT)
184 #define TAG(x) x##_fallback
185 #include "fxtritmp.h"
186
187 #define IND (FX_FLAT_BIT | FX_FALLBACK_BIT)
188 #define TAG(x) x##_flat_fallback
189 #include "fxtritmp.h"
190
191 #define IND (FX_OFFSET_BIT | FX_FALLBACK_BIT)
192 #define TAG(x) x##_offset_fallback
193 #include "fxtritmp.h"
194
195 #define IND (FX_OFFSET_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT)
196 #define TAG(x) x##_offset_flat_fallback
197 #include "fxtritmp.h"
198
199 #define IND (FX_TWOSIDE_BIT | FX_FALLBACK_BIT)
200 #define TAG(x) x##_twoside_fallback
201 #include "fxtritmp.h"
202
203 #define IND (FX_TWOSIDE_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT)
204 #define TAG(x) x##_twoside_flat_fallback
205 #include "fxtritmp.h"
206
207 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FALLBACK_BIT)
208 #define TAG(x) x##_twoside_offset_fallback
209 #include "fxtritmp.h"
210
211 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT)
212 #define TAG(x) x##_twoside_offset_flat_fallback
213 #include "fxtritmp.h"
214
215 #define IND (FX_UNFILLED_BIT)
216 #define TAG(x) x##_unfilled
217 #include "fxtritmp.h"
218
219 #define IND (FX_FLAT_BIT | FX_UNFILLED_BIT)
220 #define TAG(x) x##_flat_unfilled
221 #include "fxtritmp.h"
222
223 #define IND (FX_OFFSET_BIT | FX_UNFILLED_BIT)
224 #define TAG(x) x##_offset_unfilled
225 #include "fxtritmp.h"
226
227 #define IND (FX_OFFSET_BIT | FX_FLAT_BIT | FX_UNFILLED_BIT)
228 #define TAG(x) x##_offset_flat_unfilled
229 #include "fxtritmp.h"
230
231 #define IND (FX_TWOSIDE_BIT | FX_UNFILLED_BIT)
232 #define TAG(x) x##_twoside_unfilled
233 #include "fxtritmp.h"
234
235 #define IND (FX_TWOSIDE_BIT | FX_FLAT_BIT | FX_UNFILLED_BIT)
236 #define TAG(x) x##_twoside_flat_unfilled
237 #include "fxtritmp.h"
238
239 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_UNFILLED_BIT)
240 #define TAG(x) x##_twoside_offset_unfilled
241 #include "fxtritmp.h"
242
243 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FLAT_BIT | FX_UNFILLED_BIT)
244 #define TAG(x) x##_twoside_offset_flat_unfilled
245 #include "fxtritmp.h"
246
247 #define IND (FX_FALLBACK_BIT | FX_UNFILLED_BIT)
248 #define TAG(x) x##_fallback_unfilled
249 #include "fxtritmp.h"
250
251 #define IND (FX_FLAT_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
252 #define TAG(x) x##_flat_fallback_unfilled
253 #include "fxtritmp.h"
254
255 #define IND (FX_OFFSET_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
256 #define TAG(x) x##_offset_fallback_unfilled
257 #include "fxtritmp.h"
258
259 #define IND (FX_OFFSET_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
260 #define TAG(x) x##_offset_flat_fallback_unfilled
261 #include "fxtritmp.h"
262
263 #define IND (FX_TWOSIDE_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
264 #define TAG(x) x##_twoside_fallback_unfilled
265 #include "fxtritmp.h"
266
267 #define IND (FX_TWOSIDE_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
268 #define TAG(x) x##_twoside_flat_fallback_unfilled
269 #include "fxtritmp.h"
270
271 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
272 #define TAG(x) x##_twoside_offset_fallback_unfilled
273 #include "fxtritmp.h"
274
275 #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT)
276 #define TAG(x) x##_twoside_offset_flat_fallback_unfilled
277 #include "fxtritmp.h"
278
279
280
281
282
283
284 void
285 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,
406 const fxVertex * v2)
407 {
408 fxMesaContext fxMesa = FX_CONTEXT(ctx);
409
410 FX_grCullMode(fxMesa->cullMode);
411
412 fxMesa->draw_line = fxMesa->initial_line;
413 fxMesa->draw_point = fxMesa->initial_point;
414 fxMesa->draw_tri = fxMesa->subsequent_tri;
415
416 fxMesa->draw_tri(ctx, v0, v1, v2);
417 }
418
419
420 static void
421 fx_cull_draw_line(GLcontext * ctx, const fxVertex * v0, const fxVertex * v1)
422 {
423 fxMesaContext fxMesa = FX_CONTEXT(ctx);
424
425 FX_grCullMode(GR_CULL_DISABLE);
426
427 fxMesa->draw_point = fxMesa->initial_point;
428 fxMesa->draw_tri = fxMesa->initial_tri;
429 fxMesa->draw_line = fxMesa->subsequent_line;
430
431 fxMesa->draw_line(ctx, v0, v1);
432 }
433
434
435 static void
436 fx_cull_draw_point(GLcontext * ctx, const fxVertex * v0)
437 {
438 fxMesaContext fxMesa = FX_CONTEXT(ctx);
439
440 FX_grCullMode(GR_CULL_DISABLE);
441
442 fxMesa->draw_line = fxMesa->initial_line;
443 fxMesa->draw_tri = fxMesa->initial_tri;
444 fxMesa->draw_point = fxMesa->subsequent_point;
445
446 fxMesa->draw_point(ctx, v0);
447 }
448
449
450 static void
451 fx_null_tri(GLcontext * ctx,
452 const fxVertex * v0, const fxVertex * v1, const fxVertex * v2)
453 {
454 (void) v0;
455 (void) v1;
456 (void) v2;
457 }
458
459
460
461
462 /**********************************************************************/
463 /* Render whole begin/end objects */
464 /**********************************************************************/
465
466
467 /* Vertices, no clipping.
468 */
469 #define RENDER_POINTS( start, count ) \
470 for ( ; start < count ; start++) \
471 grDrawPoint( &v[ELT(start)].v );
472
473 #define RENDER_LINE( i1, i ) \
474 grDrawLine( &v[i1].v, &v[i].v )
475
476 #define RENDER_TRI( i2, i1, i ) \
477 grDrawTriangle( &v[i2].v, &v[i1].v, &v[i].v )
478
479 #define RENDER_QUAD( i3, i2, i1, i ) \
480 grDrawTriangle( &v[i3].v, &v[i2].v, &v[i].v ); \
481 grDrawTriangle( &v[i2].v, &v[i1].v, &v[i].v )
482
483 #define TAG(x) fx_##x##_verts
484 #define LOCAL_VARS \
485 fxVertex *v = FX_CONTEXT(ctx)->verts; \
486 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
487 (void) elt;
488
489 /* Verts, no clipping.
490 */
491 #define ELT(x) x
492 #define RESET_STIPPLE
493 #define RESET_OCCLUSION
494 #define PRESERVE_VB_DEFS
495 #include "tnl/t_vb_rendertmp.h"
496
497
498 /* Elts, no clipping.
499 */
500 #undef ELT
501 #undef TAG
502 #define TAG(x) fx_##x##_elts
503 #define ELT(x) elt[x]
504 #include "tnl/t_vb_rendertmp.h"
505
506
507 /**********************************************************************/
508 /* Choose render functions */
509 /**********************************************************************/
510
511
512
513
514 #define POINT_FALLBACK (DD_POINT_SMOOTH )
515 #define LINE_FALLBACK (DD_LINE_STIPPLE)
516 #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE )
517 #define ANY_FALLBACK (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)
518
519
520 #define ANY_RENDER_FLAGS (DD_FLATSHADE | \
521 DD_TRI_LIGHT_TWOSIDE | \
522 DD_TRI_OFFSET | \
523 DD_TRI_UNFILLED)
524
525
526
527 /* Setup the Point, Line, Triangle and Quad functions based on the
528 * current rendering state. Wherever possible, use the hardware to
529 * render the primitive. Otherwise, fallback to software rendering.
530 */
531 void
532 fxDDChooseRenderState(GLcontext * ctx)
533 {
534 fxMesaContext fxMesa = FX_CONTEXT(ctx);
535 GLuint flags = ctx->_TriangleCaps;
536 GLuint index = 0;
537
538 if (!fxMesa->is_in_hardware) {
539 /* Build software vertices directly. No acceleration is
540 * possible. GrVertices may be insufficient for this mode.
541 */
542 ctx->Driver.PointsFunc = _swsetup_Points;
543 ctx->Driver.LineFunc = _swsetup_Line;
544 ctx->Driver.TriangleFunc = _swsetup_Triangle;
545 ctx->Driver.QuadFunc = _swsetup_Quad;
546 ctx->Driver.RenderTabVerts = _tnl_render_tab_verts;
547 ctx->Driver.RenderTabElts = _tnl_render_tab_elts;
548
549 fxMesa->render_index = FX_FALLBACK_BIT;
550 return;
551 }
552
553 if (flags & ANY_RENDER_FLAGS) {
554 if (flags & DD_FLATSHADE)
555 index |= FX_FLAT_BIT;
556 if (flags & DD_TRI_LIGHT_TWOSIDE)
557 index |= FX_TWOSIDE_BIT;
558 if (flags & DD_TRI_OFFSET)
559 index |= FX_OFFSET_BIT;
560 if (flags & DD_TRI_UNFILLED)
561 index |= FX_UNFILLED_BIT;
562 }
563
564 if (flags & (ANY_FALLBACK |
565 DD_LINE_WIDTH | DD_POINT_SIZE | DD_TRI_CULL_FRONT_BACK)) {
566
567 /* Hook in fallbacks for specific primitives.
568
569 * Set up a system to turn culling on/off for wide points and
570 * lines. Alternately: figure out what tris to send so that
571 * culling isn't a problem.
572 *
573 * This replaces the ReducedPrimitiveChange mechanism.
574 */
575 index |= FX_FALLBACK_BIT;
576 fxMesa->initial_point = fx_cull_draw_point;
577 fxMesa->initial_line = fx_cull_draw_line;
578 fxMesa->initial_tri = fx_cull_draw_tri;
579
580 fxMesa->subsequent_point = fx_draw_point;
581 fxMesa->subsequent_line = fx_draw_line;
582 fxMesa->subsequent_tri = fx_draw_tri;
583
584 if (flags & POINT_FALLBACK)
585 fxMesa->initial_point = fx_fallback_point;
586
587 if (flags & LINE_FALLBACK)
588 fxMesa->initial_line = fx_fallback_line;
589
590 if ((flags & DD_LINE_SMOOTH) && ctx->Line.Width != 1.0)
591 fxMesa->initial_line = fx_fallback_line;
592
593 if (flags & TRI_FALLBACK)
594 fxMesa->initial_tri = fx_fallback_tri;
595
596 if (flags & DD_TRI_CULL_FRONT_BACK)
597 fxMesa->initial_tri = fx_null_tri;
598
599 fxMesa->draw_point = fxMesa->initial_point;
600 fxMesa->draw_line = fxMesa->initial_line;
601 fxMesa->draw_tri = fxMesa->initial_tri;
602 }
603 else if (fxMesa->render_index & FX_FALLBACK_BIT) {
604 FX_grCullMode(fxMesa->cullMode);
605 }
606
607 ctx->Driver.PointsFunc = rast_tab[index].points;
608 ctx->Driver.LineFunc = rast_tab[index].line;
609 ctx->Driver.TriangleFunc = rast_tab[index].triangle;
610 ctx->Driver.QuadFunc = rast_tab[index].quad;
611 fxMesa->render_index = index;
612
613 if (fxMesa->render_index == 0) {
614 ctx->Driver.RenderTabVerts = fx_render_tab_verts;
615 ctx->Driver.RenderTabElts = fx_render_tab_elts;
616 }
617 else {
618 ctx->Driver.RenderTabVerts = _tnl_render_tab_verts;
619 ctx->Driver.RenderTabElts = _tnl_render_tab_elts;
620 }
621 }
622
623
624
625
626 #else
627
628
629 /*
630 * Need this to provide at least one external definition.
631 */
632
633 extern int gl_fx_dummy_function_trifuncs(void);
634 int
635 gl_fx_dummy_function_trifuncs(void)
636 {
637 return 0;
638 }
639
640 #endif /* FX */