mesa: Prefix main includes with dir to avoid conflicts.
[mesa.git] / src / mesa / vf / vf.c
1 /*
2 * Copyright 2003 Tungsten Graphics, inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Keith Whitwell <keithw@tungstengraphics.com>
26 */
27
28 #include "main/glheader.h"
29 #include "main/context.h"
30 #include "main/colormac.h"
31
32 #include "vf.h"
33
34 #define DBG 0
35
36
37
38 static GLboolean match_fastpath( struct vertex_fetch *vf,
39 const struct vf_fastpath *fp)
40 {
41 GLuint j;
42
43 if (vf->attr_count != fp->attr_count)
44 return GL_FALSE;
45
46 for (j = 0; j < vf->attr_count; j++)
47 if (vf->attr[j].format != fp->attr[j].format ||
48 vf->attr[j].inputsize != fp->attr[j].size ||
49 vf->attr[j].vertoffset != fp->attr[j].offset)
50 return GL_FALSE;
51
52 if (fp->match_strides) {
53 if (vf->vertex_stride != fp->vertex_stride)
54 return GL_FALSE;
55
56 for (j = 0; j < vf->attr_count; j++)
57 if (vf->attr[j].inputstride != fp->attr[j].stride)
58 return GL_FALSE;
59 }
60
61 return GL_TRUE;
62 }
63
64 static GLboolean search_fastpath_emit( struct vertex_fetch *vf )
65 {
66 struct vf_fastpath *fp = vf->fastpath;
67
68 for ( ; fp ; fp = fp->next) {
69 if (match_fastpath(vf, fp)) {
70 vf->emit = fp->func;
71 return GL_TRUE;
72 }
73 }
74
75 return GL_FALSE;
76 }
77
78 void vf_register_fastpath( struct vertex_fetch *vf,
79 GLboolean match_strides )
80 {
81 struct vf_fastpath *fastpath = CALLOC_STRUCT(vf_fastpath);
82 GLuint i;
83
84 fastpath->vertex_stride = vf->vertex_stride;
85 fastpath->attr_count = vf->attr_count;
86 fastpath->match_strides = match_strides;
87 fastpath->func = vf->emit;
88 fastpath->attr = (struct vf_attr_type *)
89 _mesa_malloc(vf->attr_count * sizeof(fastpath->attr[0]));
90
91 for (i = 0; i < vf->attr_count; i++) {
92 fastpath->attr[i].format = vf->attr[i].format;
93 fastpath->attr[i].stride = vf->attr[i].inputstride;
94 fastpath->attr[i].size = vf->attr[i].inputsize;
95 fastpath->attr[i].offset = vf->attr[i].vertoffset;
96 }
97
98 fastpath->next = vf->fastpath;
99 vf->fastpath = fastpath;
100 }
101
102
103
104
105 /***********************************************************************
106 * Build codegen functions or return generic ones:
107 */
108 static void choose_emit_func( struct vertex_fetch *vf,
109 GLuint count,
110 GLubyte *dest)
111 {
112 vf->emit = NULL;
113
114 /* Does this match an existing (hardwired, codegen or known-bad)
115 * fastpath?
116 */
117 if (search_fastpath_emit(vf)) {
118 /* Use this result. If it is null, then it is already known
119 * that the current state will fail for codegen and there is no
120 * point trying again.
121 */
122 }
123 else if (vf->codegen_emit) {
124 vf->codegen_emit( vf );
125 }
126
127 if (!vf->emit) {
128 vf_generate_hardwired_emit(vf);
129 }
130
131 /* Otherwise use the generic version:
132 */
133 if (!vf->emit)
134 vf->emit = vf_generic_emit;
135
136 vf->emit( vf, count, dest );
137 }
138
139
140
141
142
143 /***********************************************************************
144 * Public entrypoints, mostly dispatch to the above:
145 */
146
147
148
149 GLuint vf_set_vertex_attributes( struct vertex_fetch *vf,
150 const struct vf_attr_map *map,
151 GLuint nr,
152 GLuint vertex_stride )
153 {
154 GLuint offset = 0;
155 GLuint i, j;
156
157 assert(nr < VF_ATTRIB_MAX);
158
159 memset(vf->lookup, 0, sizeof(vf->lookup));
160
161 for (j = 0, i = 0; i < nr; i++) {
162 const GLuint format = map[i].format;
163 if (format == EMIT_PAD) {
164 if (DBG)
165 _mesa_printf("%d: pad %d, offset %d\n", i,
166 map[i].offset, offset);
167
168 offset += map[i].offset;
169
170 }
171 else {
172 assert(vf->lookup[map[i].attrib] == 0);
173 vf->lookup[map[i].attrib] = &vf->attr[j];
174
175 vf->attr[j].attrib = map[i].attrib;
176 vf->attr[j].format = format;
177 vf->attr[j].insert = vf_format_info[format].insert;
178 vf->attr[j].extract = vf_format_info[format].extract;
179 vf->attr[j].vertattrsize = vf_format_info[format].attrsize;
180 vf->attr[j].vertoffset = offset;
181
182 if (DBG)
183 _mesa_printf("%d: %s, offset %d\n", i,
184 vf_format_info[format].name,
185 vf->attr[j].vertoffset);
186
187 offset += vf_format_info[format].attrsize;
188 j++;
189 }
190 }
191
192 vf->attr_count = j;
193 vf->vertex_stride = vertex_stride ? vertex_stride : offset;
194 vf->emit = choose_emit_func;
195
196 assert(vf->vertex_stride >= offset);
197 return vf->vertex_stride;
198 }
199
200
201
202 void vf_set_vp_matrix( struct vertex_fetch *vf,
203 const GLfloat *viewport )
204 {
205 assert(vf->allow_viewport_emits);
206
207 /* scale */
208 vf->vp[0] = viewport[MAT_SX];
209 vf->vp[1] = viewport[MAT_SY];
210 vf->vp[2] = viewport[MAT_SZ];
211 vf->vp[3] = 1.0;
212
213 /* translate */
214 vf->vp[4] = viewport[MAT_TX];
215 vf->vp[5] = viewport[MAT_TY];
216 vf->vp[6] = viewport[MAT_TZ];
217 vf->vp[7] = 0.0;
218 }
219
220 void vf_set_vp_scale_translate( struct vertex_fetch *vf,
221 const GLfloat *scale,
222 const GLfloat *translate )
223 {
224 assert(vf->allow_viewport_emits);
225
226 vf->vp[0] = scale[0];
227 vf->vp[1] = scale[1];
228 vf->vp[2] = scale[2];
229 vf->vp[3] = scale[3];
230
231 vf->vp[4] = translate[0];
232 vf->vp[5] = translate[1];
233 vf->vp[6] = translate[2];
234 vf->vp[7] = translate[3];
235 }
236
237
238 /* Set attribute pointers, adjusted for start position:
239 */
240 void vf_set_sources( struct vertex_fetch *vf,
241 GLvector4f * const sources[],
242 GLuint start )
243 {
244 struct vf_attr *a = vf->attr;
245 GLuint j;
246
247 for (j = 0; j < vf->attr_count; j++) {
248 const GLvector4f *vptr = sources[a[j].attrib];
249
250 if ((a[j].inputstride != vptr->stride) ||
251 (a[j].inputsize != vptr->size))
252 vf->emit = choose_emit_func;
253
254 a[j].inputstride = vptr->stride;
255 a[j].inputsize = vptr->size;
256 a[j].do_insert = a[j].insert[vptr->size - 1];
257 a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
258 }
259 }
260
261
262
263 /* Emit count VB vertices to dest.
264 */
265 void vf_emit_vertices( struct vertex_fetch *vf,
266 GLuint count,
267 void *dest )
268 {
269 vf->emit( vf, count, (GLubyte*) dest );
270 }
271
272
273 /* Extract a named attribute from a hardware vertex. Will have to
274 * reverse any viewport transformation, swizzling or other conversions
275 * which may have been applied.
276 *
277 * This is mainly required for on-the-fly vertex translations to
278 * swrast format.
279 */
280 void vf_get_attr( struct vertex_fetch *vf,
281 const void *vertex,
282 GLenum attr,
283 const GLfloat *dflt,
284 GLfloat *dest )
285 {
286 const struct vf_attr *a = vf->attr;
287 const GLuint attr_count = vf->attr_count;
288 GLuint j;
289
290 for (j = 0; j < attr_count; j++) {
291 if (a[j].attrib == attr) {
292 a[j].extract( &a[j], dest, (GLubyte *)vertex + a[j].vertoffset );
293 return;
294 }
295 }
296
297 /* Else return the value from ctx->Current.
298 */
299 _mesa_memcpy( dest, dflt, 4*sizeof(GLfloat));
300 }
301
302
303
304
305 struct vertex_fetch *vf_create( GLboolean allow_viewport_emits )
306 {
307 struct vertex_fetch *vf = CALLOC_STRUCT(vertex_fetch);
308 GLuint i;
309
310 for (i = 0; i < VF_ATTRIB_MAX; i++)
311 vf->attr[i].vf = vf;
312
313 vf->allow_viewport_emits = allow_viewport_emits;
314
315 switch(CHAN_TYPE) {
316 case GL_UNSIGNED_BYTE:
317 vf->chan_scale[0] = 255.0;
318 vf->chan_scale[1] = 255.0;
319 vf->chan_scale[2] = 255.0;
320 vf->chan_scale[3] = 255.0;
321 break;
322 case GL_UNSIGNED_SHORT:
323 vf->chan_scale[0] = 65535.0;
324 vf->chan_scale[1] = 65535.0;
325 vf->chan_scale[2] = 65535.0;
326 vf->chan_scale[3] = 65535.0;
327 break;
328 default:
329 vf->chan_scale[0] = 1.0;
330 vf->chan_scale[1] = 1.0;
331 vf->chan_scale[2] = 1.0;
332 vf->chan_scale[3] = 1.0;
333 break;
334 }
335
336 vf->identity[0] = 0.0;
337 vf->identity[1] = 0.0;
338 vf->identity[2] = 0.0;
339 vf->identity[3] = 1.0;
340
341 vf->codegen_emit = NULL;
342
343 #ifdef USE_SSE_ASM
344 if (!_mesa_getenv("MESA_NO_CODEGEN"))
345 vf->codegen_emit = vf_generate_sse_emit;
346 #endif
347
348 return vf;
349 }
350
351
352 void vf_destroy( struct vertex_fetch *vf )
353 {
354 struct vf_fastpath *fp, *tmp;
355
356 for (fp = vf->fastpath ; fp ; fp = tmp) {
357 tmp = fp->next;
358 FREE(fp->attr);
359
360 /* KW: At the moment, fp->func is constrained to be allocated by
361 * _mesa_exec_alloc(), as the hardwired fastpaths in
362 * t_vertex_generic.c are handled specially. It would be nice
363 * to unify them, but this probably won't change until this
364 * module gets another overhaul.
365 */
366 _mesa_exec_free((void *) fp->func);
367 FREE(fp);
368 }
369
370 vf->fastpath = NULL;
371 FREE(vf);
372 }