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
)
168 static GLboolean
emit_3f_3( struct tnl_clipspace_codegen
*p
)
171 p
->emit_mov(p
, out(0), in(0)) &&
172 p
->emit_mov(p
, out(1), in(1)) &&
173 p
->emit_mov(p
, out(2), in(2));
176 static GLboolean
emit_3f_2( struct tnl_clipspace_codegen
*p
)
179 p
->emit_mov(p
, out(0), in(0)) &&
180 p
->emit_mov(p
, out(1), in(1)) &&
181 p
->emit_const(p
, out(2), 0.0);
184 static GLboolean
emit_3f_1( struct tnl_clipspace_codegen
*p
)
187 p
->emit_mov(p
, out(0), in(0)) &&
188 p
->emit_const(p
, out(1), 0.0) &&
189 p
->emit_const(p
, out(2), 0.0);
193 static GLboolean
emit_2f_2( struct tnl_clipspace_codegen
*p
)
196 p
->emit_mov(p
, out(0), in(0)) &&
197 p
->emit_mov(p
, out(1), in(1));
200 static GLboolean
emit_2f_1( struct tnl_clipspace_codegen
*p
)
203 p
->emit_mov(p
, out(0), in(0)) &&
204 p
->emit_const(p
, out(1), 0.0);
207 static GLboolean
emit_1f_1( struct tnl_clipspace_codegen
*p
)
210 p
->emit_mov(p
, out(0), in(0));
213 static GLboolean
emit_4chan_4f_rgba_4( struct tnl_clipspace_codegen
*p
)
216 p
->emit_float_to_chan(p
, out(0), in(0)) &&
217 p
->emit_float_to_chan(p
, out(1), in(1)) &&
218 p
->emit_float_to_chan(p
, out(2), in(2)) &&
219 p
->emit_float_to_chan(p
, out(3), in(3));
222 static GLboolean
emit_4chan_4f_rgba_3( struct tnl_clipspace_codegen
*p
)
225 p
->emit_float_to_chan(p
, out(0), in(0)) &&
226 p
->emit_float_to_chan(p
, out(1), in(1)) &&
227 p
->emit_float_to_chan(p
, out(2), in(2)) &&
228 p
->emit_const_chan(p
, out(3), CHAN_MAX
);
231 static GLboolean
emit_4chan_4f_rgba_2( struct tnl_clipspace_codegen
*p
)
234 p
->emit_float_to_chan(p
, out(0), in(0)) &&
235 p
->emit_float_to_chan(p
, out(1), in(1)) &&
236 p
->emit_const_chan(p
, out(2), 0) &&
237 p
->emit_const_chan(p
, out(3), CHAN_MAX
);
240 static GLboolean
emit_4chan_4f_rgba_1( struct tnl_clipspace_codegen
*p
)
243 p
->emit_float_to_chan(p
, out(0), in(0)) &&
244 p
->emit_const_chan(p
, out(1), 0) &&
245 p
->emit_const_chan(p
, out(2), 0) &&
246 p
->emit_const_chan(p
, out(3), CHAN_MAX
);
249 static GLboolean
emit_4ub_4f_rgba_4( struct tnl_clipspace_codegen
*p
)
252 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
253 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
254 p
->emit_float_to_ubyte(p
, out(2), in(2)) &&
255 p
->emit_float_to_ubyte(p
, out(3), in(3));
258 static GLboolean
emit_4ub_4f_rgba_3( struct tnl_clipspace_codegen
*p
)
261 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
262 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
263 p
->emit_float_to_ubyte(p
, out(2), in(2)) &&
264 p
->emit_const_ubyte(p
, out(3), 0xff);
267 static GLboolean
emit_4ub_4f_rgba_2( struct tnl_clipspace_codegen
*p
)
270 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
271 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
272 p
->emit_const_ubyte(p
, out(2), 0) &&
273 p
->emit_const_ubyte(p
, out(3), 0xff);
276 static GLboolean
emit_4ub_4f_rgba_1( struct tnl_clipspace_codegen
*p
)
279 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
280 p
->emit_const_ubyte(p
, out(1), 0) &&
281 p
->emit_const_ubyte(p
, out(2), 0) &&
282 p
->emit_const_ubyte(p
, out(3), 0xff);
285 static GLboolean
emit_4ub_4f_bgra_4( struct tnl_clipspace_codegen
*p
)
288 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
289 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
290 p
->emit_float_to_ubyte(p
, out(0), in(2)) &&
291 p
->emit_float_to_ubyte(p
, out(3), in(3));
294 static GLboolean
emit_4ub_4f_bgra_3( struct tnl_clipspace_codegen
*p
)
297 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
298 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
299 p
->emit_float_to_ubyte(p
, out(0), in(2)) &&
300 p
->emit_const_ubyte(p
, out(3), 0xff);
303 static GLboolean
emit_4ub_4f_bgra_2( struct tnl_clipspace_codegen
*p
)
306 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
307 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
308 p
->emit_const_ubyte(p
, out(0), 0) &&
309 p
->emit_const_ubyte(p
, out(3), 0xff);
312 static GLboolean
emit_4ub_4f_bgra_1( struct tnl_clipspace_codegen
*p
)
315 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
316 p
->emit_const_ubyte(p
, out(1), 0) &&
317 p
->emit_const_ubyte(p
, out(0), 0) &&
318 p
->emit_const_ubyte(p
, out(3), 0xff);
321 static GLboolean
emit_3ub_3f_rgb_3( struct tnl_clipspace_codegen
*p
)
324 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
325 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
326 p
->emit_float_to_ubyte(p
, out(2), in(2));
329 static GLboolean
emit_3ub_3f_rgb_2( struct tnl_clipspace_codegen
*p
)
332 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
333 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
334 p
->emit_const_ubyte(p
, out(2), 0);
337 static GLboolean
emit_3ub_3f_rgb_1( struct tnl_clipspace_codegen
*p
)
340 p
->emit_float_to_ubyte(p
, out(0), in(0)) &&
341 p
->emit_const_ubyte(p
, out(1), 0) &&
342 p
->emit_const_ubyte(p
, out(2), 0);
345 static GLboolean
emit_3ub_3f_bgr_3( struct tnl_clipspace_codegen
*p
)
348 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
349 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
350 p
->emit_float_to_ubyte(p
, out(0), in(2));
353 static GLboolean
emit_3ub_3f_bgr_2( struct tnl_clipspace_codegen
*p
)
356 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
357 p
->emit_float_to_ubyte(p
, out(1), in(1)) &&
358 p
->emit_const_ubyte(p
, out(0), 0);
361 static GLboolean
emit_3ub_3f_bgr_1( struct tnl_clipspace_codegen
*p
)
364 p
->emit_float_to_ubyte(p
, out(2), in(0)) &&
365 p
->emit_const_ubyte(p
, out(1), 0) &&
366 p
->emit_const_ubyte(p
, out(0), 0);
370 static GLboolean
emit_1ub_1f_1( struct tnl_clipspace_codegen
*p
)
373 p
->emit_float_to_ubyte(p
, out(0), in(0));
383 GLboolean (*emit
[4])( struct tnl_clipspace_codegen
* );
384 } emit_info
[EMIT_MAX
] = {
386 { "1f", GL_FLOAT
, GL_FALSE
,
387 { emit_1f_1
, emit_1f_1
, emit_1f_1
, emit_1f_1
} },
389 { "2f", GL_FLOAT
, GL_FALSE
,
390 { emit_2f_1
, emit_2f_2
, emit_2f_2
, emit_2f_2
} },
392 { "3f", GL_FLOAT
, GL_FALSE
,
393 { emit_3f_1
, emit_3f_2
, emit_3f_3
, emit_3f_3
} },
395 { "4f", GL_FLOAT
, GL_FALSE
,
396 { emit_4f_1
, emit_4f_2
, emit_4f_3
, emit_4f_4
} },
398 { "2f_viewport", GL_FLOAT
, GL_TRUE
,
399 { emit_2f_viewport_1
, emit_2f_viewport_2
, emit_2f_viewport_2
,
400 emit_2f_viewport_2
} },
402 { "3f_viewport", GL_FLOAT
, GL_TRUE
,
403 { emit_3f_viewport_1
, emit_3f_viewport_2
, emit_3f_viewport_3
,
404 emit_3f_viewport_3
} },
406 { "4f_viewport", GL_FLOAT
, GL_TRUE
,
407 { emit_4f_viewport_1
, emit_4f_viewport_2
, emit_4f_viewport_3
,
408 emit_4f_viewport_4
} },
410 { "3f_xyw", GL_FLOAT
, GL_FALSE
,
411 { emit_3f_xyw_err
, emit_3f_xyw_err
, emit_3f_xyw_err
,
414 { "1ub_1f", GL_UNSIGNED_BYTE
, GL_FALSE
,
415 { emit_1ub_1f_1
, emit_1ub_1f_1
, emit_1ub_1f_1
, emit_1ub_1f_1
} },
417 { "3ub_3f_rgb", GL_UNSIGNED_BYTE
, GL_FALSE
,
418 { emit_3ub_3f_rgb_1
, emit_3ub_3f_rgb_2
, emit_3ub_3f_rgb_3
,
419 emit_3ub_3f_rgb_3
} },
421 { "3ub_3f_bgr", GL_UNSIGNED_BYTE
, GL_FALSE
,
422 { emit_3ub_3f_bgr_1
, emit_3ub_3f_bgr_2
, emit_3ub_3f_bgr_3
,
423 emit_3ub_3f_bgr_3
} },
425 { "4ub_4f_rgba", GL_UNSIGNED_BYTE
, GL_FALSE
,
426 { emit_4ub_4f_rgba_1
, emit_4ub_4f_rgba_2
, emit_4ub_4f_rgba_3
,
427 emit_4ub_4f_rgba_4
} },
429 { "4ub_4f_bgra", GL_UNSIGNED_BYTE
, GL_FALSE
,
430 { emit_4ub_4f_bgra_1
, emit_4ub_4f_bgra_2
, emit_4ub_4f_bgra_3
,
431 emit_4ub_4f_bgra_4
} },
433 { "4chan_4f_rgba", CHAN_TYPE
, GL_FALSE
,
434 { emit_4chan_4f_rgba_1
, emit_4chan_4f_rgba_2
, emit_4chan_4f_rgba_3
,
435 emit_4chan_4f_rgba_4
} },
443 /***********************************************************************
444 * list(attrib, size) --> function
446 * Because of the dependence of size, this all has to take place after
447 * the pipeline has been run.
450 tnl_emit_func
_tnl_codegen_emit( GLcontext
*ctx
)
452 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
453 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
454 struct tnl_clipspace_attr
*a
= vtx
->attr
;
455 struct tnl_clipspace_codegen
*p
= &vtx
->codegen
;
456 const GLuint count
= vtx
->attr_count
;
459 /* Need a faster lookup, or is this linear scan of an MRU list good
460 * enough? MRU chosen based on the guess that consecutive VB's are
461 * likely to be of the same format. A hash of attributes and sizes
462 * might be a better technique.
464 * With the vtx code now in place, it should be possible to track
465 * changes to the sizes of input arrays (and state, of course) and
466 * only invalidate this function when those sizes have changed.
469 foreach (l
, p
->codegen_list
) {
470 if (l
->attr_count
!= count
)
474 * a[j].vp will not change for a given attrib
475 * a[j].vertex_offset will not change nothing else has changed.
477 for (j
= 0; j
< count
; j
++)
478 if (a
[j
].attrib
!= l
->a
[j
].attrib
||
479 a
[j
].sz
!= l
->a
[j
].sz
)
483 move_to_head(l
, p
->codegen_list
);
489 p
->emit_header( p
, vtx
);
491 for (j
= 0; j
< count
; j
++) {
492 GLuint sz
= VB
->AttribPtr
[a
[j
].attrib
]->size
- 1;
493 p
->emit_attr_header( p
, a
, j
,
494 emit_info
[a
[j
].format
].out_type
,
495 emit_info
[a
[j
].format
].need_vp
);
497 if (!emit_info
[a
[j
].format
].emit
[sz
]( p
)) {
498 fprintf(stderr
, "codegen failed\n");
502 p
->emit_attr_footer( p
);
507 return p
->emit_store_func( p
);