a94edb53a44a7aa85ced1fc6dde12022820704e5
[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 ) \
237 do { \
238 r128_color_t *color = (r128_color_t *)&((v)->ui[coloroffset]); \
239 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
240 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
241 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
242 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
243 } while (0)
244
245 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
246
247 #define VERT_SET_SPEC( v0, c ) \
248 do { \
249 if (havespec) { \
250 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
251 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
252 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
253 } \
254 } while (0)
255 #define VERT_COPY_SPEC( v0, v1 ) \
256 do { \
257 if (havespec) { \
258 v0->v.specular.red = v1->v.specular.red; \
259 v0->v.specular.green = v1->v.specular.green; \
260 v0->v.specular.blue = v1->v.specular.blue; \
261 } \
262 } while (0)
263
264 /* These don't need LE32_TO_CPU() as they used to save and restore
265 * colors which are already in the correct format.
266 */
267 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
268 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
269 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
270 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
271
272
273 #define LOCAL_VARS(n) \
274 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
275 GLuint color[n], spec[n]; \
276 GLuint coloroffset = (rmesa->vertex_size == 4 ? 3 : 4); \
277 GLboolean havespec = (rmesa->vertex_size == 4 ? 0 : 1); \
278 (void) color; (void) spec; (void) coloroffset; (void) havespec;
279
280 /***********************************************************************
281 * Helpers for rendering unfilled primitives *
282 ***********************************************************************/
283
284 #define RASTERIZE(x) if (rmesa->hw_primitive != hw_prim[x]) \
285 r128RasterPrimitive( ctx, hw_prim[x] )
286 #define RENDER_PRIMITIVE rmesa->render_primitive
287 #define IND R128_FALLBACK_BIT
288 #define TAG(x) x
289 #include "tnl_dd/t_dd_unfilled.h"
290 #undef IND
291
292
293 /***********************************************************************
294 * Generate GL render functions *
295 ***********************************************************************/
296
297
298 #define IND (0)
299 #define TAG(x) x
300 #include "tnl_dd/t_dd_tritmp.h"
301
302 #define IND (R128_OFFSET_BIT)
303 #define TAG(x) x##_offset
304 #include "tnl_dd/t_dd_tritmp.h"
305
306 #define IND (R128_TWOSIDE_BIT)
307 #define TAG(x) x##_twoside
308 #include "tnl_dd/t_dd_tritmp.h"
309
310 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT)
311 #define TAG(x) x##_twoside_offset
312 #include "tnl_dd/t_dd_tritmp.h"
313
314 #define IND (R128_UNFILLED_BIT)
315 #define TAG(x) x##_unfilled
316 #include "tnl_dd/t_dd_tritmp.h"
317
318 #define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT)
319 #define TAG(x) x##_offset_unfilled
320 #include "tnl_dd/t_dd_tritmp.h"
321
322 #define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT)
323 #define TAG(x) x##_twoside_unfilled
324 #include "tnl_dd/t_dd_tritmp.h"
325
326 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT)
327 #define TAG(x) x##_twoside_offset_unfilled
328 #include "tnl_dd/t_dd_tritmp.h"
329
330 #define IND (R128_FALLBACK_BIT)
331 #define TAG(x) x##_fallback
332 #include "tnl_dd/t_dd_tritmp.h"
333
334 #define IND (R128_OFFSET_BIT|R128_FALLBACK_BIT)
335 #define TAG(x) x##_offset_fallback
336 #include "tnl_dd/t_dd_tritmp.h"
337
338 #define IND (R128_TWOSIDE_BIT|R128_FALLBACK_BIT)
339 #define TAG(x) x##_twoside_fallback
340 #include "tnl_dd/t_dd_tritmp.h"
341
342 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_FALLBACK_BIT)
343 #define TAG(x) x##_twoside_offset_fallback
344 #include "tnl_dd/t_dd_tritmp.h"
345
346 #define IND (R128_UNFILLED_BIT|R128_FALLBACK_BIT)
347 #define TAG(x) x##_unfilled_fallback
348 #include "tnl_dd/t_dd_tritmp.h"
349
350 #define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
351 #define TAG(x) x##_offset_unfilled_fallback
352 #include "tnl_dd/t_dd_tritmp.h"
353
354 #define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
355 #define TAG(x) x##_twoside_unfilled_fallback
356 #include "tnl_dd/t_dd_tritmp.h"
357
358 #define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT| \
359 R128_FALLBACK_BIT)
360 #define TAG(x) x##_twoside_offset_unfilled_fallback
361 #include "tnl_dd/t_dd_tritmp.h"
362
363
364 static void init_rast_tab( void )
365 {
366 init();
367 init_offset();
368 init_twoside();
369 init_twoside_offset();
370 init_unfilled();
371 init_offset_unfilled();
372 init_twoside_unfilled();
373 init_twoside_offset_unfilled();
374 init_fallback();
375 init_offset_fallback();
376 init_twoside_fallback();
377 init_twoside_offset_fallback();
378 init_unfilled_fallback();
379 init_offset_unfilled_fallback();
380 init_twoside_unfilled_fallback();
381 init_twoside_offset_unfilled_fallback();
382 }
383
384
385
386 /***********************************************************************
387 * Rasterization fallback helpers *
388 ***********************************************************************/
389
390
391 /* This code is hit only when a mix of accelerated and unaccelerated
392 * primitives are being drawn, and only for the unaccelerated
393 * primitives.
394 */
395 static void
396 r128_fallback_tri( r128ContextPtr rmesa,
397 r128Vertex *v0,
398 r128Vertex *v1,
399 r128Vertex *v2 )
400 {
401 GLcontext *ctx = rmesa->glCtx;
402 SWvertex v[3];
403 r128_translate_vertex( ctx, v0, &v[0] );
404 r128_translate_vertex( ctx, v1, &v[1] );
405 r128_translate_vertex( ctx, v2, &v[2] );
406 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
407 }
408
409
410 static void
411 r128_fallback_line( r128ContextPtr rmesa,
412 r128Vertex *v0,
413 r128Vertex *v1 )
414 {
415 GLcontext *ctx = rmesa->glCtx;
416 SWvertex v[2];
417 r128_translate_vertex( ctx, v0, &v[0] );
418 r128_translate_vertex( ctx, v1, &v[1] );
419 _swrast_Line( ctx, &v[0], &v[1] );
420 }
421
422
423 static void
424 r128_fallback_point( r128ContextPtr rmesa,
425 r128Vertex *v0 )
426 {
427 GLcontext *ctx = rmesa->glCtx;
428 SWvertex v[1];
429 r128_translate_vertex( ctx, v0, &v[0] );
430 _swrast_Point( ctx, &v[0] );
431 }
432
433
434
435 /**********************************************************************/
436 /* Render unclipped begin/end objects */
437 /**********************************************************************/
438
439 #define VERT(x) (r128Vertex *)(r128verts + (x << shift))
440 #define RENDER_POINTS( start, count ) \
441 for ( ; start < count ; start++) \
442 r128_draw_point( rmesa, VERT(start) )
443 #define RENDER_LINE( v0, v1 ) \
444 r128_draw_line( rmesa, VERT(v0), VERT(v1) )
445 #define RENDER_TRI( v0, v1, v2 ) \
446 r128_draw_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
447 #define RENDER_QUAD( v0, v1, v2, v3 ) \
448 r128_draw_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
449 #define INIT(x) do { \
450 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
451 r128RenderPrimitive( ctx, x ); \
452 } while (0)
453 #undef LOCAL_VARS
454 #define LOCAL_VARS \
455 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
456 const GLuint shift = rmesa->vertex_stride_shift; \
457 const char *r128verts = (char *)rmesa->verts; \
458 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
459 (void) elt;
460 #define RESET_STIPPLE
461 #define RESET_OCCLUSION
462 #define PRESERVE_VB_DEFS
463 #define ELT(x) (x)
464 #define TAG(x) r128_##x##_verts
465 #include "tnl/t_vb_rendertmp.h"
466 #undef ELT
467 #undef TAG
468 #define TAG(x) r128_##x##_elts
469 #define ELT(x) elt[x]
470 #include "tnl/t_vb_rendertmp.h"
471
472
473 /**********************************************************************/
474 /* Render clipped primitives */
475 /**********************************************************************/
476
477 static void r128RenderClippedPoly( GLcontext *ctx, const GLuint *elts,
478 GLuint n )
479 {
480 TNLcontext *tnl = TNL_CONTEXT(ctx);
481 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
482
483 /* Render the new vertices as an unclipped polygon.
484 */
485 {
486 GLuint *tmp = VB->Elts;
487 VB->Elts = (GLuint *)elts;
488 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
489 VB->Elts = tmp;
490 }
491 }
492
493 static void r128RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
494 {
495 TNLcontext *tnl = TNL_CONTEXT(ctx);
496 tnl->Driver.Render.Line( ctx, ii, jj );
497 }
498
499 static void r128FastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
500 GLuint n )
501 {
502 r128ContextPtr rmesa = R128_CONTEXT( ctx );
503 GLuint vertsize = rmesa->vertex_size;
504 GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
505 GLubyte *r128verts = (GLubyte *)rmesa->verts;
506 const GLuint shift = rmesa->vertex_stride_shift;
507 const GLuint *start = (const GLuint *)VERT(elts[0]);
508 int i,j;
509
510 rmesa->num_verts += (n-2) * 3;
511
512 for (i = 2 ; i < n ; i++) {
513 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
514 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
515 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
516 }
517 }
518
519
520
521
522 /**********************************************************************/
523 /* Choose render functions */
524 /**********************************************************************/
525
526 #define _R128_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
527 _DD_NEW_LINE_SMOOTH | \
528 _DD_NEW_POINT_SMOOTH | \
529 _DD_NEW_TRI_SMOOTH | \
530 _DD_NEW_TRI_UNFILLED | \
531 _DD_NEW_TRI_LIGHT_TWOSIDE | \
532 _DD_NEW_TRI_OFFSET) \
533
534
535 #define POINT_FALLBACK (DD_POINT_SMOOTH)
536 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
537 #define TRI_FALLBACK (DD_TRI_SMOOTH)
538 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
539 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
540
541
542 static void r128ChooseRenderState(GLcontext *ctx)
543 {
544 r128ContextPtr rmesa = R128_CONTEXT(ctx);
545 GLuint flags = ctx->_TriangleCaps;
546 GLuint index = 0;
547
548 if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
549 rmesa->draw_point = r128_draw_point;
550 rmesa->draw_line = r128_draw_line;
551 rmesa->draw_tri = r128_draw_triangle;
552
553 if (flags & ANY_RASTER_FLAGS) {
554 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R128_TWOSIDE_BIT;
555 if (flags & DD_TRI_OFFSET) index |= R128_OFFSET_BIT;
556 if (flags & DD_TRI_UNFILLED) index |= R128_UNFILLED_BIT;
557 }
558
559 /* Hook in fallbacks for specific primitives.
560 */
561 if (flags & (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)) {
562 if (flags & POINT_FALLBACK) rmesa->draw_point = r128_fallback_point;
563 if (flags & LINE_FALLBACK) rmesa->draw_line = r128_fallback_line;
564 if (flags & TRI_FALLBACK) rmesa->draw_tri = r128_fallback_tri;
565 index |= R128_FALLBACK_BIT;
566 }
567 }
568
569 if (index != rmesa->RenderIndex) {
570 TNLcontext *tnl = TNL_CONTEXT(ctx);
571 tnl->Driver.Render.Points = rast_tab[index].points;
572 tnl->Driver.Render.Line = rast_tab[index].line;
573 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
574 tnl->Driver.Render.Quad = rast_tab[index].quad;
575
576 if (index == 0) {
577 tnl->Driver.Render.PrimTabVerts = r128_render_tab_verts;
578 tnl->Driver.Render.PrimTabElts = r128_render_tab_elts;
579 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
580 tnl->Driver.Render.ClippedPolygon = r128FastRenderClippedPoly;
581 } else {
582 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
583 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
584 tnl->Driver.Render.ClippedLine = r128RenderClippedLine;
585 tnl->Driver.Render.ClippedPolygon = r128RenderClippedPoly;
586 }
587
588 rmesa->RenderIndex = index;
589 }
590 }
591
592 /**********************************************************************/
593 /* Validate state at pipeline start */
594 /**********************************************************************/
595
596 static void r128RunPipeline( GLcontext *ctx )
597 {
598 r128ContextPtr rmesa = R128_CONTEXT(ctx);
599
600 if (rmesa->new_state || rmesa->NewGLState & _NEW_TEXTURE)
601 r128DDUpdateHWState( ctx );
602
603 if (!rmesa->Fallback && rmesa->NewGLState) {
604 if (rmesa->NewGLState & _R128_NEW_VERTEX_STATE)
605 r128ChooseVertexState( ctx );
606
607 if (rmesa->NewGLState & _R128_NEW_RENDER_STATE)
608 r128ChooseRenderState( ctx );
609
610 rmesa->NewGLState = 0;
611 }
612
613 _tnl_run_pipeline( ctx );
614 }
615
616 /**********************************************************************/
617 /* High level hooks for t_vb_render.c */
618 /**********************************************************************/
619
620 /* This is called when Mesa switches between rendering triangle
621 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
622 * and lines, points and bitmaps.
623 *
624 * As the r128 uses triangles to render lines and points, it is
625 * necessary to turn off hardware culling when rendering these
626 * primitives.
627 */
628
629 static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim )
630 {
631 r128ContextPtr rmesa = R128_CONTEXT(ctx);
632
633 rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE;
634
635 if ( ctx->Polygon.StippleFlag && hwprim == GL_TRIANGLES ) {
636 rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_32x32_MONO_FG_LA;
637 }
638 else {
639 rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_SOLID_COLOR;
640 }
641
642 rmesa->new_state |= R128_NEW_CONTEXT;
643 rmesa->dirty |= R128_UPLOAD_CONTEXT;
644
645 if (rmesa->hw_primitive != hwprim) {
646 FLUSH_BATCH( rmesa );
647 rmesa->hw_primitive = hwprim;
648 }
649 }
650
651 static void r128RenderPrimitive( GLcontext *ctx, GLenum prim )
652 {
653 r128ContextPtr rmesa = R128_CONTEXT(ctx);
654 GLuint hw = hw_prim[prim];
655 rmesa->render_primitive = prim;
656 if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
657 return;
658 r128RasterPrimitive( ctx, hw );
659 }
660
661
662 static void r128RenderStart( GLcontext *ctx )
663 {
664 /* Check for projective texturing. Make sure all texcoord
665 * pointers point to something. (fix in mesa?)
666 */
667 r128CheckTexSizes( ctx );
668 }
669
670 static void r128RenderFinish( GLcontext *ctx )
671 {
672 if (R128_CONTEXT(ctx)->RenderIndex & R128_FALLBACK_BIT)
673 _swrast_flush( ctx );
674 }
675
676
677 /**********************************************************************/
678 /* Transition to/from hardware rasterization. */
679 /**********************************************************************/
680
681 void r128Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
682 {
683 TNLcontext *tnl = TNL_CONTEXT(ctx);
684 r128ContextPtr rmesa = R128_CONTEXT(ctx);
685 GLuint oldfallback = rmesa->Fallback;
686
687 if (mode) {
688 rmesa->Fallback |= bit;
689 if (oldfallback == 0) {
690 FLUSH_BATCH( rmesa );
691 _swsetup_Wakeup( ctx );
692 rmesa->RenderIndex = ~0;
693 }
694 }
695 else {
696 rmesa->Fallback &= ~bit;
697 if (oldfallback == bit) {
698 _swrast_flush( ctx );
699 tnl->Driver.Render.Start = r128RenderStart;
700 tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
701 tnl->Driver.Render.Finish = r128RenderFinish;
702 tnl->Driver.Render.BuildVertices = r128BuildVertices;
703 rmesa->NewGLState |= (_R128_NEW_RENDER_STATE|
704 _R128_NEW_VERTEX_STATE);
705 }
706 }
707 }
708
709
710 /**********************************************************************/
711 /* Initialization. */
712 /**********************************************************************/
713
714 void r128InitTriFuncs( GLcontext *ctx )
715 {
716 r128ContextPtr rmesa = R128_CONTEXT(ctx);
717 TNLcontext *tnl = TNL_CONTEXT(ctx);
718 static int firsttime = 1;
719
720 if (firsttime) {
721 init_rast_tab();
722 firsttime = 0;
723 }
724
725 tnl->Driver.RunPipeline = r128RunPipeline;
726 tnl->Driver.Render.Start = r128RenderStart;
727 tnl->Driver.Render.Finish = r128RenderFinish;
728 tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
729 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
730 tnl->Driver.Render.BuildVertices = r128BuildVertices;
731 rmesa->NewGLState |= (_R128_NEW_RENDER_STATE|
732 _R128_NEW_VERTEX_STATE);
733
734 /* r128Fallback( ctx, 0x100000, 1 ); */
735 }