Before calling _mesa_create_context(), initialize a dd_function_table struct
[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 points_func points;
194 line_func line;
195 triangle_func triangle;
196 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 sz)
693 {
694 GLuint mcs = (imesa->CurrentTexObj[i]->Setup[I830_TEXREG_MCS] &
695 ~TEXCOORDTYPE_MASK);
696
697 if (sz == 4) {
698 mcs |= TEXCOORDTYPE_HOMOGENEOUS;
699 } else {
700 mcs |= TEXCOORDTYPE_CARTESIAN;
701 }
702
703 if (mcs != imesa->CurrentTexObj[i]->Setup[I830_TEXREG_MCS]) {
704 I830_STATECHANGE(imesa, I830_UPLOAD_TEX_N(i));
705 imesa->CurrentTexObj[i]->Setup[I830_TEXREG_MCS] = mcs;
706 }
707 }
708
709
710 #define SZ_TO_HW(sz) ((sz-2)&0x3)
711 #define EMIT_SZ(sz) (EMIT_1F + (sz) - 1)
712 #define EMIT_ATTR( ATTR, STYLE, V0 ) \
713 do { \
714 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = (ATTR); \
715 imesa->vertex_attrs[imesa->vertex_attr_count].format = (STYLE); \
716 imesa->vertex_attr_count++; \
717 v0 |= V0; \
718 } while (0)
719
720
721 #define VRTX_TEX_SET_FMT(n, x) ((x)<<((n)*2))
722
723 /* Make sure hardware vertex format is appropriate for VB state.
724 */
725 static void i830RenderStart( GLcontext *ctx )
726 {
727 i830ContextPtr imesa = I830_CONTEXT(ctx);
728 TNLcontext *tnl = TNL_CONTEXT(ctx);
729 struct vertex_buffer *VB = &tnl->vb;
730 GLuint index = tnl->render_inputs;
731 GLuint v0 = STATE3D_VERTEX_FORMAT_CMD;
732 GLuint v2 = STATE3D_VERTEX_FORMAT_2_CMD;
733
734 /* Important:
735 */
736 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
737 imesa->vertex_attr_count = 0;
738
739 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
740 * build up a hardware vertex.
741 */
742 if (index & _TNL_BITS_TEX_ANY) {
743 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VRTX_HAS_XYZW );
744 }
745 else {
746 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, VRTX_HAS_XYZ );
747 }
748
749 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, VRTX_HAS_DIFFUSE );
750
751 if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
752 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, VRTX_HAS_SPEC );
753 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VRTX_HAS_SPEC );
754 }
755
756 if (index & _TNL_BITS_TEX_ANY) {
757 int i, last_stage = 0;
758
759 /* Still using 2 as max tex units, but this code is fine for all
760 * 8 units supported by mesa:
761 */
762 for (i = 0; i < 2 ; i++)
763 if (index & _TNL_BIT_TEX(i))
764 last_stage = i+1;
765
766
767 for (i = 0; i < last_stage; i++) {
768 GLuint sz = VB->TexCoordPtr[i]->size;
769
770 v2 |= VRTX_TEX_SET_FMT(i, SZ_TO_HW(sz));
771 EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_SZ(sz), 0 );
772
773 if (imesa->CurrentTexObj[i])
774 set_projective_texturing( imesa, i, sz );
775 }
776
777 v0 |= VRTX_TEX_COORD_COUNT(last_stage);
778 }
779
780 /* Only need to change the vertex emit code if there has been a
781 * statechange to a new hardware vertex format:
782 */
783 if (v0 != imesa->Setup[I830_CTXREG_VF] ||
784 v2 != imesa->Setup[I830_CTXREG_VF2] ) {
785
786 I830_STATECHANGE( imesa, I830_UPLOAD_CTX );
787
788 /* Must do this *after* statechange, so as not to affect
789 * buffered vertices reliant on the old state:
790 */
791 imesa->vertex_size =
792 _tnl_install_attrs( ctx,
793 imesa->vertex_attrs,
794 imesa->vertex_attr_count,
795 imesa->ViewportMatrix.m, 0 );
796
797 imesa->vertex_size >>= 2;
798
799 imesa->Setup[I830_CTXREG_VF] = v0;
800 imesa->Setup[I830_CTXREG_VF2] = v2;
801 }
802 }
803
804
805 static void i830RenderFinish( GLcontext *ctx )
806 {
807 if (I830_CONTEXT(ctx)->RenderIndex & I830_FALLBACK_BIT)
808 _swrast_flush( ctx );
809 }
810
811
812
813
814 /* System to flush dma and emit state changes based on the rasterized
815 * primitive.
816 */
817 void i830RasterPrimitive( GLcontext *ctx,
818 GLenum rprim,
819 GLuint hwprim )
820 {
821 i830ContextPtr imesa = I830_CONTEXT(ctx);
822 GLuint aa = imesa->Setup[I830_CTXREG_AA];
823 GLuint st1 = imesa->StippleSetup[I830_STPREG_ST1];
824
825 aa &= ~AA_LINE_ENABLE;
826
827 if (I830_DEBUG & DEBUG_PRIMS) {
828 /* Prints reduced prim, and hw prim */
829 char *prim_name = "Unknown";
830
831 switch(hwprim) {
832 case PRIM3D_POINTLIST:
833 prim_name = "PointList";
834 break;
835 case PRIM3D_LINELIST:
836 prim_name = "LineList";
837 break;
838 case PRIM3D_LINESTRIP:
839 prim_name = "LineStrip";
840 break;
841 case PRIM3D_TRILIST:
842 prim_name = "TriList";
843 break;
844 case PRIM3D_TRISTRIP:
845 prim_name = "TriStrip";
846 break;
847 case PRIM3D_TRIFAN:
848 prim_name = "TriFan";
849 break;
850 case PRIM3D_POLY:
851 prim_name = "Polygons";
852 break;
853 default:
854 break;
855 }
856
857 fprintf(stderr, "%s : rprim(%s), hwprim(%s)\n",
858 __FUNCTION__,
859 _mesa_lookup_enum_by_nr(rprim),
860 prim_name);
861 }
862
863 switch (rprim) {
864 case GL_TRIANGLES:
865 aa |= AA_LINE_DISABLE;
866 if (ctx->Polygon.StippleFlag)
867 st1 |= ST1_ENABLE;
868 else
869 st1 &= ~ST1_ENABLE;
870 break;
871 case GL_LINES:
872 st1 &= ~ST1_ENABLE;
873 if (ctx->Line.SmoothFlag) {
874 aa |= AA_LINE_ENABLE;
875 } else {
876 aa |= AA_LINE_DISABLE;
877 }
878 break;
879 case GL_POINTS:
880 st1 &= ~ST1_ENABLE;
881 aa |= AA_LINE_DISABLE;
882 break;
883 default:
884 return;
885 }
886
887 imesa->reduced_primitive = rprim;
888
889 if (aa != imesa->Setup[I830_CTXREG_AA]) {
890 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
891 imesa->Setup[I830_CTXREG_AA] = aa;
892 }
893
894 #if 0
895 if (st1 != imesa->StippleSetup[I830_STPREG_ST1]) {
896 I830_STATECHANGE(imesa, I830_UPLOAD_STIPPLE);
897 imesa->StippleSetup[I830_STPREG_ST1] = st1;
898 }
899 #endif
900
901 if (hwprim != imesa->hw_primitive) {
902 I830_STATECHANGE(imesa, 0);
903 imesa->hw_primitive = hwprim;
904 }
905 }
906
907 /**********************************************************************/
908 /* Transition to/from hardware rasterization. */
909 /**********************************************************************/
910
911 static char *fallbackStrings[] = {
912 "Texture",
913 "Draw buffer",
914 "Read buffer",
915 "Color mask",
916 "Render mode",
917 "Stencil",
918 "Stipple",
919 "User disable"
920 };
921
922
923 static char *getFallbackString(GLuint bit)
924 {
925 int i = 0;
926 while (bit > 1) {
927 i++;
928 bit >>= 1;
929 }
930 return fallbackStrings[i];
931 }
932
933
934
935 void i830Fallback( i830ContextPtr imesa, GLuint bit, GLboolean mode )
936 {
937 GLcontext *ctx = imesa->glCtx;
938 TNLcontext *tnl = TNL_CONTEXT(ctx);
939 GLuint oldfallback = imesa->Fallback;
940
941 if (mode) {
942 imesa->Fallback |= bit;
943 if (oldfallback == 0) {
944 I830_FIREVERTICES(imesa);
945 if (I830_DEBUG & DEBUG_FALLBACKS)
946 fprintf(stderr, "ENTER FALLBACK %s\n", getFallbackString( bit ));
947 _swsetup_Wakeup( ctx );
948 imesa->RenderIndex = ~0;
949 }
950 }
951 else {
952 imesa->Fallback &= ~bit;
953 if (oldfallback == bit) {
954 _swrast_flush( ctx );
955 if (I830_DEBUG & DEBUG_FALLBACKS)
956 fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit ));
957 tnl->Driver.Render.Start = i830RenderStart;
958 tnl->Driver.Render.PrimitiveNotify = i830RenderPrimitive;
959 tnl->Driver.Render.Finish = i830RenderFinish;
960
961 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
962 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
963 tnl->Driver.Render.Interp = _tnl_interp;
964
965 _tnl_invalidate_vertex_state( ctx, ~0 );
966 _tnl_invalidate_vertices( ctx, ~0 );
967 _tnl_install_attrs( ctx,
968 imesa->vertex_attrs,
969 imesa->vertex_attr_count,
970 imesa->ViewportMatrix.m, 0 );
971
972 imesa->NewGLState |= _I830_NEW_RENDERSTATE;
973 }
974 }
975 }
976
977
978
979
980 /**********************************************************************/
981 /* Initialization. */
982 /**********************************************************************/
983
984
985 void i830InitTriFuncs( GLcontext *ctx )
986 {
987 TNLcontext *tnl = TNL_CONTEXT(ctx);
988 static int firsttime = 1;
989
990 if (firsttime) {
991 init_rast_tab();
992 firsttime = 0;
993 }
994
995 tnl->Driver.RunPipeline = i830RunPipeline;
996 tnl->Driver.Render.Start = i830RenderStart;
997 tnl->Driver.Render.Finish = i830RenderFinish;
998 tnl->Driver.Render.PrimitiveNotify = i830RenderPrimitive;
999 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
1000 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1001 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1002 tnl->Driver.Render.Interp = _tnl_interp;
1003
1004 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
1005 22 * sizeof(GLfloat) );
1006
1007 I830_CONTEXT(ctx)->verts = (char *)tnl->clipspace.vertex_buf;
1008 }