1 /* 2 * Mesa 3-D graphics library 3 * Version: 7.1 4 * 5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Keith Whitwell <keith (at) tungstengraphics.com> 26 */ 27 28 #include "main/glheader.h" 29 #include "main/colormac.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 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 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 */ 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[FRAG_ATTRIB_COL1]); 141 COPY_4V(s[1], v1->attrib[FRAG_ATTRIB_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[FRAG_ATTRIB_COL1], v2->attrib[FRAG_ATTRIB_COL1]); 147 COPY_4V(v1->attrib[FRAG_ATTRIB_COL1], v2->attrib[FRAG_ATTRIB_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[FRAG_ATTRIB_COL1], s[0]); 154 COPY_4V(v1->attrib[FRAG_ATTRIB_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 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 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 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 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