2
* Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3
* Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
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:
12
* The above copyright notice and this permission notice (including the
13
* next paragraph) shall be included in all copies or substantial portions
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.
35
#include "swrast/swrast.h"
36
#include "swrast_setup/swrast_setup.h"
37
#include "tnl/t_context.h"
38
#include "tnl/t_pipeline.h"
40
#include "via_context.h"
42
#include "via_state.h"
44
#include "via_ioctl.h"
45
#include "via_3d_reg.h"
48
/***********************************************************************
49
* Emit primitives as inline vertices *
50
***********************************************************************/
51
#define LINE_FALLBACK (0)
52
#define POINT_FALLBACK (0)
53
#define TRI_FALLBACK (0)
54
#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
55
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
59
#define COPY_DWORDS(vb, vertsize, v) \
61
via_sse_memcpy(vb, v, vertsize * 4); \
65
#if defined( USE_X86_ASM )
66
#define COPY_DWORDS(vb, vertsize, v) \
70
__asm__ __volatile__("rep ; movsl" \
71
: "=%c" (j), "=D" (vb), "=S" (__tmp) \
77
#define COPY_DWORDS(vb, vertsize, v) \
80
for (j = 0; j < vertsize; j++) \
81
vb[j] = ((GLuint *)v)[j]; \
87
static void via_draw_triangle(struct via_context *vmesa,
92
GLuint vertsize = vmesa->vertexSize;
93
GLuint *vb = viaExtendPrimitive(vmesa, 3 * 4 * vertsize);
95
COPY_DWORDS(vb, vertsize, v0);
96
COPY_DWORDS(vb, vertsize, v1);
97
COPY_DWORDS(vb, vertsize, v2);
101
static void via_draw_quad(struct via_context *vmesa,
107
GLuint vertsize = vmesa->vertexSize;
108
GLuint *vb = viaExtendPrimitive(vmesa, 6 * 4 * vertsize);
110
COPY_DWORDS(vb, vertsize, v0);
111
COPY_DWORDS(vb, vertsize, v1);
112
COPY_DWORDS(vb, vertsize, v3);
113
COPY_DWORDS(vb, vertsize, v1);
114
COPY_DWORDS(vb, vertsize, v2);
115
COPY_DWORDS(vb, vertsize, v3);
118
static void via_draw_line(struct via_context *vmesa,
122
GLuint vertsize = vmesa->vertexSize;
123
GLuint *vb = viaExtendPrimitive(vmesa, 2 * 4 * vertsize);
124
COPY_DWORDS(vb, vertsize, v0);
125
COPY_DWORDS(vb, vertsize, v1);
129
static void via_draw_point(struct via_context *vmesa,
132
GLuint vertsize = vmesa->vertexSize;
133
GLuint *vb = viaExtendPrimitive(vmesa, 4 * vertsize);
134
COPY_DWORDS(vb, vertsize, v0);
138
/* Fallback drawing functions for the ptex hack.
140
#define PTEX_VERTEX( tmp, vertex_size, v) \
143
GLfloat rhw = 1.0 / v->f[vertex_size]; \
144
for ( j = 0 ; j < vertex_size ; j++ ) \
145
tmp.f[j] = v->f[j]; \
146
tmp.f[3] *= v->f[vertex_size]; \
147
tmp.f[vertex_size-2] *= rhw; \
148
tmp.f[vertex_size-1] *= rhw; \
151
static void via_ptex_tri (struct via_context *vmesa,
156
GLuint vertsize = vmesa->hwVertexSize;
157
GLuint *vb = viaExtendPrimitive(vmesa, 3*4*vertsize);
160
PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp);
161
PTEX_VERTEX(tmp, vertsize, v1); COPY_DWORDS(vb, vertsize, &tmp);
162
PTEX_VERTEX(tmp, vertsize, v2); COPY_DWORDS(vb, vertsize, &tmp);
165
static void via_ptex_line (struct via_context *vmesa,
169
GLuint vertsize = vmesa->hwVertexSize;
170
GLuint *vb = viaExtendPrimitive(vmesa, 2*4*vertsize);
173
PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp);
174
PTEX_VERTEX(tmp, vertsize, v1); COPY_DWORDS(vb, vertsize, &tmp);
177
static void via_ptex_point (struct via_context *vmesa,
180
GLuint vertsize = vmesa->hwVertexSize;
181
GLuint *vb = viaExtendPrimitive(vmesa, 1*4*vertsize);
184
PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp);
191
/***********************************************************************
192
* Macros for via_dd_tritmp.h to draw basic primitives *
193
***********************************************************************/
195
#define TRI(a, b, c) \
198
vmesa->drawTri(vmesa, a, b, c); \
200
via_draw_triangle(vmesa, a, b, c); \
203
#define QUAD(a, b, c, d) \
206
vmesa->drawTri(vmesa, a, b, d); \
207
vmesa->drawTri(vmesa, b, c, d); \
210
via_draw_quad(vmesa, a, b, c, d); \
213
#define LINE(v0, v1) \
216
vmesa->drawLine(vmesa, v0, v1); \
218
via_draw_line(vmesa, v0, v1); \
224
vmesa->drawPoint(vmesa, v0); \
226
via_draw_point(vmesa, v0); \
230
/***********************************************************************
231
* Build render functions from dd templates *
232
***********************************************************************/
234
#define VIA_OFFSET_BIT 0x01
235
#define VIA_TWOSIDE_BIT 0x02
236
#define VIA_UNFILLED_BIT 0x04
237
#define VIA_FALLBACK_BIT 0x08
238
#define VIA_MAX_TRIFUNC 0x10
242
tnl_points_func points;
244
tnl_triangle_func triangle;
246
} rast_tab[VIA_MAX_TRIFUNC + 1];
249
#define DO_FALLBACK (IND & VIA_FALLBACK_BIT)
250
#define DO_OFFSET (IND & VIA_OFFSET_BIT)
251
#define DO_UNFILLED (IND & VIA_UNFILLED_BIT)
252
#define DO_TWOSIDE (IND & VIA_TWOSIDE_BIT)
258
#define DO_FULL_QUAD 1
262
#define HAVE_BACK_COLORS 0
263
#define HAVE_HW_FLATSHADE 1
264
#define VERTEX viaVertex
267
/* Only used to pull back colors into vertices (ie, we know color is
270
#define VIA_COLOR(dst, src) \
278
#define VIA_SPEC(dst, src) \
286
#define DEPTH_SCALE vmesa->polygon_offset_scale
287
#define UNFILLED_TRI unfilled_tri
288
#define UNFILLED_QUAD unfilled_quad
289
#define VERT_X(_v) _v->v.x
290
#define VERT_Y(_v) _v->v.y
291
#define VERT_Z(_v) _v->v.z
292
#define AREA_IS_CCW(a) (a > 0)
293
#define GET_VERTEX(e) (vmesa->verts + (e * vmesa->vertexSize * sizeof(int)))
295
#define VERT_SET_RGBA( v, c ) \
297
via_color_t *color = (via_color_t *)&((v)->ui[coloroffset]); \
298
UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
299
UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
300
UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
301
UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
304
#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
306
#define VERT_SET_SPEC( v, c ) \
309
via_color_t *color = (via_color_t *)&((v)->ui[specoffset]); \
310
UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
311
UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
312
UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
315
#define VERT_COPY_SPEC( v0, v1 ) \
318
v0->ub4[specoffset][0] = v1->ub4[specoffset][0]; \
319
v0->ub4[specoffset][1] = v1->ub4[specoffset][1]; \
320
v0->ub4[specoffset][2] = v1->ub4[specoffset][2]; \
325
#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
326
#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
327
#define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
328
#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
331
#define LOCAL_VARS(n) \
332
struct via_context *vmesa = VIA_CONTEXT(ctx); \
333
GLuint color[n], spec[n]; \
334
GLuint coloroffset = vmesa->coloroffset; \
335
GLuint specoffset = vmesa->specoffset; \
336
(void)color; (void)spec; (void)coloroffset; (void)specoffset;
339
/***********************************************************************
340
* Helpers for rendering unfilled primitives *
341
***********************************************************************/
343
static const GLenum hwPrim[GL_POLYGON + 2] = {
358
#define RASTERIZE(x) viaRasterPrimitive( ctx, x, hwPrim[x] )
359
#define RENDER_PRIMITIVE vmesa->renderPrimitive
361
#define IND VIA_FALLBACK_BIT
362
#include "tnl_dd/t_dd_unfilled.h"
366
/***********************************************************************
367
* Generate GL render functions *
368
***********************************************************************/
373
#include "tnl_dd/t_dd_tritmp.h"
375
#define IND (VIA_OFFSET_BIT)
376
#define TAG(x) x##_offset
377
#include "tnl_dd/t_dd_tritmp.h"
379
#define IND (VIA_TWOSIDE_BIT)
380
#define TAG(x) x##_twoside
381
#include "tnl_dd/t_dd_tritmp.h"
383
#define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT)
384
#define TAG(x) x##_twoside_offset
385
#include "tnl_dd/t_dd_tritmp.h"
387
#define IND (VIA_UNFILLED_BIT)
388
#define TAG(x) x##_unfilled
389
#include "tnl_dd/t_dd_tritmp.h"
391
#define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT)
392
#define TAG(x) x##_offset_unfilled
393
#include "tnl_dd/t_dd_tritmp.h"
395
#define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT)
396
#define TAG(x) x##_twoside_unfilled
397
#include "tnl_dd/t_dd_tritmp.h"
399
#define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT)
400
#define TAG(x) x##_twoside_offset_unfilled
401
#include "tnl_dd/t_dd_tritmp.h"
403
#define IND (VIA_FALLBACK_BIT)
404
#define TAG(x) x##_fallback
405
#include "tnl_dd/t_dd_tritmp.h"
407
#define IND (VIA_OFFSET_BIT|VIA_FALLBACK_BIT)
408
#define TAG(x) x##_offset_fallback
409
#include "tnl_dd/t_dd_tritmp.h"
411
#define IND (VIA_TWOSIDE_BIT|VIA_FALLBACK_BIT)
412
#define TAG(x) x##_twoside_fallback
413
#include "tnl_dd/t_dd_tritmp.h"
415
#define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_FALLBACK_BIT)
416
#define TAG(x) x##_twoside_offset_fallback
417
#include "tnl_dd/t_dd_tritmp.h"
419
#define IND (VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
420
#define TAG(x) x##_unfilled_fallback
421
#include "tnl_dd/t_dd_tritmp.h"
423
#define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
424
#define TAG(x) x##_offset_unfilled_fallback
425
#include "tnl_dd/t_dd_tritmp.h"
427
#define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
428
#define TAG(x) x##_twoside_unfilled_fallback
429
#include "tnl_dd/t_dd_tritmp.h"
431
#define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT| \
433
#define TAG(x) x##_twoside_offset_unfilled_fallback
434
#include "tnl_dd/t_dd_tritmp.h"
437
/* Catchall case for flat, separate specular triangles (via has flat
438
* diffuse shading, but always does specular color with gouraud).
445
#define DO_FALLBACK (0)
446
#define DO_OFFSET (ctx->_TriangleCaps & DD_TRI_OFFSET)
447
#define DO_UNFILLED (ctx->_TriangleCaps & DD_TRI_UNFILLED)
448
#define DO_TWOSIDE (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE)
450
#define TAG(x) x##_flat_specular
451
#define IND VIA_MAX_TRIFUNC
452
#include "tnl_dd/t_dd_tritmp.h"
455
static void init_rast_tab(void)
460
init_twoside_offset();
462
init_offset_unfilled();
463
init_twoside_unfilled();
464
init_twoside_offset_unfilled();
466
init_offset_fallback();
467
init_twoside_fallback();
468
init_twoside_offset_fallback();
469
init_unfilled_fallback();
470
init_offset_unfilled_fallback();
471
init_twoside_unfilled_fallback();
472
init_twoside_offset_unfilled_fallback();
474
init_flat_specular(); /* special! */
478
/***********************************************************************
479
* Rasterization fallback helpers *
480
***********************************************************************/
483
/* This code is hit only when a mix of accelerated and unaccelerated
484
* primitives are being drawn, and only for the unaccelerated
488
via_fallback_tri(struct via_context *vmesa,
493
GLcontext *ctx = vmesa->glCtx;
495
_swsetup_Translate(ctx, v0, &v[0]);
496
_swsetup_Translate(ctx, v1, &v[1]);
497
_swsetup_Translate(ctx, v2, &v[2]);
498
viaSpanRenderStart( ctx );
499
_swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
500
viaSpanRenderFinish( ctx );
505
via_fallback_line(struct via_context *vmesa,
509
GLcontext *ctx = vmesa->glCtx;
511
_swsetup_Translate(ctx, v0, &v[0]);
512
_swsetup_Translate(ctx, v1, &v[1]);
513
viaSpanRenderStart( ctx );
514
_swrast_Line(ctx, &v[0], &v[1]);
515
viaSpanRenderFinish( ctx );
520
via_fallback_point(struct via_context *vmesa,
523
GLcontext *ctx = vmesa->glCtx;
525
_swsetup_Translate(ctx, v0, &v[0]);
526
viaSpanRenderStart( ctx );
527
_swrast_Point(ctx, &v[0]);
528
viaSpanRenderFinish( ctx );
531
static void viaResetLineStipple( GLcontext *ctx )
533
struct via_context *vmesa = VIA_CONTEXT(ctx);
534
vmesa->regCmdB |= HC_HLPrst_MASK;
537
/**********************************************************************/
538
/* Render unclipped begin/end objects */
539
/**********************************************************************/
541
#define V(x) (viaVertex *)(vertptr + ((x) * vertsize * sizeof(int)))
542
#define RENDER_POINTS(start, count) \
543
for (; start < count; start++) POINT(V(ELT(start)));
544
#define RENDER_LINE(v0, v1) LINE(V(v0), V(v1))
545
#define RENDER_TRI( v0, v1, v2) TRI( V(v0), V(v1), V(v2))
546
#define RENDER_QUAD(v0, v1, v2, v3) QUAD(V(v0), V(v1), V(v2), V(v3))
547
#define INIT(x) viaRasterPrimitive(ctx, x, hwPrim[x])
550
struct via_context *vmesa = VIA_CONTEXT(ctx); \
551
GLubyte *vertptr = (GLubyte *)vmesa->verts; \
552
const GLuint vertsize = vmesa->vertexSize; \
553
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
554
const GLboolean stipple = ctx->Line.StippleFlag; \
555
(void) elt; (void) stipple;
556
#define RESET_STIPPLE if ( stipple ) viaResetLineStipple( ctx );
557
#define RESET_OCCLUSION
558
#define PRESERVE_VB_DEFS
560
#define TAG(x) via_##x##_verts
561
#include "tnl/t_vb_rendertmp.h"
564
#define TAG(x) via_##x##_elts
565
#define ELT(x) elt[x]
566
#include "tnl/t_vb_rendertmp.h"
569
#undef NEED_EDGEFLAG_SETUP
572
#undef RESET_OCCLUSION
575
/**********************************************************************/
576
/* Render clipped primitives */
577
/**********************************************************************/
581
static void viaRenderClippedPoly(GLcontext *ctx, const GLuint *elts,
584
TNLcontext *tnl = TNL_CONTEXT(ctx);
585
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
586
GLuint prim = VIA_CONTEXT(ctx)->renderPrimitive;
588
/* Render the new vertices as an unclipped polygon.
591
GLuint *tmp = VB->Elts;
592
VB->Elts = (GLuint *)elts;
593
tnl->Driver.Render.PrimTabElts[GL_POLYGON](ctx, 0, n,
594
PRIM_BEGIN|PRIM_END);
598
/* Restore the render primitive
600
if (prim != GL_POLYGON &&
601
prim != GL_POLYGON + 1)
602
tnl->Driver.Render.PrimitiveNotify( ctx, prim );
605
static void viaRenderClippedLine(GLcontext *ctx, GLuint ii, GLuint jj)
607
TNLcontext *tnl = TNL_CONTEXT(ctx);
608
tnl->Driver.Render.Line(ctx, ii, jj);
611
static void viaFastRenderClippedPoly(GLcontext *ctx, const GLuint *elts,
614
struct via_context *vmesa = VIA_CONTEXT(ctx);
615
GLuint vertsize = vmesa->vertexSize;
616
GLuint *vb = viaExtendPrimitive(vmesa, (n - 2) * 3 * 4 * vertsize);
617
GLubyte *vertptr = (GLubyte *)vmesa->verts;
618
const GLuint *start = (const GLuint *)V(elts[0]);
621
for (i = 2; i < n; i++) {
622
COPY_DWORDS(vb, vertsize, V(elts[i - 1]));
623
COPY_DWORDS(vb, vertsize, V(elts[i]));
624
COPY_DWORDS(vb, vertsize, start);
629
/**********************************************************************/
630
/* Choose render functions */
631
/**********************************************************************/
634
#define _VIA_NEW_VERTEX (_NEW_TEXTURE | \
635
_DD_NEW_SEPARATE_SPECULAR | \
636
_DD_NEW_TRI_UNFILLED | \
637
_DD_NEW_TRI_LIGHT_TWOSIDE | \
640
#define _VIA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
641
_DD_NEW_TRI_UNFILLED | \
642
_DD_NEW_TRI_LIGHT_TWOSIDE | \
643
_DD_NEW_TRI_OFFSET | \
644
_DD_NEW_TRI_STIPPLE | \
648
static void viaChooseRenderState(GLcontext *ctx)
650
TNLcontext *tnl = TNL_CONTEXT(ctx);
651
struct via_context *vmesa = VIA_CONTEXT(ctx);
652
GLuint flags = ctx->_TriangleCaps;
655
if (vmesa->ptexHack) {
656
vmesa->drawPoint = via_ptex_point;
657
vmesa->drawLine = via_ptex_line;
658
vmesa->drawTri = via_ptex_tri;
659
index |= VIA_FALLBACK_BIT;
662
vmesa->drawPoint = via_draw_point;
663
vmesa->drawLine = via_draw_line;
664
vmesa->drawTri = via_draw_triangle;
667
if (flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) {
668
if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
669
index |= VIA_TWOSIDE_BIT;
670
if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
671
index |= VIA_UNFILLED_BIT;
672
if (flags & DD_TRI_OFFSET)
673
index |= VIA_OFFSET_BIT;
674
if (flags & ANY_FALLBACK_FLAGS)
675
index |= VIA_FALLBACK_BIT;
677
/* Hook in fallbacks for specific primitives. */
678
if (flags & POINT_FALLBACK)
679
vmesa->drawPoint = via_fallback_point;
681
if (flags & LINE_FALLBACK)
682
vmesa->drawLine = via_fallback_line;
684
if (flags & TRI_FALLBACK)
685
vmesa->drawTri = via_fallback_tri;
688
if ((flags & DD_SEPARATE_SPECULAR) && ctx->Light.ShadeModel == GL_FLAT)
689
index = VIA_MAX_TRIFUNC; /* flat specular */
691
if (vmesa->renderIndex != index) {
692
vmesa->renderIndex = index;
694
tnl->Driver.Render.Points = rast_tab[index].points;
695
tnl->Driver.Render.Line = rast_tab[index].line;
696
tnl->Driver.Render.Triangle = rast_tab[index].triangle;
697
tnl->Driver.Render.Quad = rast_tab[index].quad;
700
tnl->Driver.Render.PrimTabVerts = via_render_tab_verts;
701
tnl->Driver.Render.PrimTabElts = via_render_tab_elts;
702
tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
703
tnl->Driver.Render.ClippedPolygon = viaFastRenderClippedPoly;
706
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
707
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
708
tnl->Driver.Render.ClippedLine = viaRenderClippedLine;
709
tnl->Driver.Render.ClippedPolygon = viaRenderClippedPoly;
715
#define VIA_EMIT_TEX1 0x01
716
#define VIA_EMIT_TEX0 0x02
717
#define VIA_EMIT_PTEX0 0x04
718
#define VIA_EMIT_RGBA 0x08
719
#define VIA_EMIT_SPEC 0x10
720
#define VIA_EMIT_FOG 0x20
721
#define VIA_EMIT_W 0x40
723
#define EMIT_ATTR( ATTR, STYLE, INDEX, REGB ) \
725
vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = (ATTR); \
726
vmesa->vertex_attrs[vmesa->vertex_attr_count].format = (STYLE); \
727
vmesa->vertex_attr_count++; \
728
setupIndex |= (INDEX); \
732
#define EMIT_PAD( N ) \
734
vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = 0; \
735
vmesa->vertex_attrs[vmesa->vertex_attr_count].format = EMIT_PAD; \
736
vmesa->vertex_attrs[vmesa->vertex_attr_count].offset = (N); \
737
vmesa->vertex_attr_count++; \
742
static void viaChooseVertexState( GLcontext *ctx )
744
struct via_context *vmesa = VIA_CONTEXT(ctx);
745
TNLcontext *tnl = TNL_CONTEXT(ctx);
746
DECLARE_RENDERINPUTS(index_bitset);
747
GLuint regCmdB = HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_Z;
748
GLuint setupIndex = 0;
750
RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
751
vmesa->vertex_attr_count = 0;
753
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to
754
* build up a hardware vertex.
756
if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) ||
757
RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
758
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VIA_EMIT_W, HC_HVPMSK_W );
759
vmesa->coloroffset = 4;
762
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
763
vmesa->coloroffset = 3;
766
/* t_context.c always includes a diffuse color */
767
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VIA_EMIT_RGBA,
770
vmesa->specoffset = 0;
771
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
772
RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
773
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
774
vmesa->specoffset = vmesa->coloroffset + 1;
775
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VIA_EMIT_SPEC,
781
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
782
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VIA_EMIT_FOG, HC_HVPMSK_Cs );
787
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
789
EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, VIA_EMIT_PTEX0,
790
(HC_HVPMSK_S | HC_HVPMSK_T) );
792
EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, VIA_EMIT_TEX0,
793
(HC_HVPMSK_S | HC_HVPMSK_T) );
796
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) {
797
EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, VIA_EMIT_TEX1,
798
(HC_HVPMSK_S | HC_HVPMSK_T) );
801
if (setupIndex != vmesa->setupIndex) {
802
vmesa->vertexSize = _tnl_install_attrs( ctx,
804
vmesa->vertex_attr_count,
805
vmesa->ViewportMatrix.m, 0 );
806
vmesa->vertexSize >>= 2;
807
vmesa->setupIndex = setupIndex;
808
vmesa->regCmdB &= ~HC_HVPMSK_MASK;
809
vmesa->regCmdB |= regCmdB;
812
vmesa->hwVertexSize = vmesa->vertexSize - 1;
814
vmesa->hwVertexSize = vmesa->vertexSize;
821
/* Check if projective texture coordinates are used and if we can fake
822
* them. Fallback to swrast if we can't. Returns GL_TRUE if projective
823
* texture coordinates must be faked, GL_FALSE otherwise.
825
static GLboolean viaCheckPTexHack( GLcontext *ctx )
827
TNLcontext *tnl = TNL_CONTEXT(ctx);
828
struct vertex_buffer *VB = &tnl->vb;
829
DECLARE_RENDERINPUTS(index_bitset);
830
GLboolean fallback = GL_FALSE;
831
GLboolean ptexHack = GL_FALSE;
833
RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
835
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 ) && VB->TexCoordPtr[0]->size == 4) {
836
if (!RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_ATTRIB_TEX1, _TNL_LAST_TEX ))
841
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 ) && VB->TexCoordPtr[1]->size == 4)
844
FALLBACK(VIA_CONTEXT(ctx), VIA_FALLBACK_PROJ_TEXTURE, fallback);
851
/**********************************************************************/
852
/* High level hooks for t_vb_render.c */
853
/**********************************************************************/
856
static void viaRenderStart(GLcontext *ctx)
858
struct via_context *vmesa = VIA_CONTEXT(ctx);
859
TNLcontext *tnl = TNL_CONTEXT(ctx);
860
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
863
GLboolean ptexHack = viaCheckPTexHack( ctx );
864
if (ptexHack != vmesa->ptexHack) {
865
vmesa->ptexHack = ptexHack;
866
vmesa->newRenderState |= _VIA_NEW_RENDERSTATE;
870
if (vmesa->newState) {
871
vmesa->newRenderState |= vmesa->newState;
872
viaValidateState( ctx );
875
if (vmesa->Fallback) {
876
tnl->Driver.Render.Start(ctx);
880
if (vmesa->newRenderState) {
881
viaChooseVertexState(ctx);
882
viaChooseRenderState(ctx);
883
vmesa->newRenderState = 0;
888
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
891
static void viaRenderFinish(GLcontext *ctx)
893
VIA_FINISH_PRIM(VIA_CONTEXT(ctx));
897
/* System to flush dma and emit state changes based on the rasterized
900
void viaRasterPrimitive(GLcontext *ctx,
904
struct via_context *vmesa = VIA_CONTEXT(ctx);
908
if (VIA_DEBUG & DEBUG_PRIMS)
909
fprintf(stderr, "%s: %s/%s/%s\n",
910
__FUNCTION__, _mesa_lookup_enum_by_nr(glprim),
911
_mesa_lookup_enum_by_nr(hwprim),
912
_mesa_lookup_enum_by_nr(ctx->Light.ShadeModel));
914
assert (!vmesa->newState);
916
vmesa->renderPrimitive = glprim;
918
if (hwprim != vmesa->hwPrimitive ||
919
ctx->Light.ShadeModel != vmesa->hwShadeModel) {
921
VIA_FINISH_PRIM(vmesa);
923
/* Ensure no wrapping inside this function */
924
viaCheckDma( vmesa, 1024 );
926
if (vmesa->newEmitState) {
930
vmesa->regCmdA_End = HC_ACMD_HCmdA;
932
if (ctx->Light.ShadeModel == GL_SMOOTH) {
933
vmesa->regCmdA_End |= HC_HShading_Gouraud;
936
vmesa->hwShadeModel = ctx->Light.ShadeModel;
937
regCmdB = vmesa->regCmdB;
941
vmesa->regCmdA_End |= HC_HPMType_Point | HC_HVCycle_Full;
942
vmesa->regCmdA_End |= HC_HShading_Gouraud; /* always Gouraud
946
vmesa->regCmdA_End |= HC_HPMType_Line | HC_HVCycle_Full;
947
regCmdB |= HC_HLPrst_MASK;
948
if (ctx->Light.ShadeModel == GL_FLAT)
949
vmesa->regCmdA_End |= HC_HShading_FlatB;
953
vmesa->regCmdA_End |= HC_HPMType_Line | HC_HVCycle_AFP |
954
HC_HVCycle_AB | HC_HVCycle_NewB;
955
regCmdB |= HC_HVCycle_AB | HC_HVCycle_NewB | HC_HLPrst_MASK;
956
if (ctx->Light.ShadeModel == GL_FLAT)
957
vmesa->regCmdA_End |= HC_HShading_FlatB;
960
vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_Full;
961
if (ctx->Light.ShadeModel == GL_FLAT)
962
vmesa->regCmdA_End |= HC_HShading_FlatC;
964
case GL_TRIANGLE_STRIP:
965
vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP |
966
HC_HVCycle_AC | HC_HVCycle_BB | HC_HVCycle_NewC;
967
regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
968
if (ctx->Light.ShadeModel == GL_FLAT)
969
vmesa->regCmdA_End |= HC_HShading_FlatC;
971
case GL_TRIANGLE_FAN:
972
vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP |
973
HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
974
regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
975
if (ctx->Light.ShadeModel == GL_FLAT)
976
vmesa->regCmdA_End |= HC_HShading_FlatC;
985
vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP |
986
HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
987
regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
988
if (ctx->Light.ShadeModel == GL_FLAT)
989
vmesa->regCmdA_End |= HC_HShading_FlatC;
996
/* assert((vmesa->dmaLow & 0x4) == 0); */
998
if (vmesa->dmaCliprectAddr == ~0) {
999
if (VIA_DEBUG & DEBUG_DMA)
1000
fprintf(stderr, "reserve cliprect space at %x\n", vmesa->dmaLow);
1001
vmesa->dmaCliprectAddr = vmesa->dmaLow;
1003
OUT_RING( HC_HEADER2 );
1004
OUT_RING( (HC_ParaType_NotTex << 16) );
1005
OUT_RING( 0xCCCCCCCC );
1006
OUT_RING( 0xCCCCCCCC );
1007
OUT_RING( 0xCCCCCCCC );
1008
OUT_RING( 0xCCCCCCCC );
1009
OUT_RING( 0xCCCCCCCC );
1010
OUT_RING( 0xCCCCCCCC );
1014
assert(vmesa->dmaLastPrim == 0);
1017
OUT_RING( HC_HEADER2 );
1018
OUT_RING( (HC_ParaType_NotTex << 16) );
1019
OUT_RING( 0xCCCCCCCC );
1020
OUT_RING( 0xDDDDDDDD );
1022
OUT_RING( HC_HEADER2 );
1023
OUT_RING( (HC_ParaType_CmdVdata << 16) );
1024
OUT_RING( regCmdB );
1025
OUT_RING( vmesa->regCmdA_End );
1028
vmesa->hwPrimitive = hwprim;
1029
vmesa->dmaLastPrim = vmesa->dmaLow;
1032
assert(!vmesa->newEmitState);
1036
/* Callback for mesa:
1038
static void viaRenderPrimitive( GLcontext *ctx, GLuint prim )
1040
viaRasterPrimitive( ctx, prim, hwPrim[prim] );
1044
void viaFinishPrimitive(struct via_context *vmesa)
1046
if (VIA_DEBUG & (DEBUG_DMA|DEBUG_PRIMS))
1047
fprintf(stderr, "%s\n", __FUNCTION__);
1049
if (!vmesa->dmaLastPrim || vmesa->dmaCliprectAddr == ~0) {
1052
else if (vmesa->dmaLow != vmesa->dmaLastPrim) {
1053
GLuint cmdA = (vmesa->regCmdA_End | HC_HPLEND_MASK |
1054
HC_HPMValidN_MASK | HC_HE3Fire_MASK);
1057
vmesa->dmaLastPrim = 0;
1059
/* KW: modified 0x1 to 0x4 below:
1061
if ((vmesa->dmaLow & 0x4) || !vmesa->useAgp) {
1062
BEGIN_RING_NOCHECK( 1 );
1067
BEGIN_RING_NOCHECK( 2 );
1073
if (vmesa->dmaLow > VIA_DMA_HIGHWATER)
1074
viaFlushDma( vmesa );
1077
if (VIA_DEBUG & (DEBUG_DMA|DEBUG_PRIMS))
1078
fprintf(stderr, "remove empty primitive\n");
1080
/* Remove the primitive header:
1082
vmesa->dmaLastPrim = 0;
1083
vmesa->dmaLow -= 8 * sizeof(GLuint);
1085
/* Maybe remove the cliprect as well:
1087
if (vmesa->dmaCliprectAddr == vmesa->dmaLow - 8 * sizeof(GLuint)) {
1088
vmesa->dmaLow -= 8 * sizeof(GLuint);
1089
vmesa->dmaCliprectAddr = ~0;
1093
vmesa->renderPrimitive = GL_POLYGON + 1;
1094
vmesa->hwPrimitive = GL_POLYGON + 1;
1095
vmesa->dmaLastPrim = 0;
1099
/**********************************************************************/
1100
/* Transition to/from hardware rasterization. */
1101
/**********************************************************************/
1104
void viaFallback(struct via_context *vmesa, GLuint bit, GLboolean mode)
1106
GLcontext *ctx = vmesa->glCtx;
1107
TNLcontext *tnl = TNL_CONTEXT(ctx);
1108
GLuint oldfallback = vmesa->Fallback;
1111
vmesa->Fallback |= bit;
1112
if (oldfallback == 0) {
1113
VIA_FLUSH_DMA(vmesa);
1115
if (VIA_DEBUG & DEBUG_FALLBACKS)
1116
fprintf(stderr, "ENTER FALLBACK %x\n", bit);
1118
_swsetup_Wakeup(ctx);
1119
vmesa->renderIndex = ~0;
1123
vmesa->Fallback &= ~bit;
1124
if (oldfallback == bit) {
1125
_swrast_flush( ctx );
1127
if (VIA_DEBUG & DEBUG_FALLBACKS)
1128
fprintf(stderr, "LEAVE FALLBACK %x\n", bit);
1130
tnl->Driver.Render.Start = viaRenderStart;
1131
tnl->Driver.Render.PrimitiveNotify = viaRenderPrimitive;
1132
tnl->Driver.Render.Finish = viaRenderFinish;
1134
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1135
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1136
tnl->Driver.Render.Interp = _tnl_interp;
1137
tnl->Driver.Render.ResetLineStipple = viaResetLineStipple;
1139
_tnl_invalidate_vertex_state( ctx, ~0 );
1140
_tnl_invalidate_vertices( ctx, ~0 );
1141
_tnl_install_attrs( ctx,
1142
vmesa->vertex_attrs,
1143
vmesa->vertex_attr_count,
1144
vmesa->ViewportMatrix.m, 0 );
1146
vmesa->newState |= (_VIA_NEW_RENDERSTATE|_VIA_NEW_VERTEX);
1151
static void viaRunPipeline( GLcontext *ctx )
1153
struct via_context *vmesa = VIA_CONTEXT(ctx);
1155
if (vmesa->newState) {
1156
vmesa->newRenderState |= vmesa->newState;
1157
viaValidateState( ctx );
1160
_tnl_run_pipeline( ctx );
1164
/**********************************************************************/
1165
/* Initialization. */
1166
/**********************************************************************/
1169
void viaInitTriFuncs(GLcontext *ctx)
1171
struct via_context *vmesa = VIA_CONTEXT(ctx);
1172
TNLcontext *tnl = TNL_CONTEXT(ctx);
1173
static int firsttime = 1;
1180
tnl->Driver.RunPipeline = viaRunPipeline;
1181
tnl->Driver.Render.Start = viaRenderStart;
1182
tnl->Driver.Render.Finish = viaRenderFinish;
1183
tnl->Driver.Render.PrimitiveNotify = viaRenderPrimitive;
1184
tnl->Driver.Render.ResetLineStipple = viaResetLineStipple;
1185
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1186
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1187
tnl->Driver.Render.Interp = _tnl_interp;
1189
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
1190
(6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
1192
vmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf;