Rename the various function types in t_context.h to include a tnl_ prefix.
[mesa.git] / src / mesa / drivers / dri / i830 / i830_tris.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_tris.c,v 1.4 2002/12/10 01:26:54 dawes 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 * Original Authors:
31 * Keith Whitwell <keith@tungstengraphics.com>
32 * Adapted for use on the I830M:
33 * Jeff Hartmann <jhartmann@2d3d.com>
34 */
35
36 #include "glheader.h"
37 #include "context.h"
38 #include "macros.h"
39 #include "enums.h"
40 #include "dd.h"
41
42 #include "swrast/swrast.h"
43 #include "swrast_setup/swrast_setup.h"
44 #include "tnl/t_context.h"
45 #include "tnl/t_pipeline.h"
46
47 #include "i830_screen.h"
48 #include "i830_dri.h"
49
50 #include "i830_tris.h"
51 #include "i830_state.h"
52 #include "i830_ioctl.h"
53 #include "i830_span.h"
54
55 static void i830RenderPrimitive( GLcontext *ctx, GLenum prim );
56
57 /***********************************************************************
58 * Emit primitives as inline vertices *
59 ***********************************************************************/
60
61 #if defined(USE_X86_ASM)
62 #define COPY_DWORDS( j, vb, vertsize, v ) \
63 do { \
64 int __tmp; \
65 __asm__ __volatile__( "rep ; movsl" \
66 : "=%c" (j), "=D" (vb), "=S" (__tmp) \
67 : "0" (vertsize), \
68 "D" ((long)vb), \
69 "S" ((long)v) ); \
70 } while (0)
71 #else
72 #define COPY_DWORDS( j, vb, vertsize, v ) \
73 do { \
74 for ( j = 0 ; j < vertsize ; j++ ) \
75 vb[j] = ((GLuint *)v)[j]; \
76 vb += vertsize; \
77 } while (0)
78 #endif
79
80 static void __inline__ i830_draw_triangle( i830ContextPtr imesa,
81 i830VertexPtr v0,
82 i830VertexPtr v1,
83 i830VertexPtr v2 )
84 {
85 GLuint vertsize = imesa->vertex_size;
86 GLuint *vb = i830AllocDmaLow( imesa, 3 * 4 * vertsize );
87 int j;
88
89 COPY_DWORDS( j, vb, vertsize, v0 );
90 COPY_DWORDS( j, vb, vertsize, v1 );
91 COPY_DWORDS( j, vb, vertsize, v2 );
92 }
93
94
95 static void __inline__ i830_draw_quad( i830ContextPtr imesa,
96 i830VertexPtr v0,
97 i830VertexPtr v1,
98 i830VertexPtr v2,
99 i830VertexPtr v3 )
100 {
101 GLuint vertsize = imesa->vertex_size;
102 GLuint *vb = i830AllocDmaLow( imesa, 6 * 4 * vertsize );
103 int j;
104
105 COPY_DWORDS( j, vb, vertsize, v0 );
106 COPY_DWORDS( j, vb, vertsize, v1 );
107 COPY_DWORDS( j, vb, vertsize, v3 );
108 COPY_DWORDS( j, vb, vertsize, v1 );
109 COPY_DWORDS( j, vb, vertsize, v2 );
110 COPY_DWORDS( j, vb, vertsize, v3 );
111 }
112
113
114 static __inline__ void i830_draw_point( i830ContextPtr imesa,
115 i830VertexPtr tmp )
116 {
117 GLuint vertsize = imesa->vertex_size;
118 GLuint *vb = i830AllocDmaLow( imesa, 4 * vertsize );
119 int j;
120
121 /* Adjust for sub pixel position */
122 *(float *)&vb[0] = tmp->v.x - 0.125;
123 *(float *)&vb[1] = tmp->v.y - 0.125;
124 for (j = 2 ; j < vertsize ; j++)
125 vb[j] = tmp->ui[j];
126 }
127
128
129 static __inline__ void i830_draw_line( i830ContextPtr imesa,
130 i830VertexPtr v0,
131 i830VertexPtr v1 )
132 {
133 GLuint vertsize = imesa->vertex_size;
134 GLuint *vb = i830AllocDmaLow( imesa, 2 * 4 * vertsize );
135 int j;
136
137 COPY_DWORDS( j, vb, vertsize, v0 );
138 COPY_DWORDS( j, vb, vertsize, v1 );
139 }
140
141
142
143 /***********************************************************************
144 * Macros for t_dd_tritmp.h to draw basic primitives *
145 ***********************************************************************/
146
147 #define TRI( a, b, c ) \
148 do { \
149 if (DO_FALLBACK) \
150 imesa->draw_tri( imesa, a, b, c ); \
151 else \
152 i830_draw_triangle( imesa, a, b, c ); \
153 } while (0)
154
155 #define QUAD( a, b, c, d ) \
156 do { \
157 if (DO_FALLBACK) { \
158 imesa->draw_tri( imesa, a, b, d ); \
159 imesa->draw_tri( imesa, b, c, d ); \
160 } else \
161 i830_draw_quad( imesa, a, b, c, d ); \
162 } while (0)
163
164 #define LINE( v0, v1 ) \
165 do { \
166 if (DO_FALLBACK) \
167 imesa->draw_line( imesa, v0, v1 ); \
168 else \
169 i830_draw_line( imesa, v0, v1 ); \
170 } while (0)
171
172 #define POINT( v0 ) \
173 do { \
174 if (DO_FALLBACK) \
175 imesa->draw_point( imesa, v0 ); \
176 else \
177 i830_draw_point( imesa, v0 ); \
178 } while (0)
179
180
181 /***********************************************************************
182 * Build render functions from dd templates *
183 ***********************************************************************/
184
185 #define I830_OFFSET_BIT 0x01
186 #define I830_TWOSIDE_BIT 0x02
187 #define I830_UNFILLED_BIT 0x04
188 #define I830_FALLBACK_BIT 0x08
189 #define I830_MAX_TRIFUNC 0x10
190
191
192 static struct {
193 tnl_points_func points;
194 tnl_line_func line;
195 tnl_triangle_func triangle;
196 tnl_quad_func quad;
197 } rast_tab[I830_MAX_TRIFUNC];
198
199
200 #define DO_FALLBACK (IND & I830_FALLBACK_BIT)
201 #define DO_OFFSET (IND & I830_OFFSET_BIT)
202 #define DO_UNFILLED (IND & I830_UNFILLED_BIT)
203 #define DO_TWOSIDE (IND & I830_TWOSIDE_BIT)
204 #define DO_FLAT 0
205 #define DO_TRI 1
206 #define DO_QUAD 1
207 #define DO_LINE 1
208 #define DO_POINTS 1
209 #define DO_FULL_QUAD 1
210
211 #define HAVE_RGBA 1
212 #define HAVE_SPEC 1
213 #define HAVE_BACK_COLORS 0
214 #define HAVE_HW_FLATSHADE 1
215 #define VERTEX i830Vertex
216 #define TAB rast_tab
217
218 #define DEPTH_SCALE (imesa->depth_scale)
219 #define UNFILLED_TRI unfilled_tri
220 #define UNFILLED_QUAD unfilled_quad
221 #define VERT_X(_v) _v->v.x
222 #define VERT_Y(_v) _v->v.y
223 #define VERT_Z(_v) _v->v.z
224 #define AREA_IS_CCW( a ) (a > 0)
225 #define GET_VERTEX(e) (imesa->verts + (e * imesa->vertex_size * sizeof(int)))
226
227 #define VERT_SET_RGBA( v, c ) \
228 do { \
229 i830_color_t *color = (i830_color_t *)&((v)->ui[coloroffset]); \
230 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
231 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
232 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
233 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
234 } while (0)
235
236 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
237
238 #define VERT_SET_SPEC( v0, c ) \
239 do { \
240 if (havespec) { \
241 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
242 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
243 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
244 } \
245 } while (0)
246 #define VERT_COPY_SPEC( v0, v1 ) \
247 do { \
248 if (havespec) { \
249 v0->v.specular.red = v1->v.specular.red; \
250 v0->v.specular.green = v1->v.specular.green; \
251 v0->v.specular.blue = v1->v.specular.blue; \
252 } \
253 } while (0)
254
255 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
256 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
257 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
258 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
259
260 #define LOCAL_VARS(n) \
261 i830ContextPtr imesa = I830_CONTEXT(ctx); \
262 GLuint color[n], spec[n]; \
263 GLuint coloroffset = (imesa->vertex_size == 4 ? 3 : 4); \
264 GLboolean havespec = (imesa->vertex_size > 4); \
265 (void) color; (void) spec; (void) coloroffset; (void) havespec;
266
267
268 /***********************************************************************
269 * Helpers for rendering unfilled primitives *
270 ***********************************************************************/
271
272 static const GLuint hw_prim[GL_POLYGON+1] = {
273 PRIM3D_POINTLIST,
274 PRIM3D_LINELIST,
275 PRIM3D_LINELIST,
276 PRIM3D_LINELIST,
277 PRIM3D_TRILIST,
278 PRIM3D_TRILIST,
279 PRIM3D_TRILIST,
280 PRIM3D_TRILIST,
281 PRIM3D_TRILIST,
282 PRIM3D_TRILIST
283 };
284
285 #define RASTERIZE(x) if (imesa->hw_primitive != hw_prim[x]) \
286 i830RasterPrimitive( ctx, x, hw_prim[x] )
287 #define RENDER_PRIMITIVE imesa->render_primitive
288 #define TAG(x) x
289 #define IND I830_FALLBACK_BIT
290 #include "tnl_dd/t_dd_unfilled.h"
291 #undef IND
292
293 /***********************************************************************
294 * Generate GL render functions *
295 ***********************************************************************/
296
297 #define IND (0)
298 #define TAG(x) x
299 #include "tnl_dd/t_dd_tritmp.h"
300
301 #define IND (I830_OFFSET_BIT)
302 #define TAG(x) x##_offset
303 #include "tnl_dd/t_dd_tritmp.h"
304
305 #define IND (I830_TWOSIDE_BIT)
306 #define TAG(x) x##_twoside
307 #include "tnl_dd/t_dd_tritmp.h"
308
309 #define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT)
310 #define TAG(x) x##_twoside_offset
311 #include "tnl_dd/t_dd_tritmp.h"
312
313 #define IND (I830_UNFILLED_BIT)
314 #define TAG(x) x##_unfilled
315 #include "tnl_dd/t_dd_tritmp.h"
316
317 #define IND (I830_OFFSET_BIT|I830_UNFILLED_BIT)
318 #define TAG(x) x##_offset_unfilled
319 #include "tnl_dd/t_dd_tritmp.h"
320
321 #define IND (I830_TWOSIDE_BIT|I830_UNFILLED_BIT)
322 #define TAG(x) x##_twoside_unfilled
323 #include "tnl_dd/t_dd_tritmp.h"
324
325 #define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_UNFILLED_BIT)
326 #define TAG(x) x##_twoside_offset_unfilled
327 #include "tnl_dd/t_dd_tritmp.h"
328
329 #define IND (I830_FALLBACK_BIT)
330 #define TAG(x) x##_fallback
331 #include "tnl_dd/t_dd_tritmp.h"
332
333 #define IND (I830_OFFSET_BIT|I830_FALLBACK_BIT)
334 #define TAG(x) x##_offset_fallback
335 #include "tnl_dd/t_dd_tritmp.h"
336
337 #define IND (I830_TWOSIDE_BIT|I830_FALLBACK_BIT)
338 #define TAG(x) x##_twoside_fallback
339 #include "tnl_dd/t_dd_tritmp.h"
340
341 #define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_FALLBACK_BIT)
342 #define TAG(x) x##_twoside_offset_fallback
343 #include "tnl_dd/t_dd_tritmp.h"
344
345 #define IND (I830_UNFILLED_BIT|I830_FALLBACK_BIT)
346 #define TAG(x) x##_unfilled_fallback
347 #include "tnl_dd/t_dd_tritmp.h"
348
349 #define IND (I830_OFFSET_BIT|I830_UNFILLED_BIT|I830_FALLBACK_BIT)
350 #define TAG(x) x##_offset_unfilled_fallback
351 #include "tnl_dd/t_dd_tritmp.h"
352
353 #define IND (I830_TWOSIDE_BIT|I830_UNFILLED_BIT|I830_FALLBACK_BIT)
354 #define TAG(x) x##_twoside_unfilled_fallback
355 #include "tnl_dd/t_dd_tritmp.h"
356
357 #define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_UNFILLED_BIT| \
358 I830_FALLBACK_BIT)
359 #define TAG(x) x##_twoside_offset_unfilled_fallback
360 #include "tnl_dd/t_dd_tritmp.h"
361
362
363 static void init_rast_tab( void )
364 {
365 init();
366 init_offset();
367 init_twoside();
368 init_twoside_offset();
369 init_unfilled();
370 init_offset_unfilled();
371 init_twoside_unfilled();
372 init_twoside_offset_unfilled();
373 init_fallback();
374 init_offset_fallback();
375 init_twoside_fallback();
376 init_twoside_offset_fallback();
377 init_unfilled_fallback();
378 init_offset_unfilled_fallback();
379 init_twoside_unfilled_fallback();
380 init_twoside_offset_unfilled_fallback();
381 }
382
383
384 /***********************************************************************
385 * Rasterization fallback helpers *
386 ***********************************************************************/
387
388
389 /* This code is hit only when a mix of accelerated and unaccelerated
390 * primitives are being drawn, and only for the unaccelerated
391 * primitives.
392 */
393 static void
394 i830_fallback_tri( i830ContextPtr imesa,
395 i830Vertex *v0,
396 i830Vertex *v1,
397 i830Vertex *v2 )
398 {
399 GLcontext *ctx = imesa->glCtx;
400 SWvertex v[3];
401
402 if (0)
403 fprintf(stderr, "\n%s\n", __FUNCTION__);
404
405 _swsetup_Translate( ctx, v0, &v[0] );
406 _swsetup_Translate( ctx, v1, &v[1] );
407 _swsetup_Translate( ctx, v2, &v[2] );
408 i830SpanRenderStart( ctx );
409 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
410 i830SpanRenderFinish( ctx );
411 }
412
413
414 static void
415 i830_fallback_line( i830ContextPtr imesa,
416 i830Vertex *v0,
417 i830Vertex *v1 )
418 {
419 GLcontext *ctx = imesa->glCtx;
420 SWvertex v[2];
421
422 if (0)
423 fprintf(stderr, "\n%s\n", __FUNCTION__);
424
425 _swsetup_Translate( ctx, v0, &v[0] );
426 _swsetup_Translate( ctx, v1, &v[1] );
427 i830SpanRenderStart( ctx );
428 _swrast_Line( ctx, &v[0], &v[1] );
429 i830SpanRenderFinish( ctx );
430 }
431
432
433 static void
434 i830_fallback_point( i830ContextPtr imesa,
435 i830Vertex *v0 )
436 {
437 GLcontext *ctx = imesa->glCtx;
438 SWvertex v[1];
439
440 if (0)
441 fprintf(stderr, "\n%s\n", __FUNCTION__);
442
443 _swsetup_Translate( ctx, v0, &v[0] );
444 i830SpanRenderStart( ctx );
445 _swrast_Point( ctx, &v[0] );
446 i830SpanRenderFinish( ctx );
447 }
448
449
450
451 /**********************************************************************/
452 /* Render unclipped begin/end objects */
453 /**********************************************************************/
454
455 #define IND 0
456 #define V(x) (i830Vertex *)(vertptr + ((x) * vertsize * sizeof(int)))
457 #define RENDER_POINTS( start, count ) \
458 for ( ; start < count ; start++) POINT( V(ELT(start)) );
459 #define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) )
460 #define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) )
461 #define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) )
462 #define INIT(x) i830RenderPrimitive( ctx, x )
463 #undef LOCAL_VARS
464 #define LOCAL_VARS \
465 i830ContextPtr imesa = I830_CONTEXT(ctx); \
466 GLubyte *vertptr = (GLubyte *)imesa->verts; \
467 const GLuint vertsize = imesa->vertex_size; \
468 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
469 (void) elt;
470 #define RESET_STIPPLE
471 #define RESET_OCCLUSION
472 #define PRESERVE_VB_DEFS
473 #define ELT(x) x
474 #define TAG(x) i830_##x##_verts
475 #include "tnl/t_vb_rendertmp.h"
476 #undef ELT
477 #undef TAG
478 #define TAG(x) i830_##x##_elts
479 #define ELT(x) elt[x]
480 #include "tnl/t_vb_rendertmp.h"
481
482 /**********************************************************************/
483 /* Render clipped primitives */
484 /**********************************************************************/
485
486
487
488 static void i830RenderClippedPoly( GLcontext *ctx, const GLuint *elts,
489 GLuint n )
490 {
491 i830ContextPtr imesa = I830_CONTEXT(ctx);
492 TNLcontext *tnl = TNL_CONTEXT(ctx);
493 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
494 GLuint prim = imesa->render_primitive;
495
496 /* Render the new vertices as an unclipped polygon.
497 */
498 {
499 GLuint *tmp = VB->Elts;
500 VB->Elts = (GLuint *)elts;
501 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n,
502 PRIM_BEGIN|PRIM_END );
503 VB->Elts = tmp;
504 }
505
506 /* Restore the render primitive
507 */
508 if (prim != GL_POLYGON)
509 tnl->Driver.Render.PrimitiveNotify( ctx, prim );
510 }
511
512 static void i830RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
513 {
514 TNLcontext *tnl = TNL_CONTEXT(ctx);
515
516 tnl->Driver.Render.Line( ctx, ii, jj );
517 }
518
519 static void i830FastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
520 GLuint n )
521 {
522 i830ContextPtr imesa = I830_CONTEXT( ctx );
523 GLuint vertsize = imesa->vertex_size;
524 GLuint *vb = i830AllocDmaLow( imesa, (n-2) * 3 * 4 * vertsize );
525 GLubyte *vertptr = (GLubyte *)imesa->verts;
526 const GLuint *start = (const GLuint *)V(elts[0]);
527 int i,j;
528
529 for (i = 2 ; i < n ; i++) {
530 COPY_DWORDS( j, vb, vertsize, V(elts[i-1]) );
531 COPY_DWORDS( j, vb, vertsize, V(elts[i]) );
532 COPY_DWORDS( j, vb, vertsize, start );
533 }
534 }
535
536 /**********************************************************************/
537 /* Choose render functions */
538 /**********************************************************************/
539
540
541
542 #define _I830_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
543 _DD_NEW_TRI_UNFILLED | \
544 _DD_NEW_TRI_LIGHT_TWOSIDE | \
545 _DD_NEW_TRI_OFFSET | \
546 _DD_NEW_TRI_STIPPLE | \
547 _NEW_POLYGONSTIPPLE)
548
549 #define POINT_FALLBACK (0)
550 #define LINE_FALLBACK (DD_LINE_STIPPLE)
551 #define TRI_FALLBACK (0)
552 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\
553 DD_TRI_STIPPLE)
554 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
555
556 static void i830ChooseRenderState(GLcontext *ctx)
557 {
558 TNLcontext *tnl = TNL_CONTEXT(ctx);
559 i830ContextPtr imesa = I830_CONTEXT(ctx);
560 GLuint flags = ctx->_TriangleCaps;
561 GLuint index = 0;
562
563 if (I830_DEBUG & DEBUG_STATE)
564 fprintf(stderr,"\n%s\n",__FUNCTION__);
565
566 if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) {
567 if (flags & ANY_RASTER_FLAGS) {
568 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= I830_TWOSIDE_BIT;
569 if (flags & DD_TRI_OFFSET) index |= I830_OFFSET_BIT;
570 if (flags & DD_TRI_UNFILLED) index |= I830_UNFILLED_BIT;
571 }
572
573 imesa->draw_point = i830_draw_point;
574 imesa->draw_line = i830_draw_line;
575 imesa->draw_tri = i830_draw_triangle;
576
577 /* Hook in fallbacks for specific primitives.
578 */
579 if (flags & ANY_FALLBACK_FLAGS)
580 {
581 if (flags & POINT_FALLBACK)
582 imesa->draw_point = i830_fallback_point;
583
584 if (flags & LINE_FALLBACK)
585 imesa->draw_line = i830_fallback_line;
586
587 if (flags & TRI_FALLBACK)
588 imesa->draw_tri = i830_fallback_tri;
589
590 if ((flags & DD_TRI_STIPPLE) && !imesa->hw_stipple) {
591 imesa->draw_tri = i830_fallback_tri;
592 }
593
594 index |= I830_FALLBACK_BIT;
595 }
596 }
597
598 if (imesa->RenderIndex != index) {
599 imesa->RenderIndex = index;
600
601 tnl->Driver.Render.Points = rast_tab[index].points;
602 tnl->Driver.Render.Line = rast_tab[index].line;
603 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
604 tnl->Driver.Render.Quad = rast_tab[index].quad;
605
606 if (index == 0) {
607 tnl->Driver.Render.PrimTabVerts = i830_render_tab_verts;
608 tnl->Driver.Render.PrimTabElts = i830_render_tab_elts;
609 tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
610 tnl->Driver.Render.ClippedPolygon = i830FastRenderClippedPoly;
611 } else {
612 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
613 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
614 tnl->Driver.Render.ClippedLine = i830RenderClippedLine;
615 tnl->Driver.Render.ClippedPolygon = i830RenderClippedPoly;
616 }
617 }
618 }
619
620 static const GLenum reduced_prim[GL_POLYGON+1] = {
621 GL_POINTS,
622 GL_LINES,
623 GL_LINES,
624 GL_LINES,
625 GL_TRIANGLES,
626 GL_TRIANGLES,
627 GL_TRIANGLES,
628 GL_TRIANGLES,
629 GL_TRIANGLES,
630 GL_TRIANGLES
631 };
632
633
634 /**********************************************************************/
635 /* High level hooks for t_vb_render.c */
636 /**********************************************************************/
637
638
639
640 /* Determine the rasterized primitive when not drawing unfilled
641 * polygons.
642 *
643 * Used only for the default render stage which always decomposes
644 * primitives to trianges/lines/points. For the accelerated stage,
645 * which renders strips as strips, the equivalent calculations are
646 * performed in i810render.c.
647 */
648 static void i830RenderPrimitive( GLcontext *ctx, GLenum prim )
649 {
650 i830ContextPtr imesa = I830_CONTEXT(ctx);
651 GLuint rprim = reduced_prim[prim];
652
653 imesa->render_primitive = prim;
654
655 if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
656 return;
657
658 if (imesa->reduced_primitive != rprim ||
659 hw_prim[prim] != imesa->hw_primitive) {
660 i830RasterPrimitive( ctx, rprim, hw_prim[prim] );
661 }
662 }
663
664 static void i830RunPipeline( GLcontext *ctx )
665 {
666 i830ContextPtr imesa = I830_CONTEXT(ctx);
667
668 if (imesa->NewGLState) {
669 if (imesa->NewGLState & _NEW_TEXTURE) {
670 I830_FIREVERTICES( imesa );
671 i830UpdateTextureState( ctx ); /* may modify imesa->NewGLState */
672 }
673
674 if (!imesa->Fallback) {
675 if (imesa->NewGLState & _I830_NEW_RENDERSTATE)
676 i830ChooseRenderState( ctx );
677 }
678
679 imesa->NewGLState = 0;
680 }
681
682 _tnl_run_pipeline( ctx );
683 }
684
685
686 #define TEXCOORDTYPE_MASK (3<<11)
687
688
689
690 static void set_projective_texturing( i830ContextPtr imesa,
691 GLuint i,
692 GLuint mcs)
693 {
694 mcs |= (imesa->CurrentTexObj[i]->Setup[I830_TEXREG_MCS] &
695 ~TEXCOORDTYPE_MASK);
696
697 if (mcs != imesa->CurrentTexObj[i]->Setup[I830_TEXREG_MCS]) {
698 I830_STATECHANGE(imesa, I830_UPLOAD_TEX_N(i));
699 imesa->CurrentTexObj[i]->Setup[I830_TEXREG_MCS] = mcs;
700 }
701 }
702
703
704 #define SZ_TO_HW(sz) ((sz-2)&0x3)
705 #define EMIT_SZ(sz) (EMIT_1F + (sz) - 1)
706 #define EMIT_ATTR( ATTR, STYLE, V0 ) \
707 do { \
708 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = (ATTR); \
709 imesa->vertex_attrs[imesa->vertex_attr_count].format = (STYLE); \
710 imesa->vertex_attr_count++; \
711 v0 |= V0; \
712 } while (0)
713
714 #define EMIT_PAD( N ) \
715 do { \
716 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = 0; \
717 imesa->vertex_attrs[imesa->vertex_attr_count].format = EMIT_PAD; \
718 imesa->vertex_attrs[imesa->vertex_attr_count].offset = (N); \
719 imesa->vertex_attr_count++; \
720 } while (0)
721
722 #define VRTX_TEX_SET_FMT(n, x) ((x)<<((n)*2))
723
724 /* Make sure hardware vertex format is appropriate for VB state.
725 */
726 static void i830RenderStart( GLcontext *ctx )
727 {
728 i830ContextPtr imesa = I830_CONTEXT(ctx);
729 TNLcontext *tnl = TNL_CONTEXT(ctx);
730 struct vertex_buffer *VB = &tnl->vb;
731 GLuint index = tnl->render_inputs;
732 GLuint v0 = STATE3D_VERTEX_FORMAT_CMD;
733 GLuint v2 = STATE3D_VERTEX_FORMAT_2_CMD;
734 GLuint force_emit = 0;
735
736 /* Important:
737 */
738 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
739 imesa->vertex_attr_count = 0;
740
741 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
742 * build up a hardware vertex.
743 */
744 if (index & _TNL_BITS_TEX_ANY) {
745 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VRTX_HAS_XYZW );
746 }
747 else {
748 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, VRTX_HAS_XYZ );
749 }
750
751 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VRTX_HAS_DIFFUSE );
752
753 if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
754
755 if (index & _TNL_BIT_COLOR1)
756 {
757 if (imesa->vertex_attrs[imesa->vertex_attr_count].format != EMIT_3UB_3F_BGR)
758 force_emit=1;
759 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VRTX_HAS_SPEC );
760 }
761 else
762 {
763 if (imesa->vertex_attrs[imesa->vertex_attr_count].format != EMIT_PAD)
764 force_emit=1;
765 EMIT_PAD( 3 );
766 }
767 if (index & _TNL_BIT_FOG)
768 {
769 if (imesa->vertex_attrs[imesa->vertex_attr_count].format != EMIT_1UB_1F)
770 force_emit=1;
771 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VRTX_HAS_SPEC );
772 }
773 else
774 {
775 if (imesa->vertex_attrs[imesa->vertex_attr_count].format != EMIT_PAD)
776 force_emit=1;
777 EMIT_PAD( 1 );
778 }
779 }
780
781 if (index & _TNL_BITS_TEX_ANY) {
782 int i, last_stage = 0;
783
784 for (i = 0; i < ctx->Const.MaxTextureUnits ; i++)
785 if (index & _TNL_BIT_TEX(i))
786 last_stage = i+1;
787
788
789 for (i = 0; i < last_stage; i++) {
790 GLuint sz = VB->TexCoordPtr[i]->size;
791 GLuint emit;
792 GLuint mcs;
793
794 /* i830 doesn't like 1D or 4D texcoords:
795 */
796 switch (sz) {
797 case 1:
798 case 2:
799 case 3: /* no attempt at cube texturing so far */
800 emit = EMIT_2F;
801 sz = 2;
802 mcs = TEXCOORDTYPE_CARTESIAN;
803 break;
804 case 4:
805 emit = EMIT_3F_XYW;
806 sz = 3;
807 mcs = TEXCOORDTYPE_HOMOGENEOUS;
808 break;
809 default:
810 continue;
811 };
812
813 v2 |= VRTX_TEX_SET_FMT(i, SZ_TO_HW(sz));
814 EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_SZ(sz), 0 );
815
816 if (imesa->CurrentTexObj[i])
817 set_projective_texturing( imesa, i, mcs );
818 }
819
820 v0 |= VRTX_TEX_COORD_COUNT(last_stage);
821 }
822
823 /* Only need to change the vertex emit code if there has been a
824 * statechange to a new hardware vertex format:
825 */
826 if (v0 != imesa->Setup[I830_CTXREG_VF] ||
827 v2 != imesa->Setup[I830_CTXREG_VF2] ||
828 force_emit == 1) {
829
830 I830_STATECHANGE( imesa, I830_UPLOAD_CTX );
831
832 /* Must do this *after* statechange, so as not to affect
833 * buffered vertices reliant on the old state:
834 */
835 imesa->vertex_size =
836 _tnl_install_attrs( ctx,
837 imesa->vertex_attrs,
838 imesa->vertex_attr_count,
839 imesa->ViewportMatrix.m, 0 );
840
841 imesa->vertex_size >>= 2;
842
843 imesa->Setup[I830_CTXREG_VF] = v0;
844 imesa->Setup[I830_CTXREG_VF2] = v2;
845 }
846 }
847
848
849 static void i830RenderFinish( GLcontext *ctx )
850 {
851 if (I830_CONTEXT(ctx)->RenderIndex & I830_FALLBACK_BIT)
852 _swrast_flush( ctx );
853 }
854
855
856
857
858 /* System to flush dma and emit state changes based on the rasterized
859 * primitive.
860 */
861 void i830RasterPrimitive( GLcontext *ctx,
862 GLenum rprim,
863 GLuint hwprim )
864 {
865 i830ContextPtr imesa = I830_CONTEXT(ctx);
866 GLuint aa = imesa->Setup[I830_CTXREG_AA];
867 GLuint st1 = imesa->StippleSetup[I830_STPREG_ST1];
868
869 aa &= ~AA_LINE_ENABLE;
870
871 if (I830_DEBUG & DEBUG_PRIMS) {
872 /* Prints reduced prim, and hw prim */
873 char *prim_name = "Unknown";
874
875 switch(hwprim) {
876 case PRIM3D_POINTLIST:
877 prim_name = "PointList";
878 break;
879 case PRIM3D_LINELIST:
880 prim_name = "LineList";
881 break;
882 case PRIM3D_LINESTRIP:
883 prim_name = "LineStrip";
884 break;
885 case PRIM3D_TRILIST:
886 prim_name = "TriList";
887 break;
888 case PRIM3D_TRISTRIP:
889 prim_name = "TriStrip";
890 break;
891 case PRIM3D_TRIFAN:
892 prim_name = "TriFan";
893 break;
894 case PRIM3D_POLY:
895 prim_name = "Polygons";
896 break;
897 default:
898 break;
899 }
900
901 fprintf(stderr, "%s : rprim(%s), hwprim(%s)\n",
902 __FUNCTION__,
903 _mesa_lookup_enum_by_nr(rprim),
904 prim_name);
905 }
906
907 switch (rprim) {
908 case GL_TRIANGLES:
909 aa |= AA_LINE_DISABLE;
910 if (ctx->Polygon.StippleFlag)
911 st1 |= ST1_ENABLE;
912 else
913 st1 &= ~ST1_ENABLE;
914 break;
915 case GL_LINES:
916 st1 &= ~ST1_ENABLE;
917 if (ctx->Line.SmoothFlag) {
918 aa |= AA_LINE_ENABLE;
919 } else {
920 aa |= AA_LINE_DISABLE;
921 }
922 break;
923 case GL_POINTS:
924 st1 &= ~ST1_ENABLE;
925 aa |= AA_LINE_DISABLE;
926 break;
927 default:
928 return;
929 }
930
931 imesa->reduced_primitive = rprim;
932
933 if (aa != imesa->Setup[I830_CTXREG_AA]) {
934 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
935 imesa->Setup[I830_CTXREG_AA] = aa;
936 }
937
938 #if 0
939 if (st1 != imesa->StippleSetup[I830_STPREG_ST1]) {
940 I830_STATECHANGE(imesa, I830_UPLOAD_STIPPLE);
941 imesa->StippleSetup[I830_STPREG_ST1] = st1;
942 }
943 #endif
944
945 if (hwprim != imesa->hw_primitive) {
946 I830_STATECHANGE(imesa, 0);
947 imesa->hw_primitive = hwprim;
948 }
949 }
950
951 /**********************************************************************/
952 /* Transition to/from hardware rasterization. */
953 /**********************************************************************/
954
955 static char *fallbackStrings[] = {
956 "Texture",
957 "Draw buffer",
958 "Read buffer",
959 "Color mask",
960 "Render mode",
961 "Stencil",
962 "Stipple",
963 "User disable"
964 };
965
966
967 static char *getFallbackString(GLuint bit)
968 {
969 int i = 0;
970 while (bit > 1) {
971 i++;
972 bit >>= 1;
973 }
974 return fallbackStrings[i];
975 }
976
977
978
979 void i830Fallback( i830ContextPtr imesa, GLuint bit, GLboolean mode )
980 {
981 GLcontext *ctx = imesa->glCtx;
982 TNLcontext *tnl = TNL_CONTEXT(ctx);
983 GLuint oldfallback = imesa->Fallback;
984
985 if (mode) {
986 imesa->Fallback |= bit;
987 if (oldfallback == 0) {
988 I830_FIREVERTICES(imesa);
989 if (I830_DEBUG & DEBUG_FALLBACKS)
990 fprintf(stderr, "ENTER FALLBACK %s\n", getFallbackString( bit ));
991 _swsetup_Wakeup( ctx );
992 imesa->RenderIndex = ~0;
993 }
994 }
995 else {
996 imesa->Fallback &= ~bit;
997 if (oldfallback == bit) {
998 _swrast_flush( ctx );
999 if (I830_DEBUG & DEBUG_FALLBACKS)
1000 fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit ));
1001 tnl->Driver.Render.Start = i830RenderStart;
1002 tnl->Driver.Render.PrimitiveNotify = i830RenderPrimitive;
1003 tnl->Driver.Render.Finish = i830RenderFinish;
1004
1005 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1006 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1007 tnl->Driver.Render.Interp = _tnl_interp;
1008
1009 _tnl_invalidate_vertex_state( ctx, ~0 );
1010 _tnl_invalidate_vertices( ctx, ~0 );
1011 _tnl_install_attrs( ctx,
1012 imesa->vertex_attrs,
1013 imesa->vertex_attr_count,
1014 imesa->ViewportMatrix.m, 0 );
1015
1016 imesa->NewGLState |= _I830_NEW_RENDERSTATE;
1017 }
1018 }
1019 }
1020
1021
1022
1023
1024 /**********************************************************************/
1025 /* Initialization. */
1026 /**********************************************************************/
1027
1028 /**
1029 * \bug
1030 * How are the magic numbers 12 and 26 in the call to \c _tnl_init_vertices
1031 * derived?
1032 */
1033 void i830InitTriFuncs( GLcontext *ctx )
1034 {
1035 TNLcontext *tnl = TNL_CONTEXT(ctx);
1036 static int firsttime = 1;
1037
1038 if (firsttime) {
1039 init_rast_tab();
1040 firsttime = 0;
1041 }
1042
1043 tnl->Driver.RunPipeline = i830RunPipeline;
1044 tnl->Driver.Render.Start = i830RenderStart;
1045 tnl->Driver.Render.Finish = i830RenderFinish;
1046 tnl->Driver.Render.PrimitiveNotify = i830RenderPrimitive;
1047 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
1048 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1049 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1050 tnl->Driver.Render.Interp = _tnl_interp;
1051
1052 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
1053 26 * sizeof(GLfloat) );
1054
1055 I830_CONTEXT(ctx)->verts = (char *)tnl->clipspace.vertex_buf;
1056 }