Merge branch 'llvm-cliptest-viewport'
[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( 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 }