1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2002  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@vmware.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 
TAG(emit)37 static 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", __func__);
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 
TAG(init)278 static 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