2 * Copyright 2003 Tungsten Graphics, inc.
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:
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
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.
25 * Keith Whitwell <keithw@tungstengraphics.com>
38 static GLboolean
match_fastpath( struct vertex_fetch
*vf
,
39 const struct vf_fastpath
*fp
)
43 if (vf
->attr_count
!= fp
->attr_count
)
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
)
52 if (fp
->match_strides
) {
53 if (vf
->vertex_stride
!= fp
->vertex_stride
)
56 for (j
= 0; j
< vf
->attr_count
; j
++)
57 if (vf
->attr
[j
].inputstride
!= fp
->attr
[j
].stride
)
64 static GLboolean
search_fastpath_emit( struct vertex_fetch
*vf
)
66 struct vf_fastpath
*fp
= vf
->fastpath
;
68 for ( ; fp
; fp
= fp
->next
) {
69 if (match_fastpath(vf
, fp
)) {
78 void vf_register_fastpath( struct vertex_fetch
*vf
,
79 GLboolean match_strides
)
81 struct vf_fastpath
*fastpath
= CALLOC_STRUCT(vf_fastpath
);
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]));
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
;
98 fastpath
->next
= vf
->fastpath
;
99 vf
->fastpath
= fastpath
;
105 /***********************************************************************
106 * Build codegen functions or return generic ones:
108 static void choose_emit_func( struct vertex_fetch
*vf
,
114 /* Does this match an existing (hardwired, codegen or known-bad)
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.
123 else if (vf
->codegen_emit
) {
124 vf
->codegen_emit( vf
);
128 vf_generate_hardwired_emit(vf
);
131 /* Otherwise use the generic version:
134 vf
->emit
= vf_generic_emit
;
136 vf
->emit( vf
, count
, dest
);
143 /***********************************************************************
144 * Public entrypoints, mostly dispatch to the above:
149 GLuint
vf_set_vertex_attributes( struct vertex_fetch
*vf
,
150 const struct vf_attr_map
*map
,
152 GLuint vertex_stride
)
157 assert(nr
< VF_ATTRIB_MAX
);
159 memset(vf
->lookup
, 0, sizeof(vf
->lookup
));
161 for (j
= 0, i
= 0; i
< nr
; i
++) {
162 const GLuint format
= map
[i
].format
;
163 if (format
== EMIT_PAD
) {
165 _mesa_printf("%d: pad %d, offset %d\n", i
,
166 map
[i
].offset
, offset
);
168 offset
+= map
[i
].offset
;
172 assert(vf
->lookup
[map
[i
].attrib
] == 0);
173 vf
->lookup
[map
[i
].attrib
] = &vf
->attr
[j
];
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
;
183 _mesa_printf("%d: %s, offset %d\n", i
,
184 vf_format_info
[format
].name
,
185 vf
->attr
[j
].vertoffset
);
187 offset
+= vf_format_info
[format
].attrsize
;
193 vf
->vertex_stride
= vertex_stride
? vertex_stride
: offset
;
194 vf
->emit
= choose_emit_func
;
196 assert(vf
->vertex_stride
>= offset
);
197 return vf
->vertex_stride
;
202 void vf_set_vp_matrix( struct vertex_fetch
*vf
,
203 const GLfloat
*viewport
)
205 assert(vf
->allow_viewport_emits
);
208 vf
->vp
[0] = viewport
[MAT_SX
];
209 vf
->vp
[1] = viewport
[MAT_SY
];
210 vf
->vp
[2] = viewport
[MAT_SZ
];
214 vf
->vp
[4] = viewport
[MAT_TX
];
215 vf
->vp
[5] = viewport
[MAT_TY
];
216 vf
->vp
[6] = viewport
[MAT_TZ
];
220 void vf_set_vp_scale_translate( struct vertex_fetch
*vf
,
221 const GLfloat
*scale
,
222 const GLfloat
*translate
)
224 assert(vf
->allow_viewport_emits
);
226 vf
->vp
[0] = scale
[0];
227 vf
->vp
[1] = scale
[1];
228 vf
->vp
[2] = scale
[2];
229 vf
->vp
[3] = scale
[3];
231 vf
->vp
[4] = translate
[0];
232 vf
->vp
[5] = translate
[1];
233 vf
->vp
[6] = translate
[2];
234 vf
->vp
[7] = translate
[3];
238 /* Set attribute pointers, adjusted for start position:
240 void vf_set_sources( struct vertex_fetch
*vf
,
241 GLvector4f
* const sources
[],
244 struct vf_attr
*a
= vf
->attr
;
247 for (j
= 0; j
< vf
->attr_count
; j
++) {
248 const GLvector4f
*vptr
= sources
[a
[j
].attrib
];
250 if ((a
[j
].inputstride
!= vptr
->stride
) ||
251 (a
[j
].inputsize
!= vptr
->size
))
252 vf
->emit
= choose_emit_func
;
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
;
263 /* Emit count VB vertices to dest.
265 void vf_emit_vertices( struct vertex_fetch
*vf
,
269 vf
->emit( vf
, count
, (GLubyte
*) dest
);
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.
277 * This is mainly required for on-the-fly vertex translations to
280 void vf_get_attr( struct vertex_fetch
*vf
,
286 const struct vf_attr
*a
= vf
->attr
;
287 const GLuint attr_count
= vf
->attr_count
;
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
);
297 /* Else return the value from ctx->Current.
299 _mesa_memcpy( dest
, dflt
, 4*sizeof(GLfloat
));
305 struct vertex_fetch
*vf_create( GLboolean allow_viewport_emits
)
307 struct vertex_fetch
*vf
= CALLOC_STRUCT(vertex_fetch
);
310 for (i
= 0; i
< VF_ATTRIB_MAX
; i
++)
313 vf
->allow_viewport_emits
= allow_viewport_emits
;
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;
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;
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;
336 vf
->identity
[0] = 0.0;
337 vf
->identity
[1] = 0.0;
338 vf
->identity
[2] = 0.0;
339 vf
->identity
[3] = 1.0;
341 vf
->codegen_emit
= NULL
;
344 if (!_mesa_getenv("MESA_NO_CODEGEN"))
345 vf
->codegen_emit
= vf_generate_sse_emit
;
352 void vf_destroy( struct vertex_fetch
*vf
)
354 struct vf_fastpath
*fp
, *tmp
;
356 for (fp
= vf
->fastpath
; fp
; fp
= tmp
) {
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.
366 _mesa_exec_free((void *) fp
->func
);