Home | History | Annotate | Download | only in tnl
      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 (at) 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 
     50 static 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 
     62 static 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 
     74 static 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 
     86 static 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 
     98 static 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 
    109 static 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 
    120 static 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 
    131 static 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 
    141 static 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 
    156 static 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 
    167 static 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 
    178 static 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 
    189 static 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 
    200 static 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 
    210 static 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 
    217 static 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 
    227 static 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 
    237 static 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 
    248 static 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 
    257 static 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 
    266 static 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 
    274 static 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 
    280 static 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 
    292 static 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 
    304 static 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 
    316 static 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 
    328 static 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 
    339 static 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 
    350 static 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 
    361 static 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 
    372 static 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 
    383 static 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 
    394 static 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 
    405 static 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 
    416 static 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 
    427 static 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 
    438 static 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 
    449 static 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 
    460 static 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 
    471 static 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 
    482 static 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 
    493 static 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 
    504 static 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 
    514 static 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 
    524 static 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 
    534 static 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 
    544 static 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 
    554 static 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 
    565 static 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 
    581 static 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 
    597 static 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 
    610 static 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 
    623 static 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 
    634 static 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 
    646 static 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 
    658 static 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 
    669 static 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 
    680 static 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 
    692 static 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 
    702 static 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 
    712 static 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 
    722 static 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 
    732 static 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 
    742 static 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 
    752 static 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 
    762 const 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)				\
    870 static 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 
    917 EMIT2(insert_3f_viewport_3, insert_4ub_4f_rgba_4, emit_viewport3_rgba4)
    918 EMIT2(insert_3f_viewport_3, insert_4ub_4f_bgra_4, emit_viewport3_bgra4)
    919 EMIT2(insert_3f_3, insert_4ub_4f_rgba_4, emit_xyz3_rgba4)
    920 
    921 EMIT3(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_viewport4_rgba4_st2)
    922 EMIT3(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2,  emit_viewport4_bgra4_st2)
    923 EMIT3(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_xyzw4_rgba4_st2)
    924 
    925 EMIT4(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_viewport4_rgba4_st2_st2)
    926 EMIT4(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, insert_2f_2,  emit_viewport4_bgra4_st2_st2)
    927 EMIT4(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  */
    933 void _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 
    991 void _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 
   1011 void _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  */
   1062 void _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  */
   1086 void _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 
   1129 void _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