9fae8c8283e519517519e36e874067f790027d32
[mesa.git] / src / mesa / drivers / dri / ffb / ffb_tris.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_tris.c,v 1.3 2002/10/30 12:51:28 alanh Exp $
2 *
3 * GLX Hardware Device Driver for Sun Creator/Creator3D
4 * Copyright (C) 2000, 2001 David S. Miller
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * DAVID MILLER, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 *
25 * David S. Miller <davem@redhat.com>
26 */
27
28 #include "glheader.h"
29 #include "mtypes.h"
30 #include "macros.h"
31 #include "swrast/swrast.h"
32 #include "swrast_setup/swrast_setup.h"
33 #include "swrast/s_context.h"
34 #include "tnl/t_context.h"
35 #include "tnl/t_pipeline.h"
36
37 #include "ffb_context.h"
38 #include "ffb_tris.h"
39 #include "ffb_lines.h"
40 #include "ffb_lock.h"
41 #include "ffb_points.h"
42 #include "ffb_state.h"
43 #include "ffb_vb.h"
44
45 #undef TRI_DEBUG
46 #undef FFB_RENDER_TRACE
47 #undef STATE_TRACE
48
49 #ifdef TRI_DEBUG
50 static void ffb_print_vertex(const ffb_vertex *v)
51 {
52 fprintf(stderr, "Vertex @(%p): "
53 "X[%f] Y[%f] Z[%f]\n",
54 v, v->x, v->y, v->z);
55 fprintf(stderr, "Vertex @(%p): "
56 "A[%f] R[%f] G[%f] B[%f]\n",
57 v,
58 v->color[0].alpha,
59 v->color[0].red,
60 v->color[0].green,
61 v->color[0].blue);
62 }
63 #define FFB_DUMP_VERTEX(V) ffb_print_vertex(V)
64 #else
65 #define FFB_DUMP_VERTEX(V) do { } while(0)
66 #endif
67
68 #define FFB_ALPHA_BIT 0x01
69 #define FFB_FLAT_BIT 0x02
70 #define FFB_TRI_CULL_BIT 0x04
71 #define MAX_FFB_RENDER_FUNCS 0x08
72
73 /***********************************************************************
74 * Build low-level triangle/quad rasterize functions *
75 ***********************************************************************/
76
77 #define FFB_TRI_FLAT_BIT 0x01
78 #define FFB_TRI_ALPHA_BIT 0x02
79 /*#define FFB_TRI_CULL_BIT 0x04*/
80
81 static ffb_tri_func ffb_tri_tab[0x8];
82 static ffb_quad_func ffb_quad_tab[0x8];
83
84 #define IND (0)
85 #define TAG(x) x
86 #include "ffb_tritmp.h"
87
88 #define IND (FFB_TRI_FLAT_BIT)
89 #define TAG(x) x##_flat
90 #include "ffb_tritmp.h"
91
92 #define IND (FFB_TRI_CULL_BIT)
93 #define TAG(x) x##_cull
94 #include "ffb_tritmp.h"
95
96 #define IND (FFB_TRI_CULL_BIT|FFB_TRI_FLAT_BIT)
97 #define TAG(x) x##_cull_flat
98 #include "ffb_tritmp.h"
99
100 #define IND (FFB_TRI_ALPHA_BIT)
101 #define TAG(x) x##_alpha
102 #include "ffb_tritmp.h"
103
104 #define IND (FFB_TRI_ALPHA_BIT|FFB_TRI_FLAT_BIT)
105 #define TAG(x) x##_alpha_flat
106 #include "ffb_tritmp.h"
107
108 #define IND (FFB_TRI_ALPHA_BIT|FFB_TRI_CULL_BIT)
109 #define TAG(x) x##_alpha_cull
110 #include "ffb_tritmp.h"
111
112 #define IND (FFB_TRI_ALPHA_BIT|FFB_TRI_CULL_BIT|FFB_TRI_FLAT_BIT)
113 #define TAG(x) x##_alpha_cull_flat
114 #include "ffb_tritmp.h"
115
116 static void init_tri_tab(void)
117 {
118 ffb_init();
119 ffb_init_flat();
120 ffb_init_cull();
121 ffb_init_cull_flat();
122 ffb_init_alpha();
123 ffb_init_alpha_flat();
124 ffb_init_alpha_cull();
125 ffb_init_alpha_cull_flat();
126 }
127
128 /* Build a SWvertex from a hardware vertex. */
129 static void ffb_translate_vertex(GLcontext *ctx, const ffb_vertex *src,
130 SWvertex *dst)
131 {
132 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
133 GLfloat *m = ctx->Viewport._WindowMap.m;
134 const GLfloat sx = m[0];
135 const GLfloat sy = m[5];
136 const GLfloat sz = m[10];
137 const GLfloat tx = m[12];
138 const GLfloat ty = m[13];
139 const GLfloat tz = m[14];
140
141 dst->attrib[FRAG_ATTRIB_WPOS][0] = sx * src->x + tx;
142 dst->attrib[FRAG_ATTRIB_WPOS][1] = sy * src->y + ty;
143 dst->attrib[FRAG_ATTRIB_WPOS][2] = sz * src->z + tz;
144 dst->attrib[FRAG_ATTRIB_WPOS][3] = 1.0;
145
146 dst->color[0] = FFB_UBYTE_FROM_COLOR(src->color[0].red);
147 dst->color[1] = FFB_UBYTE_FROM_COLOR(src->color[0].green);
148 dst->color[2] = FFB_UBYTE_FROM_COLOR(src->color[0].blue);
149 dst->color[3] = FFB_UBYTE_FROM_COLOR(src->color[0].alpha);
150 }
151
152 /***********************************************************************
153 * Build fallback triangle/quad rasterize functions *
154 ***********************************************************************/
155
156 static void ffb_fallback_triangle(GLcontext *ctx, ffb_vertex *v0,
157 ffb_vertex *v1, ffb_vertex *v2)
158 {
159 SWvertex v[3];
160
161 ffb_translate_vertex(ctx, v0, &v[0]);
162 ffb_translate_vertex(ctx, v1, &v[1]);
163 ffb_translate_vertex(ctx, v2, &v[2]);
164
165 _swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
166 }
167
168 static void ffb_fallback_quad(GLcontext *ctx,
169 ffb_vertex *v0, ffb_vertex *v1,
170 ffb_vertex *v2, ffb_vertex *v3)
171 {
172 SWvertex v[4];
173
174 ffb_translate_vertex(ctx, v0, &v[0]);
175 ffb_translate_vertex(ctx, v1, &v[1]);
176 ffb_translate_vertex(ctx, v2, &v[2]);
177 ffb_translate_vertex(ctx, v3, &v[3]);
178
179 _swrast_Quad(ctx, &v[0], &v[1], &v[2], &v[3]);
180 }
181
182 void ffb_fallback_line(GLcontext *ctx, ffb_vertex *v0, ffb_vertex *v1)
183 {
184 SWvertex v[2];
185
186 ffb_translate_vertex(ctx, v0, &v[0]);
187 ffb_translate_vertex(ctx, v1, &v[1]);
188
189 _swrast_Line(ctx, &v[0], &v[1]);
190 }
191
192 void ffb_fallback_point(GLcontext *ctx, ffb_vertex *v0)
193 {
194 SWvertex v[1];
195
196 ffb_translate_vertex(ctx, v0, &v[0]);
197
198 _swrast_Point(ctx, &v[0]);
199 }
200
201 /***********************************************************************
202 * Rasterization functions for culled tris/quads *
203 ***********************************************************************/
204
205 static void ffb_nodraw_triangle(GLcontext *ctx, ffb_vertex *v0,
206 ffb_vertex *v1, ffb_vertex *v2)
207 {
208 (void) (ctx && v0 && v1 && v2);
209 }
210
211 static void ffb_nodraw_quad(GLcontext *ctx,
212 ffb_vertex *v0, ffb_vertex *v1,
213 ffb_vertex *v2, ffb_vertex *v3)
214 {
215 (void) (ctx && v0 && v1 && v2 && v3);
216 }
217
218 static void ffb_update_cullsign(GLcontext *ctx)
219 {
220 GLfloat backface_sign = 1;
221
222 switch (ctx->Polygon.CullFaceMode) {
223 case GL_BACK:
224 if (ctx->Polygon.FrontFace==GL_CCW)
225 backface_sign = -1;
226 break;
227
228 case GL_FRONT:
229 if (ctx->Polygon.FrontFace!=GL_CCW)
230 backface_sign = -1;
231 break;
232
233 default:
234 break;
235 };
236
237 FFB_CONTEXT(ctx)->backface_sign = backface_sign;
238 }
239
240 /***********************************************************************
241 * Choose triangle/quad rasterize functions *
242 ***********************************************************************/
243
244 void ffbChooseTriangleState(GLcontext *ctx)
245 {
246 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
247 GLuint flags = ctx->_TriangleCaps;
248 GLuint ind = 0;
249
250 if (flags & DD_TRI_SMOOTH) {
251 fmesa->draw_tri = ffb_fallback_triangle;
252 fmesa->draw_quad = ffb_fallback_quad;
253 return;
254 }
255
256 if (flags & DD_FLATSHADE)
257 ind |= FFB_TRI_FLAT_BIT;
258
259 if (ctx->Polygon.CullFlag) {
260 if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
261 fmesa->draw_tri = ffb_nodraw_triangle;
262 fmesa->draw_quad = ffb_nodraw_quad;
263 return;
264 }
265
266 ind |= FFB_TRI_CULL_BIT;
267 ffb_update_cullsign(ctx);
268 } else
269 FFB_CONTEXT(ctx)->backface_sign = 0;
270
271 /* If blending or the alpha test is enabled we need to
272 * provide alpha components to the chip, else we can
273 * do without it and thus feed vertex data to the chip
274 * more efficiently.
275 */
276 if (ctx->Color.BlendEnabled || ctx->Color.AlphaEnabled)
277 ind |= FFB_TRI_ALPHA_BIT;
278
279 fmesa->draw_tri = ffb_tri_tab[ind];
280 fmesa->draw_quad = ffb_quad_tab[ind];
281 }
282
283 static const GLenum reduced_prim[GL_POLYGON+1] = {
284 GL_POINTS,
285 GL_LINES,
286 GL_LINES,
287 GL_LINES,
288 GL_TRIANGLES,
289 GL_TRIANGLES,
290 GL_TRIANGLES,
291 GL_TRIANGLES,
292 GL_TRIANGLES,
293 GL_TRIANGLES
294 };
295
296 static void ffbRenderPrimitive(GLcontext *ctx, GLenum prim);
297 static void ffbRasterPrimitive(GLcontext *ctx, GLenum rprim);
298
299 /***********************************************************************
300 * Build render functions from dd templates *
301 ***********************************************************************/
302
303 #define FFB_OFFSET_BIT 0x01
304 #define FFB_TWOSIDE_BIT 0x02
305 #define FFB_UNFILLED_BIT 0x04
306 #define FFB_MAX_TRIFUNC 0x08
307
308 static struct {
309 tnl_triangle_func triangle;
310 tnl_quad_func quad;
311 } rast_tab[FFB_MAX_TRIFUNC];
312
313 #define DO_OFFSET (IND & FFB_OFFSET_BIT)
314 #define DO_UNFILLED (IND & FFB_UNFILLED_BIT)
315 #define DO_TWOSIDE (IND & FFB_TWOSIDE_BIT)
316 #define DO_FLAT 0
317 #define DO_QUAD 1
318 #define DO_FULL_QUAD 1
319 #define DO_TRI 1
320 #define DO_LINE 0
321 #define DO_POINTS 0
322
323 #define QUAD( a, b, c, d ) fmesa->draw_quad( ctx, a, b, c, d )
324 #define TRI( a, b, c ) fmesa->draw_tri( ctx, a, b, c )
325 #define LINE( a, b ) fmesa->draw_line( ctx, a, b )
326 #define POINT( a ) fmesa->draw_point( ctx, a )
327
328 #define HAVE_BACK_COLORS 1
329 #define HAVE_RGBA 1
330 #define HAVE_SPEC 0
331 #define HAVE_HW_FLATSHADE 1
332 #define VERTEX ffb_vertex
333 #define TAB rast_tab
334
335 #define UNFILLED_TRI unfilled_tri
336 #define UNFILLED_QUAD unfilled_quad
337 #define DEPTH_SCALE (fmesa->depth_scale)
338 #define VERT_X(_v) (_v->x)
339 #define VERT_Y(_v) (_v->y)
340 #define VERT_Z(_v) (_v->z)
341 #define AREA_IS_CCW( a ) (a < fmesa->ffb_zero)
342 #define GET_VERTEX(e) (&fmesa->verts[e])
343 #define INSANE_VERTICES
344 #define VERT_SET_Z(v,val) ((v)->z = (val))
345 #define VERT_Z_ADD(v,val) ((v)->z += (val))
346
347 #define VERT_COPY_RGBA1( _v ) _v->color[0] = _v->color[1]
348 #define VERT_COPY_RGBA( v0, v1 ) v0->color[0] = v1->color[0]
349 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->color[0]
350 #define VERT_RESTORE_RGBA( idx ) v[idx]->color[0] = color[idx]
351
352 #define LOCAL_VARS(n) \
353 ffbContextPtr fmesa = FFB_CONTEXT(ctx); \
354 __DRIdrawablePrivate *dPriv = fmesa->driDrawable; \
355 ffb_color color[n]; \
356 (void) color; (void) dPriv;
357
358 /***********************************************************************
359 * Helpers for rendering unfilled primitives *
360 ***********************************************************************/
361
362 #define RASTERIZE(x) if (fmesa->raster_primitive != reduced_prim[x]) \
363 ffbRasterPrimitive( ctx, reduced_prim[x] )
364 #define RENDER_PRIMITIVE fmesa->render_primitive
365 #define TAG(x) x
366 #include "tnl_dd/t_dd_unfilled.h"
367
368 /***********************************************************************
369 * Generate GL render functions *
370 ***********************************************************************/
371
372 #define IND (0)
373 #define TAG(x) x
374 #include "tnl_dd/t_dd_tritmp.h"
375
376 #define IND (FFB_OFFSET_BIT)
377 #define TAG(x) x##_offset
378 #include "tnl_dd/t_dd_tritmp.h"
379
380 #define IND (FFB_TWOSIDE_BIT)
381 #define TAG(x) x##_twoside
382 #include "tnl_dd/t_dd_tritmp.h"
383
384 #define IND (FFB_TWOSIDE_BIT|FFB_OFFSET_BIT)
385 #define TAG(x) x##_twoside_offset
386 #include "tnl_dd/t_dd_tritmp.h"
387
388 #define IND (FFB_UNFILLED_BIT)
389 #define TAG(x) x##_unfilled
390 #include "tnl_dd/t_dd_tritmp.h"
391
392 #define IND (FFB_OFFSET_BIT|FFB_UNFILLED_BIT)
393 #define TAG(x) x##_offset_unfilled
394 #include "tnl_dd/t_dd_tritmp.h"
395
396 #define IND (FFB_TWOSIDE_BIT|FFB_UNFILLED_BIT)
397 #define TAG(x) x##_twoside_unfilled
398 #include "tnl_dd/t_dd_tritmp.h"
399
400 #define IND (FFB_TWOSIDE_BIT|FFB_OFFSET_BIT|FFB_UNFILLED_BIT)
401 #define TAG(x) x##_twoside_offset_unfilled
402 #include "tnl_dd/t_dd_tritmp.h"
403
404 static void init_rast_tab( void )
405 {
406 init();
407 init_offset();
408 init_twoside();
409 init_twoside_offset();
410 init_unfilled();
411 init_offset_unfilled();
412 init_twoside_unfilled();
413 init_twoside_offset_unfilled();
414 }
415
416 /**********************************************************************/
417 /* Render clipped primitives */
418 /**********************************************************************/
419
420 static void ffbRenderClippedPolygon(GLcontext *ctx, const GLuint *elts, GLuint n)
421 {
422 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
423 TNLcontext *tnl = TNL_CONTEXT(ctx);
424 struct vertex_buffer *VB = &tnl->vb;
425 GLuint prim = fmesa->render_primitive;
426
427 /* Render the new vertices as an unclipped polygon. */
428 {
429 GLuint *tmp = VB->Elts;
430 VB->Elts = (GLuint *)elts;
431 tnl->Driver.Render.PrimTabElts[GL_POLYGON](ctx, 0, n, PRIM_BEGIN|PRIM_END);
432 VB->Elts = tmp;
433 }
434
435 /* Restore the render primitive. */
436 if (prim != GL_POLYGON)
437 tnl->Driver.Render.PrimitiveNotify(ctx, prim);
438 }
439
440 static void ffbRenderClippedLine(GLcontext *ctx, GLuint ii, GLuint jj)
441 {
442 TNLcontext *tnl = TNL_CONTEXT(ctx);
443 tnl->Driver.Render.Line(ctx, ii, jj);
444 }
445
446 /**********************************************************************/
447 /* Render unclipped begin/end objects */
448 /**********************************************************************/
449
450 static void ffb_vb_noop(GLcontext *ctx, GLuint start, GLuint count, GLuint flags)
451 {
452 (void)(ctx && start && count && flags);
453 }
454
455 #define ELT(x) x
456
457 #define IND 0
458 #define TAG(x) x
459 #include "ffb_rendertmp.h"
460
461 #define IND (FFB_FLAT_BIT)
462 #define TAG(x) x##_flat
463 #include "ffb_rendertmp.h"
464
465 #define IND (FFB_ALPHA_BIT)
466 #define TAG(x) x##_alpha
467 #include "ffb_rendertmp.h"
468
469 #define IND (FFB_FLAT_BIT | FFB_ALPHA_BIT)
470 #define TAG(x) x##_flat_alpha
471 #include "ffb_rendertmp.h"
472
473 #define IND (FFB_TRI_CULL_BIT)
474 #define TAG(x) x##_tricull
475 #include "ffb_rendertmp.h"
476
477 #define IND (FFB_FLAT_BIT | FFB_TRI_CULL_BIT)
478 #define TAG(x) x##_flat_tricull
479 #include "ffb_rendertmp.h"
480
481 #define IND (FFB_ALPHA_BIT | FFB_TRI_CULL_BIT)
482 #define TAG(x) x##_alpha_tricull
483 #include "ffb_rendertmp.h"
484
485 #define IND (FFB_FLAT_BIT | FFB_ALPHA_BIT | FFB_TRI_CULL_BIT)
486 #define TAG(x) x##_flat_alpha_tricull
487 #include "ffb_rendertmp.h"
488
489 #undef ELT
490 #define ELT(x) elt[x]
491
492 #define IND 0
493 #define TAG(x) x##_elt
494 #include "ffb_rendertmp.h"
495
496 #define IND (FFB_FLAT_BIT)
497 #define TAG(x) x##_flat_elt
498 #include "ffb_rendertmp.h"
499
500 #define IND (FFB_ALPHA_BIT)
501 #define TAG(x) x##_alpha_elt
502 #include "ffb_rendertmp.h"
503
504 #define IND (FFB_FLAT_BIT | FFB_ALPHA_BIT)
505 #define TAG(x) x##_flat_alpha_elt
506 #include "ffb_rendertmp.h"
507
508 #define IND (FFB_TRI_CULL_BIT)
509 #define TAG(x) x##_tricull_elt
510 #include "ffb_rendertmp.h"
511
512 #define IND (FFB_FLAT_BIT | FFB_TRI_CULL_BIT)
513 #define TAG(x) x##_flat_tricull_elt
514 #include "ffb_rendertmp.h"
515
516 #define IND (FFB_ALPHA_BIT | FFB_TRI_CULL_BIT)
517 #define TAG(x) x##_alpha_tricull_elt
518 #include "ffb_rendertmp.h"
519
520 #define IND (FFB_FLAT_BIT | FFB_ALPHA_BIT | FFB_TRI_CULL_BIT)
521 #define TAG(x) x##_flat_alpha_tricull_elt
522 #include "ffb_rendertmp.h"
523
524 static void *render_tabs[MAX_FFB_RENDER_FUNCS];
525 static void *render_tabs_elt[MAX_FFB_RENDER_FUNCS];
526
527 static void init_render_tab(void)
528 {
529 int i;
530
531 render_tabs[0] = render_tab;
532 render_tabs[FFB_FLAT_BIT] = render_tab_flat;
533 render_tabs[FFB_ALPHA_BIT] = render_tab_alpha;
534 render_tabs[FFB_FLAT_BIT|FFB_ALPHA_BIT] = render_tab_flat_alpha;
535 render_tabs[FFB_TRI_CULL_BIT] = render_tab_tricull;
536 render_tabs[FFB_FLAT_BIT|FFB_TRI_CULL_BIT] = render_tab_flat_tricull;
537 render_tabs[FFB_ALPHA_BIT|FFB_TRI_CULL_BIT] = render_tab_alpha_tricull;
538 render_tabs[FFB_FLAT_BIT|FFB_ALPHA_BIT|FFB_TRI_CULL_BIT] =
539 render_tab_flat_alpha_tricull;
540
541 render_tabs_elt[0] = render_tab_elt;
542 render_tabs_elt[FFB_FLAT_BIT] = render_tab_flat_elt;
543 render_tabs_elt[FFB_ALPHA_BIT] = render_tab_alpha_elt;
544 render_tabs_elt[FFB_FLAT_BIT|FFB_ALPHA_BIT] = render_tab_flat_alpha_elt;
545 render_tabs_elt[FFB_TRI_CULL_BIT] = render_tab_tricull_elt;
546 render_tabs_elt[FFB_FLAT_BIT|FFB_TRI_CULL_BIT] = render_tab_flat_tricull_elt;
547 render_tabs_elt[FFB_ALPHA_BIT|FFB_TRI_CULL_BIT] = render_tab_alpha_tricull_elt;
548 render_tabs_elt[FFB_FLAT_BIT|FFB_ALPHA_BIT|FFB_TRI_CULL_BIT] =
549 render_tab_flat_alpha_tricull_elt;
550
551 for (i = 0; i < MAX_FFB_RENDER_FUNCS; i++) {
552 tnl_render_func *rf = render_tabs[i];
553 tnl_render_func *rfe = render_tabs_elt[i];
554
555 if (i & FFB_TRI_CULL_BIT) {
556 int from_idx = (i & ~FFB_TRI_CULL_BIT);
557 tnl_render_func *rf_from = render_tabs[from_idx];
558 tnl_render_func *rfe_from = render_tabs_elt[from_idx];
559 int j;
560
561 for (j = GL_POINTS; j < GL_TRIANGLES; j++) {
562 rf[j] = rf_from[j];
563 rfe[j] = rfe_from[j];
564 }
565 }
566 }
567 }
568
569 /**********************************************************************/
570 /* Choose render functions */
571 /**********************************************************************/
572
573 #ifdef FFB_RENDER_TRACE
574 static void ffbPrintRenderFlags(GLuint index, GLuint render_index)
575 {
576 fprintf(stderr,
577 "ffbChooseRenderState: "
578 "index(%s%s%s) "
579 "render_index(%s%s%s)\n",
580 ((index & FFB_TWOSIDE_BIT) ? "twoside " : ""),
581 ((index & FFB_OFFSET_BIT) ? "offset " : ""),
582 ((index & FFB_UNFILLED_BIT) ? "unfilled " : ""),
583 ((render_index & FFB_FLAT_BIT) ? "flat " : ""),
584 ((render_index & FFB_ALPHA_BIT) ? "alpha " : ""),
585 ((render_index & FFB_TRI_CULL_BIT) ? "tricull " : ""));
586 }
587 #endif
588
589 void ffbChooseRenderState(GLcontext *ctx)
590 {
591 GLuint flags = ctx->_TriangleCaps;
592 TNLcontext *tnl = TNL_CONTEXT(ctx);
593 GLuint index = 0;
594
595 /* Per-primitive fallbacks and the selection of fmesa->draw_* are
596 * handled elsewhere.
597 */
598 if (flags & DD_TRI_LIGHT_TWOSIDE)
599 index |= FFB_TWOSIDE_BIT;
600
601 if (flags & DD_TRI_OFFSET)
602 index |= FFB_OFFSET_BIT;
603
604 if (flags & DD_TRI_UNFILLED)
605 index |= FFB_UNFILLED_BIT;
606
607 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
608 tnl->Driver.Render.Quad = rast_tab[index].quad;
609
610 if (index == 0) {
611 GLuint render_index = 0;
612
613 if (flags & DD_FLATSHADE)
614 render_index |= FFB_FLAT_BIT;
615
616 if (ctx->Color.BlendEnabled || ctx->Color.AlphaEnabled)
617 render_index |= FFB_ALPHA_BIT;
618
619 if (ctx->Polygon.CullFlag)
620 render_index |= FFB_TRI_CULL_BIT;
621
622 #ifdef FFB_RENDER_TRACE
623 ffbPrintRenderFlags(index, render_index);
624 #endif
625 tnl->Driver.Render.PrimTabVerts = render_tabs[render_index];
626 tnl->Driver.Render.PrimTabElts = render_tabs_elt[render_index];
627 } else {
628 #ifdef FFB_RENDER_TRACE
629 ffbPrintRenderFlags(index, 0);
630 #endif
631 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
632 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
633 }
634
635 tnl->Driver.Render.ClippedPolygon = ffbRenderClippedPolygon;
636 tnl->Driver.Render.ClippedLine = ffbRenderClippedLine;
637 }
638
639 static void ffbRunPipeline(GLcontext *ctx)
640 {
641 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
642
643 if (fmesa->bad_fragment_attrs == 0 &&
644 fmesa->new_gl_state) {
645 if (fmesa->new_gl_state & _FFB_NEW_TRIANGLE)
646 ffbChooseTriangleState(ctx);
647 if (fmesa->new_gl_state & _FFB_NEW_LINE)
648 ffbChooseLineState(ctx);
649 if (fmesa->new_gl_state & _FFB_NEW_POINT)
650 ffbChoosePointState(ctx);
651 if (fmesa->new_gl_state & _FFB_NEW_RENDER)
652 ffbChooseRenderState(ctx);
653 if (fmesa->new_gl_state & _FFB_NEW_VERTEX)
654 ffbChooseVertexState(ctx);
655
656 fmesa->new_gl_state = 0;
657 }
658
659 _tnl_run_pipeline(ctx);
660 }
661
662 static void ffbRenderStart(GLcontext *ctx)
663 {
664 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
665
666 LOCK_HARDWARE(fmesa);
667 fmesa->hw_locked = 1;
668
669 if (fmesa->state_dirty != 0)
670 ffbSyncHardware(fmesa);
671 }
672
673 static void ffbRenderFinish(GLcontext *ctx)
674 {
675 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
676
677 UNLOCK_HARDWARE(fmesa);
678 fmesa->hw_locked = 0;
679 }
680
681 /* Even when doing full software rendering we need to
682 * wrap render{start,finish} so that the hardware is kept
683 * in sync (because multipass rendering changes the write
684 * buffer etc.)
685 */
686 static void ffbSWRenderStart(GLcontext *ctx)
687 {
688 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
689
690 LOCK_HARDWARE(fmesa);
691 fmesa->hw_locked = 1;
692
693 if (fmesa->state_dirty != 0)
694 ffbSyncHardware(fmesa);
695 }
696
697 static void ffbSWRenderFinish(GLcontext *ctx)
698 {
699 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
700
701 UNLOCK_HARDWARE(fmesa);
702 fmesa->hw_locked = 0;
703 }
704
705 static void ffbRasterPrimitive(GLcontext *ctx, GLenum rprim)
706 {
707 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
708 GLuint drawop, fbc, ppc;
709 int do_sw = 0;
710
711 fmesa->raster_primitive = rprim;
712
713 drawop = fmesa->drawop;
714 fbc = fmesa->fbc;
715 ppc = fmesa->ppc & ~(FFB_PPC_ZS_MASK | FFB_PPC_CS_MASK);
716
717 #ifdef STATE_TRACE
718 fprintf(stderr,
719 "ffbReducedPrimitiveChange: rprim(%d) ", rprim);
720 #endif
721 switch(rprim) {
722 case GL_POINTS:
723 #ifdef STATE_TRACE
724 fprintf(stderr, "GL_POINTS ");
725 #endif
726 if (fmesa->draw_point == ffb_fallback_point) {
727 do_sw = 1;
728 break;
729 }
730
731 if (ctx->Point.SmoothFlag) {
732 ppc |= (FFB_PPC_ZS_VAR | FFB_PPC_CS_CONST);
733 drawop = FFB_DRAWOP_AADOT;
734 } else {
735 ppc |= (FFB_PPC_ZS_CONST | FFB_PPC_CS_CONST);
736 drawop = FFB_DRAWOP_DOT;
737 }
738 break;
739
740 case GL_LINES:
741 #ifdef STATE_TRACE
742 fprintf(stderr, "GL_LINES ");
743 #endif
744 if (fmesa->draw_line == ffb_fallback_line) {
745 do_sw = 1;
746 break;
747 }
748
749 if (ctx->_TriangleCaps & DD_FLATSHADE) {
750 ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_CONST;
751 } else {
752 ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_VAR;
753 }
754 if (ctx->Line.SmoothFlag)
755 drawop = FFB_DRAWOP_AALINE;
756 else
757 drawop = FFB_DRAWOP_DDLINE;
758 break;
759
760 case GL_TRIANGLES:
761 #ifdef STATE_TRACE
762 fprintf(stderr, "GL_POLYGON ");
763 #endif
764 if (fmesa->draw_tri == ffb_fallback_triangle) {
765 do_sw = 1;
766 break;
767 }
768
769 ppc &= ~FFB_PPC_APE_MASK;
770 if (ctx->Polygon.StippleFlag)
771 ppc |= FFB_PPC_APE_ENABLE;
772 else
773 ppc |= FFB_PPC_APE_DISABLE;
774
775 if (ctx->_TriangleCaps & DD_FLATSHADE) {
776 ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_CONST;
777 } else {
778 ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_VAR;
779 }
780 drawop = FFB_DRAWOP_TRIANGLE;
781 break;
782
783 default:
784 #ifdef STATE_TRACE
785 fprintf(stderr, "unknown %d!\n", rprim);
786 #endif
787 return;
788 };
789
790 #ifdef STATE_TRACE
791 fprintf(stderr, "do_sw(%d) ", do_sw);
792 #endif
793 if (do_sw != 0) {
794 fbc &= ~(FFB_FBC_WB_C);
795 fbc &= ~(FFB_FBC_ZE_MASK | FFB_FBC_RGBE_MASK);
796 fbc |= FFB_FBC_ZE_OFF | FFB_FBC_RGBE_MASK;
797 ppc &= ~(FFB_PPC_XS_MASK | FFB_PPC_ABE_MASK |
798 FFB_PPC_DCE_MASK | FFB_PPC_APE_MASK);
799 ppc |= (FFB_PPC_ZS_VAR | FFB_PPC_CS_VAR | FFB_PPC_XS_WID |
800 FFB_PPC_ABE_DISABLE | FFB_PPC_DCE_DISABLE |
801 FFB_PPC_APE_DISABLE);
802 } else {
803 fbc |= FFB_FBC_WB_C;
804 fbc &= ~(FFB_FBC_RGBE_MASK);
805 fbc |= FFB_FBC_RGBE_MASK;
806 ppc &= ~(FFB_PPC_ABE_MASK | FFB_PPC_XS_MASK);
807 if (ctx->Color.BlendEnabled) {
808 if ((rprim == GL_POINTS && !ctx->Point.SmoothFlag) ||
809 (rprim != GL_POINTS && ctx->_TriangleCaps & DD_FLATSHADE))
810 ppc |= FFB_PPC_ABE_ENABLE | FFB_PPC_XS_CONST;
811 else
812 ppc |= FFB_PPC_ABE_ENABLE | FFB_PPC_XS_VAR;
813 } else {
814 ppc |= FFB_PPC_ABE_DISABLE | FFB_PPC_XS_WID;
815 }
816 }
817 #ifdef STATE_TRACE
818 fprintf(stderr, "fbc(%08x) ppc(%08x)\n", fbc, ppc);
819 #endif
820
821 FFBFifo(fmesa, 4);
822 if (fmesa->drawop != drawop)
823 fmesa->regs->drawop = fmesa->drawop = drawop;
824 if (fmesa->fbc != fbc)
825 fmesa->regs->fbc = fmesa->fbc = fbc;
826 if (fmesa->ppc != ppc)
827 fmesa->regs->ppc = fmesa->ppc = ppc;
828 if (do_sw != 0) {
829 fmesa->regs->cmp =
830 (fmesa->cmp & ~(0xff<<16)) | (0x80 << 16);
831 } else
832 fmesa->regs->cmp = fmesa->cmp;
833 }
834
835 static void ffbRenderPrimitive(GLcontext *ctx, GLenum prim)
836 {
837 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
838 GLuint rprim = reduced_prim[prim];
839
840 fmesa->render_primitive = prim;
841
842 if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
843 return;
844
845 if (fmesa->raster_primitive != rprim) {
846 ffbRasterPrimitive( ctx, rprim );
847 }
848 }
849
850
851
852
853 /**********************************************************************/
854 /* Transition to/from hardware rasterization. */
855 /**********************************************************************/
856
857 static char *fallbackStrings[] = {
858 "Fog enabled",
859 "Blend function",
860 "Blend ROP",
861 "Blend equation",
862 "Stencil",
863 "Texture",
864 "LIBGL_SOFTWARE_RENDERING"
865 };
866
867 static char *getFallbackString(GLuint bit)
868 {
869 int i = 0;
870
871 while (bit > 1) {
872 i++;
873 bit >>= 1;
874 }
875 return fallbackStrings[i];
876 }
877
878 void ffbFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
879 {
880 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
881 TNLcontext *tnl = TNL_CONTEXT(ctx);
882 GLuint oldfallback = fmesa->bad_fragment_attrs;
883
884 if (mode) {
885 fmesa->bad_fragment_attrs |= bit;
886 if (oldfallback == 0) {
887 /* FFB_FIREVERTICES(fmesa); */
888 _swsetup_Wakeup( ctx );
889 if (fmesa->debugFallbacks)
890 fprintf(stderr, "FFB begin software fallback: 0x%x %s\n",
891 bit, getFallbackString(bit));
892 }
893 } else {
894 fmesa->bad_fragment_attrs &= ~bit;
895 if (oldfallback == bit) {
896 _swrast_flush( ctx );
897
898 tnl->Driver.Render.Start = ffbRenderStart;
899 tnl->Driver.Render.PrimitiveNotify = ffbRenderPrimitive;
900 tnl->Driver.Render.Finish = ffbRenderFinish;
901 fmesa->new_gl_state = ~0;
902
903 /* Just re-choose everything:
904 */
905 ffbChooseVertexState(ctx);
906 ffbChooseRenderState(ctx);
907 ffbChooseTriangleState(ctx);
908 ffbChooseLineState(ctx);
909 ffbChoosePointState(ctx);
910
911 if (fmesa->debugFallbacks)
912 fprintf(stderr, "FFB end software fallback: 0x%x %s\n",
913 bit, getFallbackString(bit));
914 }
915 }
916 }
917
918 /**********************************************************************/
919 /* Initialization. */
920 /**********************************************************************/
921
922 void ffbDDInitRenderFuncs( GLcontext *ctx )
923 {
924 TNLcontext *tnl = TNL_CONTEXT(ctx);
925 SWcontext *swrast = SWRAST_CONTEXT(ctx);
926 static int firsttime = 1;
927
928 if (firsttime) {
929 init_rast_tab();
930 init_tri_tab();
931 init_render_tab();
932 firsttime = 0;
933 }
934
935 tnl->Driver.RunPipeline = ffbRunPipeline;
936 tnl->Driver.Render.Start = ffbRenderStart;
937 tnl->Driver.Render.Finish = ffbRenderFinish;
938 tnl->Driver.Render.PrimitiveNotify = ffbRenderPrimitive;
939 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
940 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
941 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
942
943 swrast->Driver.SpanRenderStart = ffbSWRenderStart;
944 swrast->Driver.SpanRenderFinish = ffbSWRenderFinish;
945 }