xref: /reactos/dll/opengl/mesa/vbxform.c (revision 53221834)
1 /* $Id: vbxform.c,v 1.22 1997/12/17 00:53:18 brianp Exp $ */
2 
3 /*
4  * Mesa 3-D graphics library
5  * Version:  2.6
6  * Copyright (C) 1995-1997  Brian Paul
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 /*
25  * $Log: vbxform.c,v $
26  * Revision 1.22  1997/12/17 00:53:18  brianp
27  * added #include "asm-386.h"
28  *
29  * Revision 1.21  1997/12/09 02:58:27  brianp
30  * added volatile keyword to prevent excess precision in clip mask computation
31  * fixed bug involving clip flags and user clipping planes
32  *
33  * Revision 1.20  1997/11/20 00:09:38  brianp
34  * transform_points4() wasn't calling asm routines
35  *
36  * Revision 1.19  1997/10/30 06:00:06  brianp
37  * added Intel X86 assembly optimzations (Josh Vanderhoof)
38  *
39  * Revision 1.18  1997/10/15 00:36:36  brianp
40  * renamed the FAST/REGULAR_MATH macros
41  *
42  * Revision 1.17  1997/10/04 00:30:52  brianp
43  * vertices specified with glVertex4 weren't always projected correctly
44  *
45  * Revision 1.16  1997/09/29 22:24:22  brianp
46  * added REGULAR/FAST_MATH macros
47  *
48  * Revision 1.15  1997/09/18 01:32:47  brianp
49  * fixed divide by zero problem for "weird" projection matrices
50  *
51  * Revision 1.14  1997/09/10 00:28:11  brianp
52  * fixed an optimization bug in viewport_map_vertices()
53  *
54  * Revision 1.13  1997/07/24 01:25:27  brianp
55  * changed precompiled header symbol from PCH to PC_HEADER
56  *
57  * Revision 1.12  1997/06/20 02:57:59  brianp
58  * changed color components from GLfixed to GLubyte
59  *
60  * Revision 1.11  1997/05/28 03:26:49  brianp
61  * added precompiled header (PCH) support
62  *
63  * Revision 1.10  1997/05/23 03:01:45  brianp
64  * commented out a few const keywords because IRIX cc chokes on them
65  *
66  * Revision 1.9  1997/04/29 01:31:07  brianp
67  * added RasterSetup() function to device driver
68  *
69  * Revision 1.8  1997/04/21 01:21:52  brianp
70  * added MATRIX_2D_NO_ROT
71  *
72  * Revision 1.7  1997/04/20 19:47:27  brianp
73  * added RenderVB to device driver
74  *
75  * Revision 1.6  1997/04/20 15:59:30  brianp
76  * removed VERTEX2_BIT stuff
77  *
78  * Revision 1.5  1997/04/14 02:12:53  brianp
79  * small optimization in transform_texcoords()
80  *
81  * Revision 1.4  1997/04/12 16:22:22  brianp
82  * removed gl_init_vb()
83  *
84  * Revision 1.3  1997/04/12 12:28:39  brianp
85  * fixed <= material_update bug, removed some unused vars
86  *
87  * Revision 1.2  1997/04/07 03:01:11  brianp
88  * optimized vertex[234] code
89  *
90  * Revision 1.1  1997/04/02 03:14:29  brianp
91  * Initial revision
92  *
93  */
94 
95 
96 /*
97  * This file implements transformation, clip testing and projection of
98  * vertices in the vertex buffer.
99  *
100  * The entry points to this file are the functions:
101  *    gl_transform_vb_part1() - first stage of vertex transformation
102  *    gl_transform_vb_part2() - second stage of vertex transformation
103  */
104 
105 
106 #ifdef PC_HEADER
107 #include "all.h"
108 #else
109 #include <stdlib.h>
110 #include "asm-386.h"
111 #include "context.h"
112 #include "fog.h"
113 #include "light.h"
114 #include "macros.h"
115 #include "matrix.h"
116 #include "mmath.h"
117 #include "shade.h"
118 #include "texture.h"
119 #include "types.h"
120 #include "vb.h"
121 #include "vbrender.h"
122 #include "vbxform.h"
123 #include "xform.h"
124 #include <wine/debug.h>
125 #endif
126 
127 WINE_DEFAULT_DEBUG_CHANNEL(opengl32);
128 
129 
130 #if 0  /* NOT USED AT THIS TIME */
131 /*
132  * Use the current modelview matrix to transform XY vertices from object
133  * to eye coordinates.
134  * Input:  ctx - the context
135  *         n - number of vertices to transform
136  *         vObj - array [n][4] of object coordinates
137  * In/Out;  vEye - array [n][4] of eye coordinates
138  */
139 static void transform_points2( GLcontext *ctx, GLuint n,
140                                const GLfloat vObj[][4], GLfloat vEye[][4] )
141 {
142    switch (ctx->ModelViewMatrixType) {
143       case MATRIX_GENERAL:
144          {
145             const GLfloat *m = ctx->ModelViewMatrix;
146             GLfloat m0 = m[0],  m4 = m[4],  m12 = m[12];
147             GLfloat m1 = m[1],  m5 = m[5],  m13 = m[13];
148             GLfloat m2 = m[2],  m6 = m[6],  m14 = m[14];
149             GLfloat m3 = m[3],  m7 = m[7],  m15 = m[15];
150             GLuint i;
151             for (i=0;i<n;i++) {
152                GLfloat ox = vObj[i][0], oy = vObj[i][1];
153                vEye[i][0] = m0 * ox + m4 * oy + m12;
154                vEye[i][1] = m1 * ox + m5 * oy + m13;
155                vEye[i][2] = m2 * ox + m6 * oy + m14;
156                vEye[i][3] = m3 * ox + m7 * oy + m15;
157             }
158          }
159          break;
160       case MATRIX_IDENTITY:
161          {
162             GLuint i;
163             for (i=0;i<n;i++) {
164                vEye[i][0] = vObj[i][0];
165                vEye[i][1] = vObj[i][1];
166                vEye[i][2] = 0.0F;
167                vEye[i][3] = 1.0F;
168             }
169          }
170          break;
171       case MATRIX_2D:
172          {
173             const GLfloat *m = ctx->ModelViewMatrix;
174             GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
175             GLfloat m12 = m[12], m13 = m[13];
176             GLuint i;
177             for (i=0;i<n;i++) {
178                GLfloat ox = vObj[i][0], oy = vObj[i][1];
179                vEye[i][0] = m0 * ox + m4 * oy + m12;
180                vEye[i][1] = m1 * ox + m5 * oy + m13;
181                vEye[i][2] = 0.0F;
182                vEye[i][3] = 1.0F;
183             }
184          }
185          break;
186       case MATRIX_2D_NO_ROT:
187          {
188             const GLfloat *m = ctx->ModelViewMatrix;
189             GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
190             GLuint i;
191             for (i=0;i<n;i++) {
192                GLfloat ox = vObj[i][0], oy = vObj[i][1];
193                vEye[i][0] = m0 * ox           + m12;
194                vEye[i][1] =           m5 * oy + m13;
195                vEye[i][2] = 0.0F;
196                vEye[i][3] = 1.0F;
197             }
198          }
199          break;
200       case MATRIX_3D:
201          {
202             const GLfloat *m = ctx->ModelViewMatrix;
203             GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
204             GLfloat m6 = m[6], m12 = m[12], m13 = m[13], m14 = m[14];
205             GLuint i;
206             for (i=0;i<n;i++) {
207                GLfloat ox = vObj[i][0], oy = vObj[i][1];
208                vEye[i][0] = m0 * ox + m4 * oy + m12;
209                vEye[i][1] = m1 * ox + m5 * oy + m13;
210                vEye[i][2] = m2 * ox + m6 * oy + m14;
211                vEye[i][3] = 1.0F;
212             }
213          }
214          break;
215       default:
216          /* should never get here */
217          gl_problem( NULL, "invalid matrix type in transform_points3()" );
218          return;
219    }
220 }
221 #endif
222 
223 
224 /*
225  * Use the current modelview matrix to transform XYZ vertices from object
226  * to eye coordinates.
227  * Input:  ctx - the context
228  *         n - number of vertices to transform
229  *         vObj - array [n][4] of object coordinates
230  * In/Out;  vEye - array [n][4] of eye coordinates
231  */
232 static void transform_points3( GLcontext *ctx, GLuint n,
233                                /*const*/ GLfloat vObj[][4], GLfloat vEye[][4] )
234 {
235 #ifndef USE_ASM
236    switch (ctx->ModelViewMatrixType) {
237       case MATRIX_GENERAL:
238          {
239             const GLfloat *m = ctx->ModelViewMatrix;
240             GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
241             GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
242             GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
243             GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
244             GLuint i;
245             for (i=0;i<n;i++) {
246                GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2];
247                vEye[i][0] = m0 * ox + m4 * oy + m8  * oz + m12;
248                vEye[i][1] = m1 * ox + m5 * oy + m9  * oz + m13;
249                vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14;
250                vEye[i][3] = m3 * ox + m7 * oy + m11 * oz + m15;
251             }
252          }
253          break;
254       case MATRIX_IDENTITY:
255          {
256             GLuint i;
257             for (i=0;i<n;i++) {
258                vEye[i][0] = vObj[i][0];
259                vEye[i][1] = vObj[i][1];
260                vEye[i][2] = vObj[i][2];
261                vEye[i][3] = 1.0F;
262             }
263          }
264          break;
265       case MATRIX_2D:
266          {
267             const GLfloat *m = ctx->ModelViewMatrix;
268             GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
269             GLfloat m12 = m[12], m13 = m[13];
270             GLuint i;
271             for (i=0;i<n;i++) {
272                GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2];
273                vEye[i][0] = m0 * ox + m4 * oy            + m12       ;
274                vEye[i][1] = m1 * ox + m5 * oy            + m13       ;
275                vEye[i][2] =                   +       oz             ;
276                vEye[i][3] =                                      1.0F;
277             }
278          }
279          break;
280       case MATRIX_2D_NO_ROT:
281          {
282             const GLfloat *m = ctx->ModelViewMatrix;
283             GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
284             GLuint i;
285             for (i=0;i<n;i++) {
286                GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2];
287                vEye[i][0] = m0 * ox                      + m12       ;
288                vEye[i][1] =           m5 * oy            + m13       ;
289                vEye[i][2] =                   +       oz             ;
290                vEye[i][3] =                                      1.0F;
291             }
292          }
293          break;
294       case MATRIX_3D:
295          {
296             const GLfloat *m = ctx->ModelViewMatrix;
297             GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
298             GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
299             GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
300             GLuint i;
301             for (i=0;i<n;i++) {
302                GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2];
303                vEye[i][0] = m0 * ox + m4 * oy +  m8 * oz + m12       ;
304                vEye[i][1] = m1 * ox + m5 * oy +  m9 * oz + m13       ;
305                vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14       ;
306                vEye[i][3] =                                      1.0F;
307             }
308          }
309          break;
310       default:
311          /* should never get here */
312          gl_problem( NULL, "invalid matrix type in transform_points3()" );
313    }
314 #else
315    switch (ctx->ModelViewMatrixType) {
316       case MATRIX_GENERAL:
317          asm_transform_points3_general( n, vEye, ctx->ModelViewMatrix, vObj );
318          break;
319       case MATRIX_IDENTITY:
320          asm_transform_points3_identity( n, vEye, vObj );
321          break;
322       case MATRIX_2D:
323          asm_transform_points3_2d( n, vEye, ctx->ModelViewMatrix, vObj );
324          break;
325       case MATRIX_2D_NO_ROT:
326          asm_transform_points3_2d_no_rot( n, vEye, ctx->ModelViewMatrix,
327                                           vObj );
328          break;
329       case MATRIX_3D:
330          asm_transform_points3_3d( n, vEye, ctx->ModelViewMatrix, vObj );
331          break;
332       default:
333          /* should never get here */
334          gl_problem( NULL, "invalid matrix type in transform_points3()" );
335          return;
336    }
337 #endif
338    if (1)
339    {
340        GLuint i;
341        for (i = 0; i < n; i++)
342        {
343            TRACE("(%3.1f, %3.1f, %3.1f, %3.1f) --> (%3.1f, %3.1f, %3.1f, %3.1f)\n",
344                    vObj[i][0], vObj[i][1], vObj[i][2], vObj[i][3],
345                    vEye[i][0], vEye[i][1], vEye[i][2], vEye[i][3]);
346        }
347    }
348 
349 }
350 
351 
352 
353 /*
354  * Use the current modelview matrix to transform XYZW vertices from object
355  * to eye coordinates.
356  * Input:  ctx - the context
357  *         n - number of vertices to transform
358  *         vObj - array [n][4] of object coordinates
359  * In/Out;  vEye - array [n][4] of eye coordinates
360  */
361 static void transform_points4( GLcontext *ctx, GLuint n,
362                                /*const*/ GLfloat vObj[][4], GLfloat vEye[][4] )
363 {
364 #ifndef USE_ASM
365    switch (ctx->ModelViewMatrixType) {
366       case MATRIX_GENERAL:
367          {
368             const GLfloat *m = ctx->ModelViewMatrix;
369             GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
370             GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
371             GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
372             GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
373             GLuint i;
374             for (i=0;i<n;i++) {
375                GLfloat ox = vObj[i][0], oy = vObj[i][1];
376                GLfloat oz = vObj[i][2], ow = vObj[i][3];
377                vEye[i][0] = m0 * ox + m4 * oy + m8  * oz + m12 * ow;
378                vEye[i][1] = m1 * ox + m5 * oy + m9  * oz + m13 * ow;
379                vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
380                vEye[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow;
381             }
382          }
383          break;
384       case MATRIX_IDENTITY:
385          {
386             GLuint i;
387             for (i=0;i<n;i++) {
388                vEye[i][0] = vObj[i][0];
389                vEye[i][1] = vObj[i][1];
390                vEye[i][2] = vObj[i][2];
391                vEye[i][3] = vObj[i][3];
392             }
393          }
394          break;
395       case MATRIX_2D:
396          {
397             const GLfloat *m = ctx->ModelViewMatrix;
398             GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
399             GLfloat m12 = m[12], m13 = m[13];
400             GLuint i;
401             for (i=0;i<n;i++) {
402                GLfloat ox = vObj[i][0], oy = vObj[i][1];
403                GLfloat oz = vObj[i][2], ow = vObj[i][3];
404                vEye[i][0] = m0 * ox + m4 * oy            + m12 * ow;
405                vEye[i][1] = m1 * ox + m5 * oy            + m13 * ow;
406                vEye[i][2] =                   +       oz           ;
407                vEye[i][3] =                                      ow;
408             }
409          }
410          break;
411       case MATRIX_2D_NO_ROT:
412          {
413             const GLfloat *m = ctx->ModelViewMatrix;
414             GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
415             GLuint i;
416             for (i=0;i<n;i++) {
417                GLfloat ox = vObj[i][0], oy = vObj[i][1];
418                GLfloat oz = vObj[i][2], ow = vObj[i][3];
419                vEye[i][0] = m0 * ox                      + m12 * ow;
420                vEye[i][1] =           m5 * oy            + m13 * ow;
421                vEye[i][2] =                   +       oz           ;
422                vEye[i][3] =                                      ow;
423             }
424          }
425          break;
426       case MATRIX_3D:
427          {
428             const GLfloat *m = ctx->ModelViewMatrix;
429             GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
430             GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
431             GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
432             GLuint i;
433             for (i=0;i<n;i++) {
434                GLfloat ox = vObj[i][0], oy = vObj[i][1];
435                GLfloat oz = vObj[i][2], ow = vObj[i][3];
436                vEye[i][0] = m0 * ox + m4 * oy +  m8 * oz + m12 * ow;
437                vEye[i][1] = m1 * ox + m5 * oy +  m9 * oz + m13 * ow;
438                vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
439                vEye[i][3] =                                      ow;
440             }
441          }
442          break;
443       default:
444          /* should never get here */
445          gl_problem( NULL, "invalid matrix type in transform_points4()" );
446    }
447 #else
448    switch (ctx->ModelViewMatrixType) {
449       case MATRIX_GENERAL:
450          asm_transform_points4_general( n, vEye, ctx->ModelViewMatrix, vObj );
451          break;
452       case MATRIX_IDENTITY:
453          asm_transform_points4_identity( n, vEye, vObj );
454          break;
455       case MATRIX_2D:
456          asm_transform_points4_2d( n, vEye, ctx->ModelViewMatrix, vObj );
457          break;
458       case MATRIX_2D_NO_ROT:
459          asm_transform_points4_2d_no_rot( n, vEye, ctx->ModelViewMatrix,
460                                           vObj );
461          break;
462       case MATRIX_3D:
463          asm_transform_points4_3d( n, vEye, ctx->ModelViewMatrix, vObj );
464          break;
465       default:
466          /* should never get here */
467          gl_problem( NULL, "invalid matrix type in transform_points4()" );
468          return;
469    }
470 #endif
471 }
472 
473 
474 
475 /*
476  * Transform an array of texture coordinates by the current texture matrix.
477  * Input:  ctx - the context
478  *         n - number of texture coordinates in array
479  * In/Out:  t - array [n][4] of texture coordinates to transform
480  */
481 static void transform_texcoords( GLcontext *ctx, GLuint n, GLfloat t[][4] )
482 {
483 #ifndef USE_ASM
484    switch (ctx->TextureMatrixType) {
485       case MATRIX_GENERAL:
486          {
487             const GLfloat *m = ctx->TextureMatrix;
488             GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
489             GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
490             GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
491             GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
492             GLuint i;
493             for (i=0;i<n;i++) {
494                GLfloat t0 = t[i][0], t1 = t[i][1], t2 = t[i][2], t3 = t[i][3];
495                t[i][0] = m0 * t0 + m4 * t1 + m8  * t2 + m12 * t3;
496                t[i][1] = m1 * t0 + m5 * t1 + m9  * t2 + m13 * t3;
497                t[i][2] = m2 * t0 + m6 * t1 + m10 * t2 + m14 * t3;
498                t[i][3] = m3 * t0 + m7 * t1 + m11 * t2 + m15 * t3;
499             }
500          }
501          break;
502       case MATRIX_IDENTITY:
503          /* Do nothing */
504          break;
505       case MATRIX_2D:
506          {
507             const GLfloat *m = ctx->TextureMatrix;
508             GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
509             GLfloat m12 = m[12], m13 = m[13];
510             GLuint i;
511             for (i=0;i<n;i++) {
512                GLfloat t0 = t[i][0], t1 = t[i][1], t2 = t[i][2], t3 = t[i][3];
513                t[i][0] = m0 * t0 + m4 * t1            + m12 * t3;
514                t[i][1] = m1 * t0 + m5 * t1            + m13 * t3;
515                t[i][2] =                   +       t2           ;
516                /*t[i][3] unchanged*/
517             }
518          }
519          break;
520       case MATRIX_3D:
521          {
522             const GLfloat *m = ctx->TextureMatrix;
523             GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
524             GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
525             GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
526             GLuint i;
527             for (i=0;i<n;i++) {
528                GLfloat t0 = t[i][0], t1 = t[i][1], t2 = t[i][2], t3 = t[i][3];
529                t[i][0] = m0 * t0 + m4 * t1 +  m8 * t2 + m12 * t3;
530                t[i][1] = m1 * t0 + m5 * t1 +  m9 * t2 + m13 * t3;
531                t[i][2] = m2 * t0 + m6 * t1 + m10 * t2 + m14 * t3;
532                /*t[i][3] unchanged*/
533             }
534          }
535          break;
536       default:
537          /* should never get here */
538          gl_problem( NULL, "invalid matrix type in transform_texcoords()" );
539    }
540 #else
541    switch (ctx->TextureMatrixType) {
542       case MATRIX_GENERAL:
543          asm_transform_points4_general( n, t, ctx->TextureMatrix, t );
544          break;
545       case MATRIX_IDENTITY:
546          /* Do nothing */
547          break;
548       case MATRIX_2D:
549          asm_transform_points4_2d( n, t, ctx->TextureMatrix, t );
550          break;
551       case MATRIX_3D:
552          asm_transform_points4_3d( n, t, ctx->TextureMatrix, t );
553          break;
554       default:
555          /* should never get here */
556          gl_problem( NULL, "invalid matrix type in transform_texcoords()" );
557          return;
558    }
559 #endif
560 }
561 
562 
563 
564 /*
565  * Apply the projection matrix to an array of vertices in Eye coordinates
566  * resulting in Clip coordinates.  Also, compute the ClipMask bitfield for
567  * each vertex.
568  *
569  * NOTE: the volatile keyword is used in this function to ensure that the
570  * FP computations are computed to low-precision.  If high precision is
571  * used (ala 80-bit X86 arithmetic) then the clipMask results may be
572  * inconsistant with the computations in clip.c.  Later, clipped polygons
573  * may be rendered incorrectly.
574  *
575  * Input:  ctx - the context
576  *         n - number of vertices
577  *         vEye - array [n][4] of Eye coordinates
578  * Output:  vClip - array [n][4] of Clip coordinates
579  *          clipMask - array [n] of clip masks
580  */
581 static void project_and_cliptest( GLcontext *ctx,
582                                   GLuint n, /*const*/ GLfloat vEye[][4],
583                                   GLfloat vClip[][4], GLubyte clipMask[],
584                                   GLubyte *orMask, GLubyte *andMask )
585 
586 {
587 #ifndef USE_ASM
588    GLubyte tmpOrMask = *orMask;
589    GLubyte tmpAndMask = *andMask;
590 
591    switch (ctx->ProjectionMatrixType) {
592       case MATRIX_GENERAL:
593          {
594             const GLfloat *m = ctx->ProjectionMatrix;
595             GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
596             GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
597             GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
598             GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
599             GLuint i;
600             for (i=0;i<n;i++) {
601                GLfloat ex = vEye[i][0], ey = vEye[i][1];
602                GLfloat ez = vEye[i][2], ew = vEye[i][3];
603                GLfloat cx = m0 * ex + m4 * ey + m8  * ez + m12 * ew;
604                GLfloat cy = m1 * ex + m5 * ey + m9  * ez + m13 * ew;
605                GLfloat cz = m2 * ex + m6 * ey + m10 * ez + m14 * ew;
606                GLfloat cw = m3 * ex + m7 * ey + m11 * ez + m15 * ew;
607                GLubyte mask = 0;
608                vClip[i][0] = cx;
609                vClip[i][1] = cy;
610                vClip[i][2] = cz;
611                vClip[i][3] = cw;
612                if (cx >  cw)       mask |= CLIP_RIGHT_BIT;
613                else if (cx < -cw)  mask |= CLIP_LEFT_BIT;
614                if (cy >  cw)       mask |= CLIP_TOP_BIT;
615                else if (cy < -cw)  mask |= CLIP_BOTTOM_BIT;
616                if (cz >  cw)       mask |= CLIP_FAR_BIT;
617                else if (cz < -cw)  mask |= CLIP_NEAR_BIT;
618                if (mask) {
619                   clipMask[i] |= mask;
620                   tmpOrMask |= mask;
621                }
622                tmpAndMask &= mask;
623             }
624          }
625          break;
626       case MATRIX_IDENTITY:
627          {
628             GLuint i;
629             for (i=0;i<n;i++) {
630                GLfloat cx = vClip[i][0] = vEye[i][0];
631                GLfloat cy = vClip[i][1] = vEye[i][1];
632                GLfloat cz = vClip[i][2] = vEye[i][2];
633                GLfloat cw = vClip[i][3] = vEye[i][3];
634                GLubyte mask = 0;
635                if (cx >  cw)       mask |= CLIP_RIGHT_BIT;
636                else if (cx < -cw)  mask |= CLIP_LEFT_BIT;
637                if (cy >  cw)       mask |= CLIP_TOP_BIT;
638                else if (cy < -cw)  mask |= CLIP_BOTTOM_BIT;
639                if (cz >  cw)       mask |= CLIP_FAR_BIT;
640                else if (cz < -cw)  mask |= CLIP_NEAR_BIT;
641                if (mask) {
642                   clipMask[i] |= mask;
643                   tmpOrMask |= mask;
644                }
645                tmpAndMask &= mask;
646             }
647          }
648          break;
649       case MATRIX_ORTHO:
650          {
651             const GLfloat *m = ctx->ProjectionMatrix;
652             GLfloat m0 = m[0], m5 = m[5], m10 = m[10], m12 = m[12];
653             GLfloat m13 = m[13], m14 = m[14];
654             GLuint i;
655             for (i=0;i<n;i++) {
656                GLfloat ex = vEye[i][0], ey = vEye[i][1];
657                GLfloat ez = vEye[i][2], ew = vEye[i][3];
658                volatile GLfloat cx = m0 * ex                      + m12 * ew;
659                volatile GLfloat cy =           m5 * ey            + m13 * ew;
660                volatile GLfloat cz =                     m10 * ez + m14 * ew;
661                volatile GLfloat cw =                                      ew;
662                GLubyte mask = 0;
663                vClip[i][0] = cx;
664                vClip[i][1] = cy;
665                vClip[i][2] = cz;
666                vClip[i][3] = cw;
667                if (cx >  cw)       mask |= CLIP_RIGHT_BIT;
668                else if (cx < -cw)  mask |= CLIP_LEFT_BIT;
669                if (cy >  cw)       mask |= CLIP_TOP_BIT;
670                else if (cy < -cw)  mask |= CLIP_BOTTOM_BIT;
671                if (cz >  cw)       mask |= CLIP_FAR_BIT;
672                else if (cz < -cw)  mask |= CLIP_NEAR_BIT;
673                if (mask) {
674                   clipMask[i] |= mask;
675                   tmpOrMask |= mask;
676                }
677                tmpAndMask &= mask;
678             }
679          }
680          break;
681       case MATRIX_PERSPECTIVE:
682          {
683             const GLfloat *m = ctx->ProjectionMatrix;
684             GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
685             GLfloat m10 = m[10], m14 = m[14];
686             GLuint i;
687             for (i=0;i<n;i++) {
688                GLfloat ex = vEye[i][0], ey = vEye[i][1];
689                GLfloat ez = vEye[i][2], ew = vEye[i][3];
690                volatile GLfloat cx = m0 * ex           + m8  * ez           ;
691                volatile GLfloat cy =           m5 * ey + m9  * ez           ;
692                volatile GLfloat cz =                     m10 * ez + m14 * ew;
693                volatile GLfloat cw =                          -ez           ;
694                GLubyte mask = 0;
695                vClip[i][0] = cx;
696                vClip[i][1] = cy;
697                vClip[i][2] = cz;
698                vClip[i][3] = cw;
699                if (cx >  cw)       mask |= CLIP_RIGHT_BIT;
700                else if (cx < -cw)  mask |= CLIP_LEFT_BIT;
701                if (cy >  cw)       mask |= CLIP_TOP_BIT;
702                else if (cy < -cw)  mask |= CLIP_BOTTOM_BIT;
703                if (cz >  cw)       mask |= CLIP_FAR_BIT;
704                else if (cz < -cw)  mask |= CLIP_NEAR_BIT;
705                if (mask) {
706                   clipMask[i] |= mask;
707                   tmpOrMask |= mask;
708                }
709                tmpAndMask &= mask;
710             }
711          }
712          break;
713       default:
714          /* should never get here */
715          gl_problem( NULL, "invalid matrix type in project_and_cliptest()" );
716    }
717 
718    *orMask = tmpOrMask;
719    *andMask = tmpAndMask;
720 #else
721    switch (ctx->ProjectionMatrixType) {
722       case MATRIX_GENERAL:
723          asm_project_and_cliptest_general( n, vClip, ctx->ProjectionMatrix, vEye,
724                                            clipMask, orMask, andMask );
725          break;
726       case MATRIX_IDENTITY:
727          asm_project_and_cliptest_identity( n, vClip, vEye, clipMask, orMask, andMask );
728          break;
729       case MATRIX_ORTHO:
730          asm_project_and_cliptest_ortho( n, vClip, ctx->ProjectionMatrix, vEye,
731                                          clipMask, orMask, andMask );
732          break;
733       case MATRIX_PERSPECTIVE:
734          asm_project_and_cliptest_perspective( n, vClip, ctx->ProjectionMatrix,
735                                                vEye, clipMask, orMask, andMask );
736          break;
737       default:
738          /* should never get here */
739          gl_problem( NULL, "invalid matrix type in project_and_cliptest()" );
740          return;
741    }
742 #endif
743 }
744 
745 
746 /* This value matches the one in clip.c, used to cope with numeric error. */
747 #define MAGIC_NUMBER -0.8e-03F
748 
749 /*
750  * Test an array of vertices against the user-defined clipping planes.
751  * Input:  ctx - the context
752  *         n - number of vertices
753  *         vEye - array [n] of vertices, in eye coordinate system
754  * Output:  clipMask - array [n] of clip values: 0=not clipped, !0=clipped
755  * Return:  CLIP_ALL - if all vertices are clipped by one of the planes
756  *          CLIP_NONE - if no vertices were clipped
757  *          CLIP_SOME - if some vertices were clipped
758  */
759 static GLuint userclip_vertices( GLcontext *ctx, GLuint n,
760                                  /*const*/ GLfloat vEye[][4],
761                                  GLubyte clipMask[] )
762 {
763    GLboolean anyClipped = GL_FALSE;
764    GLuint p;
765 
766    ASSERT(ctx->Transform.AnyClip);
767 
768    for (p=0;p<MAX_CLIP_PLANES;p++) {
769       if (ctx->Transform.ClipEnabled[p]) {
770          GLfloat a = ctx->Transform.ClipEquation[p][0];
771          GLfloat b = ctx->Transform.ClipEquation[p][1];
772          GLfloat c = ctx->Transform.ClipEquation[p][2];
773          GLfloat d = ctx->Transform.ClipEquation[p][3];
774          GLboolean allClipped = GL_TRUE;
775          GLuint i;
776          for (i=0;i<n;i++) {
777             GLfloat dot = vEye[i][0] * a + vEye[i][1] * b
778                         + vEye[i][2] * c + vEye[i][3] * d;
779             if (dot < MAGIC_NUMBER) {
780                /* this vertex is clipped */
781                clipMask[i] = CLIP_USER_BIT;
782                anyClipped = GL_TRUE;
783             }
784             else {
785                /* vertex not clipped */
786                allClipped = GL_FALSE;
787             }
788          }
789          if (allClipped) {
790             return CLIP_ALL;
791          }
792       }
793    }
794 
795    return anyClipped ? CLIP_SOME : CLIP_NONE;
796 }
797 
798 
799 
800 /*
801  * Transform an array of vertices from clip coordinate space to window
802  * coordinates.
803  * Input:  ctx - the context
804  *         n - number of vertices to transform
805  *         vClip - array [n] of input vertices
806  *         clipMask - array [n] of vertex clip masks.  NULL = no clipped verts
807  * Output:  vWin - array [n] of vertices in window coordinate system
808  */
809 static void viewport_map_vertices( GLcontext *ctx,
810                                    GLuint n, /*const*/ GLfloat vClip[][4],
811                                    const GLubyte clipMask[], GLfloat vWin[][3])
812 {
813    GLfloat sx = ctx->Viewport.Sx;
814    GLfloat tx = ctx->Viewport.Tx;
815    GLfloat sy = ctx->Viewport.Sy;
816    GLfloat ty = ctx->Viewport.Ty;
817    GLfloat sz = ctx->Viewport.Sz;
818    GLfloat tz = ctx->Viewport.Tz;
819 
820    if ((ctx->ProjectionMatrixType==MATRIX_ORTHO ||
821         ctx->ProjectionMatrixType==MATRIX_IDENTITY)
822        && ctx->ModelViewMatrixType!=MATRIX_GENERAL
823        && (ctx->VB->VertexSizeMask & VERTEX4_BIT)==0) {
824       /* don't need to divide by W */
825       if (clipMask) {
826          /* one or more vertices are clipped */
827          GLuint i;
828          for (i=0;i<n;i++) {
829             if (clipMask[i]==0) {
830                vWin[i][0] = vClip[i][0] * sx + tx;
831                vWin[i][1] = vClip[i][1] * sy + ty;
832                vWin[i][2] = vClip[i][2] * sz + tz;
833             }
834          }
835       }
836       else {
837          /* no vertices are clipped */
838          GLuint i;
839          for (i=0;i<n;i++) {
840             vWin[i][0] = vClip[i][0] * sx + tx;
841             vWin[i][1] = vClip[i][1] * sy + ty;
842             vWin[i][2] = vClip[i][2] * sz + tz;
843          }
844       }
845    }
846    else {
847       /* need to divide by W */
848       if (clipMask) {
849          /* one or more vertices are clipped */
850          GLuint i;
851          for (i=0;i<n;i++) {
852             if (clipMask[i] == 0) {
853                if (vClip[i][3] != 0.0F) {
854                   GLfloat wInv = 1.0F / vClip[i][3];
855                   vWin[i][0] = vClip[i][0] * wInv * sx + tx;
856                   vWin[i][1] = vClip[i][1] * wInv * sy + ty;
857                   vWin[i][2] = vClip[i][2] * wInv * sz + tz;
858                }
859                else {
860                   /* Div by zero!  Can't set window coords to infinity, so...*/
861                   vWin[i][0] = 0.0F;
862                   vWin[i][1] = 0.0F;
863                   vWin[i][2] = 0.0F;
864                }
865             }
866          }
867       }
868       else {
869          /* no vertices are clipped */
870          GLuint i;
871          for (i=0;i<n;i++) {
872             if (vClip[i][3] != 0.0F) {
873                GLfloat wInv = 1.0F / vClip[i][3];
874                vWin[i][0] = vClip[i][0] * wInv * sx + tx;
875                vWin[i][1] = vClip[i][1] * wInv * sy + ty;
876                vWin[i][2] = vClip[i][2] * wInv * sz + tz;
877             }
878             else {
879                /* Divide by zero!  Can't set window coords to infinity, so...*/
880                vWin[i][0] = 0.0F;
881                vWin[i][1] = 0.0F;
882                vWin[i][2] = 0.0F;
883             }
884          }
885       }
886    }
887    if (1)
888    {
889        GLuint i;
890        for (i = 0; i < n; i++)
891        {
892            TRACE("(%3.1f, %3.1f, %3.1f, %3.1f) --> (%3.1f, %3.1f, %3.1f)\n",
893                    vClip[i][0], vClip[i][1], vClip[i][2], vClip[i][3],
894                    vWin[i][0], vWin[i][1], vWin[i][2]);
895        }
896    }
897 }
898 
899 
900 
901 /*
902  * Check if the global material has to be updated with info that was
903  * associated with a vertex via glMaterial.
904  * This function is used when any material values get changed between
905  * glBegin/glEnd either by calling glMaterial() or by calling glColor()
906  * when GL_COLOR_MATERIAL is enabled.
907  */
908 static void update_material( GLcontext *ctx, GLuint i )
909 {
910    struct vertex_buffer *VB = ctx->VB;
911 
912    if (VB->MaterialMask[i]) {
913       if (VB->MaterialMask[i] & FRONT_AMBIENT_BIT) {
914          COPY_4V( ctx->Light.Material[0].Ambient, VB->Material[i][0].Ambient );
915       }
916       if (VB->MaterialMask[i] & BACK_AMBIENT_BIT) {
917          COPY_4V( ctx->Light.Material[1].Ambient, VB->Material[i][1].Ambient );
918       }
919       if (VB->MaterialMask[i] & FRONT_DIFFUSE_BIT) {
920          COPY_4V( ctx->Light.Material[0].Diffuse, VB->Material[i][0].Diffuse );
921       }
922       if (VB->MaterialMask[i] & BACK_DIFFUSE_BIT) {
923          COPY_4V( ctx->Light.Material[1].Diffuse, VB->Material[i][1].Diffuse );
924       }
925       if (VB->MaterialMask[i] & FRONT_SPECULAR_BIT) {
926          COPY_4V( ctx->Light.Material[0].Specular, VB->Material[i][0].Specular );
927       }
928       if (VB->MaterialMask[i] & BACK_SPECULAR_BIT) {
929          COPY_4V( ctx->Light.Material[1].Specular, VB->Material[i][1].Specular );
930       }
931       if (VB->MaterialMask[i] & FRONT_EMISSION_BIT) {
932          COPY_4V( ctx->Light.Material[0].Emission, VB->Material[i][0].Emission );
933       }
934       if (VB->MaterialMask[i] & BACK_EMISSION_BIT) {
935          COPY_4V( ctx->Light.Material[1].Emission, VB->Material[i][1].Emission );
936       }
937       if (VB->MaterialMask[i] & FRONT_SHININESS_BIT) {
938          ctx->Light.Material[0].Shininess = VB->Material[i][0].Shininess;
939          gl_compute_material_shine_table( &ctx->Light.Material[0] );
940       }
941       if (VB->MaterialMask[i] & BACK_SHININESS_BIT) {
942          ctx->Light.Material[1].Shininess = VB->Material[i][1].Shininess;
943          gl_compute_material_shine_table( &ctx->Light.Material[1] );
944       }
945       if (VB->MaterialMask[i] & FRONT_INDEXES_BIT) {
946          ctx->Light.Material[0].AmbientIndex = VB->Material[i][0].AmbientIndex;
947          ctx->Light.Material[0].DiffuseIndex = VB->Material[i][0].DiffuseIndex;
948          ctx->Light.Material[0].SpecularIndex = VB->Material[i][0].SpecularIndex;
949       }
950       if (VB->MaterialMask[i] & BACK_INDEXES_BIT) {
951          ctx->Light.Material[1].AmbientIndex = VB->Material[i][1].AmbientIndex;
952          ctx->Light.Material[1].DiffuseIndex = VB->Material[i][1].DiffuseIndex;
953          ctx->Light.Material[1].SpecularIndex = VB->Material[i][1].SpecularIndex;
954       }
955       VB->MaterialMask[i] = 0;  /* reset now */
956    }
957 }
958 
959 
960 /*
961  * Compute the shading (lighting) for the vertices in the vertex buffer.
962  */
963 static void shade_vertices( GLcontext *ctx )
964 {
965    struct vertex_buffer *VB = ctx->VB;
966 
967    if (ctx->Visual->RGBAflag) {
968       if (!VB->MonoMaterial) {
969          /* Material may change with each vertex */
970          GLuint i;
971          for (i=VB->Start; i<VB->Count; i++) {
972             update_material( ctx, i );
973             gl_color_shade_vertices( ctx, 0, 1, &VB->Eye[i],
974                                      &VB->Normal[i], &VB->Fcolor[i]);
975             if (ctx->Light.Model.TwoSide) {
976                gl_color_shade_vertices( ctx, 1, 1, &VB->Eye[i],
977                                         &VB->Normal[i], &VB->Bcolor[i]);
978             }
979          }
980          /* Need this in case a glColor/glMaterial is called after the
981           * last vertex between glBegin/glEnd.
982           */
983          update_material( ctx, VB->Count );
984       }
985       else {
986          if (ctx->Light.Fast) {
987             if (VB->MonoNormal) {
988                /* call optimized shader */
989                GLubyte color[1][4];
990                GLuint i;
991                gl_color_shade_vertices_fast( ctx, 0,  /* front side */
992                                              1,
993                                              VB->Normal + VB->Start,
994                                              color );
995                for (i=VB->Start; i<VB->Count; i++) {
996                   COPY_4V( VB->Fcolor[i], color[0] );
997                }
998                if (ctx->Light.Model.TwoSide) {
999                   gl_color_shade_vertices_fast( ctx, 1,  /* back side */
1000                                                 1,
1001                                                 VB->Normal + VB->Start,
1002                                                 color );
1003                   for (i=VB->Start; i<VB->Count; i++) {
1004                      COPY_4V( VB->Bcolor[i], color[0] );
1005                   }
1006                }
1007 
1008             }
1009             else {
1010                /* call optimized shader */
1011                gl_color_shade_vertices_fast( ctx, 0,  /* front side */
1012                                              VB->Count - VB->Start,
1013                                              VB->Normal + VB->Start,
1014                                              VB->Fcolor + VB->Start );
1015                if (ctx->Light.Model.TwoSide) {
1016                   gl_color_shade_vertices_fast( ctx, 1,  /* back side */
1017                                                 VB->Count - VB->Start,
1018                                                 VB->Normal + VB->Start,
1019                                                 VB->Bcolor + VB->Start );
1020                }
1021             }
1022          }
1023          else {
1024             /* call slower, full-featured shader */
1025             gl_color_shade_vertices( ctx, 0,
1026                                      VB->Count - VB->Start,
1027                                      VB->Eye + VB->Start,
1028                                      VB->Normal + VB->Start,
1029                                      VB->Fcolor + VB->Start );
1030             if (ctx->Light.Model.TwoSide) {
1031                gl_color_shade_vertices( ctx, 1,
1032                                         VB->Count - VB->Start,
1033                                         VB->Eye + VB->Start,
1034                                         VB->Normal + VB->Start,
1035                                         VB->Bcolor + VB->Start );
1036             }
1037          }
1038       }
1039    }
1040    else {
1041       /* Color index mode */
1042       if (!VB->MonoMaterial) {
1043          /* Material may change with each vertex */
1044          GLuint i;
1045          /* NOTE the <= here.  This is needed in case glColor/glMaterial
1046           * is called after the last glVertex inside a glBegin/glEnd pair.
1047           */
1048          for (i=VB->Start; i<VB->Count; i++) {
1049             update_material( ctx, i );
1050             gl_index_shade_vertices( ctx, 0, 1, &VB->Eye[i],
1051                                      &VB->Normal[i], &VB->Findex[i] );
1052             if (ctx->Light.Model.TwoSide) {
1053                gl_index_shade_vertices( ctx, 1, 1, &VB->Eye[i],
1054                                         &VB->Normal[i], &VB->Bindex[i] );
1055             }
1056          }
1057          /* Need this in case a glColor/glMaterial is called after the
1058           * last vertex between glBegin/glEnd.
1059           */
1060          update_material( ctx, VB->Count );
1061       }
1062       else {
1063          gl_index_shade_vertices( ctx, 0,
1064                                   VB->Count - VB->Start,
1065                                   VB->Eye + VB->Start,
1066                                   VB->Normal + VB->Start,
1067                                   VB->Findex + VB->Start );
1068          if (ctx->Light.Model.TwoSide) {
1069             gl_index_shade_vertices( ctx, 1,
1070                                      VB->Count - VB->Start,
1071                                      VB->Eye + VB->Start,
1072                                      VB->Normal + VB->Start,
1073                                      VB->Bindex + VB->Start );
1074          }
1075       }
1076    }
1077 }
1078 
1079 
1080 
1081 /*
1082  * Compute fog for the vertices in the vertex buffer.
1083  */
1084 static void fog_vertices( GLcontext *ctx )
1085 {
1086    struct vertex_buffer *VB = ctx->VB;
1087 
1088    if (ctx->Visual->RGBAflag) {
1089       /* Fog RGB colors */
1090       gl_fog_color_vertices( ctx, VB->Count - VB->Start,
1091                              VB->Eye + VB->Start,
1092                              VB->Fcolor + VB->Start );
1093       if (ctx->LightTwoSide) {
1094          gl_fog_color_vertices( ctx, VB->Count - VB->Start,
1095                                 VB->Eye + VB->Start,
1096                                 VB->Bcolor + VB->Start );
1097       }
1098    }
1099    else {
1100       /* Fog color indexes */
1101       gl_fog_index_vertices( ctx, VB->Count - VB->Start,
1102                              VB->Eye + VB->Start,
1103                              VB->Findex + VB->Start );
1104       if (ctx->LightTwoSide) {
1105          gl_fog_index_vertices( ctx, VB->Count - VB->Start,
1106                                 VB->Eye + VB->Start,
1107                                 VB->Bindex + VB->Start );
1108       }
1109    }
1110 }
1111 
1112 
1113 
1114 /*
1115  * When the Vertex Buffer is full, this function applies the modelview
1116  * matrix to transform vertices and normals from object coordinates to
1117  * eye coordinates.  Next, we'll call gl_transform_vb_part2()...
1118  * This function might not be called when using vertex arrays.
1119  */
1120 void gl_transform_vb_part1( GLcontext *ctx, GLboolean allDone )
1121 {
1122    struct vertex_buffer *VB = ctx->VB;
1123 #ifdef PROFILE
1124    GLdouble t0 = gl_time();
1125 #endif
1126 
1127    ASSERT( VB->Count>0 );
1128 
1129    /* Apply the modelview matrix to transform vertexes from Object
1130     * to Eye coords.
1131     */
1132    if (VB->VertexSizeMask==VERTEX4_BIT) {
1133       transform_points4( ctx, VB->Count - VB->Start,
1134                          VB->Obj + VB->Start, VB->Eye + VB->Start );
1135    }
1136    else {
1137       transform_points3( ctx, VB->Count - VB->Start,
1138                          VB->Obj + VB->Start, VB->Eye + VB->Start );
1139    }
1140 
1141    /* Now transform the normal vectors */
1142    if (ctx->NeedNormals) {
1143       gl_xform_normals_3fv( VB->Count - VB->Start,
1144                             VB->Normal + VB->Start, ctx->ModelViewInv,
1145                             VB->Normal + VB->Start, ctx->Transform.Normalize );
1146    }
1147 
1148 #ifdef PROFILE
1149    ctx->VertexTime += gl_time() - t0;
1150 #endif
1151 
1152    /* lighting, project, etc */
1153    gl_transform_vb_part2( ctx, allDone );
1154 }
1155 
1156 
1157 
1158 /*
1159  * Part 2 of Vertex Buffer transformation:  compute lighting, clipflags,
1160  * fog, texture coords, etc.
1161  * Before this function is called the VB->Eye coordinates must have
1162  * already been computed.
1163  * Callers:  gl_transform_vb_part1(), glDrawArraysEXT()
1164  */
1165 void gl_transform_vb_part2( GLcontext *ctx, GLboolean allDone )
1166 {
1167    struct vertex_buffer *VB = ctx->VB;
1168 #ifdef PROFILE
1169    GLdouble t0 = gl_time();
1170 #endif
1171 
1172    ASSERT( VB->Count>0 );
1173 
1174    /* Test vertices in eye coordinate space against user clipping planes */
1175    if (ctx->Transform.AnyClip) {
1176       GLuint result = userclip_vertices( ctx, VB->Count - VB->Start,
1177                                          VB->Eye + VB->Start,
1178                                          VB->ClipMask + VB->Start );
1179       if (result==CLIP_ALL) {
1180          /* All vertices were outside one of the clip planes! */
1181          VB->ClipOrMask = CLIP_ALL_BITS; /* force reset of clipping flags */
1182          gl_reset_vb( ctx, allDone );
1183          return;
1184       }
1185       else if (result==CLIP_SOME) {
1186          VB->ClipOrMask = CLIP_USER_BIT;
1187       }
1188       else {
1189          VB->ClipAndMask = 0;
1190       }
1191    }
1192 
1193    /* Apply the projection matrix to the Eye coordinates, resulting in
1194     * Clip coordinates.  Also, compute the ClipMask for each vertex.
1195     */
1196    project_and_cliptest( ctx, VB->Count - VB->Start, VB->Eye + VB->Start,
1197                          VB->Clip + VB->Start, VB->ClipMask + VB->Start,
1198                          &VB->ClipOrMask, &VB->ClipAndMask );
1199 
1200    if (VB->ClipAndMask) {
1201       /* All vertices clipped by one plane, all done! */
1202       /*assert(VB->ClipOrMask);*/
1203       VB->ClipOrMask = CLIP_ALL_BITS; /* force reset of clipping flags */
1204       gl_reset_vb( ctx, allDone );
1205       return;
1206    }
1207 
1208    /* Lighting */
1209    if (ctx->Light.Enabled) {
1210       shade_vertices(ctx);
1211    }
1212 
1213    /* Per-vertex fog */
1214    if (ctx->Fog.Enabled && ctx->Hint.Fog!=GL_NICEST) {
1215       fog_vertices(ctx);
1216    }
1217 
1218    /* Generate/transform texture coords */
1219    if (ctx->Texture.Enabled || ctx->RenderMode==GL_FEEDBACK) {
1220       if (ctx->Texture.TexGenEnabled) {
1221          gl_texgen( ctx, VB->Count - VB->Start,
1222                     VB->Obj + VB->Start,
1223                     VB->Eye + VB->Start,
1224                     VB->Normal + VB->Start,
1225                     VB->TexCoord + VB->Start );
1226       }
1227       if (ctx->NewTextureMatrix) {
1228          gl_analyze_texture_matrix(ctx);
1229       }
1230       if (ctx->TextureMatrixType!=MATRIX_IDENTITY) {
1231          transform_texcoords( ctx, VB->Count - VB->Start,
1232                               VB->TexCoord + VB->Start );
1233       }
1234    }
1235 
1236    /* Use the viewport parameters to transform vertices from Clip
1237     * coordinates to Window coordinates.
1238     */
1239    viewport_map_vertices( ctx, VB->Count - VB->Start, VB->Clip + VB->Start,
1240                           VB->ClipOrMask ? VB->ClipMask + VB->Start : NULL,
1241                           VB->Win + VB->Start );
1242 
1243    /* Device driver rasterization setup.  3Dfx driver, for example. */
1244    if (ctx->Driver.RasterSetup) {
1245       (*ctx->Driver.RasterSetup)( ctx, 0, VB->Count );
1246    }
1247 
1248 
1249 #ifdef PROFILE
1250    ctx->VertexTime += gl_time() - t0;
1251    ctx->VertexCount += VB->Count - VB->Start;
1252 #endif
1253 
1254    /*
1255     * Now we're ready to rasterize the Vertex Buffer!!!
1256     *
1257     * If the device driver can't rasterize the vertex buffer then we'll
1258     * do it ourselves.
1259     */
1260    if (!ctx->Driver.RenderVB || !(*ctx->Driver.RenderVB)(ctx,allDone)) {
1261       gl_render_vb( ctx, allDone );
1262    }
1263 }
1264