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 (at) 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 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 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 */ 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 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 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 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 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