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
73static void _XFORMAPI
74TAG(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
99static void _XFORMAPI
100TAG(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
119static void _XFORMAPI
120TAG(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
141static void _XFORMAPI
142TAG(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
162static void _XFORMAPI
163TAG(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
186static void _XFORMAPI
187TAG(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
209static void _XFORMAPI
210TAG(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 */
239static void _XFORMAPI
240TAG(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
265static void _XFORMAPI
266TAG(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
286static void _XFORMAPI
287TAG(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
308static void _XFORMAPI
309TAG(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
329static void _XFORMAPI
330TAG(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 */
356static void _XFORMAPI
357TAG(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
385static void _XFORMAPI
386TAG(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
410static void _XFORMAPI
411TAG(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
436static void _XFORMAPI
437TAG(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
458static void _XFORMAPI
459TAG(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
481static void _XFORMAPI
482TAG(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
503static void _XFORMAPI
504TAG(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 */
529static void _XFORMAPI
530TAG(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
552static void _XFORMAPI
553TAG(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
578static void _XFORMAPI
579TAG(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
604static void _XFORMAPI
605TAG(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
627static void _XFORMAPI
628TAG(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
651static void _XFORMAPI
652TAG(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
674static void _XFORMAPI
675TAG(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
699static void _XFORMAPI
700TAG(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
723static void _XFORMAPI
724TAG(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
747static transform_func TAG(transform_tab_1)[7];
748static transform_func TAG(transform_tab_2)[7];
749static transform_func TAG(transform_tab_3)[7];
750static 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 */
756static 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