ss_tritmp.h revision 23caf20169ac38436ee9c13914f1d6aa7cf6bb5e
1/*
2 * Mesa 3-D graphics library
3 * Version:  3.5
4 *
5 * Copyright (C) 1999  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 <keithw@valinux.com>
26 */
27
28
29static void TAG(triangle)(GLcontext *ctx,
30			  GLuint e0, GLuint e1, GLuint e2,
31			  GLuint pv)
32{
33   struct vertex_buffer *VB = TNL_VB(ctx);
34   SWvertex *verts = SWSETUP_VB(VB)->verts;
35   SWvertex *v[3];
36   GLfloat offset;
37   GLfloat z[3];
38   GLubyte c[3][4], s[3][4];
39   GLuint i[3];
40   GLenum mode = GL_FILL;
41
42   v[0] = &verts[e0];
43   v[1] = &verts[e1];
44   v[2] = &verts[e2];
45
46   if (IND & (SS_TWOSIDE_BIT | SS_FLAT_BIT)) {
47      SS_COLOR(c[0], v[0]->color);
48
49      if (IND & SS_TWOSIDE_BIT) {
50	 SS_COLOR(c[1], v[1]->color);
51	 SS_COLOR(c[2], v[2]->color);
52      }
53
54      if (IND & SS_COPY_EXTRAS) {
55	 SS_SPEC(s[0], v[0]->specular);
56	 SS_IND(i[0], v[0]->index);
57
58	 if (IND & SS_TWOSIDE_BIT) {
59	    SS_SPEC(s[1], v[1]->specular);
60	    SS_IND(i[1], v[1]->index);
61
62	    SS_SPEC(s[2], v[2]->specular);
63	    SS_IND(i[2], v[2]->index);
64	 }
65      }
66   }
67
68   if (IND & (SS_TWOSIDE_BIT | SS_OFFSET_BIT | SS_UNFILLED_BIT))
69   {
70      GLfloat ex = v[0]->win[0] - v[2]->win[0];
71      GLfloat ey = v[0]->win[1] - v[2]->win[1];
72      GLfloat fx = v[1]->win[0] - v[2]->win[0];
73      GLfloat fy = v[1]->win[1] - v[2]->win[1];
74      GLfloat cc  = ex*fy - ey*fx;
75
76      if (IND & (SS_TWOSIDE_BIT | SS_UNFILLED_BIT))
77      {
78	 GLuint  facing = (cc < 0.0) ^ ctx->Polygon.FrontBit;
79
80	 if (IND & SS_UNFILLED_BIT)
81	    mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;
82
83	 if (IND & SS_TWOSIDE_BIT) {
84	    GLubyte (*vbcolor)[4] = VB->Color[facing]->data;
85	    GLubyte (*vbspec)[4] = VB->SecondaryColor[facing]->data;
86	    GLuint *vbindex = VB->Index[facing]->data;
87
88	    if (IND & SS_FLAT_BIT) {
89	       SS_COLOR(v[0]->color, vbcolor[pv]);
90	       SS_COLOR(v[1]->color, vbcolor[pv]);
91	       SS_COLOR(v[2]->color, vbcolor[pv]);
92
93	       if (IND & SS_COPY_EXTRAS) {
94		  SS_SPEC(v[0]->specular, vbspec[pv]);
95		  SS_SPEC(v[1]->specular, vbspec[pv]);
96		  SS_SPEC(v[2]->specular, vbspec[pv]);
97
98		  SS_IND(v[0]->index, vbindex[pv]);
99		  SS_IND(v[1]->index, vbindex[pv]);
100		  SS_IND(v[2]->index, vbindex[pv]);
101	       }
102	    } else {
103	       SS_COLOR(v[0]->color, vbcolor[e0]);
104	       SS_COLOR(v[1]->color, vbcolor[e1]);
105	       SS_COLOR(v[2]->color, vbcolor[e2]);
106
107	       if (IND & SS_COPY_EXTRAS) {
108		  SS_SPEC(v[0]->specular, vbspec[e0]);
109		  SS_SPEC(v[1]->specular, vbspec[e1]);
110		  SS_SPEC(v[2]->specular, vbspec[e2]);
111
112		  SS_IND(v[0]->index, vbindex[e0]);
113		  SS_IND(v[1]->index, vbindex[e1]);
114		  SS_IND(v[2]->index, vbindex[e2]);
115	       }
116	    }
117	 }
118      }
119
120      if (IND & SS_OFFSET_BIT)
121      {
122	 offset = ctx->Polygon.OffsetUnits;
123	 z[0] = v[0]->win[2];
124	 z[1] = v[1]->win[2];
125	 z[2] = v[2]->win[2];
126	 if (cc * cc > 1e-16) {
127	    GLfloat ez = z[0] - z[2];
128	    GLfloat fz = z[1] - z[2];
129	    GLfloat a = ey*fz - ez*fy;
130	    GLfloat b = ez*fx - ex*fz;
131	    GLfloat ic = 1.0 / cc;
132	    GLfloat ac = a * ic;
133	    GLfloat bc = b * ic;
134	    if (ac < 0.0f) ac = -ac;
135	    if (bc < 0.0f) bc = -bc;
136	    offset += MAX2(ac, bc) * ctx->Polygon.OffsetFactor;
137	 }
138      }
139   }
140   else if (IND & SS_FLAT_BIT)
141   {
142      GLubyte *color = VB->Color[0]->data[pv];
143      GLubyte *spec = VB->SecondaryColor[0]->data[pv];
144      GLuint index = VB->Index[0]->data[pv];
145
146      SS_COLOR(v[0]->color, color);
147
148      if (IND & SS_COPY_EXTRAS) {
149	 SS_SPEC(v[0]->specular, spec);
150	 SS_IND(v[0]->index, index);
151      }
152   }
153
154   if (mode == GL_POINT) {
155      GLubyte *ef = VB->EdgeFlagPtr->data;
156      if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetPoint) {
157	 v[0]->win[2] += offset;
158	 v[1]->win[2] += offset;
159	 v[2]->win[2] += offset;
160      }
161      if (ef[e0]&0x1) { ef[e0] &= ~0x1; _swrast_Point( ctx, v[0] ); }
162      if (ef[e1]&0x1) { ef[e1] &= ~0x1; _swrast_Point( ctx, v[1] ); }
163      if (ef[e2]&0x2) { ef[e2] &= ~0x2; _swrast_Point( ctx, v[2] ); }
164   } else if (mode == GL_LINE) {
165      GLubyte *ef = VB->EdgeFlagPtr->data;
166      if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetLine) {
167	 v[0]->win[2] += offset;
168	 v[1]->win[2] += offset;
169	 v[2]->win[2] += offset;
170      }
171      if (ef[e0]&0x1) { ef[e0] &= ~0x1; _swrast_Line( ctx, v[0], v[1] ); }
172      if (ef[e1]&0x1) { ef[e1] &= ~0x1; _swrast_Line( ctx, v[1], v[2] ); }
173      if (ef[e2]&0x2) { ef[e2] &= ~0x2; _swrast_Line( ctx, v[2], v[0] ); }
174   } else {
175      if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetFill) {
176	 v[0]->win[2] += offset;
177	 v[1]->win[2] += offset;
178	 v[2]->win[2] += offset;
179      }
180      _swrast_Triangle( ctx, v[0], v[1], v[2] );
181   }
182
183   if (IND & SS_OFFSET_BIT) {
184      v[0]->win[2] = z[0];
185      v[1]->win[2] = z[1];
186      v[2]->win[2] = z[2];
187   }
188
189   if (IND & (SS_FLAT_BIT | SS_TWOSIDE_BIT)) {
190      SS_COLOR(v[0]->color, c[0]);
191
192      if (IND & SS_TWOSIDE_BIT) {
193	 SS_COLOR(v[1]->color, c[1]);
194	 SS_COLOR(v[2]->color, c[2]);
195      }
196
197      if (IND & SS_COPY_EXTRAS) {
198	 SS_SPEC(v[0]->specular, s[0]);
199	 SS_IND(v[0]->index, i[0]);
200
201	 if (IND & SS_TWOSIDE_BIT) {
202	    SS_SPEC(v[1]->specular, s[1]);
203	    SS_IND(v[1]->index, i[1]);
204
205	    SS_SPEC(v[2]->specular, s[2]);
206	    SS_IND(v[2]->index, i[2]);
207	 }
208      }
209   }
210}
211
212
213
214/* Need to do something with edgeflags:
215 */
216static void TAG(quad)( GLcontext *ctx, GLuint v0,
217		       GLuint v1, GLuint v2, GLuint v3,
218		       GLuint pv )
219{
220   TAG(triangle)( ctx, v0, v1, v3, pv );
221   TAG(triangle)( ctx, v1, v2, v3, pv );
222}
223
224
225static void TAG(line)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint pv )
226{
227   struct vertex_buffer *VB = TNL_VB(ctx);
228   SWvertex *verts = SWSETUP_VB(VB)->verts;
229   GLubyte c[2][4], s[2][4];
230   GLuint i[2];
231   SWvertex *vert0 = &verts[v0];
232   SWvertex *vert1 = &verts[v1];
233
234
235   if (IND & SS_FLAT_BIT) {
236      GLubyte *color = VB->Color[0]->data[pv];
237      GLubyte *spec = VB->SecondaryColor[0]->data[pv];
238      GLuint index = VB->Index[0]->data[pv];
239
240      SS_COLOR(c[0], vert0->color);
241      SS_COLOR(vert0->color, color);
242
243      if (IND & SS_COPY_EXTRAS) {
244	 SS_SPEC(s[0], vert0->specular);
245	 SS_SPEC(vert0->specular, spec);
246
247	 SS_IND(i[0], vert0->index);
248	 SS_IND(vert0->index, index);
249      }
250   }
251
252   _swrast_Line( ctx, vert0, vert1 );
253
254   if (IND & SS_FLAT_BIT) {
255      SS_COLOR(vert0->color, c[0]);
256
257      if (IND & SS_COPY_EXTRAS) {
258	 SS_SPEC(vert0->specular, s[0]);
259	 SS_IND(vert0->index, i[0]);
260      }
261   }
262}
263
264
265static void TAG(points)( GLcontext *ctx, GLuint first, GLuint last )
266{
267   struct vertex_buffer *VB = TNL_VB(ctx);
268   SWvertex *verts = SWSETUP_VB(VB)->verts;
269   int i;
270
271   for(i=first;i<=last;i++)
272      if(VB->ClipMask[i]==0)
273	 _swrast_Point( ctx, &verts[i] );
274}
275
276
277
278
279static void TAG(init)( void )
280{
281   tri_tab[IND] = TAG(triangle);
282   quad_tab[IND] = TAG(quad);
283   line_tab[IND] = TAG(line);
284   points_tab[IND] = TAG(points);
285}
286
287
288#undef IND
289#undef TAG
290
291
292
293