• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "main/stencil.h"
33 #include "main/state.h"
34 
35 #include "tnl/t_context.h"
36 
37 #include "ss_triangle.h"
38 #include "ss_context.h"
39 
40 #define SS_OFFSET_BIT	    0x1
41 #define SS_TWOSIDE_BIT	    0x2
42 #define SS_UNFILLED_BIT	    0x4
43 #define SS_MAX_TRIFUNC      0x8
44 
45 static tnl_triangle_func tri_tab[SS_MAX_TRIFUNC];
46 static tnl_quad_func     quad_tab[SS_MAX_TRIFUNC];
47 
48 
49 /*
50  * Render a triangle respecting edge flags.
51  */
52 typedef void (* swsetup_edge_render_prim_tri)(struct gl_context *ctx,
53                                               const GLubyte *ef,
54                                               GLuint e0,
55                                               GLuint e1,
56                                               GLuint e2,
57                                               const SWvertex *v0,
58                                               const SWvertex *v1,
59                                               const SWvertex *v2);
60 
61 /*
62  * Render a triangle using lines and respecting edge flags.
63  */
64 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)65 _swsetup_edge_render_line_tri(struct gl_context *ctx,
66                               const GLubyte *ef,
67                               GLuint e0,
68                               GLuint e1,
69                               GLuint e2,
70                               const SWvertex *v0,
71                               const SWvertex *v1,
72                               const SWvertex *v2)
73 {
74    SScontext *swsetup = SWSETUP_CONTEXT(ctx);
75 
76    if (swsetup->render_prim == GL_POLYGON) {
77       if (ef[e2]) _swrast_Line( ctx, v2, v0 );
78       if (ef[e0]) _swrast_Line( ctx, v0, v1 );
79       if (ef[e1]) _swrast_Line( ctx, v1, v2 );
80    } else {
81       if (ef[e0]) _swrast_Line( ctx, v0, v1 );
82       if (ef[e1]) _swrast_Line( ctx, v1, v2 );
83       if (ef[e2]) _swrast_Line( ctx, v2, v0 );
84    }
85 }
86 
87 /*
88  * Render a triangle using points and respecting edge flags.
89  */
90 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)91 _swsetup_edge_render_point_tri(struct gl_context *ctx,
92                                const GLubyte *ef,
93                                GLuint e0,
94                                GLuint e1,
95                                GLuint e2,
96                                const SWvertex *v0,
97                                const SWvertex *v1,
98                                const SWvertex *v2)
99 {
100    if (ef[e0]) _swrast_Point( ctx, v0 );
101    if (ef[e1]) _swrast_Point( ctx, v1 );
102    if (ef[e2]) _swrast_Point( ctx, v2 );
103 
104    _swrast_flush(ctx);
105 }
106 
107 /*
108  * Render a triangle respecting cull and shade model.
109  */
_swsetup_render_tri(struct gl_context * ctx,GLuint e0,GLuint e1,GLuint e2,GLuint facing,swsetup_edge_render_prim_tri render)110 static void _swsetup_render_tri(struct gl_context *ctx,
111                                 GLuint e0,
112                                 GLuint e1,
113                                 GLuint e2,
114                                 GLuint facing,
115                                 swsetup_edge_render_prim_tri render)
116 {
117    SScontext *swsetup = SWSETUP_CONTEXT(ctx);
118    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
119    GLubyte *ef = VB->EdgeFlag;
120    SWvertex *verts = swsetup->verts;
121    SWvertex *v0 = &verts[e0];
122    SWvertex *v1 = &verts[e1];
123    SWvertex *v2 = &verts[e2];
124 
125    /* cull testing */
126    if (ctx->Polygon.CullFlag) {
127       if (facing == 1 && ctx->Polygon.CullFaceMode != GL_FRONT)
128          return;
129       if (facing == 0 && ctx->Polygon.CullFaceMode != GL_BACK)
130          return;
131    }
132 
133    _swrast_SetFacing(ctx, facing);
134 
135    if (ctx->Light.ShadeModel == GL_FLAT) {
136       GLchan c[2][4];
137       GLfloat s[2][4];
138 
139       /* save colors/indexes for v0, v1 vertices */
140       COPY_CHAN4(c[0], v0->color);
141       COPY_CHAN4(c[1], v1->color);
142       COPY_4V(s[0], v0->attrib[VARYING_SLOT_COL1]);
143       COPY_4V(s[1], v1->attrib[VARYING_SLOT_COL1]);
144 
145       /* copy v2 color/indexes to v0, v1 indexes */
146       COPY_CHAN4(v0->color, v2->color);
147       COPY_CHAN4(v1->color, v2->color);
148       COPY_4V(v0->attrib[VARYING_SLOT_COL1], v2->attrib[VARYING_SLOT_COL1]);
149       COPY_4V(v1->attrib[VARYING_SLOT_COL1], v2->attrib[VARYING_SLOT_COL1]);
150 
151       render(ctx, ef, e0, e1, e2, v0, v1, v2);
152 
153       COPY_CHAN4(v0->color, c[0]);
154       COPY_CHAN4(v1->color, c[1]);
155       COPY_4V(v0->attrib[VARYING_SLOT_COL1], s[0]);
156       COPY_4V(v1->attrib[VARYING_SLOT_COL1], s[1]);
157    }
158    else {
159       render(ctx, ef, e0, e1, e2, v0, v1, v2);
160    }
161 }
162 
163 #define SS_COLOR(a,b) UNCLAMPED_FLOAT_TO_RGBA_CHAN(a,b)
164 #define SS_SPEC(a,b) COPY_4V(a,b)
165 #define SS_IND(a,b) (a = b)
166 
167 #define IND (0)
168 #define TAG(x) x##_rgba
169 #include "ss_tritmp.h"
170 
171 #define IND (SS_OFFSET_BIT)
172 #define TAG(x) x##_offset_rgba
173 #include "ss_tritmp.h"
174 
175 #define IND (SS_TWOSIDE_BIT)
176 #define TAG(x) x##_twoside_rgba
177 #include "ss_tritmp.h"
178 
179 #define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT)
180 #define TAG(x) x##_offset_twoside_rgba
181 #include "ss_tritmp.h"
182 
183 #define IND (SS_UNFILLED_BIT)
184 #define TAG(x) x##_unfilled_rgba
185 #include "ss_tritmp.h"
186 
187 #define IND (SS_OFFSET_BIT|SS_UNFILLED_BIT)
188 #define TAG(x) x##_offset_unfilled_rgba
189 #include "ss_tritmp.h"
190 
191 #define IND (SS_TWOSIDE_BIT|SS_UNFILLED_BIT)
192 #define TAG(x) x##_twoside_unfilled_rgba
193 #include "ss_tritmp.h"
194 
195 #define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT|SS_UNFILLED_BIT)
196 #define TAG(x) x##_offset_twoside_unfilled_rgba
197 #include "ss_tritmp.h"
198 
199 
_swsetup_trifuncs_init(struct gl_context * ctx)200 void _swsetup_trifuncs_init( struct gl_context *ctx )
201 {
202    (void) ctx;
203 
204    init_rgba();
205    init_offset_rgba();
206    init_twoside_rgba();
207    init_offset_twoside_rgba();
208    init_unfilled_rgba();
209    init_offset_unfilled_rgba();
210    init_twoside_unfilled_rgba();
211    init_offset_twoside_unfilled_rgba();
212 }
213 
214 
swsetup_points(struct gl_context * ctx,GLuint first,GLuint last)215 static void swsetup_points( struct gl_context *ctx, GLuint first, GLuint last )
216 {
217    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
218    SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
219    GLuint i;
220 
221    if (VB->Elts) {
222       for (i = first; i < last; i++)
223 	 if (VB->ClipMask[VB->Elts[i]] == 0)
224 	    _swrast_Point( ctx, &verts[VB->Elts[i]] );
225    }
226    else {
227       for (i = first; i < last; i++)
228 	 if (VB->ClipMask[i] == 0)
229 	    _swrast_Point( ctx, &verts[i] );
230    }
231 }
232 
swsetup_line(struct gl_context * ctx,GLuint v0,GLuint v1)233 static void swsetup_line( struct gl_context *ctx, GLuint v0, GLuint v1 )
234 {
235    SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
236    _swrast_Line( ctx, &verts[v0], &verts[v1] );
237 }
238 
239 
240 
_swsetup_choose_trifuncs(struct gl_context * ctx)241 void _swsetup_choose_trifuncs( struct gl_context *ctx )
242 {
243    TNLcontext *tnl = TNL_CONTEXT(ctx);
244    GLuint ind = 0;
245 
246    if (ctx->Polygon.OffsetPoint ||
247        ctx->Polygon.OffsetLine ||
248        ctx->Polygon.OffsetFill)
249       ind |= SS_OFFSET_BIT;
250 
251    if ((ctx->Light.Enabled && ctx->Light.Model.TwoSide) ||
252        (ctx->VertexProgram._Current && ctx->VertexProgram.TwoSideEnabled))
253       ind |= SS_TWOSIDE_BIT;
254 
255    /* We piggyback the two-sided stencil front/back determination on the
256     * unfilled triangle path.
257     */
258    if (ctx->Polygon.FrontMode != GL_FILL ||
259        ctx->Polygon.BackMode != GL_FILL ||
260        (ctx->Stencil.Enabled && _mesa_stencil_is_two_sided(ctx)))
261       ind |= SS_UNFILLED_BIT;
262 
263    tnl->Driver.Render.Triangle = tri_tab[ind];
264    tnl->Driver.Render.Quad = quad_tab[ind];
265    tnl->Driver.Render.Line = swsetup_line;
266    tnl->Driver.Render.Points = swsetup_points;
267 }
268