ff46de18c03970c9ccadc7315f12b904002ef0cd
[mesa.git] / src / mesa / drivers / dri / unichrome / via_tris.c
1 /*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <stdio.h>
26 #include <math.h>
27
28 #include "glheader.h"
29 #include "context.h"
30 #include "mtypes.h"
31 #include "macros.h"
32 #include "colormac.h"
33 #include "enums.h"
34
35 #include "swrast/swrast.h"
36 #include "swrast_setup/swrast_setup.h"
37 #include "tnl/t_context.h"
38 #include "tnl/t_pipeline.h"
39
40 #include "via_context.h"
41 #include "via_tris.h"
42 #include "via_state.h"
43 #include "via_span.h"
44 #include "via_ioctl.h"
45
46 /***********************************************************************
47 * Emit primitives as inline vertices *
48 ***********************************************************************/
49
50 #if 1
51 #define COPY_DWORDS(vb, vertsize, v) \
52 do { \
53 int j; \
54 int __tmp; \
55 __asm__ __volatile__("rep ; movsl" \
56 : "=%c" (j), "=D" (vb), "=S" (__tmp) \
57 : "0" (vertsize), \
58 "D" ((long)vb), \
59 "S" ((long)v)); \
60 } while (0)
61 #else
62 #define COPY_DWORDS(vb, vertsize, v) \
63 do { \
64 int j; \
65 for (j = 0; j < vertsize; j++) \
66 vb[j] = ((GLuint *)v)[j]; \
67 vb += vertsize; \
68 } while (0)
69 #endif
70
71 static void via_draw_triangle(viaContextPtr vmesa,
72 viaVertexPtr v0,
73 viaVertexPtr v1,
74 viaVertexPtr v2)
75 {
76 GLuint vertsize = vmesa->vertexSize;
77 GLuint *vb = viaExtendPrimitive(vmesa, 3 * 4 * vertsize);
78
79 COPY_DWORDS(vb, vertsize, v0);
80 COPY_DWORDS(vb, vertsize, v1);
81 COPY_DWORDS(vb, vertsize, v2);
82 }
83
84
85 static void via_draw_quad(viaContextPtr vmesa,
86 viaVertexPtr v0,
87 viaVertexPtr v1,
88 viaVertexPtr v2,
89 viaVertexPtr v3)
90 {
91 GLuint vertsize = vmesa->vertexSize;
92 GLuint *vb = viaExtendPrimitive(vmesa, 6 * 4 * vertsize);
93
94 COPY_DWORDS(vb, vertsize, v0);
95 COPY_DWORDS(vb, vertsize, v1);
96 COPY_DWORDS(vb, vertsize, v3);
97 COPY_DWORDS(vb, vertsize, v1);
98 COPY_DWORDS(vb, vertsize, v2);
99 COPY_DWORDS(vb, vertsize, v3);
100 }
101
102 static void via_draw_line(viaContextPtr vmesa,
103 viaVertexPtr v0,
104 viaVertexPtr v1)
105 {
106 GLuint vertsize = vmesa->vertexSize;
107 GLuint *vb = viaExtendPrimitive(vmesa, 2 * 4 * vertsize);
108 COPY_DWORDS(vb, vertsize, v0);
109 COPY_DWORDS(vb, vertsize, v1);
110 }
111
112
113 static void via_draw_point(viaContextPtr vmesa,
114 viaVertexPtr v0)
115 {
116 GLuint vertsize = vmesa->vertexSize;
117 GLuint *vb = viaExtendPrimitive(vmesa, 4 * vertsize);
118 COPY_DWORDS(vb, vertsize, v0);
119 }
120
121
122 /* Fallback drawing functions for the ptex hack.
123 */
124 #define PTEX_VERTEX( tmp, vertex_size, v) \
125 do { \
126 GLuint j; \
127 GLfloat rhw = 1.0 / v->f[vertex_size]; \
128 for ( j = 0 ; j < vertex_size ; j++ ) \
129 tmp.f[j] = v->f[j]; \
130 tmp.f[3] *= v->f[vertex_size]; \
131 tmp.f[vertex_size-2] *= rhw; \
132 tmp.f[vertex_size-1] *= rhw; \
133 } while (0)
134
135 static void via_ptex_tri (viaContextPtr vmesa,
136 viaVertexPtr v0,
137 viaVertexPtr v1,
138 viaVertexPtr v2)
139 {
140 GLuint vertsize = vmesa->hwVertexSize;
141 GLuint *vb = viaExtendPrimitive(vmesa, 3*4*vertsize);
142 viaVertex tmp;
143
144 PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp);
145 PTEX_VERTEX(tmp, vertsize, v1); COPY_DWORDS(vb, vertsize, &tmp);
146 PTEX_VERTEX(tmp, vertsize, v2); COPY_DWORDS(vb, vertsize, &tmp);
147 }
148
149 static void via_ptex_line (viaContextPtr vmesa,
150 viaVertexPtr v0,
151 viaVertexPtr v1)
152 {
153 GLuint vertsize = vmesa->hwVertexSize;
154 GLuint *vb = viaExtendPrimitive(vmesa, 2*4*vertsize);
155 viaVertex tmp;
156
157 PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp);
158 PTEX_VERTEX(tmp, vertsize, v1); COPY_DWORDS(vb, vertsize, &tmp);
159 }
160
161 static void via_ptex_point (viaContextPtr vmesa,
162 viaVertexPtr v0)
163 {
164 GLuint vertsize = vmesa->hwVertexSize;
165 GLuint *vb = viaExtendPrimitive(vmesa, 1*4*vertsize);
166 viaVertex tmp;
167
168 PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp);
169 }
170
171
172
173
174
175 /***********************************************************************
176 * Macros for via_dd_tritmp.h to draw basic primitives *
177 ***********************************************************************/
178
179 #define TRI(a, b, c) \
180 do { \
181 if (DO_FALLBACK) \
182 vmesa->drawTri(vmesa, a, b, c); \
183 else \
184 via_draw_triangle(vmesa, a, b, c); \
185 } while (0)
186
187 #define QUAD(a, b, c, d) \
188 do { \
189 if (DO_FALLBACK) { \
190 vmesa->drawTri(vmesa, a, b, d); \
191 vmesa->drawTri(vmesa, b, c, d); \
192 } \
193 else \
194 via_draw_quad(vmesa, a, b, c, d); \
195 } while (0)
196
197 #define LINE(v0, v1) \
198 do { \
199 if (DO_FALLBACK) \
200 vmesa->drawLine(vmesa, v0, v1); \
201 else \
202 via_draw_line(vmesa, v0, v1); \
203 } while (0)
204
205 #define POINT(v0) \
206 do { \
207 if (DO_FALLBACK) \
208 vmesa->drawPoint(vmesa, v0); \
209 else \
210 via_draw_point(vmesa, v0); \
211 } while (0)
212
213
214 /***********************************************************************
215 * Build render functions from dd templates *
216 ***********************************************************************/
217
218 #define VIA_OFFSET_BIT 0x01
219 #define VIA_TWOSIDE_BIT 0x02
220 #define VIA_UNFILLED_BIT 0x04
221 #define VIA_FALLBACK_BIT 0x08
222 #define VIA_MAX_TRIFUNC 0x10
223
224
225 static struct {
226 tnl_points_func points;
227 tnl_line_func line;
228 tnl_triangle_func triangle;
229 tnl_quad_func quad;
230 } rast_tab[VIA_MAX_TRIFUNC];
231
232
233 #define DO_FALLBACK (IND & VIA_FALLBACK_BIT)
234 #define DO_OFFSET (IND & VIA_OFFSET_BIT)
235 #define DO_UNFILLED (IND & VIA_UNFILLED_BIT)
236 #define DO_TWOSIDE (IND & VIA_TWOSIDE_BIT)
237 #define DO_FLAT 0
238 #define DO_TRI 1
239 #define DO_QUAD 1
240 #define DO_LINE 1
241 #define DO_POINTS 1
242 #define DO_FULL_QUAD 1
243
244 #define HAVE_RGBA 1
245 #define HAVE_SPEC 1
246 #define HAVE_BACK_COLORS 0
247 #define HAVE_HW_FLATSHADE 1
248 #define VERTEX viaVertex
249 #define TAB rast_tab
250
251 /* Only used to pull back colors into vertices (ie, we know color is
252 * floating point).
253 */
254 #define VIA_COLOR(dst, src) \
255 do { \
256 dst[0] = src[2]; \
257 dst[1] = src[1]; \
258 dst[2] = src[0]; \
259 dst[3] = src[3]; \
260 } while (0)
261
262 #define VIA_SPEC(dst, src) \
263 do { \
264 dst[0] = src[2]; \
265 dst[1] = src[1]; \
266 dst[2] = src[0]; \
267 } while (0)
268
269
270 #define DEPTH_SCALE vmesa->polygon_offset_scale
271 #define UNFILLED_TRI unfilled_tri
272 #define UNFILLED_QUAD unfilled_quad
273 #define VERT_X(_v) _v->v.x
274 #define VERT_Y(_v) _v->v.y
275 #define VERT_Z(_v) _v->v.z
276 #define AREA_IS_CCW(a) (a > 0)
277 #define GET_VERTEX(e) (vmesa->verts + (e * vmesa->vertexSize * sizeof(int)))
278
279 #define VERT_SET_RGBA( v, c ) \
280 do { \
281 via_color_t *color = (via_color_t *)&((v)->ui[coloroffset]); \
282 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
283 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
284 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
285 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
286 } while (0)
287
288 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
289
290 #define VERT_SET_SPEC( v0, c ) \
291 do { \
292 if (specoffset) { \
293 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
294 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
295 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
296 } \
297 } while (0)
298 #define VERT_COPY_SPEC( v0, v1 ) \
299 do { \
300 if (specoffset) { \
301 v0->v.specular.red = v1->v.specular.red; \
302 v0->v.specular.green = v1->v.specular.green; \
303 v0->v.specular.blue = v1->v.specular.blue; \
304 } \
305 } while (0)
306
307
308 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
309 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
310 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
311 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
312
313
314 #define LOCAL_VARS(n) \
315 viaContextPtr vmesa = VIA_CONTEXT(ctx); \
316 GLuint color[n], spec[n]; \
317 GLuint coloroffset = vmesa->coloroffset; \
318 GLuint specoffset = vmesa->specoffset; \
319 (void)color; (void)spec; (void)coloroffset; (void)specoffset;
320
321
322 /***********************************************************************
323 * Helpers for rendering unfilled primitives *
324 ***********************************************************************/
325
326 static const GLenum hwPrim[GL_POLYGON + 1] = {
327 GL_POINTS,
328 GL_LINES,
329 GL_LINES,
330 GL_LINES,
331 GL_TRIANGLES,
332 GL_TRIANGLES,
333 GL_TRIANGLES,
334 GL_TRIANGLES,
335 GL_TRIANGLES,
336 GL_TRIANGLES
337 };
338
339
340 #define RASTERIZE(x) viaRasterPrimitive( ctx, x, hwPrim[x] )
341 #define RENDER_PRIMITIVE vmesa->renderPrimitive
342 #define TAG(x) x
343 #define IND VIA_FALLBACK_BIT
344 #include "tnl_dd/t_dd_unfilled.h"
345 #undef IND
346 #undef RASTERIZE
347
348 /***********************************************************************
349 * Generate GL render functions *
350 ***********************************************************************/
351 #define RASTERIZE(x)
352
353 #define IND (0)
354 #define TAG(x) x
355 #include "tnl_dd/t_dd_tritmp.h"
356
357 #define IND (VIA_OFFSET_BIT)
358 #define TAG(x) x##_offset
359 #include "tnl_dd/t_dd_tritmp.h"
360
361 #define IND (VIA_TWOSIDE_BIT)
362 #define TAG(x) x##_twoside
363 #include "tnl_dd/t_dd_tritmp.h"
364
365 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT)
366 #define TAG(x) x##_twoside_offset
367 #include "tnl_dd/t_dd_tritmp.h"
368
369 #define IND (VIA_UNFILLED_BIT)
370 #define TAG(x) x##_unfilled
371 #include "tnl_dd/t_dd_tritmp.h"
372
373 #define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT)
374 #define TAG(x) x##_offset_unfilled
375 #include "tnl_dd/t_dd_tritmp.h"
376
377 #define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT)
378 #define TAG(x) x##_twoside_unfilled
379 #include "tnl_dd/t_dd_tritmp.h"
380
381 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT)
382 #define TAG(x) x##_twoside_offset_unfilled
383 #include "tnl_dd/t_dd_tritmp.h"
384
385 #define IND (VIA_FALLBACK_BIT)
386 #define TAG(x) x##_fallback
387 #include "tnl_dd/t_dd_tritmp.h"
388
389 #define IND (VIA_OFFSET_BIT|VIA_FALLBACK_BIT)
390 #define TAG(x) x##_offset_fallback
391 #include "tnl_dd/t_dd_tritmp.h"
392
393 #define IND (VIA_TWOSIDE_BIT|VIA_FALLBACK_BIT)
394 #define TAG(x) x##_twoside_fallback
395 #include "tnl_dd/t_dd_tritmp.h"
396
397 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_FALLBACK_BIT)
398 #define TAG(x) x##_twoside_offset_fallback
399 #include "tnl_dd/t_dd_tritmp.h"
400
401 #define IND (VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
402 #define TAG(x) x##_unfilled_fallback
403 #include "tnl_dd/t_dd_tritmp.h"
404
405 #define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
406 #define TAG(x) x##_offset_unfilled_fallback
407 #include "tnl_dd/t_dd_tritmp.h"
408
409 #define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
410 #define TAG(x) x##_twoside_unfilled_fallback
411 #include "tnl_dd/t_dd_tritmp.h"
412
413 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT| \
414 VIA_FALLBACK_BIT)
415 #define TAG(x) x##_twoside_offset_unfilled_fallback
416 #include "tnl_dd/t_dd_tritmp.h"
417
418
419 static void init_rast_tab(void)
420 {
421 init();
422 init_offset();
423 init_twoside();
424 init_twoside_offset();
425 init_unfilled();
426 init_offset_unfilled();
427 init_twoside_unfilled();
428 init_twoside_offset_unfilled();
429 init_fallback();
430 init_offset_fallback();
431 init_twoside_fallback();
432 init_twoside_offset_fallback();
433 init_unfilled_fallback();
434 init_offset_unfilled_fallback();
435 init_twoside_unfilled_fallback();
436 init_twoside_offset_unfilled_fallback();
437 }
438
439
440 /***********************************************************************
441 * Rasterization fallback helpers *
442 ***********************************************************************/
443
444
445 /* This code is hit only when a mix of accelerated and unaccelerated
446 * primitives are being drawn, and only for the unaccelerated
447 * primitives.
448 */
449 static void
450 via_fallback_tri(viaContextPtr vmesa,
451 viaVertex *v0,
452 viaVertex *v1,
453 viaVertex *v2)
454 {
455 GLcontext *ctx = vmesa->glCtx;
456 SWvertex v[3];
457 _swsetup_Translate(ctx, v0, &v[0]);
458 _swsetup_Translate(ctx, v1, &v[1]);
459 _swsetup_Translate(ctx, v2, &v[2]);
460 viaSpanRenderStart( ctx );
461 _swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
462 viaSpanRenderFinish( ctx );
463 }
464
465
466 static void
467 via_fallback_line(viaContextPtr vmesa,
468 viaVertex *v0,
469 viaVertex *v1)
470 {
471 GLcontext *ctx = vmesa->glCtx;
472 SWvertex v[2];
473 _swsetup_Translate(ctx, v0, &v[0]);
474 _swsetup_Translate(ctx, v1, &v[1]);
475 viaSpanRenderStart( ctx );
476 _swrast_Line(ctx, &v[0], &v[1]);
477 viaSpanRenderFinish( ctx );
478 }
479
480
481 static void
482 via_fallback_point(viaContextPtr vmesa,
483 viaVertex *v0)
484 {
485 GLcontext *ctx = vmesa->glCtx;
486 SWvertex v[1];
487 _swsetup_Translate(ctx, v0, &v[0]);
488 viaSpanRenderStart( ctx );
489 _swrast_Point(ctx, &v[0]);
490 viaSpanRenderFinish( ctx );
491 }
492
493 static void viaResetLineStipple( GLcontext *ctx )
494 {
495 viaContextPtr vmesa = VIA_CONTEXT(ctx);
496 vmesa->regCmdB |= HC_HLPrst_MASK;
497 }
498
499 /**********************************************************************/
500 /* Render unclipped begin/end objects */
501 /**********************************************************************/
502 #define IND 0
503 #define V(x) (viaVertex *)(vertptr + ((x) * vertsize * sizeof(int)))
504 #define RENDER_POINTS(start, count) \
505 for (; start < count; start++) POINT(V(ELT(start)));
506 #define RENDER_LINE(v0, v1) LINE(V(v0), V(v1))
507 #define RENDER_TRI( v0, v1, v2) TRI( V(v0), V(v1), V(v2))
508 #define RENDER_QUAD(v0, v1, v2, v3) QUAD(V(v0), V(v1), V(v2), V(v3))
509 #define INIT(x) viaRasterPrimitive(ctx, x, hwPrim[x])
510 #undef LOCAL_VARS
511 #define LOCAL_VARS \
512 viaContextPtr vmesa = VIA_CONTEXT(ctx); \
513 GLubyte *vertptr = (GLubyte *)vmesa->verts; \
514 const GLuint vertsize = vmesa->vertexSize; \
515 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
516 const GLboolean stipple = ctx->Line.StippleFlag; \
517 (void) elt; (void) stipple;
518 #define RESET_STIPPLE if ( stipple ) { printf("RESET\n"); viaResetLineStipple( ctx ); }
519 #define RESET_OCCLUSION
520 #define PRESERVE_VB_DEFS
521 #define ELT(x) x
522 #define TAG(x) via_##x##_verts
523 #include "tnl/t_vb_rendertmp.h"
524 #undef ELT
525 #undef TAG
526 #define TAG(x) via_##x##_elts
527 #define ELT(x) elt[x]
528 #include "tnl/t_vb_rendertmp.h"
529 #undef ELT
530 #undef TAG
531 #undef NEED_EDGEFLAG_SETUP
532 #undef EDGEFLAG_GET
533 #undef EDGEFLAG_SET
534 #undef RESET_OCCLUSION
535
536
537 /**********************************************************************/
538 /* Render clipped primitives */
539 /**********************************************************************/
540
541
542
543 static void viaRenderClippedPoly(GLcontext *ctx, const GLuint *elts,
544 GLuint n)
545 {
546 TNLcontext *tnl = TNL_CONTEXT(ctx);
547 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
548 GLuint prim = VIA_CONTEXT(ctx)->renderPrimitive;
549
550 /* Render the new vertices as an unclipped polygon.
551 */
552 {
553 GLuint *tmp = VB->Elts;
554 VB->Elts = (GLuint *)elts;
555 tnl->Driver.Render.PrimTabElts[GL_POLYGON](ctx, 0, n,
556 PRIM_BEGIN|PRIM_END);
557 VB->Elts = tmp;
558 }
559
560 /* Restore the render primitive
561 */
562 if (prim != GL_POLYGON)
563 tnl->Driver.Render.PrimitiveNotify( ctx, prim );
564 }
565
566 static void viaRenderClippedLine(GLcontext *ctx, GLuint ii, GLuint jj)
567 {
568 TNLcontext *tnl = TNL_CONTEXT(ctx);
569 tnl->Driver.Render.Line(ctx, ii, jj);
570 }
571
572 static void viaFastRenderClippedPoly(GLcontext *ctx, const GLuint *elts,
573 GLuint n)
574 {
575 viaContextPtr vmesa = VIA_CONTEXT(ctx);
576 GLuint vertsize = vmesa->vertexSize;
577 GLuint *vb = viaExtendPrimitive(vmesa, (n - 2) * 3 * 4 * vertsize);
578 GLubyte *vertptr = (GLubyte *)vmesa->verts;
579 const GLuint *start = (const GLuint *)V(elts[0]);
580 int i;
581
582 for (i = 2; i < n; i++) {
583 COPY_DWORDS(vb, vertsize, V(elts[i - 1]));
584 COPY_DWORDS(vb, vertsize, V(elts[i]));
585 COPY_DWORDS(vb, vertsize, start);
586 }
587 }
588
589 /**********************************************************************/
590 /* Choose render functions */
591 /**********************************************************************/
592
593
594
595
596 #define _VIA_NEW_VERTEX (_NEW_TEXTURE | \
597 _DD_NEW_SEPARATE_SPECULAR | \
598 _DD_NEW_TRI_UNFILLED | \
599 _DD_NEW_TRI_LIGHT_TWOSIDE | \
600 _NEW_FOG)
601
602 #define _VIA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
603 _DD_NEW_TRI_UNFILLED | \
604 _DD_NEW_TRI_LIGHT_TWOSIDE | \
605 _DD_NEW_TRI_OFFSET | \
606 _DD_NEW_TRI_STIPPLE | \
607 _NEW_POLYGONSTIPPLE)
608
609 #define LINE_FALLBACK (0)
610 #define POINT_FALLBACK (0)
611 #define TRI_FALLBACK (0)
612 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
613 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
614
615 static void viaChooseRenderState(GLcontext *ctx)
616 {
617 TNLcontext *tnl = TNL_CONTEXT(ctx);
618 viaContextPtr vmesa = VIA_CONTEXT(ctx);
619 GLuint flags = ctx->_TriangleCaps;
620 GLuint index = 0;
621
622 if (vmesa->ptexHack) {
623 vmesa->drawPoint = via_ptex_point;
624 vmesa->drawLine = via_ptex_line;
625 vmesa->drawTri = via_ptex_tri;
626 index |= VIA_FALLBACK_BIT;
627 }
628 else {
629 vmesa->drawPoint = via_draw_point;
630 vmesa->drawLine = via_draw_line;
631 vmesa->drawTri = via_draw_triangle;
632 }
633
634 if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) {
635 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= VIA_TWOSIDE_BIT;
636 if (flags & DD_TRI_OFFSET) index |= VIA_OFFSET_BIT;
637 if (flags & DD_TRI_UNFILLED) index |= VIA_UNFILLED_BIT;
638 if (flags & ANY_FALLBACK_FLAGS) index |= VIA_FALLBACK_BIT;
639
640 /* Hook in fallbacks for specific primitives.
641 */
642 if (flags & POINT_FALLBACK)
643 vmesa->drawPoint = via_fallback_point;
644
645 if (flags & LINE_FALLBACK)
646 vmesa->drawLine = via_fallback_line;
647
648 if (flags & TRI_FALLBACK)
649 vmesa->drawTri = via_fallback_tri;
650 }
651
652 if (vmesa->renderIndex != index) {
653 vmesa->renderIndex = index;
654
655 tnl->Driver.Render.Points = rast_tab[index].points;
656 tnl->Driver.Render.Line = rast_tab[index].line;
657 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
658 tnl->Driver.Render.Quad = rast_tab[index].quad;
659
660 if (index == 0) {
661 tnl->Driver.Render.PrimTabVerts = via_render_tab_verts;
662 tnl->Driver.Render.PrimTabElts = via_render_tab_elts;
663 tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
664 tnl->Driver.Render.ClippedPolygon = viaFastRenderClippedPoly;
665 }
666 else {
667 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
668 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
669 tnl->Driver.Render.ClippedLine = viaRenderClippedLine;
670 tnl->Driver.Render.ClippedPolygon = viaRenderClippedPoly;
671 }
672 }
673 }
674
675
676 #define VIA_EMIT_TEX1 0x01
677 #define VIA_EMIT_TEX0 0x02
678 #define VIA_EMIT_PTEX0 0x04
679 #define VIA_EMIT_RGBA 0x08
680 #define VIA_EMIT_SPEC 0x10
681 #define VIA_EMIT_FOG 0x20
682 #define VIA_EMIT_W 0x40
683
684 #define EMIT_ATTR( ATTR, STYLE, INDEX, REGB ) \
685 do { \
686 vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = (ATTR); \
687 vmesa->vertex_attrs[vmesa->vertex_attr_count].format = (STYLE); \
688 vmesa->vertex_attr_count++; \
689 setupIndex |= (INDEX); \
690 regCmdB |= (REGB); \
691 } while (0)
692
693 #define EMIT_PAD( N ) \
694 do { \
695 vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = 0; \
696 vmesa->vertex_attrs[vmesa->vertex_attr_count].format = EMIT_PAD; \
697 vmesa->vertex_attrs[vmesa->vertex_attr_count].offset = (N); \
698 vmesa->vertex_attr_count++; \
699 } while (0)
700
701
702
703 static void viaChooseVertexState( GLcontext *ctx )
704 {
705 viaContextPtr vmesa = VIA_CONTEXT(ctx);
706 TNLcontext *tnl = TNL_CONTEXT(ctx);
707 GLuint index = tnl->render_inputs;
708 GLuint regCmdB = HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_Z;
709 GLuint setupIndex = 0;
710
711 vmesa->vertex_attr_count = 0;
712
713 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
714 * build up a hardware vertex.
715 */
716 if (index & (_TNL_BITS_TEX_ANY|_TNL_BIT_FOG)) {
717 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VIA_EMIT_W, HC_HVPMSK_W );
718 vmesa->coloroffset = 4;
719 }
720 else {
721 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
722 vmesa->coloroffset = 3;
723 }
724
725 /* t_context.c always includes a diffuse color */
726 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VIA_EMIT_RGBA, HC_HVPMSK_Cd );
727
728 vmesa->specoffset = 0;
729 if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
730 if ((index & _TNL_BIT_COLOR1)) {
731 vmesa->specoffset = vmesa->coloroffset + 1;
732 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VIA_EMIT_SPEC, HC_HVPMSK_Cs );
733 }
734 else
735 EMIT_PAD( 3 );
736
737 if ((index & _TNL_BIT_FOG))
738 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VIA_EMIT_FOG, HC_HVPMSK_Cs );
739 else
740 EMIT_PAD( 1 );
741 }
742
743 if (index & _TNL_BIT_TEX(0)) {
744 if (vmesa->ptexHack)
745 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, VIA_EMIT_PTEX0, (HC_HVPMSK_S | HC_HVPMSK_T) );
746 else
747 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, VIA_EMIT_TEX0, (HC_HVPMSK_S | HC_HVPMSK_T) );
748 }
749
750 if (index & _TNL_BIT_TEX(1)) {
751 EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, VIA_EMIT_TEX1, (HC_HVPMSK_S | HC_HVPMSK_T) );
752 }
753
754 if (setupIndex != vmesa->setupIndex) {
755 vmesa->vertexSize = _tnl_install_attrs( ctx,
756 vmesa->vertex_attrs,
757 vmesa->vertex_attr_count,
758 vmesa->ViewportMatrix.m, 0 );
759 vmesa->vertexSize >>= 2;
760 vmesa->setupIndex = setupIndex;
761 vmesa->regCmdB &= ~HC_HVPMSK_MASK;
762 vmesa->regCmdB |= regCmdB;
763
764 if (vmesa->ptexHack)
765 vmesa->hwVertexSize = vmesa->vertexSize - 1;
766 else
767 vmesa->hwVertexSize = vmesa->vertexSize;
768 }
769 }
770
771
772
773
774 /* Check if projective texture coordinates are used and if we can fake
775 * them. Fallback to swrast if we can't. Returns GL_TRUE if projective
776 * texture coordinates must be faked, GL_FALSE otherwise.
777 */
778 static GLboolean viaCheckPTexHack( GLcontext *ctx )
779 {
780 TNLcontext *tnl = TNL_CONTEXT(ctx);
781 struct vertex_buffer *VB = &tnl->vb;
782 GLuint index = tnl->render_inputs;
783 GLboolean fallback = GL_FALSE;
784 GLboolean ptexHack = GL_FALSE;
785
786 if (index & _TNL_BIT_TEX(0) && VB->TexCoordPtr[0]->size == 4) {
787 if ((index & _TNL_BITS_TEX_ANY) == _TNL_BIT_TEX(0))
788 ptexHack = GL_TRUE;
789 else
790 fallback = GL_TRUE;
791 }
792 if ((index & _TNL_BIT_TEX(1)) && VB->TexCoordPtr[1]->size == 4)
793 fallback = GL_TRUE;
794
795 FALLBACK(VIA_CONTEXT(ctx), VIA_FALLBACK_PROJ_TEXTURE, fallback);
796 return ptexHack;
797 }
798
799
800
801
802 /**********************************************************************/
803 /* High level hooks for t_vb_render.c */
804 /**********************************************************************/
805
806
807 static void viaRenderStart(GLcontext *ctx)
808 {
809 viaContextPtr vmesa = VIA_CONTEXT(ctx);
810 TNLcontext *tnl = TNL_CONTEXT(ctx);
811 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
812
813 {
814 GLboolean ptexHack = viaCheckPTexHack( ctx );
815 if (ptexHack != vmesa->ptexHack) {
816 vmesa->ptexHack = ptexHack;
817 vmesa->newRenderState |= _VIA_NEW_RENDERSTATE;
818 }
819 }
820
821 if (vmesa->newState) {
822 vmesa->newRenderState |= vmesa->newState;
823 viaValidateState( ctx );
824 }
825
826 if (vmesa->Fallback) {
827 tnl->Driver.Render.Start(ctx);
828 return;
829 }
830
831 if (vmesa->newRenderState) {
832 viaChooseVertexState(ctx);
833 viaChooseRenderState(ctx);
834 vmesa->newRenderState = 0;
835 }
836
837 /* Important:
838 */
839 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
840 }
841
842 static void viaRenderFinish(GLcontext *ctx)
843 {
844 VIA_FINISH_PRIM(VIA_CONTEXT(ctx));
845 }
846
847
848 /* System to flush dma and emit state changes based on the rasterized
849 * primitive.
850 */
851 void viaRasterPrimitive(GLcontext *ctx,
852 GLenum glprim,
853 GLenum hwprim)
854 {
855 viaContextPtr vmesa = VIA_CONTEXT(ctx);
856 GLuint regCmdB;
857 RING_VARS;
858
859 if (VIA_DEBUG)
860 fprintf(stderr, "%s: %s/%s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(glprim),
861 _mesa_lookup_enum_by_nr(hwprim));
862
863 vmesa->renderPrimitive = glprim;
864
865 if (hwprim != vmesa->hwPrimitive) {
866 VIA_FINISH_PRIM(vmesa);
867
868 viaCheckDma( vmesa, 1024 ); /* Ensure no wrapping inside this function */
869
870 if (vmesa->newEmitState) {
871 viaEmitState(vmesa);
872 }
873
874 vmesa->regCmdA_End = HC_ACMD_HCmdA;
875
876 if (ctx->Light.ShadeModel == GL_SMOOTH) {
877 vmesa->regCmdA_End |= HC_HShading_Gouraud;
878 }
879
880 regCmdB = vmesa->regCmdB;
881
882 switch (hwprim) {
883 case GL_POINTS:
884 vmesa->regCmdA_End |= HC_HPMType_Point | HC_HVCycle_Full;
885 vmesa->regCmdA_End |= HC_HShading_Gouraud; /* always Gouraud shade points?!? */
886 break;
887 case GL_LINES:
888 vmesa->regCmdA_End |= HC_HPMType_Line | HC_HVCycle_Full;
889 if (ctx->Light.ShadeModel == GL_FLAT)
890 vmesa->regCmdA_End |= HC_HShading_FlatB;
891 break;
892 case GL_LINE_LOOP:
893 case GL_LINE_STRIP:
894 vmesa->regCmdA_End |= HC_HPMType_Line | HC_HVCycle_AFP |
895 HC_HVCycle_AB | HC_HVCycle_NewB;
896 regCmdB |= HC_HVCycle_AB | HC_HVCycle_NewB | HC_HLPrst_MASK;
897 if (ctx->Light.ShadeModel == GL_FLAT)
898 vmesa->regCmdA_End |= HC_HShading_FlatB;
899 break;
900 case GL_TRIANGLES:
901 vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_Full;
902 if (ctx->Light.ShadeModel == GL_FLAT)
903 vmesa->regCmdA_End |= HC_HShading_FlatC;
904 break;
905 case GL_TRIANGLE_STRIP:
906 vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP |
907 HC_HVCycle_AC | HC_HVCycle_BB | HC_HVCycle_NewC;
908 regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
909 if (ctx->Light.ShadeModel == GL_FLAT)
910 vmesa->regCmdA_End |= HC_HShading_FlatB;
911 break;
912 case GL_TRIANGLE_FAN:
913 vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP |
914 HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
915 regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
916 if (ctx->Light.ShadeModel == GL_FLAT)
917 vmesa->regCmdA_End |= HC_HShading_FlatC;
918 break;
919 case GL_QUADS:
920 abort();
921 return;
922 case GL_QUAD_STRIP:
923 abort();
924 return;
925 case GL_POLYGON:
926 vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP |
927 HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
928 regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
929 if (ctx->Light.ShadeModel == GL_FLAT)
930 vmesa->regCmdA_End |= HC_HShading_FlatC;
931 break;
932 default:
933 abort();
934 return;
935 }
936
937 /* assert((vmesa->dmaLow & 0x4) == 0); */
938
939 if (vmesa->dmaCliprectAddr == ~0) {
940 if (VIA_DEBUG) fprintf(stderr, "reserve cliprect space at %x\n", vmesa->dmaLow);
941 vmesa->dmaCliprectAddr = vmesa->dmaLow;
942 BEGIN_RING(8);
943 OUT_RING( HC_HEADER2 );
944 OUT_RING( (HC_ParaType_NotTex << 16) );
945 OUT_RING( 0xCCCCCCCC );
946 OUT_RING( 0xCCCCCCCC );
947 OUT_RING( 0xCCCCCCCC );
948 OUT_RING( 0xCCCCCCCC );
949 OUT_RING( 0xCCCCCCCC );
950 OUT_RING( 0xCCCCCCCC );
951 ADVANCE_RING();
952 }
953
954 assert(vmesa->dmaLastPrim == 0);
955
956 BEGIN_RING(8);
957 OUT_RING( HC_HEADER2 );
958 OUT_RING( (HC_ParaType_NotTex << 16) );
959 OUT_RING( 0xCCCCCCCC );
960 OUT_RING( 0xDDDDDDDD );
961
962 OUT_RING( HC_HEADER2 );
963 OUT_RING( (HC_ParaType_CmdVdata << 16) );
964 OUT_RING( regCmdB );
965 OUT_RING( vmesa->regCmdA_End );
966 ADVANCE_RING();
967
968 vmesa->hwPrimitive = hwprim;
969 vmesa->dmaLastPrim = vmesa->dmaLow;
970 }
971 else {
972 assert(!vmesa->newEmitState);
973 }
974 }
975
976 /* Callback for mesa:
977 */
978 static void viaRenderPrimitive( GLcontext *ctx, GLuint prim )
979 {
980 viaRasterPrimitive( ctx, prim, hwPrim[prim] );
981 }
982
983
984 void viaFinishPrimitive(viaContextPtr vmesa)
985 {
986 if (VIA_DEBUG)
987 fprintf(stderr, "%s\n", __FUNCTION__);
988
989 if (!vmesa->dmaLastPrim || vmesa->dmaCliprectAddr == ~0) {
990 assert(0);
991 }
992 else if (vmesa->dmaLow != vmesa->dmaLastPrim) {
993 GLuint cmdA = vmesa->regCmdA_End | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK;
994 RING_VARS;
995
996 vmesa->dmaLastPrim = 0;
997
998 /* KW: modified 0x1 to 0x4 below:
999 */
1000 if ((vmesa->dmaLow & 0x4) || !vmesa->useAgp) {
1001 BEGIN_RING_NOCHECK( 1 );
1002 OUT_RING( cmdA );
1003 ADVANCE_RING();
1004 }
1005 else {
1006 BEGIN_RING_NOCHECK( 2 );
1007 OUT_RING( cmdA );
1008 OUT_RING( cmdA );
1009 ADVANCE_RING();
1010 }
1011
1012 if (vmesa->dmaLow > VIA_DMA_HIGHWATER)
1013 viaFlushDma( vmesa );
1014 }
1015 else {
1016 if (VIA_DEBUG)
1017 fprintf(stderr, "remove empty primitive\n");
1018
1019 /* Remove the primitive header:
1020 */
1021 vmesa->dmaLastPrim = 0;
1022 vmesa->dmaLow -= 8 * sizeof(GLuint);
1023
1024 /* Maybe remove the cliprect as well:
1025 */
1026 if (vmesa->dmaCliprectAddr == vmesa->dmaLow - 8 * sizeof(GLuint)) {
1027 vmesa->dmaLow -= 8 * sizeof(GLuint);
1028 vmesa->dmaCliprectAddr = ~0;
1029 }
1030 }
1031
1032 vmesa->renderPrimitive = GL_POLYGON + 1;
1033 vmesa->hwPrimitive = GL_POLYGON + 1;
1034 vmesa->dmaLastPrim = 0;
1035 }
1036
1037
1038 /**********************************************************************/
1039 /* Transition to/from hardware rasterization. */
1040 /**********************************************************************/
1041
1042
1043 void viaFallback(viaContextPtr vmesa, GLuint bit, GLboolean mode)
1044 {
1045 GLcontext *ctx = vmesa->glCtx;
1046 TNLcontext *tnl = TNL_CONTEXT(ctx);
1047 GLuint oldfallback = vmesa->Fallback;
1048 if (VIA_DEBUG) fprintf(stderr, "%s old %x bit %x mode %d\n", __FUNCTION__,
1049 vmesa->Fallback, bit, mode);
1050
1051 if (mode) {
1052 vmesa->Fallback |= bit;
1053 if (oldfallback == 0) {
1054 VIA_FLUSH_DMA(vmesa);
1055 _swsetup_Wakeup(ctx);
1056 vmesa->renderIndex = ~0;
1057 }
1058 }
1059 else {
1060 vmesa->Fallback &= ~bit;
1061 if (oldfallback == bit) {
1062 _swrast_flush( ctx );
1063
1064 tnl->Driver.Render.Start = viaRenderStart;
1065 tnl->Driver.Render.PrimitiveNotify = viaRenderPrimitive;
1066 tnl->Driver.Render.Finish = viaRenderFinish;
1067
1068 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1069 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1070 tnl->Driver.Render.Interp = _tnl_interp;
1071 tnl->Driver.Render.ResetLineStipple = viaResetLineStipple;
1072
1073 _tnl_invalidate_vertex_state( ctx, ~0 );
1074 _tnl_invalidate_vertices( ctx, ~0 );
1075 _tnl_install_attrs( ctx,
1076 vmesa->vertex_attrs,
1077 vmesa->vertex_attr_count,
1078 vmesa->ViewportMatrix.m, 0 );
1079
1080 vmesa->newState |= (_VIA_NEW_RENDERSTATE|_VIA_NEW_VERTEX);
1081 }
1082 }
1083 }
1084
1085
1086 /**********************************************************************/
1087 /* Initialization. */
1088 /**********************************************************************/
1089
1090
1091 void viaInitTriFuncs(GLcontext *ctx)
1092 {
1093 viaContextPtr vmesa = VIA_CONTEXT(ctx);
1094 TNLcontext *tnl = TNL_CONTEXT(ctx);
1095 static int firsttime = 1;
1096
1097 if (firsttime) {
1098 init_rast_tab();
1099 firsttime = 0;
1100 }
1101
1102 tnl->Driver.RunPipeline = _tnl_run_pipeline;
1103 tnl->Driver.Render.Start = viaRenderStart;
1104 tnl->Driver.Render.Finish = viaRenderFinish;
1105 tnl->Driver.Render.PrimitiveNotify = viaRenderPrimitive;
1106 tnl->Driver.Render.ResetLineStipple = viaResetLineStipple;
1107 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1108 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1109 tnl->Driver.Render.Interp = _tnl_interp;
1110
1111 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
1112 (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
1113
1114 vmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf;
1115
1116 }