Add render stage for unclipped vb's to fx driver.
[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
15 #include "fxdrv.h"
16 #include "fxglidew.h"
17
18
19
20
21
22
23
24
25 static void
26 fx_draw_point( GLcontext *ctx, const fxVertex *v )
27 {
28 GLfloat sz = ctx->Point._Size;
29
30 if ( sz <= 1.0 )
31 {
32 grDrawPoint( &(v->v) );
33 }
34 else
35 {
36 GrVertex verts[4];
37
38 sz *= .5;
39
40 verts[0] = v->v;
41 verts[1] = v->v;
42 verts[2] = v->v;
43 verts[3] = v->v;
44
45 verts[0].x = v->v.x - sz;
46 verts[0].y = v->v.y - sz;
47
48 verts[1].x = v->v.x + sz;
49 verts[1].y = v->v.y - sz;
50
51 verts[2].x = v->v.x + sz;
52 verts[2].y = v->v.y + sz;
53
54 verts[3].x = v->v.x - sz;
55 verts[3].y = v->v.y + sz;
56
57 grDrawTriangle( &verts[0], &verts[1], &verts[3] );
58 grDrawTriangle( &verts[1], &verts[2], &verts[3] );
59 }
60 }
61
62
63 static void
64 fx_draw_line( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1 )
65 {
66 float width = ctx->Line.Width;
67
68 if ( width <= 1.0 )
69 {
70 grDrawLine( &(v0->v), &(v1->v) );
71 }
72 else
73 {
74 GrVertex verts[4];
75 float dx, dy, ix, iy;
76
77 dx = v0->v.x - v1->v.x;
78 dy = v0->v.y - v1->v.y;
79
80 if (dx * dx > dy * dy) {
81 iy = width * .5;
82 ix = 0;
83 } else {
84 iy = 0;
85 ix = width * .5;
86 }
87
88
89 verts[0] = v0->v;
90 verts[0].x -= ix;
91 verts[0].y -= iy;
92
93 verts[1] = v0->v;
94 verts[1].x += ix;
95 verts[1].y += iy;
96
97 verts[2] = v1->v;
98 verts[2].x += ix;
99 verts[2].y += iy;
100
101 verts[3] = v1->v;
102 verts[3].x -= ix;
103 verts[3].y -= iy;
104
105 grDrawTriangle( &verts[0], &verts[1], &verts[3] );
106 grDrawTriangle( &verts[1], &verts[2], &verts[3] );
107 }
108 }
109
110 static void
111 fx_draw_tri( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1,
112 const fxVertex *v2 )
113 {
114 grDrawTriangle( &(v0->v), &(v1->v), &(v2->v) );
115 }
116
117
118
119 #define FX_COLOR(vert, c) { \
120 GLubyte *col = c; \
121 vert->v.r=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]); \
122 vert->v.g=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]); \
123 vert->v.b=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]); \
124 vert->v.a=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]); \
125 }
126
127 #define FX_COPY_COLOR( dst, src ) { \
128 dst->v.r = src->v.r; \
129 dst->v.g = src->v.g; \
130 dst->v.b = src->v.b; \
131 dst->v.a = src->v.a; \
132 }
133
134
135
136 #define FX_FLAT_BIT 0x01
137 #define FX_OFFSET_BIT 0x02
138 #define FX_TWOSIDE_BIT 0x04
139 #define FX_UNFILLED_BIT 0x10
140 #define FX_FALLBACK_BIT 0x20
141 #define FX_MAX_TRIFUNC 0x40
142
143 static struct {
144 points_func points;
145 line_func line;
146 triangle_func triangle;
147 quad_func quad;
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 fxDDTrifuncInit( void )
285 {
286 init();
287 init_flat();
288 init_offset();
289 init_offset_flat();
290 init_twoside();
291 init_twoside_flat();
292 init_twoside_offset();
293 init_twoside_offset_flat();
294 init_fallback();
295 init_flat_fallback();
296 init_offset_fallback();
297 init_offset_flat_fallback();
298 init_twoside_fallback();
299 init_twoside_flat_fallback();
300 init_twoside_offset_fallback();
301 init_twoside_offset_flat_fallback();
302
303 init_unfilled();
304 init_flat_unfilled();
305 init_offset_unfilled();
306 init_offset_flat_unfilled();
307 init_twoside_unfilled();
308 init_twoside_flat_unfilled();
309 init_twoside_offset_unfilled();
310 init_twoside_offset_flat_unfilled();
311 init_fallback_unfilled();
312 init_flat_fallback_unfilled();
313 init_offset_fallback_unfilled();
314 init_offset_flat_fallback_unfilled();
315 init_twoside_fallback_unfilled();
316 init_twoside_flat_fallback_unfilled();
317 init_twoside_offset_fallback_unfilled();
318 init_twoside_offset_flat_fallback_unfilled();
319 }
320
321
322 /* Build an SWvertex from a GrVertex. This is workable because in
323 * states where the GrVertex is insufficent (eg seperate-specular),
324 * the driver initiates a total fallback, and builds SWvertices
325 * directly -- it recognizes that it will never have use for the
326 * GrVertex.
327 *
328 * This code is hit only when a mix of accelerated and unaccelerated
329 * primitives are being drawn, and only for the unaccelerated
330 * primitives.
331 */
332 static void
333 fx_translate_vertex(GLcontext *ctx, const fxVertex *src, SWvertex *dst)
334 {
335 fxMesaContext fxMesa = FX_CONTEXT( ctx );
336 GLuint ts0 = fxMesa->tmu_source[0];
337 GLuint ts1 = fxMesa->tmu_source[1];
338 GLfloat w = 1.0 / src->v.oow;
339
340 dst->win[0] = src->v.x;
341 dst->win[1] = src->v.y;
342 dst->win[2] = src->v.ooz;
343 dst->win[3] = src->v.oow;
344
345 dst->color[0] = (GLubyte) src->v.r;
346 dst->color[1] = (GLubyte) src->v.g;
347 dst->color[2] = (GLubyte) src->v.b;
348 dst->color[3] = (GLubyte) src->v.a;
349
350 dst->texcoord[ts0][0] = fxMesa->inv_s0scale * src->v.tmuvtx[0].sow * w;
351 dst->texcoord[ts0][1] = fxMesa->inv_t0scale * src->v.tmuvtx[0].tow * w;
352
353 if (fxMesa->stw_hint_state & GR_STWHINT_W_DIFF_TMU0)
354 dst->texcoord[ts0][3] = src->v.tmuvtx[0].oow * w;
355 else
356 dst->texcoord[ts0][3] = 1.0;
357
358 dst->texcoord[ts1][0] = fxMesa->inv_s1scale * src->v.tmuvtx[1].sow * w;
359 dst->texcoord[ts1][1] = fxMesa->inv_t1scale * src->v.tmuvtx[1].tow * w;
360
361 if (fxMesa->stw_hint_state & GR_STWHINT_W_DIFF_TMU1)
362 dst->texcoord[ts1][3] = src->v.tmuvtx[1].oow * w;
363 else
364 dst->texcoord[ts1][3] = 1.0;
365 }
366
367
368 static void
369 fx_fallback_tri( GLcontext *ctx,
370 const fxVertex *v0, const fxVertex *v1, const fxVertex *v2 )
371 {
372 SWvertex v[3];
373 fx_translate_vertex( ctx, v0, &v[0] );
374 fx_translate_vertex( ctx, v1, &v[1] );
375 fx_translate_vertex( ctx, v2, &v[2] );
376 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
377 }
378
379
380 static void
381 fx_fallback_line( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1 )
382 {
383 SWvertex v[2];
384 fx_translate_vertex( ctx, v0, &v[0] );
385 fx_translate_vertex( ctx, v1, &v[1] );
386 _swrast_Line( ctx, &v[0], &v[1] );
387 }
388
389
390 static void
391 fx_fallback_point( GLcontext *ctx, const fxVertex *v0 )
392 {
393 SWvertex v[1];
394 fx_translate_vertex( ctx, v0, &v[0] );
395 _swrast_Point( ctx, &v[0] );
396 }
397
398
399 /* System to turn culling off for rasterized lines and points, and
400 * back on for rasterized triangles.
401 */
402 static void
403 fx_cull_draw_tri( GLcontext *ctx,
404 const fxVertex *v0, const fxVertex *v1, const fxVertex *v2 )
405 {
406 fxMesaContext fxMesa = FX_CONTEXT( ctx );
407
408 FX_grCullMode(fxMesa->cullMode);
409
410 fxMesa->draw_line = fxMesa->initial_line;
411 fxMesa->draw_point = fxMesa->initial_point;
412 fxMesa->draw_tri = fxMesa->subsequent_tri;
413
414 fxMesa->draw_tri( ctx, v0, v1, v2 );
415 }
416
417
418 static void
419 fx_cull_draw_line( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1 )
420 {
421 fxMesaContext fxMesa = FX_CONTEXT( ctx );
422
423 FX_grCullMode( GR_CULL_DISABLE );
424
425 fxMesa->draw_point = fxMesa->initial_point;
426 fxMesa->draw_tri = fxMesa->initial_tri;
427 fxMesa->draw_line = fxMesa->subsequent_line;
428
429 fxMesa->draw_line( ctx, v0, v1 );
430 }
431
432
433 static void
434 fx_cull_draw_point( GLcontext *ctx, const fxVertex *v0 )
435 {
436 fxMesaContext fxMesa = FX_CONTEXT( ctx );
437
438 FX_grCullMode(GR_CULL_DISABLE);
439
440 fxMesa->draw_line = fxMesa->initial_line;
441 fxMesa->draw_tri = fxMesa->initial_tri;
442 fxMesa->draw_point = fxMesa->subsequent_point;
443
444 fxMesa->draw_point( ctx, v0 );
445 }
446
447
448 static void
449 fx_null_tri( GLcontext *ctx,
450 const fxVertex *v0, const fxVertex *v1, const fxVertex *v2 )
451 {
452 (void) v0;
453 (void) v1;
454 (void) v2;
455 }
456
457
458
459 #define POINT_FALLBACK (DD_POINT_SMOOTH )
460 #define LINE_FALLBACK (DD_LINE_STIPPLE)
461 #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE )
462 #define ANY_FALLBACK (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)
463
464
465 #define ANY_RENDER_FLAGS (DD_FLATSHADE | \
466 DD_TRI_LIGHT_TWOSIDE | \
467 DD_TRI_OFFSET | \
468 DD_TRI_UNFILLED)
469
470
471
472 /* Setup the Point, Line, Triangle and Quad functions based on the
473 * current rendering state. Wherever possible, use the hardware to
474 * render the primitive. Otherwise, fallback to software rendering.
475 */
476 void fxDDChooseRenderState( GLcontext *ctx )
477 {
478 fxMesaContext fxMesa = FX_CONTEXT( ctx );
479 GLuint flags = ctx->_TriangleCaps;
480 GLuint index = 0;
481
482 if ( !fxMesa->is_in_hardware ) {
483 /* Build software vertices directly. No acceleration is
484 * possible. GrVertices may be insufficient for this mode.
485 */
486 ctx->Driver.PointsFunc = _swsetup_Points;
487 ctx->Driver.LineFunc = _swsetup_Line;
488 ctx->Driver.TriangleFunc = _swsetup_Triangle;
489 ctx->Driver.QuadFunc = _swsetup_Quad;
490
491 fxMesa->render_index = FX_FALLBACK_BIT;
492 return;
493 }
494
495 if ( flags & ANY_RENDER_FLAGS ) {
496 if ( flags & DD_FLATSHADE ) index |= FX_FLAT_BIT;
497 if ( flags & DD_TRI_LIGHT_TWOSIDE ) index |= FX_TWOSIDE_BIT;
498 if ( flags & DD_TRI_OFFSET ) index |= FX_OFFSET_BIT;
499 if ( flags & DD_TRI_UNFILLED ) index |= FX_UNFILLED_BIT;
500 }
501
502 if ( flags & (ANY_FALLBACK|
503 DD_LINE_WIDTH|
504 DD_POINT_SIZE|
505 DD_TRI_CULL_FRONT_BACK) ) {
506
507 /* Hook in fallbacks for specific primitives.
508 *
509 * Set up a system to turn culling on/off for wide points and
510 * lines. Alternately: figure out what tris to send so that
511 * culling isn't a problem.
512 *
513 * This replaces the ReducedPrimitiveChange mechanism.
514 */
515 index |= FX_FALLBACK_BIT;
516 fxMesa->initial_point = fx_cull_draw_point;
517 fxMesa->initial_line = fx_cull_draw_line;
518 fxMesa->initial_tri = fx_cull_draw_tri;
519
520 fxMesa->subsequent_point = fx_draw_point;
521 fxMesa->subsequent_line = fx_draw_line;
522 fxMesa->subsequent_tri = fx_draw_tri;
523
524 if ( flags & POINT_FALLBACK )
525 fxMesa->initial_point = fx_fallback_point;
526
527 if ( flags & LINE_FALLBACK )
528 fxMesa->initial_line = fx_fallback_line;
529
530 if ((flags & DD_LINE_SMOOTH) && ctx->Line.Width != 1.0)
531 fxMesa->initial_line = fx_fallback_line;
532
533 if ( flags & TRI_FALLBACK )
534 fxMesa->initial_tri = fx_fallback_tri;
535
536 if ( flags & DD_TRI_CULL_FRONT_BACK )
537 fxMesa->initial_tri = fx_null_tri;
538
539 fxMesa->draw_point = fxMesa->initial_point;
540 fxMesa->draw_line = fxMesa->initial_line;
541 fxMesa->draw_tri = fxMesa->initial_tri;
542 }
543 else if (fxMesa->render_index & FX_FALLBACK_BIT) {
544 FX_grCullMode(fxMesa->cullMode);
545 }
546
547 ctx->Driver.PointsFunc = rast_tab[index].points;
548 ctx->Driver.LineFunc = rast_tab[index].line;
549 ctx->Driver.TriangleFunc = rast_tab[index].triangle;
550 ctx->Driver.QuadFunc = rast_tab[index].quad;
551 fxMesa->render_index = index;
552 }
553
554
555 #else
556
557
558 /*
559 * Need this to provide at least one external definition.
560 */
561
562 extern int gl_fx_dummy_function_trifuncs(void);
563 int gl_fx_dummy_function_trifuncs(void)
564 {
565 return 0;
566 }
567
568 #endif /* FX */