Home | History | Annotate | Download | only in tnl
      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 (at) 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 
     49 static 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 
     61 static 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 
     73 static 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 
     85 static 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 
     97 static 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 
    108 static 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 
    119 static 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 
    130 static 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 
    140 static 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 
    155 static 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 
    166 static 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 
    177 static 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 
    188 static 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 
    199 static 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 
    209 static 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 
    216 static 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 
    226 static 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 
    236 static 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 
    247 static 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 
    256 static 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 
    265 static 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 
    273 static 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 
    279 static 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 
    291 static 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 
    303 static 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 
    315 static 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 
    327 static 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 
    338 static 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 
    349 static 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 
    360 static 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 
    371 static 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 
    382 static 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 
    393 static 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 
    404 static 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 
    415 static 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 
    426 static 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 
    437 static 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 
    448 static 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 
    459 static 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 
    470 static 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 
    481 static 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 
    492 static 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 
    503 static 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 
    513 static 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 
    523 static 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 
    533 static 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 
    543 static 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 
    553 static 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 
    564 static 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 
    580 static 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 
    596 static 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 
    609 static 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 
    622 static 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 
    633 static 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 
    645 static 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 
    657 static 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 
    668 static 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 
    679 static 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 
    691 static 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 
    701 static 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 
    711 static 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 
    721 static 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 
    731 static 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 
    741 static 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 
    751 static 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 
    761 const 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)				\
    869 static 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 
    916 EMIT2(insert_3f_viewport_3, insert_4ub_4f_rgba_4, emit_viewport3_rgba4)
    917 EMIT2(insert_3f_viewport_3, insert_4ub_4f_bgra_4, emit_viewport3_bgra4)
    918 EMIT2(insert_3f_3, insert_4ub_4f_rgba_4, emit_xyz3_rgba4)
    919 
    920 EMIT3(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_viewport4_rgba4_st2)
    921 EMIT3(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2,  emit_viewport4_bgra4_st2)
    922 EMIT3(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_xyzw4_rgba4_st2)
    923 
    924 EMIT4(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_viewport4_rgba4_st2_st2)
    925 EMIT4(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, insert_2f_2,  emit_viewport4_bgra4_st2_st2)
    926 EMIT4(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  */
    932 void _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 
    990 void _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 
   1010 void _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  */
   1061 void _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  */
   1085 void _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 
   1128 void _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