1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg *
24848b8605Smrg * Authors:
25848b8605Smrg *    Keith Whitwell <keithw@vmware.com>
26848b8605Smrg */
27848b8605Smrg
28848b8605Smrg
29848b8605Smrg/**
30848b8605Smrg * This is where we handle assigning vertex colors based on front/back
31848b8605Smrg * facing, compute polygon offset and handle glPolygonMode().
32848b8605Smrg */
33848b8605Smrgstatic void TAG(triangle)(struct gl_context *ctx, GLuint e0, GLuint e1, GLuint e2 )
34848b8605Smrg{
35848b8605Smrg   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
36848b8605Smrg   SScontext *swsetup = SWSETUP_CONTEXT(ctx);
37848b8605Smrg   SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
38848b8605Smrg   SWvertex *v[3];
39848b8605Smrg   GLfloat z[3];
40848b8605Smrg   GLfloat offset, oz0, oz1, oz2;
41848b8605Smrg   GLenum mode = GL_FILL;
42848b8605Smrg   GLuint facing = 0;
43848b8605Smrg   GLchan saved_color[3][4] = { { 0 } };
44848b8605Smrg   GLfloat saved_col0[3][4] = { { 0 } };
45848b8605Smrg   GLfloat saved_spec[3][4] = { { 0 } };
46848b8605Smrg
47848b8605Smrg   v[0] = &verts[e0];
48848b8605Smrg   v[1] = &verts[e1];
49848b8605Smrg   v[2] = &verts[e2];
50848b8605Smrg
51848b8605Smrg   if (IND & (SS_TWOSIDE_BIT | SS_OFFSET_BIT | SS_UNFILLED_BIT))
52848b8605Smrg   {
53848b8605Smrg      GLfloat ex = v[0]->attrib[VARYING_SLOT_POS][0] - v[2]->attrib[VARYING_SLOT_POS][0];
54848b8605Smrg      GLfloat ey = v[0]->attrib[VARYING_SLOT_POS][1] - v[2]->attrib[VARYING_SLOT_POS][1];
55848b8605Smrg      GLfloat fx = v[1]->attrib[VARYING_SLOT_POS][0] - v[2]->attrib[VARYING_SLOT_POS][0];
56848b8605Smrg      GLfloat fy = v[1]->attrib[VARYING_SLOT_POS][1] - v[2]->attrib[VARYING_SLOT_POS][1];
57848b8605Smrg      GLfloat cc  = ex*fy - ey*fx;
58848b8605Smrg
59848b8605Smrg      if (IND & (SS_TWOSIDE_BIT | SS_UNFILLED_BIT))
60848b8605Smrg      {
61b8e80941Smrg	 facing = (cc < 0.0F) ^ _mesa_polygon_get_front_bit(ctx);
62848b8605Smrg
63848b8605Smrg	 if (IND & SS_UNFILLED_BIT)
64848b8605Smrg	    mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;
65848b8605Smrg
66848b8605Smrg	 if (facing == 1) {
67848b8605Smrg	    if (IND & SS_TWOSIDE_BIT) {
68848b8605Smrg               if (VB->BackfaceColorPtr) {
69848b8605Smrg                  GLfloat (*vbcolor)[4] = VB->BackfaceColorPtr->data;
70848b8605Smrg
71848b8605Smrg                  if (swsetup->intColors) {
72848b8605Smrg                     COPY_CHAN4(saved_color[0], v[0]->color);
73848b8605Smrg                     COPY_CHAN4(saved_color[1], v[1]->color);
74848b8605Smrg                     COPY_CHAN4(saved_color[2], v[2]->color);
75848b8605Smrg                  }
76848b8605Smrg                  else {
77848b8605Smrg                     COPY_4V(saved_col0[0], v[0]->attrib[VARYING_SLOT_COL0]);
78848b8605Smrg                     COPY_4V(saved_col0[1], v[1]->attrib[VARYING_SLOT_COL0]);
79848b8605Smrg                     COPY_4V(saved_col0[2], v[2]->attrib[VARYING_SLOT_COL0]);
80848b8605Smrg                  }
81848b8605Smrg
82848b8605Smrg                  if (VB->BackfaceColorPtr->stride) {
83848b8605Smrg                     if (swsetup->intColors) {
84848b8605Smrg                        SS_COLOR(v[0]->color, vbcolor[e0]);
85848b8605Smrg                        SS_COLOR(v[1]->color, vbcolor[e1]);
86848b8605Smrg                        SS_COLOR(v[2]->color, vbcolor[e2]);
87848b8605Smrg                     }
88848b8605Smrg                     else {
89848b8605Smrg                        COPY_4V(v[0]->attrib[VARYING_SLOT_COL0], vbcolor[e0]);
90848b8605Smrg                        COPY_4V(v[1]->attrib[VARYING_SLOT_COL0], vbcolor[e1]);
91848b8605Smrg                        COPY_4V(v[2]->attrib[VARYING_SLOT_COL0], vbcolor[e2]);
92848b8605Smrg                     }
93848b8605Smrg                  }
94848b8605Smrg                  else {
95848b8605Smrg                     /* flat shade */
96848b8605Smrg                     if (swsetup->intColors) {
97848b8605Smrg                        SS_COLOR(v[0]->color, vbcolor[0]);
98848b8605Smrg                        SS_COLOR(v[1]->color, vbcolor[0]);
99848b8605Smrg                        SS_COLOR(v[2]->color, vbcolor[0]);
100848b8605Smrg                     }
101848b8605Smrg                     else {
102848b8605Smrg                        COPY_4V(v[0]->attrib[VARYING_SLOT_COL0], vbcolor[0]);
103848b8605Smrg                        COPY_4V(v[1]->attrib[VARYING_SLOT_COL0], vbcolor[0]);
104848b8605Smrg                        COPY_4V(v[2]->attrib[VARYING_SLOT_COL0], vbcolor[0]);
105848b8605Smrg                     }
106848b8605Smrg                  }
107848b8605Smrg               }
108848b8605Smrg
109848b8605Smrg               if (VB->BackfaceSecondaryColorPtr) {
110848b8605Smrg		  GLfloat (*vbspec)[4] = VB->BackfaceSecondaryColorPtr->data;
111848b8605Smrg
112848b8605Smrg		  COPY_4V(saved_spec[0], v[0]->attrib[VARYING_SLOT_COL1]);
113848b8605Smrg		  COPY_4V(saved_spec[1], v[1]->attrib[VARYING_SLOT_COL1]);
114848b8605Smrg		  COPY_4V(saved_spec[2], v[2]->attrib[VARYING_SLOT_COL1]);
115848b8605Smrg
116848b8605Smrg		  if (VB->BackfaceSecondaryColorPtr->stride) {
117848b8605Smrg		    SS_SPEC(v[0]->attrib[VARYING_SLOT_COL1], vbspec[e0]);
118848b8605Smrg		    SS_SPEC(v[1]->attrib[VARYING_SLOT_COL1], vbspec[e1]);
119848b8605Smrg		    SS_SPEC(v[2]->attrib[VARYING_SLOT_COL1], vbspec[e2]);
120848b8605Smrg		  }
121848b8605Smrg		  else {
122848b8605Smrg		    SS_SPEC(v[0]->attrib[VARYING_SLOT_COL1], vbspec[0]);
123848b8605Smrg		    SS_SPEC(v[1]->attrib[VARYING_SLOT_COL1], vbspec[0]);
124848b8605Smrg		    SS_SPEC(v[2]->attrib[VARYING_SLOT_COL1], vbspec[0]);
125848b8605Smrg		  }
126848b8605Smrg	       }
127848b8605Smrg	    }
128848b8605Smrg	 }
129848b8605Smrg      }
130848b8605Smrg
131848b8605Smrg      if (IND & SS_OFFSET_BIT) {
132848b8605Smrg         const GLfloat max = ctx->DrawBuffer->_DepthMaxF;
133848b8605Smrg         /* save original Z values (restored later) */
134848b8605Smrg	 z[0] = v[0]->attrib[VARYING_SLOT_POS][2];
135848b8605Smrg	 z[1] = v[1]->attrib[VARYING_SLOT_POS][2];
136848b8605Smrg	 z[2] = v[2]->attrib[VARYING_SLOT_POS][2];
137848b8605Smrg         /* Note that Z values are already scaled to [0,65535] (for example)
138848b8605Smrg          * so no MRD value is used here.
139848b8605Smrg          */
140848b8605Smrg	 offset = ctx->Polygon.OffsetUnits;
141b8e80941Smrg	 if (cc * cc > 1e-16F) {
142848b8605Smrg	    const GLfloat ez = z[0] - z[2];
143848b8605Smrg	    const GLfloat fz = z[1] - z[2];
144848b8605Smrg	    const GLfloat oneOverArea = 1.0F / cc;
145b8e80941Smrg	    const GLfloat dzdx = fabsf((ey * fz - ez * fy) * oneOverArea);
146b8e80941Smrg	    const GLfloat dzdy = fabsf((ez * fx - ex * fz) * oneOverArea);
147848b8605Smrg	    offset += MAX2(dzdx, dzdy) * ctx->Polygon.OffsetFactor;
148848b8605Smrg	 }
149848b8605Smrg         /* new Z values */
150848b8605Smrg         oz0 = CLAMP(v[0]->attrib[VARYING_SLOT_POS][2] + offset, 0.0F, max);
151848b8605Smrg         oz1 = CLAMP(v[1]->attrib[VARYING_SLOT_POS][2] + offset, 0.0F, max);
152848b8605Smrg         oz2 = CLAMP(v[2]->attrib[VARYING_SLOT_POS][2] + offset, 0.0F, max);
153848b8605Smrg      }
154848b8605Smrg   }
155848b8605Smrg
156848b8605Smrg   if (mode == GL_POINT) {
157848b8605Smrg      if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetPoint) {
158848b8605Smrg	 v[0]->attrib[VARYING_SLOT_POS][2] = oz0;
159848b8605Smrg	 v[1]->attrib[VARYING_SLOT_POS][2] = oz1;
160848b8605Smrg	 v[2]->attrib[VARYING_SLOT_POS][2] = oz2;
161848b8605Smrg      }
162848b8605Smrg      _swsetup_render_tri(ctx, e0, e1, e2, facing, _swsetup_edge_render_point_tri);
163848b8605Smrg   } else if (mode == GL_LINE) {
164848b8605Smrg      if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetLine) {
165848b8605Smrg	 v[0]->attrib[VARYING_SLOT_POS][2] = oz0;
166848b8605Smrg	 v[1]->attrib[VARYING_SLOT_POS][2] = oz1;
167848b8605Smrg	 v[2]->attrib[VARYING_SLOT_POS][2] = oz2;
168848b8605Smrg      }
169848b8605Smrg      _swsetup_render_tri(ctx, e0, e1, e2, facing, _swsetup_edge_render_line_tri);
170848b8605Smrg   } else {
171848b8605Smrg      if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetFill) {
172848b8605Smrg	 v[0]->attrib[VARYING_SLOT_POS][2] = oz0;
173848b8605Smrg	 v[1]->attrib[VARYING_SLOT_POS][2] = oz1;
174848b8605Smrg	 v[2]->attrib[VARYING_SLOT_POS][2] = oz2;
175848b8605Smrg      }
176848b8605Smrg      _swrast_Triangle( ctx, v[0], v[1], v[2] );
177848b8605Smrg   }
178848b8605Smrg
179848b8605Smrg   /*
180848b8605Smrg    * Restore original vertex colors, etc.
181848b8605Smrg    */
182848b8605Smrg   if (IND & SS_OFFSET_BIT) {
183848b8605Smrg      v[0]->attrib[VARYING_SLOT_POS][2] = z[0];
184848b8605Smrg      v[1]->attrib[VARYING_SLOT_POS][2] = z[1];
185848b8605Smrg      v[2]->attrib[VARYING_SLOT_POS][2] = z[2];
186848b8605Smrg   }
187848b8605Smrg
188848b8605Smrg   if (IND & SS_TWOSIDE_BIT) {
189848b8605Smrg      if (facing == 1) {
190848b8605Smrg	if (VB->BackfaceColorPtr) {
191848b8605Smrg	  if (swsetup->intColors) {
192848b8605Smrg	    COPY_CHAN4(v[0]->color, saved_color[0]);
193848b8605Smrg	    COPY_CHAN4(v[1]->color, saved_color[1]);
194848b8605Smrg	    COPY_CHAN4(v[2]->color, saved_color[2]);
195848b8605Smrg	  }
196848b8605Smrg	  else {
197848b8605Smrg	    COPY_4V(v[0]->attrib[VARYING_SLOT_COL0], saved_col0[0]);
198848b8605Smrg	    COPY_4V(v[1]->attrib[VARYING_SLOT_COL0], saved_col0[1]);
199848b8605Smrg	    COPY_4V(v[2]->attrib[VARYING_SLOT_COL0], saved_col0[2]);
200848b8605Smrg	  }
201848b8605Smrg	}
202848b8605Smrg
203848b8605Smrg	if (VB->BackfaceSecondaryColorPtr) {
204848b8605Smrg	  COPY_4V(v[0]->attrib[VARYING_SLOT_COL1], saved_spec[0]);
205848b8605Smrg	  COPY_4V(v[1]->attrib[VARYING_SLOT_COL1], saved_spec[1]);
206848b8605Smrg	  COPY_4V(v[2]->attrib[VARYING_SLOT_COL1], saved_spec[2]);
207848b8605Smrg	}
208848b8605Smrg      }
209848b8605Smrg   }
210848b8605Smrg}
211848b8605Smrg
212848b8605Smrg
213848b8605Smrg
214848b8605Smrg/* Need to fixup edgeflags when decomposing to triangles:
215848b8605Smrg */
216848b8605Smrgstatic void TAG(quadfunc)( struct gl_context *ctx, GLuint v0,
217848b8605Smrg		       GLuint v1, GLuint v2, GLuint v3 )
218848b8605Smrg{
219848b8605Smrg   if (IND & SS_UNFILLED_BIT) {
220848b8605Smrg      struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
221848b8605Smrg      if (VB->EdgeFlag) { /* XXX this test shouldn't be needed (bug 12614) */
222848b8605Smrg         GLubyte ef1 = VB->EdgeFlag[v1];
223848b8605Smrg         GLubyte ef3 = VB->EdgeFlag[v3];
224848b8605Smrg         VB->EdgeFlag[v1] = 0;
225848b8605Smrg         TAG(triangle)( ctx, v0, v1, v3 );
226848b8605Smrg         VB->EdgeFlag[v1] = ef1;
227848b8605Smrg         VB->EdgeFlag[v3] = 0;
228848b8605Smrg         TAG(triangle)( ctx, v1, v2, v3 );
229848b8605Smrg         VB->EdgeFlag[v3] = ef3;
230848b8605Smrg      }
231848b8605Smrg   } else {
232848b8605Smrg      TAG(triangle)( ctx, v0, v1, v3 );
233848b8605Smrg      TAG(triangle)( ctx, v1, v2, v3 );
234848b8605Smrg   }
235848b8605Smrg}
236848b8605Smrg
237848b8605Smrg
238848b8605Smrg
239848b8605Smrg
240848b8605Smrgstatic void TAG(init)( void )
241848b8605Smrg{
242848b8605Smrg   tri_tab[IND] = TAG(triangle);
243848b8605Smrg   quad_tab[IND] = TAG(quadfunc);
244848b8605Smrg}
245848b8605Smrg
246848b8605Smrg
247848b8605Smrg#undef IND
248848b8605Smrg#undef TAG
249