OSDN Git Service

9fae8c8283e519517519e36e874067f790027d32
[android-x86/external-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 }