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