Merge branch 'mesa_7_7_branch'
[mesa.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( GLcontext *ctx, GLuint hwprim );
66 static void r128RenderPrimitive( GLcontext *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_RGBA 1
162 #define HAVE_SPEC 1
163 #define HAVE_BACK_COLORS 0
164 #define HAVE_HW_FLATSHADE 1
165 #define VERTEX r128Vertex
166 #define TAB rast_tab
167
168 #define DEPTH_SCALE rmesa->depth_scale
169 #define UNFILLED_TRI unfilled_tri
170 #define UNFILLED_QUAD unfilled_quad
171 #define VERT_X(_v) _v->v.x
172 #define VERT_Y(_v) _v->v.y
173 #define VERT_Z(_v) _v->v.z
174 #define AREA_IS_CCW( a ) (a > 0)
175 #define GET_VERTEX(e) (rmesa->verts + (e * rmesa->vertex_size * sizeof(int)))
176
177 #define VERT_SET_RGBA( v, c ) \
178 do { \
179 r128_color_t *color = (r128_color_t *)&((v)->ui[coloroffset]); \
180 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
181 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
182 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
183 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
184 } while (0)
185
186 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
187
188 #define VERT_SET_SPEC( v0, c ) \
189 do { \
190 if (havespec) { \
191 r128_color_t *spec = (r128_color_t *)&((v0)->ui[specoffset]); \
192 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
193 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
194 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
195 } \
196 } while (0)
197 #define VERT_COPY_SPEC( v0, v1 ) \
198 do { \
199 if (havespec) { \
200 r128_color_t *spec0 = (r128_color_t *)&((v0)->ui[specoffset]); \
201 r128_color_t *spec1 = (r128_color_t *)&((v1)->ui[specoffset]); \
202 spec0->red = spec1->red; \
203 spec0->green = spec1->green; \
204 spec0->blue = spec1->blue; \
205 } \
206 } while (0)
207
208 /* These don't need LE32_TO_CPU() as they are used to save and restore
209 * colors which are already in the correct format.
210 */
211 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
212 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
213 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[specoffset]
214 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[specoffset] = spec[idx]
215
216
217 #define LOCAL_VARS(n) \
218 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
219 GLuint color[n] = { 0 }; \
220 GLuint spec[n] = { 0 }; \
221 GLuint coloroffset = rmesa->coloroffset; \
222 GLuint specoffset = rmesa->specoffset; \
223 GLboolean havespec = (rmesa->specoffset != 0); \
224 (void) color; (void) spec; (void) specoffset; \
225 (void) coloroffset; (void) havespec;
226
227 /***********************************************************************
228 * Helpers for rendering unfilled primitives *
229 ***********************************************************************/
230
231 #define RASTERIZE(x) if (rmesa->hw_primitive != hw_prim[x]) \
232 r128RasterPrimitive( ctx, hw_prim[x] )
233 #define RENDER_PRIMITIVE rmesa->render_primitive
234 #define IND R128_FALLBACK_BIT
235 #define TAG(x) x
236 #include "tnl_dd/t_dd_unfilled.h"
237 #undef IND
238
239
240 /***********************************************************************
241 * Generate GL render functions *
242 ***********************************************************************/
243
244
245 #define IND (0)
246 #define TAG(x) x
247 #include "tnl_dd/t_dd_tritmp.h"
248
249 #define IND (R128_OFFSET_BIT)
250 #define TAG(x) x##_offset
251 #include "tnl_dd/t_dd_tritmp.h"
252
253 #define IND (R128_TWOSIDE_BIT)
254 #define TAG(x) x##_twoside
255 #include "tnl_dd/t_dd_tritmp.h"
256
257 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT)
258 #define TAG(x) x##_twoside_offset
259 #include "tnl_dd/t_dd_tritmp.h"
260
261 #define IND (R128_UNFILLED_BIT)
262 #define TAG(x) x##_unfilled
263 #include "tnl_dd/t_dd_tritmp.h"
264
265 #define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT)
266 #define TAG(x) x##_offset_unfilled
267 #include "tnl_dd/t_dd_tritmp.h"
268
269 #define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT)
270 #define TAG(x) x##_twoside_unfilled
271 #include "tnl_dd/t_dd_tritmp.h"
272
273 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT)
274 #define TAG(x) x##_twoside_offset_unfilled
275 #include "tnl_dd/t_dd_tritmp.h"
276
277 #define IND (R128_FALLBACK_BIT)
278 #define TAG(x) x##_fallback
279 #include "tnl_dd/t_dd_tritmp.h"
280
281 #define IND (R128_OFFSET_BIT|R128_FALLBACK_BIT)
282 #define TAG(x) x##_offset_fallback
283 #include "tnl_dd/t_dd_tritmp.h"
284
285 #define IND (R128_TWOSIDE_BIT|R128_FALLBACK_BIT)
286 #define TAG(x) x##_twoside_fallback
287 #include "tnl_dd/t_dd_tritmp.h"
288
289 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_FALLBACK_BIT)
290 #define TAG(x) x##_twoside_offset_fallback
291 #include "tnl_dd/t_dd_tritmp.h"
292
293 #define IND (R128_UNFILLED_BIT|R128_FALLBACK_BIT)
294 #define TAG(x) x##_unfilled_fallback
295 #include "tnl_dd/t_dd_tritmp.h"
296
297 #define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
298 #define TAG(x) x##_offset_unfilled_fallback
299 #include "tnl_dd/t_dd_tritmp.h"
300
301 #define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
302 #define TAG(x) x##_twoside_unfilled_fallback
303 #include "tnl_dd/t_dd_tritmp.h"
304
305 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT| \
306 R128_FALLBACK_BIT)
307 #define TAG(x) x##_twoside_offset_unfilled_fallback
308 #include "tnl_dd/t_dd_tritmp.h"
309
310
311 static void init_rast_tab( void )
312 {
313 init();
314 init_offset();
315 init_twoside();
316 init_twoside_offset();
317 init_unfilled();
318 init_offset_unfilled();
319 init_twoside_unfilled();
320 init_twoside_offset_unfilled();
321 init_fallback();
322 init_offset_fallback();
323 init_twoside_fallback();
324 init_twoside_offset_fallback();
325 init_unfilled_fallback();
326 init_offset_unfilled_fallback();
327 init_twoside_unfilled_fallback();
328 init_twoside_offset_unfilled_fallback();
329 }
330
331
332
333 /***********************************************************************
334 * Rasterization fallback helpers *
335 ***********************************************************************/
336
337
338 /* This code is hit only when a mix of accelerated and unaccelerated
339 * primitives are being drawn, and only for the unaccelerated
340 * primitives.
341 */
342 static void
343 r128_fallback_tri( r128ContextPtr rmesa,
344 r128Vertex *v0,
345 r128Vertex *v1,
346 r128Vertex *v2 )
347 {
348 GLcontext *ctx = rmesa->glCtx;
349 SWvertex v[3];
350 _swsetup_Translate( ctx, v0, &v[0] );
351 _swsetup_Translate( ctx, v1, &v[1] );
352 _swsetup_Translate( ctx, v2, &v[2] );
353 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
354 }
355
356
357 static void
358 r128_fallback_line( r128ContextPtr rmesa,
359 r128Vertex *v0,
360 r128Vertex *v1 )
361 {
362 GLcontext *ctx = rmesa->glCtx;
363 SWvertex v[2];
364 _swsetup_Translate( ctx, v0, &v[0] );
365 _swsetup_Translate( ctx, v1, &v[1] );
366 _swrast_Line( ctx, &v[0], &v[1] );
367 }
368
369
370 static void
371 r128_fallback_point( r128ContextPtr rmesa,
372 r128Vertex *v0 )
373 {
374 GLcontext *ctx = rmesa->glCtx;
375 SWvertex v[1];
376 _swsetup_Translate( ctx, v0, &v[0] );
377 _swrast_Point( ctx, &v[0] );
378 }
379
380
381
382 /**********************************************************************/
383 /* Render unclipped begin/end objects */
384 /**********************************************************************/
385
386 #define RENDER_POINTS( start, count ) \
387 for ( ; start < count ; start++) \
388 r128_point( rmesa, VERT(start) )
389 #define RENDER_LINE( v0, v1 ) \
390 r128_line( rmesa, VERT(v0), VERT(v1) )
391 #define RENDER_TRI( v0, v1, v2 ) \
392 r128_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
393 #define RENDER_QUAD( v0, v1, v2, v3 ) \
394 r128_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
395 #define INIT(x) do { \
396 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
397 r128RenderPrimitive( ctx, x ); \
398 } while (0)
399 #undef LOCAL_VARS
400 #define LOCAL_VARS \
401 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
402 const GLuint vertsize = rmesa->vertex_size; \
403 const char *vertptr = (char *)rmesa->verts; \
404 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
405 (void) elt;
406 #define RESET_STIPPLE
407 #define RESET_OCCLUSION
408 #define PRESERVE_VB_DEFS
409 #define ELT(x) (x)
410 #define TAG(x) r128_##x##_verts
411 #include "tnl/t_vb_rendertmp.h"
412 #undef ELT
413 #undef TAG
414 #define TAG(x) r128_##x##_elts
415 #define ELT(x) elt[x]
416 #include "tnl/t_vb_rendertmp.h"
417
418
419 /**********************************************************************/
420 /* Choose render functions */
421 /**********************************************************************/
422
423 #define POINT_FALLBACK (DD_POINT_SMOOTH)
424 #define LINE_FALLBACK (DD_LINE_STIPPLE)
425 #define TRI_FALLBACK (DD_TRI_SMOOTH)
426 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
427 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
428 #define _R128_NEW_RENDER_STATE (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)
429
430 void r128ChooseRenderState(GLcontext *ctx)
431 {
432 r128ContextPtr rmesa = R128_CONTEXT(ctx);
433 GLuint flags = ctx->_TriangleCaps;
434 GLuint index = 0;
435
436 if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
437 rmesa->draw_point = r128_point;
438 rmesa->draw_line = r128_line;
439 rmesa->draw_tri = r128_triangle;
440
441 if (flags & ANY_RASTER_FLAGS) {
442 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R128_TWOSIDE_BIT;
443 if (flags & DD_TRI_OFFSET) index |= R128_OFFSET_BIT;
444 if (flags & DD_TRI_UNFILLED) index |= R128_UNFILLED_BIT;
445 }
446
447 /* Hook in fallbacks for specific primitives.
448 */
449 if (flags & (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)) {
450 if (flags & POINT_FALLBACK) rmesa->draw_point = r128_fallback_point;
451 if (flags & LINE_FALLBACK) rmesa->draw_line = r128_fallback_line;
452 if (flags & TRI_FALLBACK) rmesa->draw_tri = r128_fallback_tri;
453 index |= R128_FALLBACK_BIT;
454 }
455 }
456
457 if (index != rmesa->RenderIndex) {
458 TNLcontext *tnl = TNL_CONTEXT(ctx);
459 tnl->Driver.Render.Points = rast_tab[index].points;
460 tnl->Driver.Render.Line = rast_tab[index].line;
461 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
462 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
463 tnl->Driver.Render.Quad = rast_tab[index].quad;
464
465 if (index == 0) {
466 tnl->Driver.Render.PrimTabVerts = r128_render_tab_verts;
467 tnl->Driver.Render.PrimTabElts = r128_render_tab_elts;
468 tnl->Driver.Render.ClippedPolygon = r128_fast_clipped_poly;
469 } else {
470 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
471 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
472 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
473 }
474
475 rmesa->RenderIndex = index;
476 }
477 }
478
479 /**********************************************************************/
480 /* Validate state at pipeline start */
481 /**********************************************************************/
482
483 static void r128RunPipeline( GLcontext *ctx )
484 {
485 r128ContextPtr rmesa = R128_CONTEXT(ctx);
486
487 if (rmesa->new_state || rmesa->NewGLState & _NEW_TEXTURE)
488 r128DDUpdateHWState( ctx );
489
490 if (!rmesa->Fallback && rmesa->NewGLState) {
491 if (rmesa->NewGLState & _R128_NEW_RENDER_STATE)
492 r128ChooseRenderState( ctx );
493
494 rmesa->NewGLState = 0;
495 }
496
497 _tnl_run_pipeline( ctx );
498 }
499
500 /**********************************************************************/
501 /* High level hooks for t_vb_render.c */
502 /**********************************************************************/
503
504 /* This is called when Mesa switches between rendering triangle
505 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
506 * and lines, points and bitmaps.
507 *
508 * As the r128 uses triangles to render lines and points, it is
509 * necessary to turn off hardware culling when rendering these
510 * primitives.
511 */
512
513 static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim )
514 {
515 r128ContextPtr rmesa = R128_CONTEXT(ctx);
516
517 rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE;
518
519 if ( ctx->Polygon.StippleFlag && hwprim == GL_TRIANGLES ) {
520 rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_32x32_MONO_FG_LA;
521 }
522 else {
523 rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_SOLID_COLOR;
524 }
525
526 rmesa->new_state |= R128_NEW_CONTEXT;
527 rmesa->dirty |= R128_UPLOAD_CONTEXT;
528
529 if (rmesa->hw_primitive != hwprim) {
530 FLUSH_BATCH( rmesa );
531 rmesa->hw_primitive = hwprim;
532 }
533 }
534
535 static void r128SetupAntialias( GLcontext *ctx, GLenum prim )
536 {
537 r128ContextPtr rmesa = R128_CONTEXT(ctx);
538
539 GLuint currAA, wantAA;
540
541 currAA = (rmesa->setup.pm4_vc_fpu_setup & R128_EDGE_ANTIALIAS) != 0;
542 if( prim >= GL_TRIANGLES )
543 wantAA = ctx->Polygon.SmoothFlag;
544 else if( prim >= GL_LINES )
545 wantAA = ctx->Line.SmoothFlag;
546 else
547 wantAA = 0;
548
549 if( wantAA != currAA )
550 {
551 FLUSH_BATCH( rmesa );
552 rmesa->setup.pm4_vc_fpu_setup ^= R128_EDGE_ANTIALIAS;
553 rmesa->dirty |= R128_UPLOAD_SETUP;
554 }
555 }
556
557 static void r128RenderPrimitive( GLcontext *ctx, GLenum prim )
558 {
559 r128ContextPtr rmesa = R128_CONTEXT(ctx);
560 GLuint hw = hw_prim[prim];
561 rmesa->render_primitive = prim;
562
563 r128SetupAntialias( ctx, prim );
564
565 if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
566 return;
567 r128RasterPrimitive( ctx, hw );
568 }
569
570 #define EMIT_ATTR( ATTR, STYLE, VF, SIZE ) \
571 do { \
572 rmesa->vertex_attrs[rmesa->vertex_attr_count].attrib = (ATTR); \
573 rmesa->vertex_attrs[rmesa->vertex_attr_count].format = (STYLE); \
574 rmesa->vertex_attr_count++; \
575 vc_frmt |= (VF); \
576 offset += (SIZE); \
577 } while (0)
578
579 #define EMIT_PAD( SIZE ) \
580 do { \
581 rmesa->vertex_attrs[rmesa->vertex_attr_count].attrib = 0; \
582 rmesa->vertex_attrs[rmesa->vertex_attr_count].format = EMIT_PAD; \
583 rmesa->vertex_attrs[rmesa->vertex_attr_count].offset = (SIZE); \
584 rmesa->vertex_attr_count++; \
585 offset += (SIZE); \
586 } while (0)
587
588 static void r128RenderStart( GLcontext *ctx )
589 {
590 r128ContextPtr rmesa = R128_CONTEXT(ctx);
591 TNLcontext *tnl = TNL_CONTEXT(ctx);
592 struct vertex_buffer *VB = &tnl->vb;
593 DECLARE_RENDERINPUTS(index_bitset);
594 GLuint vc_frmt = 0;
595 GLboolean fallback_projtex = GL_FALSE;
596 GLuint offset = 0;
597
598 RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
599
600 /* Important: */
601 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
602 rmesa->vertex_attr_count = 0;
603 rmesa->specoffset = 0;
604
605 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
606 * build up a hardware vertex.
607 */
608 if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ))
609 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, R128_CCE_VC_FRMT_RHW, 4 );
610 else
611 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 3 );
612
613 rmesa->coloroffset = offset;
614 #if MESA_LITTLE_ENDIAN
615 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA,
616 R128_CCE_VC_FRMT_DIFFUSE_ARGB, 4 );
617 #else
618 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ARGB,
619 R128_CCE_VC_FRMT_DIFFUSE_ARGB, 4 );
620 #endif
621
622 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
623 RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
624 #if MESA_LITTLE_ENDIAN
625 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
626 rmesa->specoffset = offset;
627 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR,
628 R128_CCE_VC_FRMT_SPEC_FRGB, 3 );
629 } else
630 EMIT_PAD( 3 );
631
632 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
633 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, R128_CCE_VC_FRMT_SPEC_FRGB,
634 1 );
635 else
636 EMIT_PAD( 1 );
637 #else
638 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
639 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, R128_CCE_VC_FRMT_SPEC_FRGB,
640 1 );
641 else
642 EMIT_PAD( 1 );
643
644 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
645 rmesa->specoffset = offset;
646 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB,
647 R128_CCE_VC_FRMT_SPEC_FRGB, 3 );
648 } else
649 EMIT_PAD( 3 );
650 #endif
651 }
652
653 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(rmesa->tmu_source[0]) )) {
654 if ( VB->AttribPtr[_TNL_ATTRIB_TEX0 + rmesa->tmu_source[0]]->size > 2 )
655 fallback_projtex = GL_TRUE;
656 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, R128_CCE_VC_FRMT_S_T, 8 );
657 }
658 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(rmesa->tmu_source[1]) )) {
659 if ( VB->AttribPtr[_TNL_ATTRIB_TEX0 + rmesa->tmu_source[1]]->size > 2 )
660 fallback_projtex = GL_TRUE;
661 EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, R128_CCE_VC_FRMT_S2_T2, 8 );
662 }
663
664 /* projective textures are not supported by the hardware */
665 FALLBACK( rmesa, R128_FALLBACK_PROJTEX, fallback_projtex );
666
667 /* Only need to change the vertex emit code if there has been a
668 * statechange to a TNL index.
669 */
670 if (!RENDERINPUTS_EQUAL( index_bitset, rmesa->tnl_state_bitset )) {
671 FLUSH_BATCH( rmesa );
672 rmesa->dirty |= R128_UPLOAD_CONTEXT;
673
674 rmesa->vertex_size =
675 _tnl_install_attrs( ctx,
676 rmesa->vertex_attrs,
677 rmesa->vertex_attr_count,
678 rmesa->hw_viewport, 0 );
679 rmesa->vertex_size >>= 2;
680
681 rmesa->vertex_format = vc_frmt;
682 }
683 }
684
685 static void r128RenderFinish( GLcontext *ctx )
686 {
687 if (R128_CONTEXT(ctx)->RenderIndex & R128_FALLBACK_BIT)
688 _swrast_flush( ctx );
689 }
690
691
692 /**********************************************************************/
693 /* Transition to/from hardware rasterization. */
694 /**********************************************************************/
695
696 static const char * const fallbackStrings[] = {
697 "Texture mode",
698 "glDrawBuffer(GL_FRONT_AND_BACK)",
699 "glReadBuffer",
700 "glEnable(GL_STENCIL) without hw stencil buffer",
701 "glRenderMode(selection or feedback)",
702 "glLogicOp (mode != GL_COPY)",
703 "GL_SEPARATE_SPECULAR_COLOR",
704 "glBlendEquation(mode != ADD)",
705 "glBlendFunc",
706 "Projective texture",
707 "Rasterization disable",
708 };
709
710
711 static const char *getFallbackString(GLuint bit)
712 {
713 int i = 0;
714 while (bit > 1) {
715 i++;
716 bit >>= 1;
717 }
718 return fallbackStrings[i];
719 }
720
721 void r128Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
722 {
723 TNLcontext *tnl = TNL_CONTEXT(ctx);
724 r128ContextPtr rmesa = R128_CONTEXT(ctx);
725 GLuint oldfallback = rmesa->Fallback;
726
727 if (mode) {
728 rmesa->Fallback |= bit;
729 if (oldfallback == 0) {
730 FLUSH_BATCH( rmesa );
731 _swsetup_Wakeup( ctx );
732 rmesa->RenderIndex = ~0;
733 if ( R128_DEBUG & DEBUG_VERBOSE_FALL ) {
734 fprintf(stderr, "R128 begin rasterization fallback: 0x%x %s\n",
735 bit, getFallbackString(bit));
736 }
737 }
738 }
739 else {
740 rmesa->Fallback &= ~bit;
741 if (oldfallback == bit) {
742 _swrast_flush( ctx );
743 tnl->Driver.Render.Start = r128RenderStart;
744 tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
745 tnl->Driver.Render.Finish = r128RenderFinish;
746
747 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
748 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
749 tnl->Driver.Render.Interp = _tnl_interp;
750
751 _tnl_invalidate_vertex_state( ctx, ~0 );
752 _tnl_invalidate_vertices( ctx, ~0 );
753 _tnl_install_attrs( ctx,
754 rmesa->vertex_attrs,
755 rmesa->vertex_attr_count,
756 rmesa->hw_viewport, 0 );
757
758 rmesa->NewGLState |= _R128_NEW_RENDER_STATE;
759 if ( R128_DEBUG & DEBUG_VERBOSE_FALL ) {
760 fprintf(stderr, "R128 end rasterization fallback: 0x%x %s\n",
761 bit, getFallbackString(bit));
762 }
763 }
764 }
765 }
766
767
768 /**********************************************************************/
769 /* Initialization. */
770 /**********************************************************************/
771
772 void r128InitTriFuncs( GLcontext *ctx )
773 {
774 r128ContextPtr rmesa = R128_CONTEXT(ctx);
775 TNLcontext *tnl = TNL_CONTEXT(ctx);
776 static int firsttime = 1;
777
778 if (firsttime) {
779 init_rast_tab();
780 firsttime = 0;
781 }
782
783 tnl->Driver.RunPipeline = r128RunPipeline;
784 tnl->Driver.Render.Start = r128RenderStart;
785 tnl->Driver.Render.Finish = r128RenderFinish;
786 tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
787 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
788 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
789 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
790 tnl->Driver.Render.Interp = _tnl_interp;
791
792 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
793 (6 + 2 * ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
794 rmesa->verts = (char *)tnl->clipspace.vertex_buf;
795 RENDERINPUTS_ONES( rmesa->tnl_state_bitset );
796
797 rmesa->NewGLState |= _R128_NEW_RENDER_STATE;
798 }