1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS 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
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Keith Whitwell <keithw@vmware.com>
26  */
27 
28 #include "c99_math.h"
29 #include "main/glheader.h"
30 #include "main/macros.h"
31 #include "main/mtypes.h"
32 
33 #include "tnl/t_context.h"
34 
35 #include "ss_triangle.h"
36 #include "ss_context.h"
37 
38 #define SS_OFFSET_BIT	    0x1
39 #define SS_TWOSIDE_BIT	    0x2
40 #define SS_UNFILLED_BIT	    0x4
41 #define SS_MAX_TRIFUNC      0x8
42 
43 static tnl_triangle_func tri_tab[SS_MAX_TRIFUNC];
44 static tnl_quad_func     quad_tab[SS_MAX_TRIFUNC];
45 
46 
47 /*
48  * Render a triangle respecting edge flags.
49  */
50 typedef void (* swsetup_edge_render_prim_tri)(struct gl_context *ctx,
51                                               const GLubyte *ef,
52                                               GLuint e0,
53                                               GLuint e1,
54                                               GLuint e2,
55                                               const SWvertex *v0,
56                                               const SWvertex *v1,
57                                               const SWvertex *v2);
58 
59 /*
60  * Render a triangle using lines and respecting edge flags.
61  */
62 static void
_swsetup_edge_render_line_tri(struct gl_context * ctx,const GLubyte * ef,GLuint e0,GLuint e1,GLuint e2,const SWvertex * v0,const SWvertex * v1,const SWvertex * v2)63 _swsetup_edge_render_line_tri(struct gl_context *ctx,
64                               const GLubyte *ef,
65                               GLuint e0,
66                               GLuint e1,
67                               GLuint e2,
68                               const SWvertex *v0,
69                               const SWvertex *v1,
70                               const SWvertex *v2)
71 {
72    SScontext *swsetup = SWSETUP_CONTEXT(ctx);
73 
74    if (swsetup->render_prim == GL_POLYGON) {
75       if (ef[e2]) _swrast_Line( ctx, v2, v0 );
76       if (ef[e0]) _swrast_Line( ctx, v0, v1 );
77       if (ef[e1]) _swrast_Line( ctx, v1, v2 );
78    } else {
79       if (ef[e0]) _swrast_Line( ctx, v0, v1 );
80       if (ef[e1]) _swrast_Line( ctx, v1, v2 );
81       if (ef[e2]) _swrast_Line( ctx, v2, v0 );
82    }
83 }
84 
85 /*
86  * Render a triangle using points and respecting edge flags.
87  */
88 static void
_swsetup_edge_render_point_tri(struct gl_context * ctx,const GLubyte * ef,GLuint e0,GLuint e1,GLuint e2,const SWvertex * v0,const SWvertex * v1,const SWvertex * v2)89 _swsetup_edge_render_point_tri(struct gl_context *ctx,
90                                const GLubyte *ef,
91                                GLuint e0,
92                                GLuint e1,
93                                GLuint e2,
94                                const SWvertex *v0,
95                                const SWvertex *v1,
96                                const SWvertex *v2)
97 {
98    if (ef[e0]) _swrast_Point( ctx, v0 );
99    if (ef[e1]) _swrast_Point( ctx, v1 );
100    if (ef[e2]) _swrast_Point( ctx, v2 );
101 
102    _swrast_flush(ctx);
103 }
104 
105 /*
106  * Render a triangle respecting cull and shade model.
107  */
_swsetup_render_tri(struct gl_context * ctx,GLuint e0,GLuint e1,GLuint e2,GLuint facing,swsetup_edge_render_prim_tri render)108 static void _swsetup_render_tri(struct gl_context *ctx,
109                                 GLuint e0,
110                                 GLuint e1,
111                                 GLuint e2,
112                                 GLuint facing,
113                                 swsetup_edge_render_prim_tri render)
114 {
115    SScontext *swsetup = SWSETUP_CONTEXT(ctx);
116    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
117    GLubyte *ef = VB->EdgeFlag;
118    SWvertex *verts = swsetup->verts;
119    SWvertex *v0 = &verts[e0];
120    SWvertex *v1 = &verts[e1];
121    SWvertex *v2 = &verts[e2];
122 
123    /* cull testing */
124    if (ctx->Polygon.CullFlag) {
125       if (facing == 1 && ctx->Polygon.CullFaceMode != GL_FRONT)
126          return;
127       if (facing == 0 && ctx->Polygon.CullFaceMode != GL_BACK)
128          return;
129    }
130 
131    _swrast_SetFacing(ctx, facing);
132 
133    if (ctx->Light.ShadeModel == GL_FLAT) {
134       GLchan c[2][4];
135       GLfloat s[2][4];
136 
137       /* save colors/indexes for v0, v1 vertices */
138       COPY_CHAN4(c[0], v0->color);
139       COPY_CHAN4(c[1], v1->color);
140       COPY_4V(s[0], v0->attrib[VARYING_SLOT_COL1]);
141       COPY_4V(s[1], v1->attrib[VARYING_SLOT_COL1]);
142 
143       /* copy v2 color/indexes to v0, v1 indexes */
144       COPY_CHAN4(v0->color, v2->color);
145       COPY_CHAN4(v1->color, v2->color);
146       COPY_4V(v0->attrib[VARYING_SLOT_COL1], v2->attrib[VARYING_SLOT_COL1]);
147       COPY_4V(v1->attrib[VARYING_SLOT_COL1], v2->attrib[VARYING_SLOT_COL1]);
148 
149       render(ctx, ef, e0, e1, e2, v0, v1, v2);
150 
151       COPY_CHAN4(v0->color, c[0]);
152       COPY_CHAN4(v1->color, c[1]);
153       COPY_4V(v0->attrib[VARYING_SLOT_COL1], s[0]);
154       COPY_4V(v1->attrib[VARYING_SLOT_COL1], s[1]);
155    }
156    else {
157       render(ctx, ef, e0, e1, e2, v0, v1, v2);
158    }
159 }
160 
161 #define SS_COLOR(a,b) UNCLAMPED_FLOAT_TO_RGBA_CHAN(a,b)
162 #define SS_SPEC(a,b) COPY_4V(a,b)
163 #define SS_IND(a,b) (a = b)
164 
165 #define IND (0)
166 #define TAG(x) x##_rgba
167 #include "ss_tritmp.h"
168 
169 #define IND (SS_OFFSET_BIT)
170 #define TAG(x) x##_offset_rgba
171 #include "ss_tritmp.h"
172 
173 #define IND (SS_TWOSIDE_BIT)
174 #define TAG(x) x##_twoside_rgba
175 #include "ss_tritmp.h"
176 
177 #define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT)
178 #define TAG(x) x##_offset_twoside_rgba
179 #include "ss_tritmp.h"
180 
181 #define IND (SS_UNFILLED_BIT)
182 #define TAG(x) x##_unfilled_rgba
183 #include "ss_tritmp.h"
184 
185 #define IND (SS_OFFSET_BIT|SS_UNFILLED_BIT)
186 #define TAG(x) x##_offset_unfilled_rgba
187 #include "ss_tritmp.h"
188 
189 #define IND (SS_TWOSIDE_BIT|SS_UNFILLED_BIT)
190 #define TAG(x) x##_twoside_unfilled_rgba
191 #include "ss_tritmp.h"
192 
193 #define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT|SS_UNFILLED_BIT)
194 #define TAG(x) x##_offset_twoside_unfilled_rgba
195 #include "ss_tritmp.h"
196 
197 
_swsetup_trifuncs_init(struct gl_context * ctx)198 void _swsetup_trifuncs_init( struct gl_context *ctx )
199 {
200    (void) ctx;
201 
202    init_rgba();
203    init_offset_rgba();
204    init_twoside_rgba();
205    init_offset_twoside_rgba();
206    init_unfilled_rgba();
207    init_offset_unfilled_rgba();
208    init_twoside_unfilled_rgba();
209    init_offset_twoside_unfilled_rgba();
210 }
211 
212 
swsetup_points(struct gl_context * ctx,GLuint first,GLuint last)213 static void swsetup_points( struct gl_context *ctx, GLuint first, GLuint last )
214 {
215    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
216    SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
217    GLuint i;
218 
219    if (VB->Elts) {
220       for (i = first; i < last; i++)
221 	 if (VB->ClipMask[VB->Elts[i]] == 0)
222 	    _swrast_Point( ctx, &verts[VB->Elts[i]] );
223    }
224    else {
225       for (i = first; i < last; i++)
226 	 if (VB->ClipMask[i] == 0)
227 	    _swrast_Point( ctx, &verts[i] );
228    }
229 }
230 
swsetup_line(struct gl_context * ctx,GLuint v0,GLuint v1)231 static void swsetup_line( struct gl_context *ctx, GLuint v0, GLuint v1 )
232 {
233    SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
234    _swrast_Line( ctx, &verts[v0], &verts[v1] );
235 }
236 
237 
238 
_swsetup_choose_trifuncs(struct gl_context * ctx)239 void _swsetup_choose_trifuncs( struct gl_context *ctx )
240 {
241    TNLcontext *tnl = TNL_CONTEXT(ctx);
242    GLuint ind = 0;
243 
244    if (ctx->Polygon.OffsetPoint ||
245        ctx->Polygon.OffsetLine ||
246        ctx->Polygon.OffsetFill)
247       ind |= SS_OFFSET_BIT;
248 
249    if ((ctx->Light.Enabled && ctx->Light.Model.TwoSide) ||
250        (ctx->VertexProgram._Current && ctx->VertexProgram.TwoSideEnabled))
251       ind |= SS_TWOSIDE_BIT;
252 
253    /* We piggyback the two-sided stencil front/back determination on the
254     * unfilled triangle path.
255     */
256    if (ctx->Polygon.FrontMode != GL_FILL ||
257        ctx->Polygon.BackMode != GL_FILL ||
258        (ctx->Stencil.Enabled && ctx->Stencil._TestTwoSide))
259       ind |= SS_UNFILLED_BIT;
260 
261    tnl->Driver.Render.Triangle = tri_tab[ind];
262    tnl->Driver.Render.Quad = quad_tab[ind];
263    tnl->Driver.Render.Line = swsetup_line;
264    tnl->Driver.Render.Points = swsetup_points;
265 }
266