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>
32 #include "t_context.h"
35 #include "simple_list.h"
37 /* Another codegen scheme, hopefully portable to a few different
38 * architectures without too much work.
44 static GLboolean
emit_4f_viewport_4( struct tnl_clipspace_codegen
*p
)
47 p
->emit_mad(p
, out(0), vp(0), in(0), vp(12)) &&
48 p
->emit_mad(p
, out(1), vp(5), in(1), vp(13)) &&
49 p
->emit_mad(p
, out(2), vp(10), in(2), vp(14)) &&
50 p
->emit_mov(p
, out(3), in(3));
53 static GLboolean
emit_4f_viewport_3( struct tnl_clipspace_codegen
*p
)
56 p
->emit_mad(p
, out(0), vp(0), in(0), vp(12)) &&
57 p
->emit_mad(p
, out(1), vp(5), in(1), vp(13)) &&
58 p
->emit_mad(p
, out(2), vp(10), in(2), vp(14)) &&
59 p
->emit_const(p
, out(3), 1.0);
62 static GLboolean
emit_4f_viewport_2( struct tnl_clipspace_codegen
*p
)
65 p
->emit_mad(p
, out(0), vp(0), in(0), vp(12)) &&
66 p
->emit_mad(p
, out(1), vp(5), in(1), vp(13)) &&
67 p
->emit_mov(p
, out(2), vp(14)) &&
68 p
->emit_const(p
, out(3), 1.0);
71 static GLboolean
emit_4f_viewport_1( struct tnl_clipspace_codegen
*p
)
74 p
->emit_mad(p
, out(0), vp(0), in(0), vp(12)) &&
75 p
->emit_mov(p
, out(1), vp(13)) &&
76 p
->emit_mov(p
, out(2), vp(14)) &&
77 p
->emit_const(p
, out(3), 1.0);
80 static GLboolean
emit_3f_viewport_3( struct tnl_clipspace_codegen
*p
)
83 p
->emit_mad(p
, out(0), vp(0), in(0), vp(12)) &&
84 p
->emit_mad(p
, out(1), vp(5), in(1), vp(13)) &&
85 p
->emit_mad(p
, out(2), vp(10), in(2), vp(14));
88 static GLboolean
emit_3f_viewport_2( struct tnl_clipspace_codegen
*p
)
91 p
->emit_mad(p
, out(0), vp(0), in(0), vp(12)) &&
92 p
->emit_mad(p
, out(1), vp(5), in(1), vp(13)) &&
93 p
->emit_mov(p
, out(2), vp(14));
96 static GLboolean
emit_3f_viewport_1( struct tnl_clipspace_codegen
*p
)
99 p
->emit_mad(p
, out(0), vp(0), in(0), vp(12)) &&
100 p
->emit_mov(p
, out(1), vp(13)) &&
101 p
->emit_mov(p
, out(2), vp(14));
104 static GLboolean
emit_2f_viewport_2( struct tnl_clipspace_codegen
*p
)
107 p
->emit_mad(p
, out(0), vp(0), in(0), vp(12)) &&
108 p
->emit_mad(p
, out(1), vp(5), in(1), vp(13));
111 static GLboolean
emit_2f_viewport_1( struct tnl_clipspace_codegen
*p
)
114 p
->emit_mad(p
, out(0), vp(0), in(0), vp(12));
118 static GLboolean
emit_4f_4( struct tnl_clipspace_codegen
*p
)
121 p
->emit_mov(p
, out(0), in(0)) &&
122 p
->emit_mov(p
, out(1), in(1)) &&
123 p
->emit_mov(p
, out(2), in(2)) &&
124 p
->emit_mov(p
, out(3), in(3));
127 static GLboolean
emit_4f_3( struct tnl_clipspace_codegen
*p
)
130 p
->emit_mov(p
, out(0), in(0)) &&
131 p
->emit_mov(p
, out(1), in(1)) &&
132 p
->emit_mov(p
, out(2), in(2)) &&
133 p
->emit_const(p
, out(3), 1.0);
136 static GLboolean
emit_4f_2( struct tnl_clipspace_codegen
*p
)
139 p
->emit_mov(p
, out(0), in(0)) &&
140 p
->emit_mov(p
, out(1), in(1)) &&
141 p
->emit_const(p
, out(2), 0.0) &&
142 p
->emit_const(p
, out(3), 1.0);
145 static GLboolean
emit_4f_1( struct tnl_clipspace_codegen
*p
)
148 p
->emit_mov(p
, out(0), in(0)) &&
149 p
->emit_const(p
, out(1), 0.0) &&
150 p
->emit_const(p
, out(2), 0.0) &&
151 p
->emit_const(p
, out(3), 1.0);
154 static GLboolean
emit_3f_xyw_4( struct tnl_clipspace_codegen
*p
)
157 p
->emit_mov(p
, out(0), in(0)) &&
158 p
->emit_mov(p
, out(1), in(1)) &&
159 p
->emit_mov(p
, out(2), in(3));
162 static GLboolean
emit_3f_xyw_err( struct tnl_clipspace_codegen
*p
)
169 static GLboolean
emit_3f_3( struct tnl_clipspace_codegen
*p
)
172 p
->emit_mov(p
, out(0), in(0)) &&
173 p
->emit_mov(p
, out(1), in(1)) &&
174 p
->emit_mov(p
, out(2), in(2));
177 static GLboolean
emit_3f_2( struct tnl_clipspace_codegen
*p
)
180 p
->emit_mov(p
, out(0), in(0)) &&
181 p
->emit_mov(p
, out(1), in(1)) &&
182 p
->emit_const(p
, out(2), 0.0);
185 static GLboolean
emit_3f_1( struct tnl_clipspace_codegen
*p
)
188 p
->emit_mov(p
, out(0), in(0)) &&
189 p
->emit_const(p
, out(1), 0.0) &&
190 p
->emit_const(p
, out(2), 0.0);
194 static GLboolean
emit_2f_2( struct tnl_clipspace_codegen
*p
)
197 p
->emit_mov(p
, out(0), in(0)) &&
198 p
->emit_mov(p
, out(1), in(1));
201 static GLboolean
emit_2f_1( struct tnl_clipspace_codegen
*p
)
204 p
->emit_mov(p
, out(0), in(0)) &&
205 p
->emit_const(p
, out(1), 0.0);
208 static GLboolean
emit_1f_1( struct tnl_clipspace_codegen
*p
)
211 p
->emit_mov(p
, out(0), in(0));
214 static GLboolean
emit_4chan_4f_rgba_4( struct tnl_clipspace_codegen
*p
)
217 p
->emit_float_to_chan(p
, out(0), in(0)) &&
218 p
->emit_float_to_chan(p
, out(1), in(1)) &&
219 p
->emit_float_to_chan(p
, out(2), in(2)) &&
220 p
->emit_float_to_chan(p
, out(3), in(3));
223 static GLboolean
emit_4chan_4f_rgba_3( struct tnl_clipspace_codegen
*p
)
226 p
->emit_float_to_chan(p
, out(0), in(0)) &&
227 p
->emit_float_to_chan(p
, out(1), in(1)) &&
228 p
->emit_float_to_chan(p
, out(2), in(2)) &&
229 p
->emit_const_chan(p
, out(3), CHAN_MAX
);
232 static GLboolean
emit_4chan_4f_rgba_2( struct tnl_clipspace_codegen
*p
)
235 p
->emit_float_to_chan(p
, out(0), in(0)) &&
236 p
->emit_float_to_chan(p
, out(1), in(1)) &&
237 p
->emit_const_chan(p
, out(2), 0) &&
238 p
->emit_const_chan(p
, out(3), CHAN_MAX
);
241 static GLboolean
emit_4chan_4f_rgba_1( struct tnl_clipspace_codegen
*p
)
244 p
->emit_float_to_chan(p
, out(0), in(0)) &&
245 p
->emit_const_chan(p
, out(1), 0) &&
246 p
->emit_const_chan(p
, out(2), 0) &&
247 p
->emit_const_chan(p
, out(3), CHAN_MAX
);
250 static GLboolean
emit_4ub_4f_rgba_4( struct tnl_clipspace_codegen
*p
)
253 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
254 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
255 p
->emit_float_to_ubyte(p
, out(2), in(2)) &&
256 p
->emit_float_to_ubyte(p
, out(3), in(3));
259 static GLboolean
emit_4ub_4f_rgba_3( struct tnl_clipspace_codegen
*p
)
262 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
263 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
264 p
->emit_float_to_ubyte(p
, out(2), in(2)) &&
265 p
->emit_const_ubyte(p
, out(3), 0xff);
268 static GLboolean
emit_4ub_4f_rgba_2( struct tnl_clipspace_codegen
*p
)
271 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
272 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
273 p
->emit_const_ubyte(p
, out(2), 0) &&
274 p
->emit_const_ubyte(p
, out(3), 0xff);
277 static GLboolean
emit_4ub_4f_rgba_1( struct tnl_clipspace_codegen
*p
)
280 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
281 p
->emit_const_ubyte(p
, out(1), 0) &&
282 p
->emit_const_ubyte(p
, out(2), 0) &&
283 p
->emit_const_ubyte(p
, out(3), 0xff);
286 static GLboolean
emit_4ub_4f_bgra_4( struct tnl_clipspace_codegen
*p
)
289 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
290 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
291 p
->emit_float_to_ubyte(p
, out(0), in(2)) &&
292 p
->emit_float_to_ubyte(p
, out(3), in(3));
295 static GLboolean
emit_4ub_4f_bgra_3( struct tnl_clipspace_codegen
*p
)
298 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
299 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
300 p
->emit_float_to_ubyte(p
, out(0), in(2)) &&
301 p
->emit_const_ubyte(p
, out(3), 0xff);
304 static GLboolean
emit_4ub_4f_bgra_2( struct tnl_clipspace_codegen
*p
)
307 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
308 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
309 p
->emit_const_ubyte(p
, out(0), 0) &&
310 p
->emit_const_ubyte(p
, out(3), 0xff);
313 static GLboolean
emit_4ub_4f_bgra_1( struct tnl_clipspace_codegen
*p
)
316 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
317 p
->emit_const_ubyte(p
, out(1), 0) &&
318 p
->emit_const_ubyte(p
, out(0), 0) &&
319 p
->emit_const_ubyte(p
, out(3), 0xff);
322 static GLboolean
emit_3ub_3f_rgb_3( struct tnl_clipspace_codegen
*p
)
325 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
326 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
327 p
->emit_float_to_ubyte(p
, out(2), in(2));
330 static GLboolean
emit_3ub_3f_rgb_2( struct tnl_clipspace_codegen
*p
)
333 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
334 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
335 p
->emit_const_ubyte(p
, out(2), 0);
338 static GLboolean
emit_3ub_3f_rgb_1( struct tnl_clipspace_codegen
*p
)
341 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
342 p
->emit_const_ubyte(p
, out(1), 0) &&
343 p
->emit_const_ubyte(p
, out(2), 0);
346 static GLboolean
emit_3ub_3f_bgr_3( struct tnl_clipspace_codegen
*p
)
349 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
350 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
351 p
->emit_float_to_ubyte(p
, out(0), in(2));
354 static GLboolean
emit_3ub_3f_bgr_2( struct tnl_clipspace_codegen
*p
)
357 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
358 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
359 p
->emit_const_ubyte(p
, out(0), 0);
362 static GLboolean
emit_3ub_3f_bgr_1( struct tnl_clipspace_codegen
*p
)
365 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
366 p
->emit_const_ubyte(p
, out(1), 0) &&
367 p
->emit_const_ubyte(p
, out(0), 0);
371 static GLboolean
emit_1ub_1f_1( struct tnl_clipspace_codegen
*p
)
374 p
->emit_float_to_ubyte(p
, out(0), in(0));
384 GLboolean (*emit
[4])( struct tnl_clipspace_codegen
* );
385 } emit_info
[EMIT_MAX
] = {
387 { "1f", GL_FLOAT
, GL_FALSE
,
388 { emit_1f_1
, emit_1f_1
, emit_1f_1
, emit_1f_1
} },
390 { "2f", GL_FLOAT
, GL_FALSE
,
391 { emit_2f_1
, emit_2f_2
, emit_2f_2
, emit_2f_2
} },
393 { "3f", GL_FLOAT
, GL_FALSE
,
394 { emit_3f_1
, emit_3f_2
, emit_3f_3
, emit_3f_3
} },
396 { "4f", GL_FLOAT
, GL_FALSE
,
397 { emit_4f_1
, emit_4f_2
, emit_4f_3
, emit_4f_4
} },
399 { "2f_viewport", GL_FLOAT
, GL_TRUE
,
400 { emit_2f_viewport_1
, emit_2f_viewport_2
, emit_2f_viewport_2
,
401 emit_2f_viewport_2
} },
403 { "3f_viewport", GL_FLOAT
, GL_TRUE
,
404 { emit_3f_viewport_1
, emit_3f_viewport_2
, emit_3f_viewport_3
,
405 emit_3f_viewport_3
} },
407 { "4f_viewport", GL_FLOAT
, GL_TRUE
,
408 { emit_4f_viewport_1
, emit_4f_viewport_2
, emit_4f_viewport_3
,
409 emit_4f_viewport_4
} },
411 { "3f_xyw", GL_FLOAT
, GL_FALSE
,
412 { emit_3f_xyw_err
, emit_3f_xyw_err
, emit_3f_xyw_err
,
415 { "1ub_1f", GL_UNSIGNED_BYTE
, GL_FALSE
,
416 { emit_1ub_1f_1
, emit_1ub_1f_1
, emit_1ub_1f_1
, emit_1ub_1f_1
} },
418 { "3ub_3f_rgb", GL_UNSIGNED_BYTE
, GL_FALSE
,
419 { emit_3ub_3f_rgb_1
, emit_3ub_3f_rgb_2
, emit_3ub_3f_rgb_3
,
420 emit_3ub_3f_rgb_3
} },
422 { "3ub_3f_bgr", GL_UNSIGNED_BYTE
, GL_FALSE
,
423 { emit_3ub_3f_bgr_1
, emit_3ub_3f_bgr_2
, emit_3ub_3f_bgr_3
,
424 emit_3ub_3f_bgr_3
} },
426 { "4ub_4f_rgba", GL_UNSIGNED_BYTE
, GL_FALSE
,
427 { emit_4ub_4f_rgba_1
, emit_4ub_4f_rgba_2
, emit_4ub_4f_rgba_3
,
428 emit_4ub_4f_rgba_4
} },
430 { "4ub_4f_bgra", GL_UNSIGNED_BYTE
, GL_FALSE
,
431 { emit_4ub_4f_bgra_1
, emit_4ub_4f_bgra_2
, emit_4ub_4f_bgra_3
,
432 emit_4ub_4f_bgra_4
} },
434 { "4chan_4f_rgba", CHAN_TYPE
, GL_FALSE
,
435 { emit_4chan_4f_rgba_1
, emit_4chan_4f_rgba_2
, emit_4chan_4f_rgba_3
,
436 emit_4chan_4f_rgba_4
} },
444 /***********************************************************************
445 * list(attrib, size) --> function
447 * Because of the dependence of size, this all has to take place after
448 * the pipeline has been run.
451 tnl_emit_func
_tnl_codegen_emit( GLcontext
*ctx
)
453 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
454 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
455 struct tnl_clipspace_attr
*a
= vtx
->attr
;
456 struct tnl_clipspace_codegen
*p
= &vtx
->codegen
;
457 const GLuint count
= vtx
->attr_count
;
460 /* Need a faster lookup, or is this linear scan of an MRU list good
461 * enough? MRU chosen based on the guess that consecutive VB's are
462 * likely to be of the same format. A hash of attributes and sizes
463 * might be a better technique.
465 * With the vtx code now in place, it should be possible to track
466 * changes to the sizes of input arrays (and state, of course) and
467 * only invalidate this function when those sizes have changed.
470 foreach (l
, p
->codegen_list
) {
471 if (l
->attr_count
!= count
)
475 * a[j].vp will not change for a given attrib
476 * a[j].vertex_offset will not change nothing else has changed.
478 for (j
= 0; j
< count
; j
++)
479 if (a
[j
].attrib
!= l
->a
[j
].attrib
||
480 a
[j
].sz
!= l
->a
[j
].sz
)
484 move_to_head(l
, p
->codegen_list
);
490 p
->emit_header( p
, vtx
);
492 for (j
= 0; j
< count
; j
++) {
493 GLuint sz
= VB
->AttribPtr
[a
[j
].attrib
]->size
- 1;
494 p
->emit_attr_header( p
, a
, j
,
495 emit_info
[a
[j
].format
].out_type
,
496 emit_info
[a
[j
].format
].need_vp
);
498 if (!emit_info
[a
[j
].format
].emit
[sz
]( p
)) {
499 fprintf(stderr
, "codegen failed\n");
503 p
->emit_attr_footer( p
);
508 return p
->emit_store_func( p
);