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