1
2/*
3 * Copyright 2003 Tungsten Graphics, inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * on the rights to use, copy, modify, merge, publish, distribute, sub
10 * license, and/or sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
20 * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 *    Keith Whitwell <keithw@tungstengraphics.com>
27 */
28
29#include "main/glheader.h"
30#include "main/context.h"
31#include "main/colormac.h"
32#include "main/simple_list.h"
33#include "swrast/s_chan.h"
34#include "t_context.h"
35#include "t_vertex.h"
36
37
38#if 0
39#define DEBUG_INSERT printf("%s\n", __FUNCTION__)
40#else
41#define DEBUG_INSERT
42#endif
43
44
45/*
46 * These functions take the NDC coordinates pointed to by 'in', apply the
47 * NDC->Viewport mapping and store the results at 'v'.
48 */
49
50static inline void insert_4f_viewport_4( const struct tnl_clipspace_attr *a, GLubyte *v,
51                      const GLfloat *in )
52{
53   GLfloat *out = (GLfloat *)v;
54   const GLfloat * const vp = a->vp;
55   DEBUG_INSERT;
56   out[0] = vp[0] * in[0] + vp[12];
57   out[1] = vp[5] * in[1] + vp[13];
58   out[2] = vp[10] * in[2] + vp[14];
59   out[3] = in[3];
60}
61
62static inline void insert_4f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v,
63				const GLfloat *in )
64{
65   GLfloat *out = (GLfloat *)v;
66   const GLfloat * const vp = a->vp;
67   DEBUG_INSERT;
68   out[0] = vp[0] * in[0] + vp[12];
69   out[1] = vp[5] * in[1] + vp[13];
70   out[2] = vp[10] * in[2] + vp[14];
71   out[3] = 1;
72}
73
74static inline void insert_4f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
75				const GLfloat *in )
76{
77   GLfloat *out = (GLfloat *)v;
78   const GLfloat * const vp = a->vp;
79   DEBUG_INSERT;
80   out[0] = vp[0] * in[0] + vp[12];
81   out[1] = vp[5] * in[1] + vp[13];
82   out[2] = vp[14];
83   out[3] = 1;
84}
85
86static inline void insert_4f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
87				const GLfloat *in )
88{
89   GLfloat *out = (GLfloat *)v;
90   const GLfloat * const vp = a->vp;
91   DEBUG_INSERT;
92   out[0] = vp[0] * in[0] + vp[12];
93   out[1] = vp[13];
94   out[2] = vp[14];
95   out[3] = 1;
96}
97
98static inline void insert_3f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v,
99				const GLfloat *in )
100{
101   GLfloat *out = (GLfloat *)v;
102   const GLfloat * const vp = a->vp;
103   DEBUG_INSERT;
104   out[0] = vp[0] * in[0] + vp[12];
105   out[1] = vp[5] * in[1] + vp[13];
106   out[2] = vp[10] * in[2] + vp[14];
107}
108
109static inline void insert_3f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
110				const GLfloat *in )
111{
112   GLfloat *out = (GLfloat *)v;
113   const GLfloat * const vp = a->vp;
114   DEBUG_INSERT;
115   out[0] = vp[0] * in[0] + vp[12];
116   out[1] = vp[5] * in[1] + vp[13];
117   out[2] = vp[14];
118}
119
120static inline void insert_3f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
121				const GLfloat *in )
122{
123   GLfloat *out = (GLfloat *)v;
124   const GLfloat * const vp = a->vp;
125   DEBUG_INSERT;
126   out[0] = vp[0] * in[0] + vp[12];
127   out[1] = vp[13];
128   out[2] = vp[14];
129}
130
131static inline void insert_2f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
132				const GLfloat *in )
133{
134   GLfloat *out = (GLfloat *)v;
135   const GLfloat * const vp = a->vp;
136   DEBUG_INSERT;
137   out[0] = vp[0] * in[0] + vp[12];
138   out[1] = vp[5] * in[1] + vp[13];
139}
140
141static inline void insert_2f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
142				const GLfloat *in )
143{
144   GLfloat *out = (GLfloat *)v;
145   const GLfloat * const vp = a->vp;
146   DEBUG_INSERT;
147   out[0] = vp[0] * in[0] + vp[12];
148   out[1] = vp[13];
149}
150
151
152/*
153 * These functions do the same as above, except for the viewport mapping.
154 */
155
156static inline void insert_4f_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
157{
158   GLfloat *out = (GLfloat *)(v);
159   (void) a;
160   DEBUG_INSERT;
161   out[0] = in[0];
162   out[1] = in[1];
163   out[2] = in[2];
164   out[3] = in[3];
165}
166
167static inline void insert_4f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
168{
169   GLfloat *out = (GLfloat *)(v);
170   (void) a;
171   DEBUG_INSERT;
172   out[0] = in[0];
173   out[1] = in[1];
174   out[2] = in[2];
175   out[3] = 1;
176}
177
178static inline void insert_4f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
179{
180   GLfloat *out = (GLfloat *)(v);
181   (void) a;
182   DEBUG_INSERT;
183   out[0] = in[0];
184   out[1] = in[1];
185   out[2] = 0;
186   out[3] = 1;
187}
188
189static inline void insert_4f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
190{
191   GLfloat *out = (GLfloat *)(v);
192   (void) a;
193   DEBUG_INSERT;
194   out[0] = in[0];
195   out[1] = 0;
196   out[2] = 0;
197   out[3] = 1;
198}
199
200static inline void insert_3f_xyw_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
201{
202   GLfloat *out = (GLfloat *)(v);
203   (void) a;
204   DEBUG_INSERT;
205   out[0] = in[0];
206   out[1] = in[1];
207   out[2] = in[3];
208}
209
210static inline void insert_3f_xyw_err( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
211{
212   (void) a; (void) v; (void) in;
213   DEBUG_INSERT;
214   exit(1);
215}
216
217static inline void insert_3f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
218{
219   GLfloat *out = (GLfloat *)(v);
220   (void) a;
221   DEBUG_INSERT;
222   out[0] = in[0];
223   out[1] = in[1];
224   out[2] = in[2];
225}
226
227static inline void insert_3f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
228{
229   GLfloat *out = (GLfloat *)(v);
230   (void) a;
231   DEBUG_INSERT;
232   out[0] = in[0];
233   out[1] = in[1];
234   out[2] = 0;
235}
236
237static inline void insert_3f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
238{
239   GLfloat *out = (GLfloat *)(v);
240   (void) a;
241   DEBUG_INSERT;
242   out[0] = in[0];
243   out[1] = 0;
244   out[2] = 0;
245}
246
247
248static inline void insert_2f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
249{
250   GLfloat *out = (GLfloat *)(v);
251   (void) a;
252   DEBUG_INSERT;
253   out[0] = in[0];
254   out[1] = in[1];
255}
256
257static inline void insert_2f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
258{
259   GLfloat *out = (GLfloat *)(v);
260   (void) a;
261   DEBUG_INSERT;
262   out[0] = in[0];
263   out[1] = 0;
264}
265
266static inline void insert_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
267{
268   GLfloat *out = (GLfloat *)(v);
269   (void) a;
270   DEBUG_INSERT;
271   out[0] = in[0];
272}
273
274static inline void insert_null( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
275{
276   DEBUG_INSERT;
277   (void) a; (void) v; (void) in;
278}
279
280static inline void insert_4chan_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v,
281				  const GLfloat *in )
282{
283   GLchan *c = (GLchan *)v;
284   DEBUG_INSERT;
285   (void) a;
286   UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
287   UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
288   UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
289   UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]);
290}
291
292static inline void insert_4chan_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v,
293				  const GLfloat *in )
294{
295   GLchan *c = (GLchan *)v;
296   DEBUG_INSERT;
297   (void) a;
298   UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
299   UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
300   UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
301   c[3] = CHAN_MAX;
302}
303
304static inline void insert_4chan_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v,
305				  const GLfloat *in )
306{
307   GLchan *c = (GLchan *)v;
308   DEBUG_INSERT;
309   (void) a;
310   UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
311   UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
312   c[2] = 0;
313   c[3] = CHAN_MAX;
314}
315
316static inline void insert_4chan_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v,
317				  const GLfloat *in )
318{
319   GLchan *c = (GLchan *)v;
320   DEBUG_INSERT;
321   (void) a;
322   UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
323   c[1] = 0;
324   c[2] = 0;
325   c[3] = CHAN_MAX;
326}
327
328static inline void insert_4ub_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v,
329				const GLfloat *in )
330{
331   DEBUG_INSERT;
332   (void) a;
333   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
334   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
335   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
336   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
337}
338
339static inline void insert_4ub_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v,
340				const GLfloat *in )
341{
342   DEBUG_INSERT;
343   (void) a;
344   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
345   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
346   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
347   v[3] = 0xff;
348}
349
350static inline void insert_4ub_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v,
351				const GLfloat *in )
352{
353   DEBUG_INSERT;
354   (void) a;
355   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
356   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
357   v[2] = 0;
358   v[3] = 0xff;
359}
360
361static inline void insert_4ub_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v,
362				const GLfloat *in )
363{
364   DEBUG_INSERT;
365   (void) a;
366   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
367   v[1] = 0;
368   v[2] = 0;
369   v[3] = 0xff;
370}
371
372static inline void insert_4ub_4f_bgra_4( const struct tnl_clipspace_attr *a, GLubyte *v,
373				const GLfloat *in )
374{
375   DEBUG_INSERT;
376   (void) a;
377   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
378   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
379   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
380   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
381}
382
383static inline void insert_4ub_4f_bgra_3( const struct tnl_clipspace_attr *a, GLubyte *v,
384				const GLfloat *in )
385{
386   DEBUG_INSERT;
387   (void) a;
388   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
389   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
390   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
391   v[3] = 0xff;
392}
393
394static inline void insert_4ub_4f_bgra_2( const struct tnl_clipspace_attr *a, GLubyte *v,
395				const GLfloat *in )
396{
397   DEBUG_INSERT;
398   (void) a;
399   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
400   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
401   v[0] = 0;
402   v[3] = 0xff;
403}
404
405static inline void insert_4ub_4f_bgra_1( const struct tnl_clipspace_attr *a, GLubyte *v,
406				const GLfloat *in )
407{
408   DEBUG_INSERT;
409   (void) a;
410   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
411   v[1] = 0;
412   v[0] = 0;
413   v[3] = 0xff;
414}
415
416static inline void insert_4ub_4f_argb_4( const struct tnl_clipspace_attr *a, GLubyte *v,
417				const GLfloat *in )
418{
419   DEBUG_INSERT;
420   (void) a;
421   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
422   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
423   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
424   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
425}
426
427static inline void insert_4ub_4f_argb_3( const struct tnl_clipspace_attr *a, GLubyte *v,
428				const GLfloat *in )
429{
430   DEBUG_INSERT;
431   (void) a;
432   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
433   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
434   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
435   v[0] = 0xff;
436}
437
438static inline void insert_4ub_4f_argb_2( const struct tnl_clipspace_attr *a, GLubyte *v,
439				const GLfloat *in )
440{
441   DEBUG_INSERT;
442   (void) a;
443   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
444   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
445   v[3] = 0x00;
446   v[0] = 0xff;
447}
448
449static inline void insert_4ub_4f_argb_1( const struct tnl_clipspace_attr *a, GLubyte *v,
450				const GLfloat *in )
451{
452   DEBUG_INSERT;
453   (void) a;
454   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
455   v[2] = 0x00;
456   v[3] = 0x00;
457   v[0] = 0xff;
458}
459
460static inline void insert_4ub_4f_abgr_4( const struct tnl_clipspace_attr *a, GLubyte *v,
461				const GLfloat *in )
462{
463   DEBUG_INSERT;
464   (void) a;
465   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
466   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
467   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
468   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
469}
470
471static inline void insert_4ub_4f_abgr_3( const struct tnl_clipspace_attr *a, GLubyte *v,
472				const GLfloat *in )
473{
474   DEBUG_INSERT;
475   (void) a;
476   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
477   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
478   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
479   v[0] = 0xff;
480}
481
482static inline void insert_4ub_4f_abgr_2( const struct tnl_clipspace_attr *a, GLubyte *v,
483				const GLfloat *in )
484{
485   DEBUG_INSERT;
486   (void) a;
487   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
488   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
489   v[1] = 0x00;
490   v[0] = 0xff;
491}
492
493static inline void insert_4ub_4f_abgr_1( const struct tnl_clipspace_attr *a, GLubyte *v,
494				const GLfloat *in )
495{
496   DEBUG_INSERT;
497   (void) a;
498   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
499   v[2] = 0x00;
500   v[1] = 0x00;
501   v[0] = 0xff;
502}
503
504static inline void insert_3ub_3f_rgb_3( const struct tnl_clipspace_attr *a, GLubyte *v,
505			       const GLfloat *in )
506{
507   DEBUG_INSERT;
508   (void) a;
509   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
510   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
511   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
512}
513
514static inline void insert_3ub_3f_rgb_2( const struct tnl_clipspace_attr *a, GLubyte *v,
515			       const GLfloat *in )
516{
517   DEBUG_INSERT;
518   (void) a;
519   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
520   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
521   v[2] = 0;
522}
523
524static inline void insert_3ub_3f_rgb_1( const struct tnl_clipspace_attr *a, GLubyte *v,
525			       const GLfloat *in )
526{
527   DEBUG_INSERT;
528   (void) a;
529   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
530   v[1] = 0;
531   v[2] = 0;
532}
533
534static inline void insert_3ub_3f_bgr_3( const struct tnl_clipspace_attr *a, GLubyte *v,
535				 const GLfloat *in )
536{
537   DEBUG_INSERT;
538   (void) a;
539   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
540   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
541   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
542}
543
544static inline void insert_3ub_3f_bgr_2( const struct tnl_clipspace_attr *a, GLubyte *v,
545				 const GLfloat *in )
546{
547   DEBUG_INSERT;
548   (void) a;
549   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
550   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
551   v[0] = 0;
552}
553
554static inline void insert_3ub_3f_bgr_1( const struct tnl_clipspace_attr *a, GLubyte *v,
555				 const GLfloat *in )
556{
557   DEBUG_INSERT;
558   (void) a;
559   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
560   v[1] = 0;
561   v[0] = 0;
562}
563
564
565static inline void insert_1ub_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v,
566			   const GLfloat *in )
567{
568   DEBUG_INSERT;
569   (void) a;
570   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
571}
572
573
574/***********************************************************************
575 * Functions to perform the reverse operations to the above, for
576 * swrast translation and clip-interpolation.
577 *
578 * Currently always extracts a full 4 floats.
579 */
580
581static void extract_4f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
582				 const GLubyte *v )
583{
584   const GLfloat *in = (const GLfloat *)v;
585   const GLfloat * const vp = a->vp;
586
587   /* Although included for completeness, the position coordinate is
588    * usually handled differently during clipping.
589    */
590   DEBUG_INSERT;
591   out[0] = (in[0] - vp[12]) / vp[0];
592   out[1] = (in[1] - vp[13]) / vp[5];
593   out[2] = (in[2] - vp[14]) / vp[10];
594   out[3] = in[3];
595}
596
597static void extract_3f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
598				 const GLubyte *v )
599{
600   const GLfloat *in = (const GLfloat *)v;
601   const GLfloat * const vp = a->vp;
602   DEBUG_INSERT;
603   out[0] = (in[0] - vp[12]) / vp[0];
604   out[1] = (in[1] - vp[13]) / vp[5];
605   out[2] = (in[2] - vp[14]) / vp[10];
606   out[3] = 1;
607}
608
609
610static void extract_2f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
611				 const GLubyte *v )
612{
613   const GLfloat *in = (const GLfloat *)v;
614   const GLfloat * const vp = a->vp;
615   DEBUG_INSERT;
616   out[0] = (in[0] - vp[12]) / vp[0];
617   out[1] = (in[1] - vp[13]) / vp[5];
618   out[2] = 0;
619   out[3] = 1;
620}
621
622
623static void extract_4f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v  )
624{
625   const GLfloat *in = (const GLfloat *)v;
626   (void) a;
627
628   out[0] = in[0];
629   out[1] = in[1];
630   out[2] = in[2];
631   out[3] = in[3];
632}
633
634static void extract_3f_xyw( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
635{
636   const GLfloat *in = (const GLfloat *)v;
637   (void) a;
638
639   out[0] = in[0];
640   out[1] = in[1];
641   out[2] = 0;
642   out[3] = in[2];
643}
644
645
646static void extract_3f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
647{
648   const GLfloat *in = (const GLfloat *)v;
649   (void) a;
650
651   out[0] = in[0];
652   out[1] = in[1];
653   out[2] = in[2];
654   out[3] = 1;
655}
656
657
658static void extract_2f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
659{
660   const GLfloat *in = (const GLfloat *)v;
661   (void) a;
662
663   out[0] = in[0];
664   out[1] = in[1];
665   out[2] = 0;
666   out[3] = 1;
667}
668
669static void extract_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
670{
671   const GLfloat *in = (const GLfloat *)v;
672   (void) a;
673
674   out[0] = in[0];
675   out[1] = 0;
676   out[2] = 0;
677   out[3] = 1;
678}
679
680static void extract_4chan_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
681				 const GLubyte *v )
682{
683   GLchan *c = (GLchan *)v;
684   (void) a;
685
686   out[0] = CHAN_TO_FLOAT(c[0]);
687   out[1] = CHAN_TO_FLOAT(c[1]);
688   out[2] = CHAN_TO_FLOAT(c[2]);
689   out[3] = CHAN_TO_FLOAT(c[3]);
690}
691
692static void extract_4ub_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
693				 const GLubyte *v )
694{
695   (void) a;
696   out[0] = UBYTE_TO_FLOAT(v[0]);
697   out[1] = UBYTE_TO_FLOAT(v[1]);
698   out[2] = UBYTE_TO_FLOAT(v[2]);
699   out[3] = UBYTE_TO_FLOAT(v[3]);
700}
701
702static void extract_4ub_4f_bgra( const struct tnl_clipspace_attr *a, GLfloat *out,
703				 const GLubyte *v )
704{
705   (void) a;
706   out[2] = UBYTE_TO_FLOAT(v[0]);
707   out[1] = UBYTE_TO_FLOAT(v[1]);
708   out[0] = UBYTE_TO_FLOAT(v[2]);
709   out[3] = UBYTE_TO_FLOAT(v[3]);
710}
711
712static void extract_4ub_4f_argb( const struct tnl_clipspace_attr *a, GLfloat *out,
713				 const GLubyte *v )
714{
715   (void) a;
716   out[3] = UBYTE_TO_FLOAT(v[0]);
717   out[0] = UBYTE_TO_FLOAT(v[1]);
718   out[1] = UBYTE_TO_FLOAT(v[2]);
719   out[2] = UBYTE_TO_FLOAT(v[3]);
720}
721
722static void extract_4ub_4f_abgr( const struct tnl_clipspace_attr *a, GLfloat *out,
723				 const GLubyte *v )
724{
725   (void) a;
726   out[3] = UBYTE_TO_FLOAT(v[0]);
727   out[2] = UBYTE_TO_FLOAT(v[1]);
728   out[1] = UBYTE_TO_FLOAT(v[2]);
729   out[0] = UBYTE_TO_FLOAT(v[3]);
730}
731
732static void extract_3ub_3f_rgb( const struct tnl_clipspace_attr *a, GLfloat *out,
733				const GLubyte *v )
734{
735   (void) a;
736   out[0] = UBYTE_TO_FLOAT(v[0]);
737   out[1] = UBYTE_TO_FLOAT(v[1]);
738   out[2] = UBYTE_TO_FLOAT(v[2]);
739   out[3] = 1;
740}
741
742static void extract_3ub_3f_bgr( const struct tnl_clipspace_attr *a, GLfloat *out,
743				const GLubyte *v )
744{
745   (void) a;
746   out[2] = UBYTE_TO_FLOAT(v[0]);
747   out[1] = UBYTE_TO_FLOAT(v[1]);
748   out[0] = UBYTE_TO_FLOAT(v[2]);
749   out[3] = 1;
750}
751
752static void extract_1ub_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
753{
754   (void) a;
755   out[0] = UBYTE_TO_FLOAT(v[0]);
756   out[1] = 0;
757   out[2] = 0;
758   out[3] = 1;
759}
760
761
762const struct tnl_format_info _tnl_format_info[EMIT_MAX] =
763{
764   { "1f",
765     extract_1f,
766     { insert_1f_1, insert_1f_1, insert_1f_1, insert_1f_1 },
767     sizeof(GLfloat) },
768
769   { "2f",
770     extract_2f,
771     { insert_2f_1, insert_2f_2, insert_2f_2, insert_2f_2 },
772     2 * sizeof(GLfloat) },
773
774   { "3f",
775     extract_3f,
776     { insert_3f_1, insert_3f_2, insert_3f_3, insert_3f_3 },
777     3 * sizeof(GLfloat) },
778
779   { "4f",
780     extract_4f,
781     { insert_4f_1, insert_4f_2, insert_4f_3, insert_4f_4 },
782     4 * sizeof(GLfloat) },
783
784   { "2f_viewport",
785     extract_2f_viewport,
786     { insert_2f_viewport_1, insert_2f_viewport_2, insert_2f_viewport_2,
787       insert_2f_viewport_2 },
788     2 * sizeof(GLfloat) },
789
790   { "3f_viewport",
791     extract_3f_viewport,
792     { insert_3f_viewport_1, insert_3f_viewport_2, insert_3f_viewport_3,
793       insert_3f_viewport_3 },
794     3 * sizeof(GLfloat) },
795
796   { "4f_viewport",
797     extract_4f_viewport,
798     { insert_4f_viewport_1, insert_4f_viewport_2, insert_4f_viewport_3,
799       insert_4f_viewport_4 },
800     4 * sizeof(GLfloat) },
801
802   { "3f_xyw",
803     extract_3f_xyw,
804     { insert_3f_xyw_err, insert_3f_xyw_err, insert_3f_xyw_err,
805       insert_3f_xyw_4 },
806     3 * sizeof(GLfloat) },
807
808   { "1ub_1f",
809     extract_1ub_1f,
810     { insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1 },
811     sizeof(GLubyte) },
812
813   { "3ub_3f_rgb",
814     extract_3ub_3f_rgb,
815     { insert_3ub_3f_rgb_1, insert_3ub_3f_rgb_2, insert_3ub_3f_rgb_3,
816       insert_3ub_3f_rgb_3 },
817     3 * sizeof(GLubyte) },
818
819   { "3ub_3f_bgr",
820     extract_3ub_3f_bgr,
821     { insert_3ub_3f_bgr_1, insert_3ub_3f_bgr_2, insert_3ub_3f_bgr_3,
822       insert_3ub_3f_bgr_3 },
823     3 * sizeof(GLubyte) },
824
825   { "4ub_4f_rgba",
826     extract_4ub_4f_rgba,
827     { insert_4ub_4f_rgba_1, insert_4ub_4f_rgba_2, insert_4ub_4f_rgba_3,
828       insert_4ub_4f_rgba_4 },
829     4 * sizeof(GLubyte) },
830
831   { "4ub_4f_bgra",
832     extract_4ub_4f_bgra,
833     { insert_4ub_4f_bgra_1, insert_4ub_4f_bgra_2, insert_4ub_4f_bgra_3,
834       insert_4ub_4f_bgra_4 },
835     4 * sizeof(GLubyte) },
836
837   { "4ub_4f_argb",
838     extract_4ub_4f_argb,
839     { insert_4ub_4f_argb_1, insert_4ub_4f_argb_2, insert_4ub_4f_argb_3,
840       insert_4ub_4f_argb_4 },
841     4 * sizeof(GLubyte) },
842
843   { "4ub_4f_abgr",
844     extract_4ub_4f_abgr,
845     { insert_4ub_4f_abgr_1, insert_4ub_4f_abgr_2, insert_4ub_4f_abgr_3,
846       insert_4ub_4f_abgr_4 },
847     4 * sizeof(GLubyte) },
848
849   { "4chan_4f_rgba",
850     extract_4chan_4f_rgba,
851     { insert_4chan_4f_rgba_1, insert_4chan_4f_rgba_2, insert_4chan_4f_rgba_3,
852       insert_4chan_4f_rgba_4 },
853     4 * sizeof(GLchan) },
854
855   { "pad",
856     NULL,
857     { NULL, NULL, NULL, NULL },
858     0 }
859
860};
861
862
863
864
865/***********************************************************************
866 * Hardwired fastpaths for emitting whole vertices or groups of
867 * vertices
868 */
869#define EMIT5(NR, F0, F1, F2, F3, F4, NAME)				\
870static void NAME( struct gl_context *ctx,					\
871		  GLuint count,						\
872		  GLubyte *v )						\
873{									\
874   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);			\
875   struct tnl_clipspace_attr *a = vtx->attr;				\
876   GLuint i;								\
877									\
878   for (i = 0 ; i < count ; i++, v += vtx->vertex_size) {		\
879      if (NR > 0) {							\
880	 F0( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr );	\
881	 a[0].inputptr += a[0].inputstride;				\
882      }									\
883      									\
884      if (NR > 1) {							\
885	 F1( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr );	\
886	 a[1].inputptr += a[1].inputstride;				\
887      }									\
888      									\
889      if (NR > 2) {							\
890	 F2( &a[2], v + a[2].vertoffset, (GLfloat *)a[2].inputptr );	\
891	 a[2].inputptr += a[2].inputstride;				\
892      }									\
893      									\
894      if (NR > 3) {							\
895	 F3( &a[3], v + a[3].vertoffset, (GLfloat *)a[3].inputptr );	\
896	 a[3].inputptr += a[3].inputstride;				\
897      }									\
898									\
899      if (NR > 4) {							\
900	 F4( &a[4], v + a[4].vertoffset, (GLfloat *)a[4].inputptr );	\
901	 a[4].inputptr += a[4].inputstride;				\
902      }									\
903   }									\
904}
905
906
907#define EMIT2(F0, F1, NAME) EMIT5(2, F0, F1, insert_null, \
908				  insert_null, insert_null, NAME)
909
910#define EMIT3(F0, F1, F2, NAME) EMIT5(3, F0, F1, F2, insert_null, \
911				      insert_null, NAME)
912
913#define EMIT4(F0, F1, F2, F3, NAME) EMIT5(4, F0, F1, F2, F3, \
914				          insert_null, NAME)
915
916
917EMIT2(insert_3f_viewport_3, insert_4ub_4f_rgba_4, emit_viewport3_rgba4)
918EMIT2(insert_3f_viewport_3, insert_4ub_4f_bgra_4, emit_viewport3_bgra4)
919EMIT2(insert_3f_3, insert_4ub_4f_rgba_4, emit_xyz3_rgba4)
920
921EMIT3(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_viewport4_rgba4_st2)
922EMIT3(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2,  emit_viewport4_bgra4_st2)
923EMIT3(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_xyzw4_rgba4_st2)
924
925EMIT4(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_viewport4_rgba4_st2_st2)
926EMIT4(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, insert_2f_2,  emit_viewport4_bgra4_st2_st2)
927EMIT4(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_xyzw4_rgba4_st2_st2)
928
929
930/* Use the codegen paths to select one of a number of hardwired
931 * fastpaths.
932 */
933void _tnl_generate_hardwired_emit( struct gl_context *ctx )
934{
935   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
936   tnl_emit_func func = NULL;
937
938   /* Does it fit a hardwired fastpath?  Help! this is growing out of
939    * control!
940    */
941   switch (vtx->attr_count) {
942   case 2:
943      if (vtx->attr[0].emit == insert_3f_viewport_3) {
944	 if (vtx->attr[1].emit == insert_4ub_4f_bgra_4)
945	    func = emit_viewport3_bgra4;
946	 else if (vtx->attr[1].emit == insert_4ub_4f_rgba_4)
947	    func = emit_viewport3_rgba4;
948      }
949      else if (vtx->attr[0].emit == insert_3f_3 &&
950	       vtx->attr[1].emit == insert_4ub_4f_rgba_4) {
951 	 func = emit_xyz3_rgba4;
952      }
953      break;
954   case 3:
955      if (vtx->attr[2].emit == insert_2f_2) {
956	 if (vtx->attr[1].emit == insert_4ub_4f_rgba_4) {
957	    if (vtx->attr[0].emit == insert_4f_viewport_4)
958	       func = emit_viewport4_rgba4_st2;
959	    else if (vtx->attr[0].emit == insert_4f_4)
960	       func = emit_xyzw4_rgba4_st2;
961	 }
962	 else if (vtx->attr[1].emit == insert_4ub_4f_bgra_4 &&
963		  vtx->attr[0].emit == insert_4f_viewport_4)
964	    func = emit_viewport4_bgra4_st2;
965      }
966      break;
967   case 4:
968      if (vtx->attr[2].emit == insert_2f_2 &&
969	  vtx->attr[3].emit == insert_2f_2) {
970	 if (vtx->attr[1].emit == insert_4ub_4f_rgba_4) {
971	    if (vtx->attr[0].emit == insert_4f_viewport_4)
972	       func = emit_viewport4_rgba4_st2_st2;
973	    else if (vtx->attr[0].emit == insert_4f_4)
974	       func = emit_xyzw4_rgba4_st2_st2;
975	 }
976	 else if (vtx->attr[1].emit == insert_4ub_4f_bgra_4 &&
977		  vtx->attr[0].emit == insert_4f_viewport_4)
978	    func = emit_viewport4_bgra4_st2_st2;
979      }
980      break;
981   }
982
983   vtx->emit = func;
984}
985
986/***********************************************************************
987 * Generic (non-codegen) functions for whole vertices or groups of
988 * vertices
989 */
990
991void _tnl_generic_emit( struct gl_context *ctx,
992			GLuint count,
993			GLubyte *v )
994{
995   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
996   struct tnl_clipspace_attr *a = vtx->attr;
997   const GLuint attr_count = vtx->attr_count;
998   const GLuint stride = vtx->vertex_size;
999   GLuint i, j;
1000
1001   for (i = 0 ; i < count ; i++, v += stride) {
1002      for (j = 0; j < attr_count; j++) {
1003	 GLfloat *in = (GLfloat *)a[j].inputptr;
1004	 a[j].inputptr += a[j].inputstride;
1005	 a[j].emit( &a[j], v + a[j].vertoffset, in );
1006      }
1007   }
1008}
1009
1010
1011void _tnl_generic_interp( struct gl_context *ctx,
1012			    GLfloat t,
1013			    GLuint edst, GLuint eout, GLuint ein,
1014			    GLboolean force_boundary )
1015{
1016   TNLcontext *tnl = TNL_CONTEXT(ctx);
1017   struct vertex_buffer *VB = &tnl->vb;
1018   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1019   const GLubyte *vin  = vtx->vertex_buf + ein  * vtx->vertex_size;
1020   const GLubyte *vout = vtx->vertex_buf + eout * vtx->vertex_size;
1021   GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
1022   const struct tnl_clipspace_attr *a = vtx->attr;
1023   const GLuint attr_count = vtx->attr_count;
1024   GLuint j;
1025   (void) force_boundary;
1026
1027   if (tnl->NeedNdcCoords) {
1028      const GLfloat *dstclip = VB->ClipPtr->data[edst];
1029      if (dstclip[3] != 0.0) {
1030	 const GLfloat w = 1.0f / dstclip[3];
1031	 GLfloat pos[4];
1032
1033	 pos[0] = dstclip[0] * w;
1034	 pos[1] = dstclip[1] * w;
1035	 pos[2] = dstclip[2] * w;
1036	 pos[3] = w;
1037
1038	 a[0].insert[4-1]( &a[0], vdst, pos );
1039      }
1040   }
1041   else {
1042      a[0].insert[4-1]( &a[0], vdst, VB->ClipPtr->data[edst] );
1043   }
1044
1045
1046   for (j = 1; j < attr_count; j++) {
1047      GLfloat fin[4], fout[4], fdst[4];
1048
1049      a[j].extract( &a[j], fin, vin + a[j].vertoffset );
1050      a[j].extract( &a[j], fout, vout + a[j].vertoffset );
1051
1052      INTERP_4F(t, fdst, fout, fin);
1053
1054      a[j].insert[4-1]( &a[j], vdst + a[j].vertoffset, fdst );
1055   }
1056}
1057
1058
1059/* Extract color attributes from one vertex and insert them into
1060 * another.  (Shortcircuit extract/insert with memcpy).
1061 */
1062void _tnl_generic_copy_pv( struct gl_context *ctx, GLuint edst, GLuint esrc )
1063{
1064   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1065   GLubyte *vsrc = vtx->vertex_buf + esrc * vtx->vertex_size;
1066   GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
1067   const struct tnl_clipspace_attr *a = vtx->attr;
1068   const GLuint attr_count = vtx->attr_count;
1069   GLuint j;
1070
1071   for (j = 0; j < attr_count; j++) {
1072      if (a[j].attrib == VERT_ATTRIB_COLOR0 ||
1073	  a[j].attrib == VERT_ATTRIB_COLOR1) {
1074
1075	 memcpy( vdst + a[j].vertoffset,
1076                 vsrc + a[j].vertoffset,
1077                 a[j].vertattrsize );
1078      }
1079   }
1080}
1081
1082
1083/* Helper functions for hardware which doesn't put back colors and/or
1084 * edgeflags into vertices.
1085 */
1086void _tnl_generic_interp_extras( struct gl_context *ctx,
1087				   GLfloat t,
1088				   GLuint dst, GLuint out, GLuint in,
1089				   GLboolean force_boundary )
1090{
1091   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
1092
1093   /* If stride is zero, BackfaceColorPtr is constant across the VB, so
1094    * there is no point interpolating between two values as they will
1095    * be identical.  In all other cases, this value is generated by
1096    * t_vb_lighttmp.h and has a stride of 4 dwords.
1097    */
1098   if (VB->BackfaceColorPtr && VB->BackfaceColorPtr->stride) {
1099      assert(VB->BackfaceColorPtr->stride == 4 * sizeof(GLfloat));
1100
1101      INTERP_4F( t,
1102		 VB->BackfaceColorPtr->data[dst],
1103		 VB->BackfaceColorPtr->data[out],
1104		 VB->BackfaceColorPtr->data[in] );
1105   }
1106
1107   if (VB->BackfaceSecondaryColorPtr) {
1108      assert(VB->BackfaceSecondaryColorPtr->stride == 4 * sizeof(GLfloat));
1109
1110      INTERP_3F( t,
1111		 VB->BackfaceSecondaryColorPtr->data[dst],
1112		 VB->BackfaceSecondaryColorPtr->data[out],
1113		 VB->BackfaceSecondaryColorPtr->data[in] );
1114   }
1115
1116   if (VB->BackfaceIndexPtr) {
1117      VB->BackfaceIndexPtr->data[dst][0] = LINTERP( t,
1118					       VB->BackfaceIndexPtr->data[out][0],
1119					       VB->BackfaceIndexPtr->data[in][0] );
1120   }
1121
1122   if (VB->EdgeFlag) {
1123      VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
1124   }
1125
1126   _tnl_generic_interp(ctx, t, dst, out, in, force_boundary);
1127}
1128
1129void _tnl_generic_copy_pv_extras( struct gl_context *ctx,
1130				  GLuint dst, GLuint src )
1131{
1132   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
1133
1134   /* See above comment:
1135    */
1136   if (VB->BackfaceColorPtr && VB->BackfaceColorPtr->stride) {
1137      COPY_4FV( VB->BackfaceColorPtr->data[dst],
1138		VB->BackfaceColorPtr->data[src] );
1139   }
1140
1141   if (VB->BackfaceSecondaryColorPtr) {
1142      COPY_4FV( VB->BackfaceSecondaryColorPtr->data[dst],
1143		VB->BackfaceSecondaryColorPtr->data[src] );
1144   }
1145
1146   if (VB->BackfaceIndexPtr) {
1147      VB->BackfaceIndexPtr->data[dst][0] = VB->BackfaceIndexPtr->data[src][0];
1148   }
1149
1150   _tnl_generic_copy_pv(ctx, dst, src);
1151}
1152
1153
1154