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