3e09427bb94f631c1fa6efcdf2ac55744a143de2
[mesa.git] / src / mesa / drivers / dri / i810 / i810tris.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810tris.c,v 1.7 2002/10/30 12:51:33 alanh Exp $ */
2 /**************************************************************************
3
4 Copyright 2001 VA Linux Systems Inc., Fremont, California.
5
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
17 Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Keith Whitwell <keith@tungstengraphics.com>
32 */
33
34 #include "glheader.h"
35 #include "mtypes.h"
36 #include "macros.h"
37 #include "enums.h"
38 #include "colormac.h"
39
40 #include "swrast/swrast.h"
41 #include "swrast_setup/swrast_setup.h"
42 #include "tnl/t_context.h"
43 #include "tnl/t_pipeline.h"
44
45 #include "i810screen.h"
46 #include "i810_dri.h"
47
48 #include "i810tris.h"
49 #include "i810state.h"
50 #include "i810vb.h"
51 #include "i810ioctl.h"
52
53 static void i810RenderPrimitive( GLcontext *ctx, GLenum prim );
54
55 /***********************************************************************
56 * Emit primitives as inline vertices *
57 ***********************************************************************/
58
59 #if defined(USE_X86_ASM)
60 #define COPY_DWORDS( j, vb, vertsize, v ) \
61 do { \
62 int __tmp; \
63 __asm__ __volatile__( "rep ; movsl" \
64 : "=%c" (j), "=D" (vb), "=S" (__tmp) \
65 : "0" (vertsize), \
66 "D" ((long)vb), \
67 "S" ((long)v) ); \
68 } while (0)
69 #else
70 #define COPY_DWORDS( j, vb, vertsize, v ) \
71 do { \
72 for ( j = 0 ; j < vertsize ; j++ ) \
73 vb[j] = ((GLuint *)v)[j]; \
74 vb += vertsize; \
75 } while (0)
76 #endif
77
78 static __inline__ void i810_draw_triangle( i810ContextPtr imesa,
79 i810VertexPtr v0,
80 i810VertexPtr v1,
81 i810VertexPtr v2 )
82 {
83 GLuint vertsize = imesa->vertex_size;
84 GLuint *vb = i810AllocDmaLow( imesa, 3 * 4 * vertsize );
85 int j;
86
87 COPY_DWORDS( j, vb, vertsize, v0 );
88 COPY_DWORDS( j, vb, vertsize, v1 );
89 COPY_DWORDS( j, vb, vertsize, v2 );
90 }
91
92
93 static __inline__ void i810_draw_quad( i810ContextPtr imesa,
94 i810VertexPtr v0,
95 i810VertexPtr v1,
96 i810VertexPtr v2,
97 i810VertexPtr v3 )
98 {
99 GLuint vertsize = imesa->vertex_size;
100 GLuint *vb = i810AllocDmaLow( imesa, 6 * 4 * vertsize );
101 int j;
102
103 COPY_DWORDS( j, vb, vertsize, v0 );
104 COPY_DWORDS( j, vb, vertsize, v1 );
105 COPY_DWORDS( j, vb, vertsize, v3 );
106 COPY_DWORDS( j, vb, vertsize, v1 );
107 COPY_DWORDS( j, vb, vertsize, v2 );
108 COPY_DWORDS( j, vb, vertsize, v3 );
109 }
110
111
112 static __inline__ void i810_draw_point( i810ContextPtr imesa,
113 i810VertexPtr tmp )
114 {
115 GLfloat sz = imesa->glCtx->Point._Size * .5;
116 int vertsize = imesa->vertex_size;
117 GLuint *vb = i810AllocDmaLow( imesa, 2 * 4 * vertsize );
118 int j;
119
120 /* Draw a point as a horizontal line.
121 */
122 *(float *)&vb[0] = tmp->v.x - sz + 0.125;
123 for (j = 1 ; j < vertsize ; j++)
124 vb[j] = tmp->ui[j];
125 vb += vertsize;
126
127 *(float *)&vb[0] = tmp->v.x + sz + 0.125;
128 for (j = 1 ; j < vertsize ; j++)
129 vb[j] = tmp->ui[j];
130 vb += vertsize;
131 }
132
133
134 static __inline__ void i810_draw_line( i810ContextPtr imesa,
135 i810VertexPtr v0,
136 i810VertexPtr v1 )
137 {
138 GLuint vertsize = imesa->vertex_size;
139 GLuint *vb = i810AllocDmaLow( imesa, 2 * 4 * vertsize );
140 int j;
141
142 COPY_DWORDS( j, vb, vertsize, v0 );
143 COPY_DWORDS( j, vb, vertsize, v1 );
144 }
145
146
147
148 /***********************************************************************
149 * Macros for t_dd_tritmp.h to draw basic primitives *
150 ***********************************************************************/
151
152 #define TRI( a, b, c ) \
153 do { \
154 if (0) fprintf(stderr, "hw TRI\n"); \
155 if (DO_FALLBACK) \
156 imesa->draw_tri( imesa, a, b, c ); \
157 else \
158 i810_draw_triangle( imesa, a, b, c ); \
159 } while (0)
160
161 #define QUAD( a, b, c, d ) \
162 do { \
163 if (0) fprintf(stderr, "hw QUAD\n"); \
164 if (DO_FALLBACK) { \
165 imesa->draw_tri( imesa, a, b, d ); \
166 imesa->draw_tri( imesa, b, c, d ); \
167 } else \
168 i810_draw_quad( imesa, a, b, c, d ); \
169 } while (0)
170
171 #define LINE( v0, v1 ) \
172 do { \
173 if (0) fprintf(stderr, "hw LINE\n"); \
174 if (DO_FALLBACK) \
175 imesa->draw_line( imesa, v0, v1 ); \
176 else \
177 i810_draw_line( imesa, v0, v1 ); \
178 } while (0)
179
180 #define POINT( v0 ) \
181 do { \
182 if (0) fprintf(stderr, "hw POINT\n"); \
183 if (DO_FALLBACK) \
184 imesa->draw_point( imesa, v0 ); \
185 else \
186 i810_draw_point( imesa, v0 ); \
187 } while (0)
188
189
190 /***********************************************************************
191 * Build render functions from dd templates *
192 ***********************************************************************/
193
194 #define I810_OFFSET_BIT 0x01
195 #define I810_TWOSIDE_BIT 0x02
196 #define I810_UNFILLED_BIT 0x04
197 #define I810_FALLBACK_BIT 0x08
198 #define I810_MAX_TRIFUNC 0x10
199
200
201 static struct {
202 tnl_points_func points;
203 tnl_line_func line;
204 tnl_triangle_func triangle;
205 tnl_quad_func quad;
206 } rast_tab[I810_MAX_TRIFUNC];
207
208
209 #define DO_FALLBACK (IND & I810_FALLBACK_BIT)
210 #define DO_OFFSET (IND & I810_OFFSET_BIT)
211 #define DO_UNFILLED (IND & I810_UNFILLED_BIT)
212 #define DO_TWOSIDE (IND & I810_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 i810Vertex
225 #define TAB rast_tab
226
227
228 #define DEPTH_SCALE (1.0/0xffff)
229 #define UNFILLED_TRI unfilled_tri
230 #define UNFILLED_QUAD unfilled_quad
231 #define VERT_X(_v) _v->v.x
232 #define VERT_Y(_v) _v->v.y
233 #define VERT_Z(_v) _v->v.z
234 #define AREA_IS_CCW( a ) (a > 0)
235 #define GET_VERTEX(e) (imesa->verts + (e * imesa->vertex_size * sizeof(int)))
236
237 #define VERT_SET_RGBA( v, c ) \
238 do { \
239 i810_color_t *color = (i810_color_t *)&((v)->ui[coloroffset]); \
240 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
241 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
242 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
243 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
244 } while (0)
245
246 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
247
248 #define VERT_SET_SPEC( v0, c ) \
249 do { \
250 if (havespec) { \
251 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
252 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
253 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
254 } \
255 } while (0)
256 #define VERT_COPY_SPEC( v0, v1 ) \
257 do { \
258 if (havespec) { \
259 v0->v.specular.red = v1->v.specular.red; \
260 v0->v.specular.green = v1->v.specular.green; \
261 v0->v.specular.blue = v1->v.specular.blue; \
262 } \
263 } while (0)
264
265 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
266 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
267 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
268 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
269
270 #define LOCAL_VARS(n) \
271 i810ContextPtr imesa = I810_CONTEXT(ctx); \
272 GLuint color[n], spec[n]; \
273 GLuint coloroffset = (imesa->vertex_size == 4 ? 3 : 4); \
274 GLboolean havespec = (imesa->vertex_size > 4); \
275 (void) color; (void) spec; (void) coloroffset; (void) havespec;
276
277
278 /***********************************************************************
279 * Helpers for rendering unfilled primitives *
280 ***********************************************************************/
281
282 static const GLuint hw_prim[GL_POLYGON+1] = {
283 PR_LINES,
284 PR_LINES,
285 PR_LINES,
286 PR_LINES,
287 PR_TRIANGLES,
288 PR_TRIANGLES,
289 PR_TRIANGLES,
290 PR_TRIANGLES,
291 PR_TRIANGLES,
292 PR_TRIANGLES
293 };
294
295 #define RASTERIZE(x) if (imesa->hw_primitive != hw_prim[x]) \
296 i810RasterPrimitive( ctx, x, hw_prim[x] )
297 #define RENDER_PRIMITIVE imesa->render_primitive
298 #define TAG(x) x
299 #define IND I810_FALLBACK_BIT
300 #include "tnl_dd/t_dd_unfilled.h"
301 #undef IND
302
303 /***********************************************************************
304 * Generate GL render functions *
305 ***********************************************************************/
306
307 #define IND (0)
308 #define TAG(x) x
309 #include "tnl_dd/t_dd_tritmp.h"
310
311 #define IND (I810_OFFSET_BIT)
312 #define TAG(x) x##_offset
313 #include "tnl_dd/t_dd_tritmp.h"
314
315 #define IND (I810_TWOSIDE_BIT)
316 #define TAG(x) x##_twoside
317 #include "tnl_dd/t_dd_tritmp.h"
318
319 #define IND (I810_TWOSIDE_BIT|I810_OFFSET_BIT)
320 #define TAG(x) x##_twoside_offset
321 #include "tnl_dd/t_dd_tritmp.h"
322
323 #define IND (I810_UNFILLED_BIT)
324 #define TAG(x) x##_unfilled
325 #include "tnl_dd/t_dd_tritmp.h"
326
327 #define IND (I810_OFFSET_BIT|I810_UNFILLED_BIT)
328 #define TAG(x) x##_offset_unfilled
329 #include "tnl_dd/t_dd_tritmp.h"
330
331 #define IND (I810_TWOSIDE_BIT|I810_UNFILLED_BIT)
332 #define TAG(x) x##_twoside_unfilled
333 #include "tnl_dd/t_dd_tritmp.h"
334
335 #define IND (I810_TWOSIDE_BIT|I810_OFFSET_BIT|I810_UNFILLED_BIT)
336 #define TAG(x) x##_twoside_offset_unfilled
337 #include "tnl_dd/t_dd_tritmp.h"
338
339 #define IND (I810_FALLBACK_BIT)
340 #define TAG(x) x##_fallback
341 #include "tnl_dd/t_dd_tritmp.h"
342
343 #define IND (I810_OFFSET_BIT|I810_FALLBACK_BIT)
344 #define TAG(x) x##_offset_fallback
345 #include "tnl_dd/t_dd_tritmp.h"
346
347 #define IND (I810_TWOSIDE_BIT|I810_FALLBACK_BIT)
348 #define TAG(x) x##_twoside_fallback
349 #include "tnl_dd/t_dd_tritmp.h"
350
351 #define IND (I810_TWOSIDE_BIT|I810_OFFSET_BIT|I810_FALLBACK_BIT)
352 #define TAG(x) x##_twoside_offset_fallback
353 #include "tnl_dd/t_dd_tritmp.h"
354
355 #define IND (I810_UNFILLED_BIT|I810_FALLBACK_BIT)
356 #define TAG(x) x##_unfilled_fallback
357 #include "tnl_dd/t_dd_tritmp.h"
358
359 #define IND (I810_OFFSET_BIT|I810_UNFILLED_BIT|I810_FALLBACK_BIT)
360 #define TAG(x) x##_offset_unfilled_fallback
361 #include "tnl_dd/t_dd_tritmp.h"
362
363 #define IND (I810_TWOSIDE_BIT|I810_UNFILLED_BIT|I810_FALLBACK_BIT)
364 #define TAG(x) x##_twoside_unfilled_fallback
365 #include "tnl_dd/t_dd_tritmp.h"
366
367 #define IND (I810_TWOSIDE_BIT|I810_OFFSET_BIT|I810_UNFILLED_BIT| \
368 I810_FALLBACK_BIT)
369 #define TAG(x) x##_twoside_offset_unfilled_fallback
370 #include "tnl_dd/t_dd_tritmp.h"
371
372
373 static void init_rast_tab( void )
374 {
375 init();
376 init_offset();
377 init_twoside();
378 init_twoside_offset();
379 init_unfilled();
380 init_offset_unfilled();
381 init_twoside_unfilled();
382 init_twoside_offset_unfilled();
383 init_fallback();
384 init_offset_fallback();
385 init_twoside_fallback();
386 init_twoside_offset_fallback();
387 init_unfilled_fallback();
388 init_offset_unfilled_fallback();
389 init_twoside_unfilled_fallback();
390 init_twoside_offset_unfilled_fallback();
391 }
392
393
394 /***********************************************************************
395 * Rasterization fallback helpers *
396 ***********************************************************************/
397
398
399 /* This code is hit only when a mix of accelerated and unaccelerated
400 * primitives are being drawn, and only for the unaccelerated
401 * primitives.
402 */
403 static void
404 i810_fallback_tri( i810ContextPtr imesa,
405 i810Vertex *v0,
406 i810Vertex *v1,
407 i810Vertex *v2 )
408 {
409 GLcontext *ctx = imesa->glCtx;
410 SWvertex v[3];
411 i810_translate_vertex( ctx, v0, &v[0] );
412 i810_translate_vertex( ctx, v1, &v[1] );
413 i810_translate_vertex( ctx, v2, &v[2] );
414 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
415 }
416
417
418 static void
419 i810_fallback_line( i810ContextPtr imesa,
420 i810Vertex *v0,
421 i810Vertex *v1 )
422 {
423 GLcontext *ctx = imesa->glCtx;
424 SWvertex v[2];
425 i810_translate_vertex( ctx, v0, &v[0] );
426 i810_translate_vertex( ctx, v1, &v[1] );
427 _swrast_Line( ctx, &v[0], &v[1] );
428 }
429
430
431 static void
432 i810_fallback_point( i810ContextPtr imesa,
433 i810Vertex *v0 )
434 {
435 GLcontext *ctx = imesa->glCtx;
436 SWvertex v[1];
437 i810_translate_vertex( ctx, v0, &v[0] );
438 _swrast_Point( ctx, &v[0] );
439 }
440
441
442
443 /**********************************************************************/
444 /* Render unclipped begin/end objects */
445 /**********************************************************************/
446
447 #define IND 0
448 #define V(x) (i810Vertex *)(vertptr + ((x)*vertsize*sizeof(int)))
449 #define RENDER_POINTS( start, count ) \
450 for ( ; start < count ; start++) POINT( V(ELT(start)) );
451 #define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) )
452 #define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) )
453 #define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) )
454 #define INIT(x) i810RenderPrimitive( ctx, x )
455 #undef LOCAL_VARS
456 #define LOCAL_VARS \
457 i810ContextPtr imesa = I810_CONTEXT(ctx); \
458 GLubyte *vertptr = (GLubyte *)imesa->verts; \
459 const GLuint vertsize = imesa->vertex_size; \
460 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
461 (void) elt;
462 #define RESET_STIPPLE
463 #define RESET_OCCLUSION
464 #define PRESERVE_VB_DEFS
465 #define ELT(x) x
466 #define TAG(x) i810_##x##_verts
467 #include "tnl/t_vb_rendertmp.h"
468 #undef ELT
469 #undef TAG
470 #define TAG(x) i810_##x##_elts
471 #define ELT(x) elt[x]
472 #include "tnl/t_vb_rendertmp.h"
473
474 /**********************************************************************/
475 /* Render clipped primitives */
476 /**********************************************************************/
477
478
479
480 static void i810RenderClippedPoly( GLcontext *ctx, const GLuint *elts,
481 GLuint n )
482 {
483 i810ContextPtr imesa = I810_CONTEXT(ctx);
484 TNLcontext *tnl = TNL_CONTEXT(ctx);
485 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
486 GLuint prim = imesa->render_primitive;
487
488 /* Render the new vertices as an unclipped polygon.
489 */
490 {
491 GLuint *tmp = VB->Elts;
492 VB->Elts = (GLuint *)elts;
493 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n,
494 PRIM_BEGIN|PRIM_END );
495 VB->Elts = tmp;
496 }
497
498 /* Restore the render primitive
499 */
500 if (prim != GL_POLYGON)
501 tnl->Driver.Render.PrimitiveNotify( ctx, prim );
502 }
503
504 static void i810RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
505 {
506 TNLcontext *tnl = TNL_CONTEXT(ctx);
507 tnl->Driver.Render.Line( ctx, ii, jj );
508 }
509
510 static void i810FastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
511 GLuint n )
512 {
513 i810ContextPtr imesa = I810_CONTEXT( ctx );
514 GLuint vertsize = imesa->vertex_size;
515 GLuint *vb = i810AllocDmaLow( imesa, (n-2) * 3 * 4 * vertsize );
516 GLubyte *vertptr = (GLubyte *)imesa->verts;
517 const GLuint *start = (const GLuint *)V(elts[0]);
518 int i,j;
519
520 for (i = 2 ; i < n ; i++) {
521 COPY_DWORDS( j, vb, vertsize, V(elts[i-1]) );
522 COPY_DWORDS( j, vb, vertsize, V(elts[i]) );
523 COPY_DWORDS( j, vb, vertsize, start );
524 }
525 }
526
527 /**********************************************************************/
528 /* Choose render functions */
529 /**********************************************************************/
530
531 /***********************************************************************
532 * Rasterization fallback helpers *
533 ***********************************************************************/
534
535
536
537 #define _I810_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
538 _DD_NEW_TRI_UNFILLED | \
539 _DD_NEW_TRI_LIGHT_TWOSIDE | \
540 _DD_NEW_TRI_OFFSET | \
541 _DD_NEW_TRI_STIPPLE | \
542 _NEW_POLYGONSTIPPLE)
543
544 #define POINT_FALLBACK (0)
545 #define LINE_FALLBACK (DD_LINE_STIPPLE)
546 #define TRI_FALLBACK (0)
547 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\
548 DD_TRI_STIPPLE)
549 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
550
551 static void i810ChooseRenderState(GLcontext *ctx)
552 {
553 TNLcontext *tnl = TNL_CONTEXT(ctx);
554 i810ContextPtr imesa = I810_CONTEXT(ctx);
555 GLuint flags = ctx->_TriangleCaps;
556 GLuint index = 0;
557
558 if (I810_DEBUG & DEBUG_STATE)
559 fprintf(stderr,"\n%s\n",__FUNCTION__);
560
561 if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) {
562 if (flags & ANY_RASTER_FLAGS) {
563 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= I810_TWOSIDE_BIT;
564 if (flags & DD_TRI_OFFSET) index |= I810_OFFSET_BIT;
565 if (flags & DD_TRI_UNFILLED) index |= I810_UNFILLED_BIT;
566 }
567
568 imesa->draw_point = i810_draw_point;
569 imesa->draw_line = i810_draw_line;
570 imesa->draw_tri = i810_draw_triangle;
571
572 /* Hook in fallbacks for specific primitives.
573 */
574 if (flags & ANY_FALLBACK_FLAGS)
575 {
576 if (flags & POINT_FALLBACK)
577 imesa->draw_point = i810_fallback_point;
578
579 if (flags & LINE_FALLBACK)
580 imesa->draw_line = i810_fallback_line;
581
582 if (flags & TRI_FALLBACK)
583 imesa->draw_tri = i810_fallback_tri;
584
585 if ((flags & DD_TRI_STIPPLE) && !imesa->stipple_in_hw)
586 imesa->draw_tri = i810_fallback_tri;
587
588 index |= I810_FALLBACK_BIT;
589 }
590 }
591
592 if (imesa->RenderIndex != index) {
593 imesa->RenderIndex = index;
594
595 tnl->Driver.Render.Points = rast_tab[index].points;
596 tnl->Driver.Render.Line = rast_tab[index].line;
597 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
598 tnl->Driver.Render.Quad = rast_tab[index].quad;
599
600 if (index == 0) {
601 tnl->Driver.Render.PrimTabVerts = i810_render_tab_verts;
602 tnl->Driver.Render.PrimTabElts = i810_render_tab_elts;
603 tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
604 tnl->Driver.Render.ClippedPolygon = i810FastRenderClippedPoly;
605 } else {
606 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
607 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
608 tnl->Driver.Render.ClippedLine = i810RenderClippedLine;
609 tnl->Driver.Render.ClippedPolygon = i810RenderClippedPoly;
610 }
611 }
612 }
613
614 static const GLenum reduced_prim[GL_POLYGON+1] = {
615 GL_POINTS,
616 GL_LINES,
617 GL_LINES,
618 GL_LINES,
619 GL_TRIANGLES,
620 GL_TRIANGLES,
621 GL_TRIANGLES,
622 GL_TRIANGLES,
623 GL_TRIANGLES,
624 GL_TRIANGLES
625 };
626
627
628 /**********************************************************************/
629 /* High level hooks for t_vb_render.c */
630 /**********************************************************************/
631
632
633
634 /* Determine the rasterized primitive when not drawing unfilled
635 * polygons.
636 *
637 * Used only for the default render stage which always decomposes
638 * primitives to trianges/lines/points. For the accelerated stage,
639 * which renders strips as strips, the equivalent calculations are
640 * performed in i810render.c.
641 */
642 static void i810RenderPrimitive( GLcontext *ctx, GLenum prim )
643 {
644 i810ContextPtr imesa = I810_CONTEXT(ctx);
645 GLuint rprim = reduced_prim[prim];
646
647 imesa->render_primitive = prim;
648
649 if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
650 return;
651
652 if (imesa->reduced_primitive != rprim ||
653 hw_prim[prim] != imesa->hw_primitive) {
654 i810RasterPrimitive( ctx, rprim, hw_prim[prim] );
655 }
656 }
657
658 static void i810RunPipeline( GLcontext *ctx )
659 {
660 i810ContextPtr imesa = I810_CONTEXT(ctx);
661
662 if (imesa->new_state) {
663 if (imesa->new_state & _NEW_TEXTURE)
664 i810UpdateTextureState( ctx ); /* may modify imesa->new_state */
665
666 if (!imesa->Fallback) {
667 if (imesa->new_state & _I810_NEW_VERTEX)
668 i810ChooseVertexState( ctx );
669
670 if (imesa->new_state & _I810_NEW_RENDERSTATE)
671 i810ChooseRenderState( ctx );
672 }
673
674 imesa->new_state = 0;
675 }
676
677 _tnl_run_pipeline( ctx );
678 }
679
680 static void i810RenderStart( GLcontext *ctx )
681 {
682 /* Check for projective textureing. Make sure all texcoord
683 * pointers point to something. (fix in mesa?)
684 */
685 i810CheckTexSizes( ctx );
686 }
687
688 static void i810RenderFinish( GLcontext *ctx )
689 {
690 if (I810_CONTEXT(ctx)->RenderIndex & I810_FALLBACK_BIT)
691 _swrast_flush( ctx );
692 }
693
694
695
696
697 /* System to flush dma and emit state changes based on the rasterized
698 * primitive.
699 */
700 void i810RasterPrimitive( GLcontext *ctx,
701 GLenum rprim,
702 GLuint hwprim )
703 {
704 i810ContextPtr imesa = I810_CONTEXT(ctx);
705 GLuint st1 = imesa->Setup[I810_CTXREG_ST1];
706 GLuint aa = imesa->Setup[I810_CTXREG_AA];
707 GLuint lcs = imesa->Setup[I810_CTXREG_LCS];
708
709 st1 &= ~ST1_ENABLE;
710 aa &= ~AA_ENABLE;
711
712 if (I810_DEBUG & DEBUG_PRIMS) {
713 /* Prints reduced prim, and hw prim */
714 char *prim_name = "Unknown";
715
716 switch(hwprim) {
717 case PR_LINES:
718 prim_name = "Lines";
719 break;
720 case PR_LINESTRIP:
721 prim_name = "LineStrip";
722 break;
723 case PR_TRIANGLES:
724 prim_name = "Triangles";
725 break;
726 case PR_TRISTRIP_0:
727 prim_name = "TriStrip_0";
728 break;
729 case PR_TRIFAN:
730 prim_name = "TriFan";
731 break;
732 case PR_POLYGON:
733 prim_name = "Polygons";
734 break;
735 default:
736 break;
737 }
738
739 fprintf(stderr, "%s : rprim(%s), hwprim(%s)\n",
740 __FUNCTION__,
741 _mesa_lookup_enum_by_nr(rprim),
742 prim_name);
743 }
744
745 switch (rprim) {
746 case GL_TRIANGLES:
747 if (ctx->Polygon.StippleFlag)
748 st1 |= ST1_ENABLE;
749 if (ctx->Polygon.SmoothFlag)
750 aa |= AA_ENABLE;
751 break;
752 case GL_LINES:
753 lcs &= ~(LCS_LINEWIDTH_3_0|LCS_LINEWIDTH_0_5);
754 lcs |= imesa->LcsLineWidth;
755 if (ctx->Line.SmoothFlag) {
756 aa |= AA_ENABLE;
757 lcs |= LCS_LINEWIDTH_0_5;
758 }
759 break;
760 case GL_POINTS:
761 lcs &= ~(LCS_LINEWIDTH_3_0|LCS_LINEWIDTH_0_5);
762 lcs |= imesa->LcsPointSize;
763 if (ctx->Point.SmoothFlag) {
764 aa |= AA_ENABLE;
765 lcs |= LCS_LINEWIDTH_0_5;
766 }
767 break;
768 default:
769 return;
770 }
771
772 imesa->reduced_primitive = rprim;
773
774 if (st1 != imesa->Setup[I810_CTXREG_ST1] ||
775 aa != imesa->Setup[I810_CTXREG_AA] ||
776 lcs != imesa->Setup[I810_CTXREG_LCS])
777 {
778 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
779 imesa->hw_primitive = hwprim;
780 imesa->Setup[I810_CTXREG_LCS] = lcs;
781 imesa->Setup[I810_CTXREG_ST1] = st1;
782 imesa->Setup[I810_CTXREG_AA] = aa;
783 }
784 else if (hwprim != imesa->hw_primitive) {
785 I810_STATECHANGE(imesa, 0);
786 imesa->hw_primitive = hwprim;
787 }
788 }
789
790 /**********************************************************************/
791 /* Transition to/from hardware rasterization. */
792 /**********************************************************************/
793 static char *fallbackStrings[] = {
794 "Texture",
795 "Draw buffer",
796 "Read buffer",
797 "Color mask",
798 "Render mode",
799 "Stencil",
800 "Stipple",
801 "User disable"
802 };
803
804
805 static char *getFallbackString(GLuint bit)
806 {
807 int i = 0;
808 while (bit > 1) {
809 i++;
810 bit >>= 1;
811 }
812 return fallbackStrings[i];
813 }
814
815 void i810Fallback( i810ContextPtr imesa, GLuint bit, GLboolean mode )
816 {
817 GLcontext *ctx = imesa->glCtx;
818 TNLcontext *tnl = TNL_CONTEXT(ctx);
819 GLuint oldfallback = imesa->Fallback;
820
821 if (0) fprintf(stderr, "%s old %x bit %x mode %d\n", __FUNCTION__,
822 imesa->Fallback, bit, mode );
823
824 if (mode) {
825 imesa->Fallback |= bit;
826 if (oldfallback == 0) {
827 I810_FIREVERTICES(imesa);
828 if (I810_DEBUG & DEBUG_FALLBACKS)
829 fprintf(stderr, "ENTER FALLBACK %s\n", getFallbackString( bit ));
830 _swsetup_Wakeup( ctx );
831 imesa->RenderIndex = ~0;
832 }
833 }
834 else {
835 imesa->Fallback &= ~bit;
836 if (oldfallback == bit) {
837 _swrast_flush( ctx );
838 if (I810_DEBUG & DEBUG_FALLBACKS)
839 fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit ));
840 tnl->Driver.Render.Start = i810RenderStart;
841 tnl->Driver.Render.PrimitiveNotify = i810RenderPrimitive;
842 tnl->Driver.Render.Finish = i810RenderFinish;
843 tnl->Driver.Render.BuildVertices = i810BuildVertices;
844 imesa->new_state |= (_I810_NEW_RENDERSTATE|_I810_NEW_VERTEX);
845 }
846 }
847 }
848
849
850 /**********************************************************************/
851 /* Initialization. */
852 /**********************************************************************/
853
854
855 void i810InitTriFuncs( GLcontext *ctx )
856 {
857 TNLcontext *tnl = TNL_CONTEXT(ctx);
858 static int firsttime = 1;
859
860 if (firsttime) {
861 init_rast_tab();
862 firsttime = 0;
863 }
864
865 tnl->Driver.RunPipeline = i810RunPipeline;
866 tnl->Driver.Render.Start = i810RenderStart;
867 tnl->Driver.Render.Finish = i810RenderFinish;
868 tnl->Driver.Render.PrimitiveNotify = i810RenderPrimitive;
869 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
870 tnl->Driver.Render.BuildVertices = i810BuildVertices;
871 }