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