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