Home | History | Annotate | Download | only in math
      1 
      2 /*
      3  * Mesa 3-D graphics library
      4  * Version:  3.5
      5  *
      6  * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the "Software"),
     10  * to deal in the Software without restriction, including without limitation
     11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     12  * and/or sell copies of the Software, and to permit persons to whom the
     13  * Software is furnished to do so, subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice shall be included
     16  * in all copies or substantial portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     21  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     22  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24  */
     25 
     26 /*
     27  * New (3.1) transformation code written by Keith Whitwell.
     28  */
     29 
     30 
     31 /*----------------------------------------------------------------------
     32  * Begin Keith's new code
     33  *
     34  *----------------------------------------------------------------------
     35  */
     36 
     37 /* KW: Fixed stride, now measured in bytes as is the OpenGL array stride.
     38  */
     39 
     40 /* KW: These are now parameterized to produce two versions, one
     41  *     which transforms all incoming points, and a second which
     42  *     takes notice of a cullmask array, and only transforms
     43  *     unculled vertices.
     44  */
     45 
     46 /* KW: 1-vectors can sneak into the texture pipeline via the array
     47  *     interface.  These functions are here because I want consistant
     48  *     treatment of the vertex sizes and a lazy strategy for
     49  *     cleaning unused parts of the vector, and so as not to exclude
     50  *     them from the vertex array interface.
     51  *
     52  *     Under our current analysis of matrices, there is no way that
     53  *     the product of a matrix and a 1-vector can remain a 1-vector,
     54  *     with the exception of the identity transform.
     55  */
     56 
     57 /* KW: No longer zero-pad outgoing vectors.  Now that external
     58  *     vectors can get into the pipeline we cannot ever assume
     59  *     that there is more to a vector than indicated by its
     60  *     size.
     61  */
     62 
     63 /* KW: Now uses clipmask and a flag to allow us to skip both/either
     64  *     cliped and/or culled vertices.
     65  */
     66 
     67 /* GH: Not any more -- it's easier (and faster) to just process the
     68  *     entire vector.  Clipping and culling are handled further down
     69  *     the pipe, most often during or after the conversion to some
     70  *     driver-specific vertex format.
     71  */
     72 
     73 static void _XFORMAPI
     74 TAG(transform_points1_general)( GLvector4f *to_vec,
     75 				const GLfloat m[16],
     76 				const GLvector4f *from_vec )
     77 {
     78    const GLuint stride = from_vec->stride;
     79    GLfloat *from = from_vec->start;
     80    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
     81    GLuint count = from_vec->count;
     82    const GLfloat m0 = m[0],  m12 = m[12];
     83    const GLfloat m1 = m[1],  m13 = m[13];
     84    const GLfloat m2 = m[2],  m14 = m[14];
     85    const GLfloat m3 = m[3],  m15 = m[15];
     86    GLuint i;
     87    STRIDE_LOOP {
     88       const GLfloat ox = from[0];
     89       to[i][0] = m0 * ox + m12;
     90       to[i][1] = m1 * ox + m13;
     91       to[i][2] = m2 * ox + m14;
     92       to[i][3] = m3 * ox + m15;
     93    }
     94    to_vec->size = 4;
     95    to_vec->flags |= VEC_SIZE_4;
     96    to_vec->count = from_vec->count;
     97 }
     98 
     99 static void _XFORMAPI
    100 TAG(transform_points1_identity)( GLvector4f *to_vec,
    101 				 const GLfloat m[16],
    102 				 const GLvector4f *from_vec )
    103 {
    104    const GLuint stride = from_vec->stride;
    105    GLfloat *from = from_vec->start;
    106    GLuint count = from_vec->count;
    107    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    108    GLuint i;
    109    (void) m;
    110    if (to_vec == from_vec) return;
    111    STRIDE_LOOP {
    112       to[i][0] = from[0];
    113    }
    114    to_vec->size = 1;
    115    to_vec->flags |= VEC_SIZE_1;
    116    to_vec->count = from_vec->count;
    117 }
    118 
    119 static void _XFORMAPI
    120 TAG(transform_points1_2d)( GLvector4f *to_vec,
    121 			   const GLfloat m[16],
    122 			   const GLvector4f *from_vec )
    123 {
    124    const GLuint stride = from_vec->stride;
    125    GLfloat *from = from_vec->start;
    126    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    127    GLuint count = from_vec->count;
    128    const GLfloat m0 = m[0], m1 = m[1];
    129    const GLfloat m12 = m[12], m13 = m[13];
    130    GLuint i;
    131    STRIDE_LOOP {
    132       const GLfloat ox = from[0];
    133       to[i][0] = m0 * ox + m12;
    134       to[i][1] = m1 * ox + m13;
    135    }
    136    to_vec->size = 2;
    137    to_vec->flags |= VEC_SIZE_2;
    138    to_vec->count = from_vec->count;
    139 }
    140 
    141 static void _XFORMAPI
    142 TAG(transform_points1_2d_no_rot)( GLvector4f *to_vec,
    143 				  const GLfloat m[16],
    144 				  const GLvector4f *from_vec )
    145 {
    146    const GLuint stride = from_vec->stride;
    147    GLfloat *from = from_vec->start;
    148    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    149    GLuint count = from_vec->count;
    150    const GLfloat m0 = m[0], m12 = m[12], m13 = m[13];
    151    GLuint i;
    152    STRIDE_LOOP {
    153       const GLfloat ox = from[0];
    154       to[i][0] = m0 * ox + m12;
    155       to[i][1] =           m13;
    156    }
    157    to_vec->size = 2;
    158    to_vec->flags |= VEC_SIZE_2;
    159    to_vec->count = from_vec->count;
    160 }
    161 
    162 static void _XFORMAPI
    163 TAG(transform_points1_3d)( GLvector4f *to_vec,
    164 			   const GLfloat m[16],
    165 			   const GLvector4f *from_vec )
    166 {
    167    const GLuint stride = from_vec->stride;
    168    GLfloat *from = from_vec->start;
    169    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    170    GLuint count = from_vec->count;
    171    const GLfloat m0 = m[0], m1 = m[1], m2 = m[2];
    172    const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
    173    GLuint i;
    174    STRIDE_LOOP {
    175       const GLfloat ox = from[0];
    176       to[i][0] = m0 * ox + m12;
    177       to[i][1] = m1 * ox + m13;
    178       to[i][2] = m2 * ox + m14;
    179    }
    180    to_vec->size = 3;
    181    to_vec->flags |= VEC_SIZE_3;
    182    to_vec->count = from_vec->count;
    183 }
    184 
    185 
    186 static void _XFORMAPI
    187 TAG(transform_points1_3d_no_rot)( GLvector4f *to_vec,
    188 				  const GLfloat m[16],
    189 				  const GLvector4f *from_vec )
    190 {
    191    const GLuint stride = from_vec->stride;
    192    GLfloat *from = from_vec->start;
    193    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    194    GLuint count = from_vec->count;
    195    const GLfloat m0 = m[0];
    196    const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
    197    GLuint i;
    198    STRIDE_LOOP {
    199       const GLfloat ox = from[0];
    200       to[i][0] = m0 * ox           + m12;
    201       to[i][1] =                     m13;
    202       to[i][2] =                     m14;
    203    }
    204    to_vec->size = 3;
    205    to_vec->flags |= VEC_SIZE_3;
    206    to_vec->count = from_vec->count;
    207 }
    208 
    209 static void _XFORMAPI
    210 TAG(transform_points1_perspective)( GLvector4f *to_vec,
    211 				    const GLfloat m[16],
    212 				    const GLvector4f *from_vec )
    213 {
    214    const GLuint stride = from_vec->stride;
    215    GLfloat *from = from_vec->start;
    216    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    217    GLuint count = from_vec->count;
    218    const GLfloat m0 = m[0], m14 = m[14];
    219    GLuint i;
    220    STRIDE_LOOP {
    221       const GLfloat ox = from[0];
    222       to[i][0] = m0 * ox                ;
    223       to[i][1] =           0            ;
    224       to[i][2] =                     m14;
    225       to[i][3] = 0;
    226    }
    227    to_vec->size = 4;
    228    to_vec->flags |= VEC_SIZE_4;
    229    to_vec->count = from_vec->count;
    230 }
    231 
    232 
    233 
    234 
    235 /* 2-vectors, which are a lot more relevant than 1-vectors, are
    236  * present early in the geometry pipeline and throughout the
    237  * texture pipeline.
    238  */
    239 static void _XFORMAPI
    240 TAG(transform_points2_general)( GLvector4f *to_vec,
    241 				const GLfloat m[16],
    242 				const GLvector4f *from_vec )
    243 {
    244    const GLuint stride = from_vec->stride;
    245    GLfloat *from = from_vec->start;
    246    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    247    GLuint count = from_vec->count;
    248    const GLfloat m0 = m[0],  m4 = m[4],  m12 = m[12];
    249    const GLfloat m1 = m[1],  m5 = m[5],  m13 = m[13];
    250    const GLfloat m2 = m[2],  m6 = m[6],  m14 = m[14];
    251    const GLfloat m3 = m[3],  m7 = m[7],  m15 = m[15];
    252    GLuint i;
    253    STRIDE_LOOP {
    254       const GLfloat ox = from[0], oy = from[1];
    255       to[i][0] = m0 * ox + m4 * oy + m12;
    256       to[i][1] = m1 * ox + m5 * oy + m13;
    257       to[i][2] = m2 * ox + m6 * oy + m14;
    258       to[i][3] = m3 * ox + m7 * oy + m15;
    259    }
    260    to_vec->size = 4;
    261    to_vec->flags |= VEC_SIZE_4;
    262    to_vec->count = from_vec->count;
    263 }
    264 
    265 static void _XFORMAPI
    266 TAG(transform_points2_identity)( GLvector4f *to_vec,
    267 				 const GLfloat m[16],
    268 				 const GLvector4f *from_vec )
    269 {
    270    const GLuint stride = from_vec->stride;
    271    GLfloat *from = from_vec->start;
    272    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    273    GLuint count = from_vec->count;
    274    GLuint i;
    275    (void) m;
    276    if (to_vec == from_vec) return;
    277    STRIDE_LOOP {
    278       to[i][0] = from[0];
    279       to[i][1] = from[1];
    280    }
    281    to_vec->size = 2;
    282    to_vec->flags |= VEC_SIZE_2;
    283    to_vec->count = from_vec->count;
    284 }
    285 
    286 static void _XFORMAPI
    287 TAG(transform_points2_2d)( GLvector4f *to_vec,
    288 			   const GLfloat m[16],
    289 			   const GLvector4f *from_vec )
    290 {
    291    const GLuint stride = from_vec->stride;
    292    GLfloat *from = from_vec->start;
    293    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    294    GLuint count = from_vec->count;
    295    const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
    296    const GLfloat m12 = m[12], m13 = m[13];
    297    GLuint i;
    298    STRIDE_LOOP {
    299       const GLfloat ox = from[0], oy = from[1];
    300       to[i][0] = m0 * ox + m4 * oy + m12;
    301       to[i][1] = m1 * ox + m5 * oy + m13;
    302    }
    303    to_vec->size = 2;
    304    to_vec->flags |= VEC_SIZE_2;
    305    to_vec->count = from_vec->count;
    306 }
    307 
    308 static void _XFORMAPI
    309 TAG(transform_points2_2d_no_rot)( GLvector4f *to_vec,
    310 				  const GLfloat m[16],
    311 				  const GLvector4f *from_vec )
    312 {
    313    const GLuint stride = from_vec->stride;
    314    GLfloat *from = from_vec->start;
    315    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    316    GLuint count = from_vec->count;
    317    const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
    318    GLuint i;
    319    STRIDE_LOOP {
    320       const GLfloat ox = from[0], oy = from[1];
    321       to[i][0] = m0 * ox           + m12;
    322       to[i][1] =           m5 * oy + m13;
    323    }
    324    to_vec->size = 2;
    325    to_vec->flags |= VEC_SIZE_2;
    326    to_vec->count = from_vec->count;
    327 }
    328 
    329 static void _XFORMAPI
    330 TAG(transform_points2_3d)( GLvector4f *to_vec,
    331 			   const GLfloat m[16],
    332 			   const GLvector4f *from_vec )
    333 {
    334    const GLuint stride = from_vec->stride;
    335    GLfloat *from = from_vec->start;
    336    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    337    GLuint count = from_vec->count;
    338    const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
    339    const GLfloat m6 = m[6], m12 = m[12], m13 = m[13], m14 = m[14];
    340    GLuint i;
    341    STRIDE_LOOP {
    342       const GLfloat ox = from[0], oy = from[1];
    343       to[i][0] = m0 * ox + m4 * oy + m12;
    344       to[i][1] = m1 * ox + m5 * oy + m13;
    345       to[i][2] = m2 * ox + m6 * oy + m14;
    346    }
    347    to_vec->size = 3;
    348    to_vec->flags |= VEC_SIZE_3;
    349    to_vec->count = from_vec->count;
    350 }
    351 
    352 
    353 /* I would actually say this was a fairly important function, from
    354  * a texture transformation point of view.
    355  */
    356 static void _XFORMAPI
    357 TAG(transform_points2_3d_no_rot)( GLvector4f *to_vec,
    358 				  const GLfloat m[16],
    359 				  const GLvector4f *from_vec )
    360 {
    361    const GLuint stride = from_vec->stride;
    362    GLfloat *from = from_vec->start;
    363    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    364    GLuint count = from_vec->count;
    365    const GLfloat m0 = m[0], m5 = m[5];
    366    const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
    367    GLuint i;
    368    STRIDE_LOOP {
    369       const GLfloat ox = from[0], oy = from[1];
    370       to[i][0] = m0 * ox           + m12;
    371       to[i][1] =           m5 * oy + m13;
    372       to[i][2] =                     m14;
    373    }
    374    if (m14 == 0) {
    375       to_vec->size = 2;
    376       to_vec->flags |= VEC_SIZE_2;
    377    } else {
    378       to_vec->size = 3;
    379       to_vec->flags |= VEC_SIZE_3;
    380    }
    381    to_vec->count = from_vec->count;
    382 }
    383 
    384 
    385 static void _XFORMAPI
    386 TAG(transform_points2_perspective)( GLvector4f *to_vec,
    387 				    const GLfloat m[16],
    388 				    const GLvector4f *from_vec )
    389 {
    390    const GLuint stride = from_vec->stride;
    391    GLfloat *from = from_vec->start;
    392    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    393    GLuint count = from_vec->count;
    394    const GLfloat m0 = m[0], m5 = m[5], m14 = m[14];
    395    GLuint i;
    396    STRIDE_LOOP {
    397       const GLfloat ox = from[0], oy = from[1];
    398       to[i][0] = m0 * ox                ;
    399       to[i][1] =           m5 * oy      ;
    400       to[i][2] =                     m14;
    401       to[i][3] = 0;
    402    }
    403    to_vec->size = 4;
    404    to_vec->flags |= VEC_SIZE_4;
    405    to_vec->count = from_vec->count;
    406 }
    407 
    408 
    409 
    410 static void _XFORMAPI
    411 TAG(transform_points3_general)( GLvector4f *to_vec,
    412 				const GLfloat m[16],
    413 				const GLvector4f *from_vec )
    414 {
    415    const GLuint stride = from_vec->stride;
    416    GLfloat *from = from_vec->start;
    417    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    418    GLuint count = from_vec->count;
    419    const GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
    420    const GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
    421    const GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
    422    const GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
    423    GLuint i;
    424    STRIDE_LOOP {
    425       const GLfloat ox = from[0], oy = from[1], oz = from[2];
    426       to[i][0] = m0 * ox + m4 * oy + m8  * oz + m12;
    427       to[i][1] = m1 * ox + m5 * oy + m9  * oz + m13;
    428       to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14;
    429       to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15;
    430    }
    431    to_vec->size = 4;
    432    to_vec->flags |= VEC_SIZE_4;
    433    to_vec->count = from_vec->count;
    434 }
    435 
    436 static void _XFORMAPI
    437 TAG(transform_points3_identity)( GLvector4f *to_vec,
    438 				 const GLfloat m[16],
    439 				 const GLvector4f *from_vec )
    440 {
    441    const GLuint stride = from_vec->stride;
    442    GLfloat *from = from_vec->start;
    443    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    444    GLuint count = from_vec->count;
    445    GLuint i;
    446    (void) m;
    447    if (to_vec == from_vec) return;
    448    STRIDE_LOOP {
    449       to[i][0] = from[0];
    450       to[i][1] = from[1];
    451       to[i][2] = from[2];
    452    }
    453    to_vec->size = 3;
    454    to_vec->flags |= VEC_SIZE_3;
    455    to_vec->count = from_vec->count;
    456 }
    457 
    458 static void _XFORMAPI
    459 TAG(transform_points3_2d)( GLvector4f *to_vec,
    460 			   const GLfloat m[16],
    461 			   const GLvector4f *from_vec )
    462 {
    463    const GLuint stride = from_vec->stride;
    464    GLfloat *from = from_vec->start;
    465    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    466    GLuint count = from_vec->count;
    467    const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
    468    const GLfloat m12 = m[12], m13 = m[13];
    469    GLuint i;
    470    STRIDE_LOOP {
    471       const GLfloat ox = from[0], oy = from[1], oz = from[2];
    472       to[i][0] = m0 * ox + m4 * oy            + m12       ;
    473       to[i][1] = m1 * ox + m5 * oy            + m13       ;
    474       to[i][2] =                   +       oz             ;
    475    }
    476    to_vec->size = 3;
    477    to_vec->flags |= VEC_SIZE_3;
    478    to_vec->count = from_vec->count;
    479 }
    480 
    481 static void _XFORMAPI
    482 TAG(transform_points3_2d_no_rot)( GLvector4f *to_vec,
    483 				  const GLfloat m[16],
    484 				  const GLvector4f *from_vec )
    485 {
    486    const GLuint stride = from_vec->stride;
    487    GLfloat *from = from_vec->start;
    488    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    489    GLuint count = from_vec->count;
    490    const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
    491    GLuint i;
    492    STRIDE_LOOP {
    493       const GLfloat ox = from[0], oy = from[1], oz = from[2];
    494       to[i][0] = m0 * ox                      + m12       ;
    495       to[i][1] =           m5 * oy            + m13       ;
    496       to[i][2] =                   +       oz             ;
    497    }
    498    to_vec->size = 3;
    499    to_vec->flags |= VEC_SIZE_3;
    500    to_vec->count = from_vec->count;
    501 }
    502 
    503 static void _XFORMAPI
    504 TAG(transform_points3_3d)( GLvector4f *to_vec,
    505 			   const GLfloat m[16],
    506 			   const GLvector4f *from_vec )
    507 {
    508    const GLuint stride = from_vec->stride;
    509    GLfloat *from = from_vec->start;
    510    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    511    GLuint count = from_vec->count;
    512    const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
    513    const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
    514    const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
    515    GLuint i;
    516    STRIDE_LOOP {
    517       const GLfloat ox = from[0], oy = from[1], oz = from[2];
    518       to[i][0] = m0 * ox + m4 * oy +  m8 * oz + m12       ;
    519       to[i][1] = m1 * ox + m5 * oy +  m9 * oz + m13       ;
    520       to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14       ;
    521    }
    522    to_vec->size = 3;
    523    to_vec->flags |= VEC_SIZE_3;
    524    to_vec->count = from_vec->count;
    525 }
    526 
    527 /* previously known as ortho...
    528  */
    529 static void _XFORMAPI
    530 TAG(transform_points3_3d_no_rot)( GLvector4f *to_vec,
    531 				  const GLfloat m[16],
    532 				  const GLvector4f *from_vec )
    533 {
    534    const GLuint stride = from_vec->stride;
    535    GLfloat *from = from_vec->start;
    536    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    537    GLuint count = from_vec->count;
    538    const GLfloat m0 = m[0], m5 = m[5];
    539    const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
    540    GLuint i;
    541    STRIDE_LOOP {
    542       const GLfloat ox = from[0], oy = from[1], oz = from[2];
    543       to[i][0] = m0 * ox                      + m12       ;
    544       to[i][1] =           m5 * oy            + m13       ;
    545       to[i][2] =                     m10 * oz + m14       ;
    546    }
    547    to_vec->size = 3;
    548    to_vec->flags |= VEC_SIZE_3;
    549    to_vec->count = from_vec->count;
    550 }
    551 
    552 static void _XFORMAPI
    553 TAG(transform_points3_perspective)( GLvector4f *to_vec,
    554 				    const GLfloat m[16],
    555 				    const GLvector4f *from_vec )
    556 {
    557    const GLuint stride = from_vec->stride;
    558    GLfloat *from = from_vec->start;
    559    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    560    GLuint count = from_vec->count;
    561    const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
    562    const GLfloat m10 = m[10], m14 = m[14];
    563    GLuint i;
    564    STRIDE_LOOP {
    565       const GLfloat ox = from[0], oy = from[1], oz = from[2];
    566       to[i][0] = m0 * ox           + m8  * oz       ;
    567       to[i][1] =           m5 * oy + m9  * oz       ;
    568       to[i][2] =                     m10 * oz + m14 ;
    569       to[i][3] =                          -oz       ;
    570    }
    571    to_vec->size = 4;
    572    to_vec->flags |= VEC_SIZE_4;
    573    to_vec->count = from_vec->count;
    574 }
    575 
    576 
    577 
    578 static void _XFORMAPI
    579 TAG(transform_points4_general)( GLvector4f *to_vec,
    580 				const GLfloat m[16],
    581 				const GLvector4f *from_vec )
    582 {
    583    const GLuint stride = from_vec->stride;
    584    GLfloat *from = from_vec->start;
    585    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    586    GLuint count = from_vec->count;
    587    const GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
    588    const GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
    589    const GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
    590    const GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
    591    GLuint i;
    592    STRIDE_LOOP {
    593       const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
    594       to[i][0] = m0 * ox + m4 * oy + m8  * oz + m12 * ow;
    595       to[i][1] = m1 * ox + m5 * oy + m9  * oz + m13 * ow;
    596       to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
    597       to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow;
    598    }
    599    to_vec->size = 4;
    600    to_vec->flags |= VEC_SIZE_4;
    601    to_vec->count = from_vec->count;
    602 }
    603 
    604 static void _XFORMAPI
    605 TAG(transform_points4_identity)( GLvector4f *to_vec,
    606 				 const GLfloat m[16],
    607 				 const GLvector4f *from_vec )
    608 {
    609    const GLuint stride = from_vec->stride;
    610    GLfloat *from = from_vec->start;
    611    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    612    GLuint count = from_vec->count;
    613    GLuint i;
    614    (void) m;
    615    if (to_vec == from_vec) return;
    616    STRIDE_LOOP {
    617       to[i][0] = from[0];
    618       to[i][1] = from[1];
    619       to[i][2] = from[2];
    620       to[i][3] = from[3];
    621    }
    622    to_vec->size = 4;
    623    to_vec->flags |= VEC_SIZE_4;
    624    to_vec->count = from_vec->count;
    625 }
    626 
    627 static void _XFORMAPI
    628 TAG(transform_points4_2d)( GLvector4f *to_vec,
    629 			   const GLfloat m[16],
    630 			   const GLvector4f *from_vec )
    631 {
    632    const GLuint stride = from_vec->stride;
    633    GLfloat *from = from_vec->start;
    634    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    635    GLuint count = from_vec->count;
    636    const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
    637    const GLfloat m12 = m[12], m13 = m[13];
    638    GLuint i;
    639    STRIDE_LOOP {
    640       const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
    641       to[i][0] = m0 * ox + m4 * oy            + m12 * ow;
    642       to[i][1] = m1 * ox + m5 * oy            + m13 * ow;
    643       to[i][2] =                   +       oz           ;
    644       to[i][3] =                                      ow;
    645    }
    646    to_vec->size = 4;
    647    to_vec->flags |= VEC_SIZE_4;
    648    to_vec->count = from_vec->count;
    649 }
    650 
    651 static void _XFORMAPI
    652 TAG(transform_points4_2d_no_rot)( GLvector4f *to_vec,
    653 				  const GLfloat m[16],
    654 				  const GLvector4f *from_vec )
    655 {
    656    const GLuint stride = from_vec->stride;
    657    GLfloat *from = from_vec->start;
    658    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    659    GLuint count = from_vec->count;
    660    const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
    661    GLuint i;
    662    STRIDE_LOOP {
    663       const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
    664       to[i][0] = m0 * ox                      + m12 * ow;
    665       to[i][1] =           m5 * oy            + m13 * ow;
    666       to[i][2] =                   +       oz           ;
    667       to[i][3] =                                      ow;
    668    }
    669    to_vec->size = 4;
    670    to_vec->flags |= VEC_SIZE_4;
    671    to_vec->count = from_vec->count;
    672 }
    673 
    674 static void _XFORMAPI
    675 TAG(transform_points4_3d)( GLvector4f *to_vec,
    676 			   const GLfloat m[16],
    677 			   const GLvector4f *from_vec )
    678 {
    679    const GLuint stride = from_vec->stride;
    680    GLfloat *from = from_vec->start;
    681    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    682    GLuint count = from_vec->count;
    683    const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
    684    const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
    685    const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
    686    GLuint i;
    687    STRIDE_LOOP {
    688       const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
    689       to[i][0] = m0 * ox + m4 * oy +  m8 * oz + m12 * ow;
    690       to[i][1] = m1 * ox + m5 * oy +  m9 * oz + m13 * ow;
    691       to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
    692       to[i][3] =                                      ow;
    693    }
    694    to_vec->size = 4;
    695    to_vec->flags |= VEC_SIZE_4;
    696    to_vec->count = from_vec->count;
    697 }
    698 
    699 static void _XFORMAPI
    700 TAG(transform_points4_3d_no_rot)( GLvector4f *to_vec,
    701 				  const GLfloat m[16],
    702 				  const GLvector4f *from_vec )
    703 {
    704    const GLuint stride = from_vec->stride;
    705    GLfloat *from = from_vec->start;
    706    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    707    GLuint count = from_vec->count;
    708    const GLfloat m0 = m[0], m5 = m[5];
    709    const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
    710    GLuint i;
    711    STRIDE_LOOP {
    712       const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
    713       to[i][0] = m0 * ox                      + m12 * ow;
    714       to[i][1] =           m5 * oy            + m13 * ow;
    715       to[i][2] =                     m10 * oz + m14 * ow;
    716       to[i][3] =                                      ow;
    717    }
    718    to_vec->size = 4;
    719    to_vec->flags |= VEC_SIZE_4;
    720    to_vec->count = from_vec->count;
    721 }
    722 
    723 static void _XFORMAPI
    724 TAG(transform_points4_perspective)( GLvector4f *to_vec,
    725 				    const GLfloat m[16],
    726 				    const GLvector4f *from_vec )
    727 {
    728    const GLuint stride = from_vec->stride;
    729    GLfloat *from = from_vec->start;
    730    GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
    731    GLuint count = from_vec->count;
    732    const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
    733    const GLfloat m10 = m[10], m14 = m[14];
    734    GLuint i;
    735    STRIDE_LOOP {
    736       const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
    737       to[i][0] = m0 * ox           + m8  * oz            ;
    738       to[i][1] =           m5 * oy + m9  * oz            ;
    739       to[i][2] =                     m10 * oz + m14 * ow ;
    740       to[i][3] =                          -oz            ;
    741    }
    742    to_vec->size = 4;
    743    to_vec->flags |= VEC_SIZE_4;
    744    to_vec->count = from_vec->count;
    745 }
    746 
    747 static transform_func TAG(transform_tab_1)[7];
    748 static transform_func TAG(transform_tab_2)[7];
    749 static transform_func TAG(transform_tab_3)[7];
    750 static transform_func TAG(transform_tab_4)[7];
    751 
    752 /* Similar functions could be called several times, with more highly
    753  * optimized routines overwriting the arrays.  This only occurs during
    754  * startup.
    755  */
    756 static void _XFORMAPI TAG(init_c_transformations)( void )
    757 {
    758 #define TAG_TAB   _mesa_transform_tab
    759 #define TAG_TAB_1 TAG(transform_tab_1)
    760 #define TAG_TAB_2 TAG(transform_tab_2)
    761 #define TAG_TAB_3 TAG(transform_tab_3)
    762 #define TAG_TAB_4 TAG(transform_tab_4)
    763 
    764    TAG_TAB[1] = TAG_TAB_1;
    765    TAG_TAB[2] = TAG_TAB_2;
    766    TAG_TAB[3] = TAG_TAB_3;
    767    TAG_TAB[4] = TAG_TAB_4;
    768 
    769    /* 1-D points (ie texcoords) */
    770    TAG_TAB_1[MATRIX_GENERAL]     = TAG(transform_points1_general);
    771    TAG_TAB_1[MATRIX_IDENTITY]    = TAG(transform_points1_identity);
    772    TAG_TAB_1[MATRIX_3D_NO_ROT]   = TAG(transform_points1_3d_no_rot);
    773    TAG_TAB_1[MATRIX_PERSPECTIVE] = TAG(transform_points1_perspective);
    774    TAG_TAB_1[MATRIX_2D]          = TAG(transform_points1_2d);
    775    TAG_TAB_1[MATRIX_2D_NO_ROT]   = TAG(transform_points1_2d_no_rot);
    776    TAG_TAB_1[MATRIX_3D]          = TAG(transform_points1_3d);
    777 
    778    /* 2-D points */
    779    TAG_TAB_2[MATRIX_GENERAL]     = TAG(transform_points2_general);
    780    TAG_TAB_2[MATRIX_IDENTITY]    = TAG(transform_points2_identity);
    781    TAG_TAB_2[MATRIX_3D_NO_ROT]   = TAG(transform_points2_3d_no_rot);
    782    TAG_TAB_2[MATRIX_PERSPECTIVE] = TAG(transform_points2_perspective);
    783    TAG_TAB_2[MATRIX_2D]          = TAG(transform_points2_2d);
    784    TAG_TAB_2[MATRIX_2D_NO_ROT]   = TAG(transform_points2_2d_no_rot);
    785    TAG_TAB_2[MATRIX_3D]          = TAG(transform_points2_3d);
    786 
    787    /* 3-D points */
    788    TAG_TAB_3[MATRIX_GENERAL]     = TAG(transform_points3_general);
    789    TAG_TAB_3[MATRIX_IDENTITY]    = TAG(transform_points3_identity);
    790    TAG_TAB_3[MATRIX_3D_NO_ROT]   = TAG(transform_points3_3d_no_rot);
    791    TAG_TAB_3[MATRIX_PERSPECTIVE] = TAG(transform_points3_perspective);
    792    TAG_TAB_3[MATRIX_2D]          = TAG(transform_points3_2d);
    793    TAG_TAB_3[MATRIX_2D_NO_ROT]   = TAG(transform_points3_2d_no_rot);
    794    TAG_TAB_3[MATRIX_3D]          = TAG(transform_points3_3d);
    795 
    796    /* 4-D points */
    797    TAG_TAB_4[MATRIX_GENERAL]     = TAG(transform_points4_general);
    798    TAG_TAB_4[MATRIX_IDENTITY]    = TAG(transform_points4_identity);
    799    TAG_TAB_4[MATRIX_3D_NO_ROT]   = TAG(transform_points4_3d_no_rot);
    800    TAG_TAB_4[MATRIX_PERSPECTIVE] = TAG(transform_points4_perspective);
    801    TAG_TAB_4[MATRIX_2D]          = TAG(transform_points4_2d);
    802    TAG_TAB_4[MATRIX_2D_NO_ROT]   = TAG(transform_points4_2d_no_rot);
    803    TAG_TAB_4[MATRIX_3D]          = TAG(transform_points4_3d);
    804 
    805 #undef TAG_TAB
    806 #undef TAG_TAB_1
    807 #undef TAG_TAB_2
    808 #undef TAG_TAB_3
    809 #undef TAG_TAB_4
    810 }
    811