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