Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / r128 / r128_tris.c
1 /* -*- c-basic-offset: 3 -*- */
2 /**************************************************************************
3
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5                      VA Linux Systems Inc., Fremont, California.
6
7 All Rights Reserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the "Software"),
11 to deal in the Software without restriction, including without limitation
12 on the rights to use, copy, modify, merge, publish, distribute, sub
13 license, and/or sell copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice (including the next
17 paragraph) shall be included in all copies or substantial portions of the
18 Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
23 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
24 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
25 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
26 USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 **************************************************************************/
29
30 /*
31  * Authors:
32  *   Keith Whitwell <keith@tungstengraphics.com>
33  *
34  */
35
36 #include "main/glheader.h"
37 #include "main/mtypes.h"
38 #include "main/colormac.h"
39 #include "main/macros.h"
40
41 #include "swrast/swrast.h"
42 #include "swrast_setup/swrast_setup.h"
43 #include "tnl/tnl.h"
44 #include "tnl/t_context.h"
45 #include "tnl/t_pipeline.h"
46
47 #include "r128_tris.h"
48 #include "r128_state.h"
49 #include "r128_tex.h"
50 #include "r128_ioctl.h"
51
52 static const GLuint hw_prim[GL_POLYGON+1] = {
53    R128_CCE_VC_CNTL_PRIM_TYPE_POINT,
54    R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
55    R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
56    R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
57    R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
58    R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
59    R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
60    R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
61    R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
62    R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
63 };
64
65 static void r128RasterPrimitive( struct gl_context *ctx, GLuint hwprim );
66 static void r128RenderPrimitive( struct gl_context *ctx, GLenum prim );
67
68
69 /***********************************************************************
70  *                    Emit primitives as inline vertices               *
71  ***********************************************************************/
72         
73 #define HAVE_QUADS 0
74 #define HAVE_LINES 1
75 #define HAVE_POINTS 1
76 #define HAVE_LE32_VERTS 1
77 #define CTX_ARG r128ContextPtr rmesa
78 #define GET_VERTEX_DWORDS() rmesa->vertex_size
79 #define ALLOC_VERTS( n, size ) r128AllocDmaLow( rmesa, (n), (size) * 4 )
80 #undef LOCAL_VARS
81 #define LOCAL_VARS                                              \
82    r128ContextPtr rmesa = R128_CONTEXT(ctx);                    \
83    const char *vertptr = rmesa->verts;
84 #define VERT(x) (r128Vertex *)(vertptr + ((x) * vertsize * 4))
85 #define VERTEX r128Vertex
86 #undef TAG
87 #define TAG(x) r128_##x
88 #include "tnl_dd/t_dd_triemit.h"
89 #undef TAG
90 #undef LOCAL_VARS
91
92
93 /***********************************************************************
94  *          Macros for t_dd_tritmp.h to draw basic primitives          *
95  ***********************************************************************/
96
97 #define TRI( a, b, c )                          \
98 do {                                            \
99    if (DO_FALLBACK)                             \
100       rmesa->draw_tri( rmesa, a, b, c );        \
101    else                                         \
102       r128_triangle( rmesa, a, b, c );          \
103 } while (0)
104
105 #define QUAD( a, b, c, d )                      \
106 do {                                            \
107    if (DO_FALLBACK) {                           \
108       rmesa->draw_tri( rmesa, a, b, d );        \
109       rmesa->draw_tri( rmesa, b, c, d );        \
110    } else                                       \
111       r128_quad( rmesa, a, b, c, d );           \
112 } while (0)
113
114 #define LINE( v0, v1 )                          \
115 do {                                            \
116    if (DO_FALLBACK)                             \
117       rmesa->draw_line( rmesa, v0, v1 );        \
118    else                                         \
119       r128_line( rmesa, v0, v1 );               \
120 } while (0)
121
122 #define POINT( v0 )                             \
123 do {                                            \
124    if (DO_FALLBACK)                             \
125       rmesa->draw_point( rmesa, v0 );           \
126    else                                         \
127       r128_point( rmesa, v0 );                  \
128 } while (0)
129
130
131 /***********************************************************************
132  *              Build render functions from dd templates               *
133  ***********************************************************************/
134
135 #define R128_OFFSET_BIT 0x01
136 #define R128_TWOSIDE_BIT        0x02
137 #define R128_UNFILLED_BIT       0x04
138 #define R128_FALLBACK_BIT       0x08
139 #define R128_MAX_TRIFUNC        0x10
140
141
142 static struct {
143    tnl_points_func              points;
144    tnl_line_func                line;
145    tnl_triangle_func    triangle;
146    tnl_quad_func                quad;
147 } rast_tab[R128_MAX_TRIFUNC];
148
149
150 #define DO_FALLBACK (IND & R128_FALLBACK_BIT)
151 #define DO_OFFSET   (IND & R128_OFFSET_BIT)
152 #define DO_UNFILLED (IND & R128_UNFILLED_BIT)
153 #define DO_TWOSIDE  (IND & R128_TWOSIDE_BIT)
154 #define DO_FLAT      0
155 #define DO_TRI       1
156 #define DO_QUAD      1
157 #define DO_LINE      1
158 #define DO_POINTS    1
159 #define DO_FULL_QUAD 1
160
161 #define HAVE_SPEC   1
162 #define HAVE_BACK_COLORS  0
163 #define HAVE_HW_FLATSHADE 1
164 #define VERTEX r128Vertex
165 #define TAB rast_tab
166
167 #define DEPTH_SCALE rmesa->depth_scale
168 #define UNFILLED_TRI unfilled_tri
169 #define UNFILLED_QUAD unfilled_quad
170 #define VERT_X(_v) _v->v.x
171 #define VERT_Y(_v) _v->v.y
172 #define VERT_Z(_v) _v->v.z
173 #define AREA_IS_CCW( a ) (a > 0)
174 #define GET_VERTEX(e) (rmesa->verts + (e * rmesa->vertex_size * sizeof(int)))
175
176 #define VERT_SET_RGBA( v, c )                                   \
177 do {                                                            \
178    r128_color_t *color = (r128_color_t *)&((v)->ui[coloroffset]);       \
179    UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]);                \
180    UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]);              \
181    UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]);               \
182    UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]);              \
183 } while (0)
184
185 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
186
187 #define VERT_SET_SPEC( v0, c )                                  \
188 do {                                                            \
189    if (havespec) {                                              \
190       r128_color_t *spec = (r128_color_t *)&((v0)->ui[specoffset]); \
191       UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]);              \
192       UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]);            \
193       UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]);             \
194    }                                                            \
195 } while (0)
196 #define VERT_COPY_SPEC( v0, v1 )                        \
197 do {                                                    \
198    if (havespec) {                                      \
199       r128_color_t *spec0 = (r128_color_t *)&((v0)->ui[specoffset]); \
200       r128_color_t *spec1 = (r128_color_t *)&((v1)->ui[specoffset]); \
201       spec0->red   = spec1->red;                        \
202       spec0->green = spec1->green;                      \
203       spec0->blue  = spec1->blue;                       \
204    }                                                    \
205 } while (0)
206
207 /* These don't need LE32_TO_CPU() as they are used to save and restore
208  * colors which are already in the correct format.
209  */
210 #define VERT_SAVE_RGBA( idx )    color[idx] = v[idx]->ui[coloroffset]
211 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
212 #define VERT_SAVE_SPEC( idx )    if (havespec) spec[idx] = v[idx]->ui[specoffset]
213 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[specoffset] = spec[idx]
214
215
216 #define LOCAL_VARS(n)                                           \
217    r128ContextPtr rmesa = R128_CONTEXT(ctx);                    \
218    GLuint color[n] = { 0 };                                     \
219    GLuint spec[n] = { 0 };                                      \
220    GLuint coloroffset = rmesa->coloroffset;                     \
221    GLuint specoffset = rmesa->specoffset;                       \
222    GLboolean havespec = (rmesa->specoffset != 0);               \
223    (void) color; (void) spec; (void) specoffset;                \
224    (void) coloroffset; (void) havespec;
225
226 /***********************************************************************
227  *                Helpers for rendering unfilled primitives            *
228  ***********************************************************************/
229
230 #define RASTERIZE(x) if (rmesa->hw_primitive != hw_prim[x]) \
231                         r128RasterPrimitive( ctx, hw_prim[x] )
232 #define RENDER_PRIMITIVE rmesa->render_primitive
233 #define IND R128_FALLBACK_BIT
234 #define TAG(x) x
235 #include "tnl_dd/t_dd_unfilled.h"
236 #undef IND
237
238
239 /***********************************************************************
240  *                      Generate GL render functions                   *
241  ***********************************************************************/
242
243
244 #define IND (0)
245 #define TAG(x) x
246 #include "tnl_dd/t_dd_tritmp.h"
247
248 #define IND (R128_OFFSET_BIT)
249 #define TAG(x) x##_offset
250 #include "tnl_dd/t_dd_tritmp.h"
251
252 #define IND (R128_TWOSIDE_BIT)
253 #define TAG(x) x##_twoside
254 #include "tnl_dd/t_dd_tritmp.h"
255
256 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT)
257 #define TAG(x) x##_twoside_offset
258 #include "tnl_dd/t_dd_tritmp.h"
259
260 #define IND (R128_UNFILLED_BIT)
261 #define TAG(x) x##_unfilled
262 #include "tnl_dd/t_dd_tritmp.h"
263
264 #define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT)
265 #define TAG(x) x##_offset_unfilled
266 #include "tnl_dd/t_dd_tritmp.h"
267
268 #define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT)
269 #define TAG(x) x##_twoside_unfilled
270 #include "tnl_dd/t_dd_tritmp.h"
271
272 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT)
273 #define TAG(x) x##_twoside_offset_unfilled
274 #include "tnl_dd/t_dd_tritmp.h"
275
276 #define IND (R128_FALLBACK_BIT)
277 #define TAG(x) x##_fallback
278 #include "tnl_dd/t_dd_tritmp.h"
279
280 #define IND (R128_OFFSET_BIT|R128_FALLBACK_BIT)
281 #define TAG(x) x##_offset_fallback
282 #include "tnl_dd/t_dd_tritmp.h"
283
284 #define IND (R128_TWOSIDE_BIT|R128_FALLBACK_BIT)
285 #define TAG(x) x##_twoside_fallback
286 #include "tnl_dd/t_dd_tritmp.h"
287
288 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_FALLBACK_BIT)
289 #define TAG(x) x##_twoside_offset_fallback
290 #include "tnl_dd/t_dd_tritmp.h"
291
292 #define IND (R128_UNFILLED_BIT|R128_FALLBACK_BIT)
293 #define TAG(x) x##_unfilled_fallback
294 #include "tnl_dd/t_dd_tritmp.h"
295
296 #define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
297 #define TAG(x) x##_offset_unfilled_fallback
298 #include "tnl_dd/t_dd_tritmp.h"
299
300 #define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
301 #define TAG(x) x##_twoside_unfilled_fallback
302 #include "tnl_dd/t_dd_tritmp.h"
303
304 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT| \
305              R128_FALLBACK_BIT)
306 #define TAG(x) x##_twoside_offset_unfilled_fallback
307 #include "tnl_dd/t_dd_tritmp.h"
308
309
310 static void init_rast_tab( void )
311 {
312    init();
313    init_offset();
314    init_twoside();
315    init_twoside_offset();
316    init_unfilled();
317    init_offset_unfilled();
318    init_twoside_unfilled();
319    init_twoside_offset_unfilled();
320    init_fallback();
321    init_offset_fallback();
322    init_twoside_fallback();
323    init_twoside_offset_fallback();
324    init_unfilled_fallback();
325    init_offset_unfilled_fallback();
326    init_twoside_unfilled_fallback();
327    init_twoside_offset_unfilled_fallback();
328 }
329
330
331
332 /***********************************************************************
333  *                    Rasterization fallback helpers                   *
334  ***********************************************************************/
335
336
337 /* This code is hit only when a mix of accelerated and unaccelerated
338  * primitives are being drawn, and only for the unaccelerated
339  * primitives.
340  */
341 static void
342 r128_fallback_tri( r128ContextPtr rmesa,
343                      r128Vertex *v0,
344                      r128Vertex *v1,
345                      r128Vertex *v2 )
346 {
347    struct gl_context *ctx = rmesa->glCtx;
348    SWvertex v[3];
349    _swsetup_Translate( ctx, v0, &v[0] );
350    _swsetup_Translate( ctx, v1, &v[1] );
351    _swsetup_Translate( ctx, v2, &v[2] );
352    _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
353 }
354
355
356 static void
357 r128_fallback_line( r128ContextPtr rmesa,
358                     r128Vertex *v0,
359                     r128Vertex *v1 )
360 {
361    struct gl_context *ctx = rmesa->glCtx;
362    SWvertex v[2];
363    _swsetup_Translate( ctx, v0, &v[0] );
364    _swsetup_Translate( ctx, v1, &v[1] );
365    _swrast_Line( ctx, &v[0], &v[1] );
366 }
367
368
369 static void
370 r128_fallback_point( r128ContextPtr rmesa,
371                      r128Vertex *v0 )
372 {
373    struct gl_context *ctx = rmesa->glCtx;
374    SWvertex v[1];
375    _swsetup_Translate( ctx, v0, &v[0] );
376    _swrast_Point( ctx, &v[0] );
377 }
378
379
380
381 /**********************************************************************/
382 /*               Render unclipped begin/end objects                   */
383 /**********************************************************************/
384
385 #define RENDER_POINTS( start, count )           \
386    for ( ; start < count ; start++)             \
387       r128_point( rmesa, VERT(start) )
388 #define RENDER_LINE( v0, v1 ) \
389    r128_line( rmesa, VERT(v0), VERT(v1) )
390 #define RENDER_TRI( v0, v1, v2 )  \
391    r128_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
392 #define RENDER_QUAD( v0, v1, v2, v3 ) \
393    r128_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
394 #define INIT(x) do {                                    \
395    if (0) fprintf(stderr, "%s\n", __FUNCTION__);        \
396    r128RenderPrimitive( ctx, x );                       \
397 } while (0)
398 #undef LOCAL_VARS
399 #define LOCAL_VARS                                              \
400     r128ContextPtr rmesa = R128_CONTEXT(ctx);           \
401     const GLuint vertsize = rmesa->vertex_size;         \
402     const char *vertptr = (char *)rmesa->verts;         \
403     const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;       \
404     (void) elt;
405 #define RESET_STIPPLE
406 #define RESET_OCCLUSION
407 #define PRESERVE_VB_DEFS
408 #define ELT(x) (x)
409 #define TAG(x) r128_##x##_verts
410 #include "tnl/t_vb_rendertmp.h"
411 #undef ELT
412 #undef TAG
413 #define TAG(x) r128_##x##_elts
414 #define ELT(x) elt[x]
415 #include "tnl/t_vb_rendertmp.h"
416
417
418 /**********************************************************************/
419 /*                    Choose render functions                         */
420 /**********************************************************************/
421
422 #define POINT_FALLBACK (DD_POINT_SMOOTH)
423 #define LINE_FALLBACK (DD_LINE_STIPPLE)
424 #define TRI_FALLBACK (DD_TRI_SMOOTH)
425 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
426 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
427 #define _R128_NEW_RENDER_STATE (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)
428
429 void r128ChooseRenderState(struct gl_context *ctx)
430 {
431    r128ContextPtr rmesa = R128_CONTEXT(ctx);
432    GLuint flags = ctx->_TriangleCaps;
433    GLuint index = 0;
434
435    if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
436       rmesa->draw_point = r128_point;
437       rmesa->draw_line = r128_line;
438       rmesa->draw_tri = r128_triangle;
439
440       if (flags & ANY_RASTER_FLAGS) {
441          if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R128_TWOSIDE_BIT;
442          if (flags & DD_TRI_OFFSET)        index |= R128_OFFSET_BIT;
443          if (flags & DD_TRI_UNFILLED)      index |= R128_UNFILLED_BIT;
444       }
445
446       /* Hook in fallbacks for specific primitives.
447        */
448       if (flags & (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)) {
449          if (flags & POINT_FALLBACK) rmesa->draw_point = r128_fallback_point;
450          if (flags & LINE_FALLBACK)  rmesa->draw_line = r128_fallback_line;
451          if (flags & TRI_FALLBACK)   rmesa->draw_tri = r128_fallback_tri;
452          index |= R128_FALLBACK_BIT;
453       }
454    }
455
456    if (index != rmesa->RenderIndex) {
457       TNLcontext *tnl = TNL_CONTEXT(ctx);
458       tnl->Driver.Render.Points = rast_tab[index].points;
459       tnl->Driver.Render.Line = rast_tab[index].line;
460       tnl->Driver.Render.ClippedLine = rast_tab[index].line;
461       tnl->Driver.Render.Triangle = rast_tab[index].triangle;
462       tnl->Driver.Render.Quad = rast_tab[index].quad;
463
464       if (index == 0) {
465          tnl->Driver.Render.PrimTabVerts = r128_render_tab_verts;
466          tnl->Driver.Render.PrimTabElts = r128_render_tab_elts;
467          tnl->Driver.Render.ClippedPolygon = r128_fast_clipped_poly;
468       } else {
469          tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
470          tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
471          tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
472       }
473
474       rmesa->RenderIndex = index;
475    }
476 }
477
478 /**********************************************************************/
479 /*                 Validate state at pipeline start                   */
480 /**********************************************************************/
481
482 static void r128RunPipeline( struct gl_context *ctx )
483 {
484    r128ContextPtr rmesa = R128_CONTEXT(ctx);
485
486    if (rmesa->new_state || rmesa->NewGLState & _NEW_TEXTURE)
487       r128DDUpdateHWState( ctx );
488
489    if (!rmesa->Fallback && rmesa->NewGLState) {
490       if (rmesa->NewGLState & _R128_NEW_RENDER_STATE)
491          r128ChooseRenderState( ctx );
492
493       rmesa->NewGLState = 0;
494    }
495
496    _tnl_run_pipeline( ctx );
497 }
498
499 /**********************************************************************/
500 /*                 High level hooks for t_vb_render.c                 */
501 /**********************************************************************/
502
503 /* This is called when Mesa switches between rendering triangle
504  * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
505  * and lines, points and bitmaps.
506  *
507  * As the r128 uses triangles to render lines and points, it is
508  * necessary to turn off hardware culling when rendering these
509  * primitives.
510  */
511
512 static void r128RasterPrimitive( struct gl_context *ctx, GLuint hwprim )
513 {
514    r128ContextPtr rmesa = R128_CONTEXT(ctx);
515
516    rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE;
517
518    if ( ctx->Polygon.StippleFlag && hwprim == GL_TRIANGLES ) {
519       rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_32x32_MONO_FG_LA;
520    }
521    else {
522       rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_SOLID_COLOR;
523    }
524
525    rmesa->new_state |= R128_NEW_CONTEXT;
526    rmesa->dirty |= R128_UPLOAD_CONTEXT;
527
528    if (rmesa->hw_primitive != hwprim) {
529       FLUSH_BATCH( rmesa );
530       rmesa->hw_primitive = hwprim;
531    }
532 }
533
534 static void r128SetupAntialias( struct gl_context *ctx, GLenum prim )
535 {
536    r128ContextPtr rmesa = R128_CONTEXT(ctx);
537
538    GLuint currAA, wantAA;
539    
540    currAA = (rmesa->setup.pm4_vc_fpu_setup & R128_EDGE_ANTIALIAS) != 0;
541    if( prim >= GL_TRIANGLES )
542       wantAA = ctx->Polygon.SmoothFlag;
543    else if( prim >= GL_LINES )
544       wantAA = ctx->Line.SmoothFlag;
545    else
546       wantAA = 0;
547       
548    if( wantAA != currAA )
549    {
550      FLUSH_BATCH( rmesa );
551      rmesa->setup.pm4_vc_fpu_setup ^= R128_EDGE_ANTIALIAS;
552      rmesa->dirty |= R128_UPLOAD_SETUP;
553    }
554 }
555
556 static void r128RenderPrimitive( struct gl_context *ctx, GLenum prim )
557 {
558    r128ContextPtr rmesa = R128_CONTEXT(ctx);
559    GLuint hw = hw_prim[prim];
560    rmesa->render_primitive = prim;
561
562    r128SetupAntialias( ctx, prim );
563    
564    if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
565       return;
566    r128RasterPrimitive( ctx, hw );
567 }
568
569 #define EMIT_ATTR( ATTR, STYLE, VF, SIZE )                              \
570 do {                                                                    \
571    rmesa->vertex_attrs[rmesa->vertex_attr_count].attrib = (ATTR);       \
572    rmesa->vertex_attrs[rmesa->vertex_attr_count].format = (STYLE);      \
573    rmesa->vertex_attr_count++;                                          \
574    vc_frmt |= (VF);                                                     \
575    offset += (SIZE);                                                    \
576 } while (0)
577
578 #define EMIT_PAD( SIZE )                                                \
579 do {                                                                    \
580    rmesa->vertex_attrs[rmesa->vertex_attr_count].attrib = 0;            \
581    rmesa->vertex_attrs[rmesa->vertex_attr_count].format = EMIT_PAD;     \
582    rmesa->vertex_attrs[rmesa->vertex_attr_count].offset = (SIZE);       \
583    rmesa->vertex_attr_count++;                                          \
584    offset += (SIZE);                                                    \
585 } while (0)
586
587 static void r128RenderStart( struct gl_context *ctx )
588 {
589    r128ContextPtr rmesa = R128_CONTEXT(ctx);
590    TNLcontext *tnl = TNL_CONTEXT(ctx);
591    struct vertex_buffer *VB = &tnl->vb;
592    DECLARE_RENDERINPUTS(index_bitset);
593    GLuint vc_frmt = 0;
594    GLboolean fallback_projtex = GL_FALSE;
595    GLuint offset = 0;
596
597    RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
598
599    /* Important: */
600    VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
601    rmesa->vertex_attr_count = 0;
602    rmesa->specoffset = 0;
603
604    /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
605     * build up a hardware vertex.
606     */
607    if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ))
608       EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, R128_CCE_VC_FRMT_RHW, 4 );
609    else
610       EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 3 );
611
612    rmesa->coloroffset = offset;
613 #if MESA_LITTLE_ENDIAN 
614    EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA,
615       R128_CCE_VC_FRMT_DIFFUSE_ARGB, 4 );
616 #else
617    EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ARGB,
618       R128_CCE_VC_FRMT_DIFFUSE_ARGB, 4 );
619 #endif
620
621    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
622        RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
623 #if MESA_LITTLE_ENDIAN
624       if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
625          rmesa->specoffset = offset;
626          EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR,
627             R128_CCE_VC_FRMT_SPEC_FRGB, 3 );
628       } else 
629          EMIT_PAD( 3 );
630
631       if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
632          EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, R128_CCE_VC_FRMT_SPEC_FRGB,
633                     1 );
634       else
635          EMIT_PAD( 1 );
636 #else
637       if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
638          EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, R128_CCE_VC_FRMT_SPEC_FRGB,
639                     1 );
640       else
641          EMIT_PAD( 1 );
642
643       if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
644          rmesa->specoffset = offset;
645          EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB,
646             R128_CCE_VC_FRMT_SPEC_FRGB, 3 );
647       } else 
648          EMIT_PAD( 3 );
649 #endif
650    }
651
652    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(rmesa->tmu_source[0]) )) {
653       if ( VB->AttribPtr[_TNL_ATTRIB_TEX0 + rmesa->tmu_source[0]]->size > 2 )
654          fallback_projtex = GL_TRUE;
655       EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, R128_CCE_VC_FRMT_S_T, 8 );
656    }
657    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(rmesa->tmu_source[1]) )) {
658       if ( VB->AttribPtr[_TNL_ATTRIB_TEX0 + rmesa->tmu_source[1]]->size > 2 )
659          fallback_projtex = GL_TRUE;
660       EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, R128_CCE_VC_FRMT_S2_T2, 8 );
661    }
662
663    /* projective textures are not supported by the hardware */
664    FALLBACK( rmesa, R128_FALLBACK_PROJTEX, fallback_projtex );
665
666    /* Only need to change the vertex emit code if there has been a
667     * statechange to a TNL index.
668     */
669    if (!RENDERINPUTS_EQUAL( index_bitset, rmesa->tnl_state_bitset )) {
670       FLUSH_BATCH( rmesa );
671       rmesa->dirty |= R128_UPLOAD_CONTEXT;
672
673       rmesa->vertex_size = 
674          _tnl_install_attrs( ctx, 
675                              rmesa->vertex_attrs, 
676                              rmesa->vertex_attr_count,
677                              rmesa->hw_viewport, 0 );
678       rmesa->vertex_size >>= 2;
679
680       rmesa->vertex_format = vc_frmt;
681    }
682 }
683
684 static void r128RenderFinish( struct gl_context *ctx )
685 {
686    if (R128_CONTEXT(ctx)->RenderIndex & R128_FALLBACK_BIT)
687       _swrast_flush( ctx );
688 }
689
690
691 /**********************************************************************/
692 /*           Transition to/from hardware rasterization.               */
693 /**********************************************************************/
694
695 static const char * const fallbackStrings[] = {
696    "Texture mode",
697    "glDrawBuffer(GL_FRONT_AND_BACK)",
698    "glReadBuffer",
699    "glEnable(GL_STENCIL) without hw stencil buffer",
700    "glRenderMode(selection or feedback)",
701    "glLogicOp (mode != GL_COPY)",
702    "GL_SEPARATE_SPECULAR_COLOR",
703    "glBlendEquation(mode != ADD)",
704    "glBlendFunc",
705    "Projective texture",
706    "Rasterization disable",
707 };
708
709
710 static const char *getFallbackString(GLuint bit)
711 {
712    int i = 0;
713    while (bit > 1) {
714       i++;
715       bit >>= 1;
716    }
717    return fallbackStrings[i];
718 }
719
720 void r128Fallback( struct gl_context *ctx, GLuint bit, GLboolean mode )
721 {
722    TNLcontext *tnl = TNL_CONTEXT(ctx);
723    r128ContextPtr rmesa = R128_CONTEXT(ctx);
724    GLuint oldfallback = rmesa->Fallback;
725
726    if (mode) {
727       rmesa->Fallback |= bit;
728       if (oldfallback == 0) {
729          FLUSH_BATCH( rmesa );
730          _swsetup_Wakeup( ctx );
731          rmesa->RenderIndex = ~0;
732          if ( R128_DEBUG & DEBUG_VERBOSE_FALL ) {
733              fprintf(stderr, "R128 begin rasterization fallback: 0x%x %s\n",
734                      bit, getFallbackString(bit));
735          }
736       }
737    }
738    else {
739       rmesa->Fallback &= ~bit;
740       if (oldfallback == bit) {
741          _swrast_flush( ctx );
742          tnl->Driver.Render.Start = r128RenderStart;
743          tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
744          tnl->Driver.Render.Finish = r128RenderFinish;
745
746          tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
747          tnl->Driver.Render.CopyPV = _tnl_copy_pv;
748          tnl->Driver.Render.Interp = _tnl_interp;
749
750          _tnl_invalidate_vertex_state( ctx, ~0 );
751          _tnl_invalidate_vertices( ctx, ~0 );
752          _tnl_install_attrs( ctx, 
753                              rmesa->vertex_attrs, 
754                              rmesa->vertex_attr_count,
755                              rmesa->hw_viewport, 0 ); 
756
757          rmesa->NewGLState |= _R128_NEW_RENDER_STATE;
758          if ( R128_DEBUG & DEBUG_VERBOSE_FALL ) {
759              fprintf(stderr, "R128 end rasterization fallback: 0x%x %s\n",
760                      bit, getFallbackString(bit));
761          }
762       }
763    }
764 }
765
766
767 /**********************************************************************/
768 /*                            Initialization.                         */
769 /**********************************************************************/
770
771 void r128InitTriFuncs( struct gl_context *ctx )
772 {
773    r128ContextPtr rmesa = R128_CONTEXT(ctx);
774    TNLcontext *tnl = TNL_CONTEXT(ctx);
775    static int firsttime = 1;
776
777    if (firsttime) {
778       init_rast_tab();
779       firsttime = 0;
780    }
781
782    tnl->Driver.RunPipeline = r128RunPipeline;
783    tnl->Driver.Render.Start = r128RenderStart;
784    tnl->Driver.Render.Finish = r128RenderFinish;
785    tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
786    tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
787    tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
788    tnl->Driver.Render.CopyPV = _tnl_copy_pv;
789    tnl->Driver.Render.Interp = _tnl_interp;
790
791    _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, 
792                        (6 + 2 * ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
793    rmesa->verts = (char *)tnl->clipspace.vertex_buf;
794    RENDERINPUTS_ONES( rmesa->tnl_state_bitset );
795
796    rmesa->NewGLState |= _R128_NEW_RENDER_STATE;
797 }