Small optimization for big-endian (e.g., PowerPC) systems.
[mesa.git] / src / mesa / drivers / dri / r128 / r128_tris.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tris.c,v 1.8 2002/10/30 12:51:43 alanh Exp $ */ /* -*- 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 "glheader.h"
37 #include "mtypes.h"
38 #include "colormac.h"
39 #include "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 CTX_ARG2 rmesa
79 #define GET_VERTEX_DWORDS() rmesa->vertex_size
80 #define ALLOC_VERTS( n, size ) r128AllocDmaLow( rmesa, (n), (size) * 4 )
81 #undef LOCAL_VARS
82 #define LOCAL_VARS \
83 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
84 const char *vertptr = rmesa->verts;
85 #define VERT(x) (r128Vertex *)(vertptr + ((x) * vertsize * 4))
86 #define VERTEX r128Vertex
87 #undef TAG
88 #define TAG(x) r128_##x
89 #include "tnl_dd/t_dd_triemit.h"
90 #undef TAG
91 #undef LOCAL_VARS
92
93
94 /***********************************************************************
95 * Macros for t_dd_tritmp.h to draw basic primitives *
96 ***********************************************************************/
97
98 #define TRI( a, b, c ) \
99 do { \
100 if (DO_FALLBACK) \
101 rmesa->draw_tri( rmesa, a, b, c ); \
102 else \
103 r128_triangle( rmesa, a, b, c ); \
104 } while (0)
105
106 #define QUAD( a, b, c, d ) \
107 do { \
108 if (DO_FALLBACK) { \
109 rmesa->draw_tri( rmesa, a, b, d ); \
110 rmesa->draw_tri( rmesa, b, c, d ); \
111 } else \
112 r128_quad( rmesa, a, b, c, d ); \
113 } while (0)
114
115 #define LINE( v0, v1 ) \
116 do { \
117 if (DO_FALLBACK) \
118 rmesa->draw_line( rmesa, v0, v1 ); \
119 else \
120 r128_line( rmesa, v0, v1 ); \
121 } while (0)
122
123 #define POINT( v0 ) \
124 do { \
125 if (DO_FALLBACK) \
126 rmesa->draw_point( rmesa, v0 ); \
127 else \
128 r128_point( rmesa, v0 ); \
129 } while (0)
130
131
132 /***********************************************************************
133 * Build render functions from dd templates *
134 ***********************************************************************/
135
136 #define R128_OFFSET_BIT 0x01
137 #define R128_TWOSIDE_BIT 0x02
138 #define R128_UNFILLED_BIT 0x04
139 #define R128_FALLBACK_BIT 0x08
140 #define R128_MAX_TRIFUNC 0x10
141
142
143 static struct {
144 tnl_points_func points;
145 tnl_line_func line;
146 tnl_triangle_func triangle;
147 tnl_quad_func quad;
148 } rast_tab[R128_MAX_TRIFUNC];
149
150
151 #define DO_FALLBACK (IND & R128_FALLBACK_BIT)
152 #define DO_OFFSET (IND & R128_OFFSET_BIT)
153 #define DO_UNFILLED (IND & R128_UNFILLED_BIT)
154 #define DO_TWOSIDE (IND & R128_TWOSIDE_BIT)
155 #define DO_FLAT 0
156 #define DO_TRI 1
157 #define DO_QUAD 1
158 #define DO_LINE 1
159 #define DO_POINTS 1
160 #define DO_FULL_QUAD 1
161
162 #define HAVE_RGBA 1
163 #define HAVE_SPEC 1
164 #define HAVE_BACK_COLORS 0
165 #define HAVE_HW_FLATSHADE 1
166 #define VERTEX r128Vertex
167 #define TAB rast_tab
168
169 #define DEPTH_SCALE rmesa->depth_scale
170 #define UNFILLED_TRI unfilled_tri
171 #define UNFILLED_QUAD unfilled_quad
172 #define VERT_X(_v) _v->v.x
173 #define VERT_Y(_v) _v->v.y
174 #define VERT_Z(_v) _v->v.z
175 #define AREA_IS_CCW( a ) (a > 0)
176 #define GET_VERTEX(e) (rmesa->verts + (e * rmesa->vertex_size * sizeof(int)))
177
178 #define VERT_SET_RGBA( v, c ) \
179 do { \
180 r128_color_t *color = (r128_color_t *)&((v)->ui[coloroffset]); \
181 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
182 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
183 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
184 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
185 } while (0)
186
187 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
188
189 #define VERT_SET_SPEC( v0, c ) \
190 do { \
191 if (havespec) { \
192 r128_color_t *spec = (r128_color_t *)&((v0)->ui[specoffset]); \
193 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
194 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
195 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
196 } \
197 } while (0)
198 #define VERT_COPY_SPEC( v0, v1 ) \
199 do { \
200 if (havespec) { \
201 r128_color_t *spec0 = (r128_color_t *)&((v0)->ui[specoffset]); \
202 r128_color_t *spec1 = (r128_color_t *)&((v1)->ui[specoffset]); \
203 spec0->red = spec1->red; \
204 spec0->green = spec1->green; \
205 spec0->blue = spec1->blue; \
206 } \
207 } while (0)
208
209 /* These don't need LE32_TO_CPU() as they are used to save and restore
210 * colors which are already in the correct format.
211 */
212 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
213 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
214 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[specoffset]
215 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[specoffset] = spec[idx]
216
217
218 #define LOCAL_VARS(n) \
219 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
220 GLuint color[n], spec[n]; \
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 /* XXX: SpanRenderStart */
354 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
355 }
356
357
358 static void
359 r128_fallback_line( r128ContextPtr rmesa,
360 r128Vertex *v0,
361 r128Vertex *v1 )
362 {
363 GLcontext *ctx = rmesa->glCtx;
364 SWvertex v[2];
365 _swsetup_Translate( ctx, v0, &v[0] );
366 _swsetup_Translate( ctx, v1, &v[1] );
367 _swrast_Line( ctx, &v[0], &v[1] );
368 }
369
370
371 static void
372 r128_fallback_point( r128ContextPtr rmesa,
373 r128Vertex *v0 )
374 {
375 GLcontext *ctx = rmesa->glCtx;
376 SWvertex v[1];
377 _swsetup_Translate( ctx, v0, &v[0] );
378 _swrast_Point( ctx, &v[0] );
379 }
380
381
382
383 /**********************************************************************/
384 /* Render unclipped begin/end objects */
385 /**********************************************************************/
386
387 #define RENDER_POINTS( start, count ) \
388 for ( ; start < count ; start++) \
389 r128_point( rmesa, VERT(start) )
390 #define RENDER_LINE( v0, v1 ) \
391 r128_line( rmesa, VERT(v0), VERT(v1) )
392 #define RENDER_TRI( v0, v1, v2 ) \
393 r128_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
394 #define RENDER_QUAD( v0, v1, v2, v3 ) \
395 r128_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
396 #define INIT(x) do { \
397 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
398 r128RenderPrimitive( ctx, x ); \
399 } while (0)
400 #undef LOCAL_VARS
401 #define LOCAL_VARS \
402 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
403 const GLuint vertsize = rmesa->vertex_size; \
404 const char *vertptr = (char *)rmesa->verts; \
405 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
406 (void) elt;
407 #define RESET_STIPPLE
408 #define RESET_OCCLUSION
409 #define PRESERVE_VB_DEFS
410 #define ELT(x) (x)
411 #define TAG(x) r128_##x##_verts
412 #include "tnl/t_vb_rendertmp.h"
413 #undef ELT
414 #undef TAG
415 #define TAG(x) r128_##x##_elts
416 #define ELT(x) elt[x]
417 #include "tnl/t_vb_rendertmp.h"
418
419
420 /**********************************************************************/
421 /* Choose render functions */
422 /**********************************************************************/
423
424 #define POINT_FALLBACK (DD_POINT_SMOOTH)
425 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
426 #define TRI_FALLBACK (DD_TRI_SMOOTH)
427 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
428 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
429 #define _R128_NEW_RENDER_STATE (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)
430
431 static void r128ChooseRenderState(GLcontext *ctx)
432 {
433 r128ContextPtr rmesa = R128_CONTEXT(ctx);
434 GLuint flags = ctx->_TriangleCaps;
435 GLuint index = 0;
436
437 if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
438 rmesa->draw_point = r128_point;
439 rmesa->draw_line = r128_line;
440 rmesa->draw_tri = r128_triangle;
441
442 if (flags & ANY_RASTER_FLAGS) {
443 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R128_TWOSIDE_BIT;
444 if (flags & DD_TRI_OFFSET) index |= R128_OFFSET_BIT;
445 if (flags & DD_TRI_UNFILLED) index |= R128_UNFILLED_BIT;
446 }
447
448 /* Hook in fallbacks for specific primitives.
449 */
450 if (flags & (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)) {
451 if (flags & POINT_FALLBACK) rmesa->draw_point = r128_fallback_point;
452 if (flags & LINE_FALLBACK) rmesa->draw_line = r128_fallback_line;
453 if (flags & TRI_FALLBACK) rmesa->draw_tri = r128_fallback_tri;
454 index |= R128_FALLBACK_BIT;
455 }
456 }
457
458 if (index != rmesa->RenderIndex) {
459 TNLcontext *tnl = TNL_CONTEXT(ctx);
460 tnl->Driver.Render.Points = rast_tab[index].points;
461 tnl->Driver.Render.Line = rast_tab[index].line;
462 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
463 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
464 tnl->Driver.Render.Quad = rast_tab[index].quad;
465
466 if (index == 0) {
467 tnl->Driver.Render.PrimTabVerts = r128_render_tab_verts;
468 tnl->Driver.Render.PrimTabElts = r128_render_tab_elts;
469 tnl->Driver.Render.ClippedPolygon = r128_fast_clipped_poly;
470 } else {
471 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
472 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
473 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
474 }
475
476 rmesa->RenderIndex = index;
477 }
478 }
479
480 /**********************************************************************/
481 /* Validate state at pipeline start */
482 /**********************************************************************/
483
484 static void r128RunPipeline( GLcontext *ctx )
485 {
486 r128ContextPtr rmesa = R128_CONTEXT(ctx);
487
488 if (rmesa->new_state || rmesa->NewGLState & _NEW_TEXTURE)
489 r128DDUpdateHWState( ctx );
490
491 if (!rmesa->Fallback && rmesa->NewGLState) {
492 if (rmesa->NewGLState & _R128_NEW_RENDER_STATE)
493 r128ChooseRenderState( ctx );
494
495 rmesa->NewGLState = 0;
496 }
497
498 _tnl_run_pipeline( ctx );
499 }
500
501 /**********************************************************************/
502 /* High level hooks for t_vb_render.c */
503 /**********************************************************************/
504
505 /* This is called when Mesa switches between rendering triangle
506 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
507 * and lines, points and bitmaps.
508 *
509 * As the r128 uses triangles to render lines and points, it is
510 * necessary to turn off hardware culling when rendering these
511 * primitives.
512 */
513
514 static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim )
515 {
516 r128ContextPtr rmesa = R128_CONTEXT(ctx);
517
518 rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE;
519
520 if ( ctx->Polygon.StippleFlag && hwprim == GL_TRIANGLES ) {
521 rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_32x32_MONO_FG_LA;
522 }
523 else {
524 rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_SOLID_COLOR;
525 }
526
527 rmesa->new_state |= R128_NEW_CONTEXT;
528 rmesa->dirty |= R128_UPLOAD_CONTEXT;
529
530 if (rmesa->hw_primitive != hwprim) {
531 FLUSH_BATCH( rmesa );
532 rmesa->hw_primitive = hwprim;
533 }
534 }
535
536 static void r128RenderPrimitive( GLcontext *ctx, GLenum prim )
537 {
538 r128ContextPtr rmesa = R128_CONTEXT(ctx);
539 GLuint hw = hw_prim[prim];
540 rmesa->render_primitive = prim;
541 if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
542 return;
543 r128RasterPrimitive( ctx, hw );
544 }
545
546 #define EMIT_ATTR( ATTR, STYLE, VF, SIZE ) \
547 do { \
548 rmesa->vertex_attrs[rmesa->vertex_attr_count].attrib = (ATTR); \
549 rmesa->vertex_attrs[rmesa->vertex_attr_count].format = (STYLE); \
550 rmesa->vertex_attr_count++; \
551 vc_frmt |= (VF); \
552 offset += (SIZE); \
553 } while (0)
554
555 #define EMIT_PAD( SIZE ) \
556 do { \
557 rmesa->vertex_attrs[rmesa->vertex_attr_count].attrib = 0; \
558 rmesa->vertex_attrs[rmesa->vertex_attr_count].format = EMIT_PAD; \
559 rmesa->vertex_attrs[rmesa->vertex_attr_count].offset = (SIZE); \
560 rmesa->vertex_attr_count++; \
561 offset += (SIZE); \
562 } while (0)
563
564 static void r128RenderStart( GLcontext *ctx )
565 {
566 r128ContextPtr rmesa = R128_CONTEXT(ctx);
567 TNLcontext *tnl = TNL_CONTEXT(ctx);
568 struct vertex_buffer *VB = &tnl->vb;
569 GLuint index = tnl->render_inputs;
570 GLuint vc_frmt = 0;
571 GLboolean fallback_projtex = GL_FALSE;
572 GLuint offset = 0;
573
574 /* Important: */
575 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
576 rmesa->vertex_attr_count = 0;
577 rmesa->specoffset = 0;
578
579 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
580 * build up a hardware vertex.
581 */
582 if ( index & _TNL_BITS_TEX_ANY )
583 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, R128_CCE_VC_FRMT_RHW, 16 );
584 else
585 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 12 );
586
587 rmesa->coloroffset = offset;
588 #if MESA_LITTLE_ENDIAN
589 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA,
590 R128_CCE_VC_FRMT_DIFFUSE_ARGB, 4 );
591 #else
592 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ARGB,
593 R128_CCE_VC_FRMT_DIFFUSE_ARGB, 4 );
594 #endif
595
596 if ( index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG) ) {
597 #if MESA_LITTLE_ENDIAN
598 if ( index & _TNL_BIT_COLOR1) {
599 rmesa->specoffset = offset;
600 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB,
601 R128_CCE_VC_FRMT_SPEC_FRGB, 3 );
602 } else
603 EMIT_PAD( 3 );
604
605 if (index & _TNL_BIT_FOG)
606 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, R128_CCE_VC_FRMT_SPEC_FRGB,
607 1 );
608 else
609 EMIT_PAD( 1 );
610 #else
611 if (index & _TNL_BIT_FOG)
612 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, R128_CCE_VC_FRMT_SPEC_FRGB,
613 1 );
614 else
615 EMIT_PAD( 1 );
616
617 if ( index & _TNL_BIT_COLOR1) {
618 rmesa->specoffset = offset;
619 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB,
620 R128_CCE_VC_FRMT_SPEC_FRGB, 3 );
621 } else
622 EMIT_PAD( 3 );
623 #endif
624 }
625
626 if ( index & _TNL_BIT_TEX(rmesa->tmu_source[0]) ) {
627 if ( VB->TexCoordPtr[rmesa->tmu_source[0]]->size > 2 )
628 fallback_projtex = GL_TRUE;
629 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, R128_CCE_VC_FRMT_S_T, 8 );
630 }
631 if ( index & _TNL_BIT_TEX(rmesa->tmu_source[1]) ) {
632 if ( VB->TexCoordPtr[rmesa->tmu_source[1]]->size > 2 )
633 fallback_projtex = GL_TRUE;
634 EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, R128_CCE_VC_FRMT_S2_T2, 8 );
635 }
636
637 /* projective textures are not supported by the hardware */
638 FALLBACK( rmesa, R128_FALLBACK_PROJTEX, fallback_projtex );
639
640 /* Only need to change the vertex emit code if there has been a
641 * statechange to a TNL index.
642 */
643 if ( index != rmesa->tnl_state ) {
644 FLUSH_BATCH( rmesa );
645 rmesa->dirty |= R128_UPLOAD_CONTEXT;
646
647 rmesa->vertex_size =
648 _tnl_install_attrs( ctx,
649 rmesa->vertex_attrs,
650 rmesa->vertex_attr_count,
651 rmesa->hw_viewport, 0 );
652 rmesa->vertex_size >>= 2;
653
654 rmesa->vertex_format = vc_frmt;
655 }
656 }
657
658 static void r128RenderFinish( GLcontext *ctx )
659 {
660 if (R128_CONTEXT(ctx)->RenderIndex & R128_FALLBACK_BIT)
661 _swrast_flush( ctx );
662 }
663
664
665 /**********************************************************************/
666 /* Transition to/from hardware rasterization. */
667 /**********************************************************************/
668
669 static const char * const fallbackStrings[] = {
670 "Texture mode",
671 "glDrawBuffer(GL_FRONT_AND_BACK)",
672 "glReadBuffer",
673 "glEnable(GL_STENCIL) without hw stencil buffer",
674 "glRenderMode(selection or feedback)",
675 "glLogicOp (mode != GL_COPY)",
676 "GL_SEPARATE_SPECULAR_COLOR",
677 "glBlendEquation",
678 "glBlendFunc(mode != ADD)",
679 "Projective texture",
680 "Rasterization disable",
681 };
682
683
684 static const char *getFallbackString(GLuint bit)
685 {
686 int i = 0;
687 while (bit > 1) {
688 i++;
689 bit >>= 1;
690 }
691 return fallbackStrings[i];
692 }
693
694 void r128Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
695 {
696 TNLcontext *tnl = TNL_CONTEXT(ctx);
697 r128ContextPtr rmesa = R128_CONTEXT(ctx);
698 GLuint oldfallback = rmesa->Fallback;
699
700 if (mode) {
701 rmesa->Fallback |= bit;
702 if (oldfallback == 0) {
703 FLUSH_BATCH( rmesa );
704 _swsetup_Wakeup( ctx );
705 rmesa->RenderIndex = ~0;
706 if ( R128_DEBUG & DEBUG_VERBOSE_FALL ) {
707 fprintf(stderr, "R128 begin rasterization fallback: 0x%x %s\n",
708 bit, getFallbackString(bit));
709 }
710 }
711 }
712 else {
713 rmesa->Fallback &= ~bit;
714 if (oldfallback == bit) {
715 _swrast_flush( ctx );
716 tnl->Driver.Render.Start = r128RenderStart;
717 tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
718 tnl->Driver.Render.Finish = r128RenderFinish;
719
720 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
721 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
722 tnl->Driver.Render.Interp = _tnl_interp;
723
724 _tnl_invalidate_vertex_state( ctx, ~0 );
725 _tnl_invalidate_vertices( ctx, ~0 );
726 _tnl_install_attrs( ctx,
727 rmesa->vertex_attrs,
728 rmesa->vertex_attr_count,
729 rmesa->hw_viewport, 0 );
730
731 rmesa->NewGLState |= _R128_NEW_RENDER_STATE;
732 if ( R128_DEBUG & DEBUG_VERBOSE_FALL ) {
733 fprintf(stderr, "R128 end rasterization fallback: 0x%x %s\n",
734 bit, getFallbackString(bit));
735 }
736 }
737 }
738 }
739
740
741 /**********************************************************************/
742 /* Initialization. */
743 /**********************************************************************/
744
745 void r128InitTriFuncs( GLcontext *ctx )
746 {
747 r128ContextPtr rmesa = R128_CONTEXT(ctx);
748 TNLcontext *tnl = TNL_CONTEXT(ctx);
749 static int firsttime = 1;
750
751 if (firsttime) {
752 init_rast_tab();
753 firsttime = 0;
754 }
755
756 tnl->Driver.RunPipeline = r128RunPipeline;
757 tnl->Driver.Render.Start = r128RenderStart;
758 tnl->Driver.Render.Finish = r128RenderFinish;
759 tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
760 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
761 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
762 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
763 tnl->Driver.Render.Interp = _tnl_interp;
764
765 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
766 (6 + 2 * ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
767 rmesa->verts = (char *)tnl->clipspace.vertex_buf;
768 rmesa->tnl_state = -1;
769
770 rmesa->NewGLState |= _R128_NEW_RENDER_STATE;
771 }