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