Tizen 2.0 Release
[profile/ivi/osmesa.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 "main/glheader.h"
34 #include "main/mtypes.h"
35 #include "main/macros.h"
36 #include "main/enums.h"
37 #include "main/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( struct gl_context *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_SPEC         1
222 #define HAVE_BACK_COLORS  0
223 #define HAVE_HW_FLATSHADE 1
224 #define VERTEX            i810Vertex
225 #define TAB               rast_tab
226
227
228 #define DEPTH_SCALE (1.0/0xffff)
229 #define UNFILLED_TRI unfilled_tri
230 #define UNFILLED_QUAD unfilled_quad
231 #define VERT_X(_v) _v->v.x
232 #define VERT_Y(_v) _v->v.y
233 #define VERT_Z(_v) _v->v.z
234 #define AREA_IS_CCW( a ) (a > 0)
235 #define GET_VERTEX(e) (imesa->verts + (e * imesa->vertex_size * sizeof(int)))
236
237 #define VERT_SET_RGBA( v, c )                                   \
238 do {                                                            \
239    i810_color_t *color = (i810_color_t *)&((v)->ui[coloroffset]);       \
240    UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]);                \
241    UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]);              \
242    UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]);               \
243    UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]);              \
244 } while (0)
245
246 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
247
248 #define VERT_SET_SPEC( v0, c )                                  \
249 do {                                                            \
250    if (havespec) {                                              \
251       UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]);     \
252       UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]);   \
253       UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]);    \
254    }                                                            \
255 } while (0)
256 #define VERT_COPY_SPEC( v0, v1 )                        \
257 do {                                                    \
258    if (havespec) {                                      \
259       v0->v.specular.red   = v1->v.specular.red;        \
260       v0->v.specular.green = v1->v.specular.green;      \
261       v0->v.specular.blue  = v1->v.specular.blue;       \
262    }                                                    \
263 } while (0)
264
265 #define VERT_SAVE_RGBA( idx )    color[idx] = v[idx]->ui[coloroffset]
266 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
267 #define VERT_SAVE_SPEC( idx )    if (havespec) spec[idx] = v[idx]->ui[5]
268 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
269
270 #define LOCAL_VARS(n)                                                   \
271    i810ContextPtr imesa = I810_CONTEXT(ctx);                            \
272    GLuint color[n] = { 0 };                                             \
273    GLuint spec[n] = { 0 };                                              \
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    struct gl_context *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    struct gl_context *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    struct gl_context *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( struct gl_context *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( struct gl_context *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( struct gl_context *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(struct gl_context *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( struct gl_context *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( struct gl_context *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( struct gl_context *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( struct gl_context *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( struct gl_context *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    struct gl_context *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( struct gl_context *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 }