1/*
2 * Mesa 3-D graphics library
3 * Version:  4.1
4 *
5 * Copyright (C) 1999-2002  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@tungstengraphics.com>
26 */
27
28#ifndef LOCALVARS
29#define LOCALVARS
30#endif
31
32#undef TCL_DEBUG
33#ifndef TCL_DEBUG
34#define TCL_DEBUG 0
35#endif
36
37static void TAG(emit)( struct gl_context *ctx,
38		       GLuint start, GLuint end,
39		       void *dest )
40{
41   LOCALVARS
42      struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
43   GLuint (*tc0)[4], (*tc1)[4], (*tc2)[4];
44   GLfloat (*col)[4], (*spec)[4];
45   GLfloat (*fog)[4];
46   GLuint (*norm)[4];
47   GLuint tc0_stride, tc1_stride, col_stride, spec_stride, fog_stride;
48   GLuint tc2_stride, norm_stride;
49   GLuint fill_tex = 0;
50   GLuint rqcoordsnoswap = 0;
51   GLuint (*coord)[4];
52   GLuint coord_stride; /* object coordinates */
53   int i;
54
55   union emit_union *v = (union emit_union *)dest;
56
57   radeon_print(RADEON_SWRENDER, RADEON_VERBOSE, "%s\n", __FUNCTION__);
58
59   coord = (GLuint (*)[4])VB->AttribPtr[_TNL_ATTRIB_POS]->data;
60   coord_stride = VB->AttribPtr[_TNL_ATTRIB_POS]->stride;
61
62   if (DO_TEX2) {
63      if (VB->AttribPtr[_TNL_ATTRIB_TEX2]) {
64	 const GLuint t2 = GET_TEXSOURCE(2);
65	 tc2 = (GLuint (*)[4])VB->AttribPtr[_TNL_ATTRIB_TEX0 + t2]->data;
66	 tc2_stride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t2]->stride;
67	 if (DO_PTEX && VB->AttribPtr[_TNL_ATTRIB_TEX0 + t2]->size < 3) {
68	    fill_tex |= (1<<2);
69	 }
70	 else if (DO_PTEX && VB->AttribPtr[_TNL_ATTRIB_TEX0 + t2]->size < 4) {
71	    rqcoordsnoswap |= (1<<2);
72	 }
73      } else {
74	 tc2 = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_TEX2];
75	 tc2_stride = 0;
76      }
77   }
78
79   if (DO_TEX1) {
80      if (VB->AttribPtr[_TNL_ATTRIB_TEX1]) {
81	 const GLuint t1 = GET_TEXSOURCE(1);
82	 tc1 = (GLuint (*)[4])VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->data;
83	 tc1_stride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->stride;
84	 if (DO_PTEX && VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->size < 3) {
85	    fill_tex |= (1<<1);
86	 }
87	 else if (DO_PTEX && VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->size < 4) {
88	    rqcoordsnoswap |= (1<<1);
89	 }
90      } else {
91	 tc1 = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_TEX1];
92	 tc1_stride = 0;
93      }
94   }
95
96   if (DO_TEX0) {
97      if (VB->AttribPtr[_TNL_ATTRIB_TEX0]) {
98	 const GLuint t0 = GET_TEXSOURCE(0);
99	 tc0_stride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->stride;
100	 tc0 = (GLuint (*)[4])VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->data;
101	 if (DO_PTEX && VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->size < 3) {
102	    fill_tex |= (1<<0);
103	 }
104	 else if (DO_PTEX && VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->size < 4) {
105	    rqcoordsnoswap |= (1<<0);
106	 }
107      } else {
108	 tc0 = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_TEX0];
109	 tc0_stride = 0;
110      }
111
112   }
113
114   if (DO_NORM) {
115      if (VB->AttribPtr[_TNL_ATTRIB_NORMAL]) {
116	 norm_stride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
117	 norm = (GLuint (*)[4])VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
118      } else {
119	 norm_stride = 0;
120	 norm = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
121      }
122   }
123
124   if (DO_RGBA) {
125      if (VB->AttribPtr[_TNL_ATTRIB_COLOR0]) {
126	 col = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data;
127	 col_stride = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride;
128      } else {
129	 col = (GLfloat (*)[4])ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
130	 col_stride = 0;
131      }
132   }
133
134   if (DO_SPEC_OR_FOG) {
135      if (VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
136	 spec = VB->AttribPtr[_TNL_ATTRIB_COLOR1]->data;
137	 spec_stride = VB->AttribPtr[_TNL_ATTRIB_COLOR1]->stride;
138      } else {
139	 spec = (GLfloat (*)[4])ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
140	 spec_stride = 0;
141      }
142   }
143
144   if (DO_SPEC_OR_FOG) {
145      if (VB->AttribPtr[_TNL_ATTRIB_FOG]) {
146	 fog = VB->AttribPtr[_TNL_ATTRIB_FOG]->data;
147	 fog_stride = VB->AttribPtr[_TNL_ATTRIB_FOG]->stride;
148      } else {
149	 fog = (GLfloat (*)[4])ctx->Current.Attrib[VERT_ATTRIB_FOG];
150	 fog_stride = 0;
151      }
152   }
153
154
155   if (start) {
156      coord =  (GLuint (*)[4])((GLubyte *)coord + start * coord_stride);
157      if (DO_TEX0)
158	 tc0 =  (GLuint (*)[4])((GLubyte *)tc0 + start * tc0_stride);
159      if (DO_TEX1)
160	 tc1 =  (GLuint (*)[4])((GLubyte *)tc1 + start * tc1_stride);
161      if (DO_TEX2)
162	 tc2 =  (GLuint (*)[4])((GLubyte *)tc2 + start * tc2_stride);
163      if (DO_NORM)
164	 norm =  (GLuint (*)[4])((GLubyte *)norm + start * norm_stride);
165      if (DO_RGBA)
166	 STRIDE_4F(col, start * col_stride);
167      if (DO_SPEC)
168	 STRIDE_4F(spec, start * spec_stride);
169      if (DO_FOG)
170	 STRIDE_4F(fog, start * fog_stride);
171   }
172
173
174   {
175      for (i=start; i < end; i++) {
176
177	 v[0].ui = coord[0][0];
178	 v[1].ui = coord[0][1];
179	 v[2].ui = coord[0][2];
180	 if (DO_W) {
181	    v[3].ui = coord[0][3];
182	    v += 4;
183	 }
184	 else
185	    v += 3;
186	 coord =  (GLuint (*)[4])((GLubyte *)coord +  coord_stride);
187
188	 if (DO_NORM) {
189	    v[0].ui = norm[0][0];
190	    v[1].ui = norm[0][1];
191	    v[2].ui = norm[0][2];
192	    v += 3;
193	    norm =  (GLuint (*)[4])((GLubyte *)norm +  norm_stride);
194	 }
195	 if (DO_RGBA) {
196	    UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.red, col[0][0]);
197	    UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.green, col[0][1]);
198	    UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.blue, col[0][2]);
199	    UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.alpha, col[0][3]);
200	    STRIDE_4F(col, col_stride);
201	    v++;
202	 }
203	 if (DO_SPEC_OR_FOG) {
204	    if (DO_SPEC) {
205	       UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.red, spec[0][0]);
206	       UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.green, spec[0][1]);
207	       UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.blue, spec[0][2]);
208	       STRIDE_4F(spec, spec_stride);
209	    }
210	    if (DO_FOG) {
211	       UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.alpha, radeonComputeFogBlendFactor(ctx, fog[0][0]));
212	       STRIDE_4F(fog, fog_stride);
213	    }
214	    if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui);
215	    v++;
216	 }
217	 if (DO_TEX0) {
218	    v[0].ui = tc0[0][0];
219	    v[1].ui = tc0[0][1];
220	    if (TCL_DEBUG) fprintf(stderr, "t0: %.2f %.2f ", v[0].f, v[1].f);
221	    if (DO_PTEX) {
222	       if (fill_tex & (1<<0))
223		  v[2].f = 1.0;
224	       else if (rqcoordsnoswap & (1<<0))
225		  v[2].ui = tc0[0][2];
226	       else
227		  v[2].ui = tc0[0][3];
228	       if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f);
229	       v += 3;
230	    }
231	    else
232	       v += 2;
233	    tc0 =  (GLuint (*)[4])((GLubyte *)tc0 +  tc0_stride);
234	 }
235	 if (DO_TEX1) {
236	    v[0].ui = tc1[0][0];
237	    v[1].ui = tc1[0][1];
238	    if (TCL_DEBUG) fprintf(stderr, "t1: %.2f %.2f ", v[0].f, v[1].f);
239	    if (DO_PTEX) {
240	       if (fill_tex & (1<<1))
241		  v[2].f = 1.0;
242	       else if (rqcoordsnoswap & (1<<1))
243		  v[2].ui = tc1[0][2];
244	       else
245		  v[2].ui = tc1[0][3];
246	       if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f);
247	       v += 3;
248	    }
249	    else
250	       v += 2;
251	    tc1 =  (GLuint (*)[4])((GLubyte *)tc1 +  tc1_stride);
252	 }
253	 if (DO_TEX2) {
254	    v[0].ui = tc2[0][0];
255	    v[1].ui = tc2[0][1];
256	    if (TCL_DEBUG) fprintf(stderr, "t2: %.2f %.2f ", v[0].f, v[1].f);
257	    if (DO_PTEX) {
258	       if (fill_tex & (1<<2))
259		  v[2].f = 1.0;
260	       else if (rqcoordsnoswap & (1<<2))
261		  v[2].ui = tc2[0][2];
262	       else
263		  v[2].ui = tc2[0][3];
264	       if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f);
265	       v += 3;
266	    }
267	    else
268	       v += 2;
269	    tc2 =  (GLuint (*)[4])((GLubyte *)tc2 +  tc2_stride);
270	 }
271	 if (TCL_DEBUG) fprintf(stderr, "\n");
272      }
273   }
274}
275
276
277
278static void TAG(init)( void )
279{
280   int sz = 3;
281   if (DO_W) sz++;
282   if (DO_NORM) sz += 3;
283   if (DO_RGBA) sz++;
284   if (DO_SPEC_OR_FOG) sz++;
285   if (DO_TEX0) sz += 2;
286   if (DO_TEX0 && DO_PTEX) sz++;
287   if (DO_TEX1) sz += 2;
288   if (DO_TEX1 && DO_PTEX) sz++;
289   if (DO_TEX2) sz += 2;
290   if (DO_TEX2 && DO_PTEX) sz++;
291
292   setup_tab[IDX].emit = TAG(emit);
293   setup_tab[IDX].vertex_format = IND;
294   setup_tab[IDX].vertex_size = sz;
295}
296
297
298#undef IND
299#undef TAG
300#undef IDX
301