patch to import Jon Smirl's work from Bitkeeper
[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_vb.h"
51 #include "r128_ioctl.h"
52
53 static const GLuint hw_prim[GL_POLYGON+1] = {
54 R128_CCE_VC_CNTL_PRIM_TYPE_POINT,
55 R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
56 R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
57 R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
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 R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
64 };
65
66 static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim );
67 static void r128RenderPrimitive( GLcontext *ctx, GLenum prim );
68
69
70 /***********************************************************************
71 * Emit primitives as inline vertices *
72 ***********************************************************************/
73
74 #if defined(USE_X86_ASM)
75 #define COPY_DWORDS( j, vb, vertsize, v ) \
76 do { \
77 int __tmp; \
78 __asm__ __volatile__( "rep ; movsl" \
79 : "=%c" (j), "=D" (vb), "=S" (__tmp) \
80 : "0" (vertsize), \
81 "D" ((long)vb), \
82 "S" ((long)v) ); \
83 } while (0)
84 #else
85 #define COPY_DWORDS( j, vb, vertsize, v ) \
86 do { \
87 for ( j = 0 ; j < vertsize ; j++ ) \
88 vb[j] = CPU_TO_LE32(((GLuint *)v)[j]); \
89 vb += vertsize; \
90 } while (0)
91 #endif
92
93 static __inline void r128_draw_quad( r128ContextPtr rmesa,
94 r128VertexPtr v0,
95 r128VertexPtr v1,
96 r128VertexPtr v2,
97 r128VertexPtr v3 )
98 {
99 GLuint vertsize = rmesa->vertex_size;
100 GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 6 * vertsize * 4 );
101 GLuint j;
102
103 rmesa->num_verts += 6;
104 COPY_DWORDS( j, vb, vertsize, v0 );
105 COPY_DWORDS( j, vb, vertsize, v1 );
106 COPY_DWORDS( j, vb, vertsize, v3 );
107 COPY_DWORDS( j, vb, vertsize, v1 );
108 COPY_DWORDS( j, vb, vertsize, v2 );
109 COPY_DWORDS( j, vb, vertsize, v3 );
110 }
111
112
113 static __inline void r128_draw_triangle( r128ContextPtr rmesa,
114 r128VertexPtr v0,
115 r128VertexPtr v1,
116 r128VertexPtr v2 )
117 {
118 GLuint vertsize = rmesa->vertex_size;
119 GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 3 * vertsize * 4 );
120 GLuint j;
121
122 rmesa->num_verts += 3;
123 COPY_DWORDS( j, vb, vertsize, v0 );
124 COPY_DWORDS( j, vb, vertsize, v1 );
125 COPY_DWORDS( j, vb, vertsize, v2 );
126 }
127
128 static __inline void r128_draw_line( r128ContextPtr rmesa,
129 r128VertexPtr v0,
130 r128VertexPtr v1 )
131 {
132 GLuint vertsize = rmesa->vertex_size;
133 GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 2 * vertsize * 4 );
134 GLuint j;
135
136 rmesa->num_verts += 2;
137 COPY_DWORDS( j, vb, vertsize, v0 );
138 COPY_DWORDS( j, vb, vertsize, v1 );
139 }
140
141 static __inline void r128_draw_point( r128ContextPtr rmesa,
142 r128VertexPtr v0 )
143 {
144 int vertsize = rmesa->vertex_size;
145 GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, vertsize * 4 );
146 int j;
147
148 rmesa->num_verts += 1;
149 COPY_DWORDS( j, vb, vertsize, v0 );
150 }
151
152 /***********************************************************************
153 * Macros for t_dd_tritmp.h to draw basic primitives *
154 ***********************************************************************/
155
156 #define TRI( a, b, c ) \
157 do { \
158 if (DO_FALLBACK) \
159 rmesa->draw_tri( rmesa, a, b, c ); \
160 else \
161 r128_draw_triangle( rmesa, a, b, c ); \
162 } while (0)
163
164 #define QUAD( a, b, c, d ) \
165 do { \
166 if (DO_FALLBACK) { \
167 rmesa->draw_tri( rmesa, a, b, d ); \
168 rmesa->draw_tri( rmesa, b, c, d ); \
169 } else \
170 r128_draw_quad( rmesa, a, b, c, d ); \
171 } while (0)
172
173 #define LINE( v0, v1 ) \
174 do { \
175 if (DO_FALLBACK) \
176 rmesa->draw_line( rmesa, v0, v1 ); \
177 else \
178 r128_draw_line( rmesa, v0, v1 ); \
179 } while (0)
180
181 #define POINT( v0 ) \
182 do { \
183 if (DO_FALLBACK) \
184 rmesa->draw_point( rmesa, v0 ); \
185 else \
186 r128_draw_point( rmesa, v0 ); \
187 } while (0)
188
189
190 /***********************************************************************
191 * Build render functions from dd templates *
192 ***********************************************************************/
193
194 #define R128_OFFSET_BIT 0x01
195 #define R128_TWOSIDE_BIT 0x02
196 #define R128_UNFILLED_BIT 0x04
197 #define R128_FALLBACK_BIT 0x08
198 #define R128_MAX_TRIFUNC 0x10
199
200
201 static struct {
202 points_func points;
203 line_func line;
204 triangle_func triangle;
205 quad_func quad;
206 } rast_tab[R128_MAX_TRIFUNC];
207
208
209 #define DO_FALLBACK (IND & R128_FALLBACK_BIT)
210 #define DO_OFFSET (IND & R128_OFFSET_BIT)
211 #define DO_UNFILLED (IND & R128_UNFILLED_BIT)
212 #define DO_TWOSIDE (IND & R128_TWOSIDE_BIT)
213 #define DO_FLAT 0
214 #define DO_TRI 1
215 #define DO_QUAD 1
216 #define DO_LINE 1
217 #define DO_POINTS 1
218 #define DO_FULL_QUAD 1
219
220 #define HAVE_RGBA 1
221 #define HAVE_SPEC 1
222 #define HAVE_BACK_COLORS 0
223 #define HAVE_HW_FLATSHADE 1
224 #define VERTEX r128Vertex
225 #define TAB rast_tab
226
227 #define DEPTH_SCALE 1.0
228 #define UNFILLED_TRI unfilled_tri
229 #define UNFILLED_QUAD unfilled_quad
230 #define VERT_X(_v) _v->v.x
231 #define VERT_Y(_v) _v->v.y
232 #define VERT_Z(_v) _v->v.z
233 #define AREA_IS_CCW( a ) (a > 0)
234 #define GET_VERTEX(e) (rmesa->verts + (e<<rmesa->vertex_stride_shift))
235
236 #define VERT_SET_RGBA( v, c ) do { \
237 r128_color_t *vc = (r128_color_t *)&(v)->ui[coloroffset]; \
238 vc->blue = (c)[2]; \
239 vc->green = (c)[1]; \
240 vc->red = (c)[0]; \
241 vc->alpha = (c)[3]; \
242 } while (0)
243 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
244 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
245 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
246
247 #define VERT_SET_SPEC( v0, c ) if (havespec) { \
248 (v0)->v.specular.red = (c)[0];\
249 (v0)->v.specular.green = (c)[1];\
250 (v0)->v.specular.blue = (c)[2]; }
251 #define VERT_COPY_SPEC( v0, v1 ) if (havespec) { \
252 (v0)->v.specular.red = v1->v.specular.red; \
253 (v0)->v.specular.green = v1->v.specular.green; \
254 (v0)->v.specular.blue = v1->v.specular.blue; }
255
256 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
257 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
258
259 #define LOCAL_VARS(n) \
260 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
261 GLuint color[n], spec[n]; \
262 GLuint coloroffset = (rmesa->vertex_size == 4 ? 3 : 4); \
263 GLboolean havespec = (rmesa->vertex_size == 4 ? 0 : 1); \
264 (void) color; (void) spec; (void) coloroffset; (void) havespec;
265
266 /***********************************************************************
267 * Helpers for rendering unfilled primitives *
268 ***********************************************************************/
269
270 #define RASTERIZE(x) if (rmesa->hw_primitive != hw_prim[x]) \
271 r128RasterPrimitive( ctx, hw_prim[x] )
272 #define RENDER_PRIMITIVE rmesa->render_primitive
273 #define IND R128_FALLBACK_BIT
274 #define TAG(x) x
275 #include "tnl_dd/t_dd_unfilled.h"
276 #undef IND
277
278
279 /***********************************************************************
280 * Generate GL render functions *
281 ***********************************************************************/
282
283
284 #define IND (0)
285 #define TAG(x) x
286 #include "tnl_dd/t_dd_tritmp.h"
287
288 #define IND (R128_OFFSET_BIT)
289 #define TAG(x) x##_offset
290 #include "tnl_dd/t_dd_tritmp.h"
291
292 #define IND (R128_TWOSIDE_BIT)
293 #define TAG(x) x##_twoside
294 #include "tnl_dd/t_dd_tritmp.h"
295
296 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT)
297 #define TAG(x) x##_twoside_offset
298 #include "tnl_dd/t_dd_tritmp.h"
299
300 #define IND (R128_UNFILLED_BIT)
301 #define TAG(x) x##_unfilled
302 #include "tnl_dd/t_dd_tritmp.h"
303
304 #define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT)
305 #define TAG(x) x##_offset_unfilled
306 #include "tnl_dd/t_dd_tritmp.h"
307
308 #define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT)
309 #define TAG(x) x##_twoside_unfilled
310 #include "tnl_dd/t_dd_tritmp.h"
311
312 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT)
313 #define TAG(x) x##_twoside_offset_unfilled
314 #include "tnl_dd/t_dd_tritmp.h"
315
316 #define IND (R128_FALLBACK_BIT)
317 #define TAG(x) x##_fallback
318 #include "tnl_dd/t_dd_tritmp.h"
319
320 #define IND (R128_OFFSET_BIT|R128_FALLBACK_BIT)
321 #define TAG(x) x##_offset_fallback
322 #include "tnl_dd/t_dd_tritmp.h"
323
324 #define IND (R128_TWOSIDE_BIT|R128_FALLBACK_BIT)
325 #define TAG(x) x##_twoside_fallback
326 #include "tnl_dd/t_dd_tritmp.h"
327
328 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_FALLBACK_BIT)
329 #define TAG(x) x##_twoside_offset_fallback
330 #include "tnl_dd/t_dd_tritmp.h"
331
332 #define IND (R128_UNFILLED_BIT|R128_FALLBACK_BIT)
333 #define TAG(x) x##_unfilled_fallback
334 #include "tnl_dd/t_dd_tritmp.h"
335
336 #define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
337 #define TAG(x) x##_offset_unfilled_fallback
338 #include "tnl_dd/t_dd_tritmp.h"
339
340 #define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
341 #define TAG(x) x##_twoside_unfilled_fallback
342 #include "tnl_dd/t_dd_tritmp.h"
343
344 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT| \
345 R128_FALLBACK_BIT)
346 #define TAG(x) x##_twoside_offset_unfilled_fallback
347 #include "tnl_dd/t_dd_tritmp.h"
348
349
350 static void init_rast_tab( void )
351 {
352 init();
353 init_offset();
354 init_twoside();
355 init_twoside_offset();
356 init_unfilled();
357 init_offset_unfilled();
358 init_twoside_unfilled();
359 init_twoside_offset_unfilled();
360 init_fallback();
361 init_offset_fallback();
362 init_twoside_fallback();
363 init_twoside_offset_fallback();
364 init_unfilled_fallback();
365 init_offset_unfilled_fallback();
366 init_twoside_unfilled_fallback();
367 init_twoside_offset_unfilled_fallback();
368 }
369
370
371
372 /***********************************************************************
373 * Rasterization fallback helpers *
374 ***********************************************************************/
375
376
377 /* This code is hit only when a mix of accelerated and unaccelerated
378 * primitives are being drawn, and only for the unaccelerated
379 * primitives.
380 */
381 static void
382 r128_fallback_tri( r128ContextPtr rmesa,
383 r128Vertex *v0,
384 r128Vertex *v1,
385 r128Vertex *v2 )
386 {
387 GLcontext *ctx = rmesa->glCtx;
388 SWvertex v[3];
389 r128_translate_vertex( ctx, v0, &v[0] );
390 r128_translate_vertex( ctx, v1, &v[1] );
391 r128_translate_vertex( ctx, v2, &v[2] );
392 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
393 }
394
395
396 static void
397 r128_fallback_line( r128ContextPtr rmesa,
398 r128Vertex *v0,
399 r128Vertex *v1 )
400 {
401 GLcontext *ctx = rmesa->glCtx;
402 SWvertex v[2];
403 r128_translate_vertex( ctx, v0, &v[0] );
404 r128_translate_vertex( ctx, v1, &v[1] );
405 _swrast_Line( ctx, &v[0], &v[1] );
406 }
407
408
409 static void
410 r128_fallback_point( r128ContextPtr rmesa,
411 r128Vertex *v0 )
412 {
413 GLcontext *ctx = rmesa->glCtx;
414 SWvertex v[1];
415 r128_translate_vertex( ctx, v0, &v[0] );
416 _swrast_Point( ctx, &v[0] );
417 }
418
419
420
421 /**********************************************************************/
422 /* Render unclipped begin/end objects */
423 /**********************************************************************/
424
425 #define VERT(x) (r128Vertex *)(r128verts + (x << shift))
426 #define RENDER_POINTS( start, count ) \
427 for ( ; start < count ; start++) \
428 r128_draw_point( rmesa, VERT(start) )
429 #define RENDER_LINE( v0, v1 ) \
430 r128_draw_line( rmesa, VERT(v0), VERT(v1) )
431 #define RENDER_TRI( v0, v1, v2 ) \
432 r128_draw_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
433 #define RENDER_QUAD( v0, v1, v2, v3 ) \
434 r128_draw_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
435 #define INIT(x) do { \
436 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
437 r128RenderPrimitive( ctx, x ); \
438 } while (0)
439 #undef LOCAL_VARS
440 #define LOCAL_VARS \
441 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
442 const GLuint shift = rmesa->vertex_stride_shift; \
443 const char *r128verts = (char *)rmesa->verts; \
444 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
445 (void) elt;
446 #define RESET_STIPPLE
447 #define RESET_OCCLUSION
448 #define PRESERVE_VB_DEFS
449 #define ELT(x) (x)
450 #define TAG(x) r128_##x##_verts
451 #include "tnl/t_vb_rendertmp.h"
452 #undef ELT
453 #undef TAG
454 #define TAG(x) r128_##x##_elts
455 #define ELT(x) elt[x]
456 #include "tnl/t_vb_rendertmp.h"
457
458
459 /**********************************************************************/
460 /* Render clipped primitives */
461 /**********************************************************************/
462
463 static void r128RenderClippedPoly( GLcontext *ctx, const GLuint *elts,
464 GLuint n )
465 {
466 TNLcontext *tnl = TNL_CONTEXT(ctx);
467 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
468
469 /* Render the new vertices as an unclipped polygon.
470 */
471 {
472 GLuint *tmp = VB->Elts;
473 VB->Elts = (GLuint *)elts;
474 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
475 VB->Elts = tmp;
476 }
477 }
478
479 static void r128RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
480 {
481 TNLcontext *tnl = TNL_CONTEXT(ctx);
482 tnl->Driver.Render.Line( ctx, ii, jj );
483 }
484
485 static void r128FastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
486 GLuint n )
487 {
488 r128ContextPtr rmesa = R128_CONTEXT( ctx );
489 GLuint vertsize = rmesa->vertex_size;
490 GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
491 GLubyte *r128verts = (GLubyte *)rmesa->verts;
492 const GLuint shift = rmesa->vertex_stride_shift;
493 const GLuint *start = (const GLuint *)VERT(elts[0]);
494 int i,j;
495
496 rmesa->num_verts += (n-2) * 3;
497
498 for (i = 2 ; i < n ; i++) {
499 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
500 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
501 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
502 }
503 }
504
505
506
507
508 /**********************************************************************/
509 /* Choose render functions */
510 /**********************************************************************/
511
512 #define _R128_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
513 _DD_NEW_LINE_SMOOTH | \
514 _DD_NEW_POINT_SMOOTH | \
515 _DD_NEW_TRI_SMOOTH | \
516 _DD_NEW_TRI_UNFILLED | \
517 _DD_NEW_TRI_LIGHT_TWOSIDE | \
518 _DD_NEW_TRI_OFFSET) \
519
520
521 #define POINT_FALLBACK (DD_POINT_SMOOTH)
522 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
523 #define TRI_FALLBACK (DD_TRI_SMOOTH)
524 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
525 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
526
527
528 static void r128ChooseRenderState(GLcontext *ctx)
529 {
530 r128ContextPtr rmesa = R128_CONTEXT(ctx);
531 GLuint flags = ctx->_TriangleCaps;
532 GLuint index = 0;
533
534 if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
535 rmesa->draw_point = r128_draw_point;
536 rmesa->draw_line = r128_draw_line;
537 rmesa->draw_tri = r128_draw_triangle;
538
539 if (flags & ANY_RASTER_FLAGS) {
540 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R128_TWOSIDE_BIT;
541 if (flags & DD_TRI_OFFSET) index |= R128_OFFSET_BIT;
542 if (flags & DD_TRI_UNFILLED) index |= R128_UNFILLED_BIT;
543 }
544
545 /* Hook in fallbacks for specific primitives.
546 */
547 if (flags & (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)) {
548 if (flags & POINT_FALLBACK) rmesa->draw_point = r128_fallback_point;
549 if (flags & LINE_FALLBACK) rmesa->draw_line = r128_fallback_line;
550 if (flags & TRI_FALLBACK) rmesa->draw_tri = r128_fallback_tri;
551 index |= R128_FALLBACK_BIT;
552 }
553 }
554
555 if (index != rmesa->RenderIndex) {
556 TNLcontext *tnl = TNL_CONTEXT(ctx);
557 tnl->Driver.Render.Points = rast_tab[index].points;
558 tnl->Driver.Render.Line = rast_tab[index].line;
559 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
560 tnl->Driver.Render.Quad = rast_tab[index].quad;
561
562 if (index == 0) {
563 tnl->Driver.Render.PrimTabVerts = r128_render_tab_verts;
564 tnl->Driver.Render.PrimTabElts = r128_render_tab_elts;
565 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
566 tnl->Driver.Render.ClippedPolygon = r128FastRenderClippedPoly;
567 } else {
568 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
569 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
570 tnl->Driver.Render.ClippedLine = r128RenderClippedLine;
571 tnl->Driver.Render.ClippedPolygon = r128RenderClippedPoly;
572 }
573
574 rmesa->RenderIndex = index;
575 }
576 }
577
578 /**********************************************************************/
579 /* Validate state at pipeline start */
580 /**********************************************************************/
581
582 static void r128RunPipeline( GLcontext *ctx )
583 {
584 r128ContextPtr rmesa = R128_CONTEXT(ctx);
585
586 if (rmesa->new_state || rmesa->NewGLState & _NEW_TEXTURE)
587 r128DDUpdateHWState( ctx );
588
589 if (!rmesa->Fallback && rmesa->NewGLState) {
590 if (rmesa->NewGLState & _R128_NEW_VERTEX_STATE)
591 r128ChooseVertexState( ctx );
592
593 if (rmesa->NewGLState & _R128_NEW_RENDER_STATE)
594 r128ChooseRenderState( ctx );
595
596 rmesa->NewGLState = 0;
597 }
598
599 _tnl_run_pipeline( ctx );
600 }
601
602 /**********************************************************************/
603 /* High level hooks for t_vb_render.c */
604 /**********************************************************************/
605
606 /* This is called when Mesa switches between rendering triangle
607 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
608 * and lines, points and bitmaps.
609 *
610 * As the r128 uses triangles to render lines and points, it is
611 * necessary to turn off hardware culling when rendering these
612 * primitives.
613 */
614
615 static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim )
616 {
617 r128ContextPtr rmesa = R128_CONTEXT(ctx);
618
619 rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE;
620
621 if ( ctx->Polygon.StippleFlag && hwprim == GL_TRIANGLES ) {
622 rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_32x32_MONO_FG_LA;
623 }
624 else {
625 rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_SOLID_COLOR;
626 }
627
628 rmesa->new_state |= R128_NEW_CONTEXT;
629 rmesa->dirty |= R128_UPLOAD_CONTEXT;
630
631 if (rmesa->hw_primitive != hwprim) {
632 FLUSH_BATCH( rmesa );
633 rmesa->hw_primitive = hwprim;
634 }
635 }
636
637 static void r128RenderPrimitive( GLcontext *ctx, GLenum prim )
638 {
639 r128ContextPtr rmesa = R128_CONTEXT(ctx);
640 GLuint hw = hw_prim[prim];
641 rmesa->render_primitive = prim;
642 if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
643 return;
644 r128RasterPrimitive( ctx, hw );
645 }
646
647
648 static void r128RenderStart( GLcontext *ctx )
649 {
650 /* Check for projective texturing. Make sure all texcoord
651 * pointers point to something. (fix in mesa?)
652 */
653 r128CheckTexSizes( ctx );
654 }
655
656 static void r128RenderFinish( GLcontext *ctx )
657 {
658 if (R128_CONTEXT(ctx)->RenderIndex & R128_FALLBACK_BIT)
659 _swrast_flush( ctx );
660 }
661
662
663 /**********************************************************************/
664 /* Transition to/from hardware rasterization. */
665 /**********************************************************************/
666
667 void r128Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
668 {
669 TNLcontext *tnl = TNL_CONTEXT(ctx);
670 r128ContextPtr rmesa = R128_CONTEXT(ctx);
671 GLuint oldfallback = rmesa->Fallback;
672
673 if (mode) {
674 rmesa->Fallback |= bit;
675 if (oldfallback == 0) {
676 FLUSH_BATCH( rmesa );
677 _swsetup_Wakeup( ctx );
678 rmesa->RenderIndex = ~0;
679 }
680 }
681 else {
682 rmesa->Fallback &= ~bit;
683 if (oldfallback == bit) {
684 _swrast_flush( ctx );
685 tnl->Driver.Render.Start = r128RenderStart;
686 tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
687 tnl->Driver.Render.Finish = r128RenderFinish;
688 tnl->Driver.Render.BuildVertices = r128BuildVertices;
689 rmesa->NewGLState |= (_R128_NEW_RENDER_STATE|
690 _R128_NEW_VERTEX_STATE);
691 }
692 }
693 }
694
695
696 /**********************************************************************/
697 /* Initialization. */
698 /**********************************************************************/
699
700 void r128InitTriFuncs( GLcontext *ctx )
701 {
702 r128ContextPtr rmesa = R128_CONTEXT(ctx);
703 TNLcontext *tnl = TNL_CONTEXT(ctx);
704 static int firsttime = 1;
705
706 if (firsttime) {
707 init_rast_tab();
708 firsttime = 0;
709 }
710
711 tnl->Driver.RunPipeline = r128RunPipeline;
712 tnl->Driver.Render.Start = r128RenderStart;
713 tnl->Driver.Render.Finish = r128RenderFinish;
714 tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
715 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
716 tnl->Driver.Render.BuildVertices = r128BuildVertices;
717 rmesa->NewGLState |= (_R128_NEW_RENDER_STATE|
718 _R128_NEW_VERTEX_STATE);
719
720 /* r128Fallback( ctx, 0x100000, 1 ); */
721 }