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>
31 #include "pipe/p_compiler.h"
32 #include "pipe/p_util.h"
40 /* TODO: remove this */
42 _mesa_exec_free( void *addr
);
45 static boolean
match_fastpath( struct draw_vertex_fetch
*vf
,
46 const struct draw_vf_fastpath
*fp
)
50 if (vf
->attr_count
!= fp
->attr_count
)
53 for (j
= 0; j
< vf
->attr_count
; j
++)
54 if (vf
->attr
[j
].format
!= fp
->attr
[j
].format
||
55 vf
->attr
[j
].inputsize
!= fp
->attr
[j
].size
||
56 vf
->attr
[j
].vertoffset
!= fp
->attr
[j
].offset
)
59 if (fp
->match_strides
) {
60 if (vf
->vertex_stride
!= fp
->vertex_stride
)
63 for (j
= 0; j
< vf
->attr_count
; j
++)
64 if (vf
->attr
[j
].inputstride
!= fp
->attr
[j
].stride
)
71 static boolean
search_fastpath_emit( struct draw_vertex_fetch
*vf
)
73 struct draw_vf_fastpath
*fp
= vf
->fastpath
;
75 for ( ; fp
; fp
= fp
->next
) {
76 if (match_fastpath(vf
, fp
)) {
85 void draw_vf_register_fastpath( struct draw_vertex_fetch
*vf
,
86 boolean match_strides
)
88 struct draw_vf_fastpath
*fastpath
= CALLOC_STRUCT(draw_vf_fastpath
);
91 fastpath
->vertex_stride
= vf
->vertex_stride
;
92 fastpath
->attr_count
= vf
->attr_count
;
93 fastpath
->match_strides
= match_strides
;
94 fastpath
->func
= vf
->emit
;
95 fastpath
->attr
= (struct draw_vf_attr_type
*)
96 MALLOC(vf
->attr_count
* sizeof(fastpath
->attr
[0]));
98 for (i
= 0; i
< vf
->attr_count
; i
++) {
99 fastpath
->attr
[i
].format
= vf
->attr
[i
].format
;
100 fastpath
->attr
[i
].stride
= vf
->attr
[i
].inputstride
;
101 fastpath
->attr
[i
].size
= vf
->attr
[i
].inputsize
;
102 fastpath
->attr
[i
].offset
= vf
->attr
[i
].vertoffset
;
105 fastpath
->next
= vf
->fastpath
;
106 vf
->fastpath
= fastpath
;
112 /***********************************************************************
113 * Build codegen functions or return generic ones:
115 static void choose_emit_func( struct draw_vertex_fetch
*vf
,
121 /* Does this match an existing (hardwired, codegen or known-bad)
124 if (search_fastpath_emit(vf
)) {
125 /* Use this result. If it is null, then it is already known
126 * that the current state will fail for codegen and there is no
127 * point trying again.
130 else if (vf
->codegen_emit
) {
131 vf
->codegen_emit( vf
);
135 draw_vf_generate_hardwired_emit(vf
);
138 /* Otherwise use the generic version:
141 vf
->emit
= draw_vf_generic_emit
;
143 vf
->emit( vf
, count
, dest
);
150 /***********************************************************************
151 * Public entrypoints, mostly dispatch to the above:
157 draw_vf_set_vertex_attributes( struct draw_vertex_fetch
*vf
,
158 const struct draw_vf_attr_map
*map
,
160 unsigned vertex_stride
)
165 assert(nr
< PIPE_ATTRIB_MAX
);
167 for (j
= 0, i
= 0; i
< nr
; i
++) {
168 const unsigned format
= map
[i
].format
;
169 if (format
== DRAW_EMIT_PAD
) {
171 debug_printf("%d: pad %d, offset %d\n", i
,
172 map
[i
].offset
, offset
);
175 offset
+= map
[i
].offset
;
179 vf
->attr
[j
].attrib
= map
[i
].attrib
;
180 vf
->attr
[j
].format
= format
;
181 vf
->attr
[j
].insert
= draw_vf_format_info
[format
].insert
;
182 vf
->attr
[j
].vertattrsize
= draw_vf_format_info
[format
].attrsize
;
183 vf
->attr
[j
].vertoffset
= offset
;
184 vf
->attr
[j
].isconst
= draw_vf_format_info
[format
].isconst
;
185 if(vf
->attr
[j
].isconst
)
186 memcpy(vf
->attr
[j
].data
, &map
[i
].data
, vf
->attr
[j
].vertattrsize
);
189 debug_printf("%d: %s, offset %d\n", i
,
190 draw_vf_format_info
[format
].name
,
191 vf
->attr
[j
].vertoffset
);
194 offset
+= draw_vf_format_info
[format
].attrsize
;
200 vf
->vertex_stride
= vertex_stride
? vertex_stride
: offset
;
201 vf
->emit
= choose_emit_func
;
203 assert(vf
->vertex_stride
>= offset
);
204 return vf
->vertex_stride
;
208 void draw_vf_set_vertex_info( struct draw_vertex_fetch
*vf
,
209 const struct vertex_info
*vinfo
,
213 struct draw_vf_attr
*a
= vf
->attr
;
214 struct draw_vf_attr_map attrs
[PIPE_MAX_SHADER_INPUTS
];
215 unsigned count
= 0; /* for debug/sanity */
216 unsigned nr_attrs
= 0;
218 for (i
= 0; i
< vinfo
->num_attribs
; i
++) {
219 j
= vinfo
->src_index
[i
];
220 switch (vinfo
->emit
[i
]) {
225 /* just copy the whole vertex as-is to the vbuf */
226 unsigned s
= vinfo
->size
;
229 /* copy the vertex header */
230 /* XXX: we actually don't copy the header, just pad it */
231 attrs
[nr_attrs
].attrib
= 0;
232 attrs
[nr_attrs
].format
= DRAW_EMIT_PAD
;
233 attrs
[nr_attrs
].offset
= offsetof(struct vertex_header
, data
);
234 s
-= offsetof(struct vertex_header
, data
)/4;
235 count
+= offsetof(struct vertex_header
, data
)/4;
237 /* copy the vertex data */
238 for(k
= 0; k
< (s
& ~0x3); k
+= 4) {
239 attrs
[nr_attrs
].attrib
= k
/4;
240 attrs
[nr_attrs
].format
= DRAW_EMIT_4F
;
241 attrs
[nr_attrs
].offset
= 0;
246 /* XXX: actually, this shouldn't be needed */
247 attrs
[nr_attrs
].attrib
= k
/4;
248 attrs
[nr_attrs
].offset
= 0;
253 attrs
[nr_attrs
].format
= DRAW_EMIT_1F
;
258 attrs
[nr_attrs
].format
= DRAW_EMIT_2F
;
263 attrs
[nr_attrs
].format
= DRAW_EMIT_3F
;
271 attrs
[nr_attrs
].attrib
= j
;
272 attrs
[nr_attrs
].format
= DRAW_EMIT_1F
;
273 attrs
[nr_attrs
].offset
= 0;
278 attrs
[nr_attrs
].attrib
= j
;
279 attrs
[nr_attrs
].format
= DRAW_EMIT_1F_CONST
;
280 attrs
[nr_attrs
].offset
= 0;
281 attrs
[nr_attrs
].data
.f
[0] = point_size
;
286 attrs
[nr_attrs
].attrib
= j
;
287 attrs
[nr_attrs
].format
= DRAW_EMIT_2F
;
288 attrs
[nr_attrs
].offset
= 0;
293 attrs
[nr_attrs
].attrib
= j
;
294 attrs
[nr_attrs
].format
= DRAW_EMIT_3F
;
295 attrs
[nr_attrs
].offset
= 0;
300 attrs
[nr_attrs
].attrib
= j
;
301 attrs
[nr_attrs
].format
= DRAW_EMIT_4F
;
302 attrs
[nr_attrs
].offset
= 0;
307 attrs
[nr_attrs
].attrib
= j
;
308 attrs
[nr_attrs
].format
= DRAW_EMIT_4UB_4F_BGRA
;
309 attrs
[nr_attrs
].offset
= 0;
318 assert(count
== vinfo
->size
);
320 draw_vf_set_vertex_attributes(vf
,
323 vinfo
->size
* sizeof(float) );
325 for (j
= 0; j
< vf
->attr_count
; j
++) {
327 a
[j
].do_insert
= a
[j
].insert
[4 - 1];
329 a
[j
].inputptr
= a
[j
].data
;
330 a
[j
].inputstride
= 0;
337 /* Set attribute pointers, adjusted for start position:
339 void draw_vf_set_sources( struct draw_vertex_fetch
*vf
,
340 GLvector4f
* const sources
[],
343 struct draw_vf_attr
*a
= vf
->attr
;
346 for (j
= 0; j
< vf
->attr_count
; j
++) {
347 const GLvector4f
*vptr
= sources
[a
[j
].attrib
];
349 if ((a
[j
].inputstride
!= vptr
->stride
) ||
350 (a
[j
].inputsize
!= vptr
->size
))
351 vf
->emit
= choose_emit_func
;
353 a
[j
].inputstride
= vptr
->stride
;
354 a
[j
].inputsize
= vptr
->size
;
355 a
[j
].do_insert
= a
[j
].insert
[vptr
->size
- 1];
356 a
[j
].inputptr
= ((uint8_t *)vptr
->data
) + start
* vptr
->stride
;
363 * Emit a vertex to dest.
365 void draw_vf_emit_vertex( struct draw_vertex_fetch
*vf
,
366 struct vertex_header
*vertex
,
369 struct draw_vf_attr
*a
= vf
->attr
;
372 for (j
= 0; j
< vf
->attr_count
; j
++) {
374 a
[j
].inputptr
= (uint8_t *)&vertex
->data
[a
[j
].attrib
][0];
375 a
[j
].inputstride
= 0; /* XXX: one-vertex-max ATM */
379 vf
->emit( vf
, 1, (uint8_t*) dest
);
384 struct draw_vertex_fetch
*draw_vf_create( void )
386 struct draw_vertex_fetch
*vf
= CALLOC_STRUCT(draw_vertex_fetch
);
389 for (i
= 0; i
< PIPE_ATTRIB_MAX
; i
++)
392 vf
->identity
[0] = 0.0;
393 vf
->identity
[1] = 0.0;
394 vf
->identity
[2] = 0.0;
395 vf
->identity
[3] = 1.0;
397 vf
->codegen_emit
= NULL
;
400 if (!GETENV("GALLIUM_NO_CODEGEN"))
401 vf
->codegen_emit
= draw_vf_generate_sse_emit
;
408 void draw_vf_destroy( struct draw_vertex_fetch
*vf
)
410 struct draw_vf_fastpath
*fp
, *tmp
;
412 for (fp
= vf
->fastpath
; fp
; fp
= tmp
) {
416 /* KW: At the moment, fp->func is constrained to be allocated by
417 * _mesa_exec_alloc(), as the hardwired fastpaths in
418 * t_vertex_generic.c are handled specially. It would be nice
419 * to unify them, but this probably won't change until this
420 * module gets another overhaul.
422 //_mesa_exec_free((void *) fp->func);