1 /* $Id: vbrender.c,v 1.21 1998/01/18 15:04:48 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: vbrender.c,v $ 26 * Revision 1.21 1998/01/18 15:04:48 brianp 27 * fixed clipmask bug in gl_reset_vb() (reported by Michael Callahan) 28 * 29 * Revision 1.20 1998/01/09 02:49:33 brianp 30 * cleaned-up gl_reset_vb(), added small GL_POLYGON optimization 31 * 32 * Revision 1.19 1997/12/29 23:49:57 brianp 33 * added a call to gl_update_lighting() in gl_reset_vb() to fix material bug 34 * 35 * Revision 1.18 1997/12/19 03:36:42 brianp 36 * check bit-wise AND of vertex clip masks to cull polygons sooner 37 * 38 * Revision 1.17 1997/12/09 02:56:57 brianp 39 * in render_clipped_polygon() only recompute window coords for new verts 40 * 41 * Revision 1.16 1997/11/20 00:00:47 brianp 42 * only call Driver.RasterSetup() once in render_clipped_polygon() 43 * 44 * Revision 1.15 1997/09/18 01:32:47 brianp 45 * fixed divide by zero problem for "weird" projection matrices 46 * 47 * Revision 1.14 1997/08/13 01:31:41 brianp 48 * cleaned up code involving LightTwoSide 49 * 50 * Revision 1.13 1997/07/24 01:25:27 brianp 51 * changed precompiled header symbol from PCH to PC_HEADER 52 * 53 * Revision 1.12 1997/07/11 02:19:52 brianp 54 * flat-shaded quads in a strip were miscolored if clipped (Randy Frank) 55 * 56 * Revision 1.11 1997/05/28 03:26:49 brianp 57 * added precompiled header (PCH) support 58 * 59 * Revision 1.10 1997/05/16 02:09:26 brianp 60 * clipped GL_TRIANGLE_STRIP triangles sometimes got wrong provoking vertex 61 * 62 * Revision 1.9 1997/04/30 02:20:00 brianp 63 * fixed a line clipping bug in GL_LINE_LOOPs 64 * 65 * Revision 1.8 1997/04/29 01:31:07 brianp 66 * added RasterSetup() function to device driver 67 * 68 * Revision 1.7 1997/04/24 00:30:17 brianp 69 * optimized glTexCoord2() code 70 * 71 * Revision 1.6 1997/04/20 19:47:06 brianp 72 * fixed an error message, added a comment 73 * 74 * Revision 1.5 1997/04/20 15:59:30 brianp 75 * removed VERTEX2_BIT stuff 76 * 77 * Revision 1.4 1997/04/20 15:27:34 brianp 78 * removed odd_flag from all polygon rendering functions 79 * 80 * Revision 1.3 1997/04/12 12:26:06 brianp 81 * now directly call ctx->Driver.Points/Line/Triangle/QuadFunc 82 * 83 * Revision 1.2 1997/04/07 03:01:11 brianp 84 * optimized vertex[234] code 85 * 86 * Revision 1.1 1997/04/02 03:14:14 brianp 87 * Initial revision 88 * 89 */ 90 91 92 /* 93 * Render points, lines, and polygons. The only entry point to this 94 * file is the gl_render_vb() function. This function is called after 95 * the vertex buffer has filled up or glEnd() has been called. 96 * 97 * This file basically only makes calls to the clipping functions and 98 * the point, line and triangle rasterizers via the function pointers. 99 * context->Driver.PointsFunc() 100 * context->Driver.LineFunc() 101 * context->Driver.TriangleFunc() 102 */ 103 104 105 #ifdef PC_HEADER 106 #include "all.h" 107 #else 108 #include "clip.h" 109 #include "context.h" 110 #include "light.h" 111 #include "macros.h" 112 #include "matrix.h" 113 #include "pb.h" 114 #include "types.h" 115 #include "vb.h" 116 #include "vbrender.h" 117 #include "xform.h" 118 #endif 119 120 121 /* 122 * This file implements rendering of points, lines and polygons defined by 123 * vertices in the vertex buffer. 124 */ 125 126 127 128 #ifdef PROFILE 129 # define START_PROFILE \ 130 { \ 131 GLdouble t0 = gl_time(); 132 133 # define END_PROFILE( TIMER, COUNTER, INCR ) \ 134 TIMER += (gl_time() - t0); \ 135 COUNTER += INCR; \ 136 } 137 #else 138 # define START_PROFILE 139 # define END_PROFILE( TIMER, COUNTER, INCR ) 140 #endif 141 142 143 144 145 /* 146 * Render a line segment from VB[v1] to VB[v2] when either one or both 147 * endpoints must be clipped. 148 */ 149 static void render_clipped_line( GLcontext *ctx, GLuint v1, GLuint v2 ) 150 { 151 GLfloat ndc_x, ndc_y, ndc_z; 152 GLuint provoking_vertex; 153 struct vertex_buffer *VB = ctx->VB; 154 155 /* which vertex dictates the color when flat shading: */ 156 provoking_vertex = v2; 157 158 /* 159 * Clipping may introduce new vertices. New vertices will be stored 160 * in the vertex buffer arrays starting with location VB->Free. After 161 * we've rendered the line, these extra vertices can be overwritten. 162 */ 163 VB->Free = VB_MAX; 164 165 /* Clip against user clipping planes */ 166 if (ctx->Transform.AnyClip) { 167 GLuint orig_v1 = v1, orig_v2 = v2; 168 if (gl_userclip_line( ctx, &v1, &v2 )==0) 169 return; 170 /* Apply projection matrix: clip = Proj * eye */ 171 if (v1!=orig_v1) { 172 TRANSFORM_POINT( VB->Clip[v1], ctx->ProjectionMatrix, VB->Eye[v1] ); 173 } 174 if (v2!=orig_v2) { 175 TRANSFORM_POINT( VB->Clip[v2], ctx->ProjectionMatrix, VB->Eye[v2] ); 176 } 177 } 178 179 /* Clip against view volume */ 180 if (gl_viewclip_line( ctx, &v1, &v2 )==0) 181 return; 182 183 /* Transform from clip coords to ndc: ndc = clip / W */ 184 if (VB->Clip[v1][3] != 0.0F) { 185 GLfloat wInv = 1.0F / VB->Clip[v1][3]; 186 ndc_x = VB->Clip[v1][0] * wInv; 187 ndc_y = VB->Clip[v1][1] * wInv; 188 ndc_z = VB->Clip[v1][2] * wInv; 189 } 190 else { 191 /* Can't divide by zero, so... */ 192 ndc_x = ndc_y = ndc_z = 0.0F; 193 } 194 195 /* Map ndc coord to window coords. */ 196 VB->Win[v1][0] = ndc_x * ctx->Viewport.Sx + ctx->Viewport.Tx; 197 VB->Win[v1][1] = ndc_y * ctx->Viewport.Sy + ctx->Viewport.Ty; 198 VB->Win[v1][2] = ndc_z * ctx->Viewport.Sz + ctx->Viewport.Tz; 199 200 /* Transform from clip coords to ndc: ndc = clip / W */ 201 if (VB->Clip[v2][3] != 0.0F) { 202 GLfloat wInv = 1.0F / VB->Clip[v2][3]; 203 ndc_x = VB->Clip[v2][0] * wInv; 204 ndc_y = VB->Clip[v2][1] * wInv; 205 ndc_z = VB->Clip[v2][2] * wInv; 206 } 207 else { 208 /* Can't divide by zero, so... */ 209 ndc_x = ndc_y = ndc_z = 0.0F; 210 } 211 212 /* Map ndc coord to window coords. */ 213 VB->Win[v2][0] = ndc_x * ctx->Viewport.Sx + ctx->Viewport.Tx; 214 VB->Win[v2][1] = ndc_y * ctx->Viewport.Sy + ctx->Viewport.Ty; 215 VB->Win[v2][2] = ndc_z * ctx->Viewport.Sz + ctx->Viewport.Tz; 216 217 if (ctx->Driver.RasterSetup) { 218 /* Device driver rasterization setup */ 219 (*ctx->Driver.RasterSetup)( ctx, v1, v1+1 ); 220 (*ctx->Driver.RasterSetup)( ctx, v2, v2+1 ); 221 } 222 223 START_PROFILE 224 (*ctx->Driver.LineFunc)( ctx, v1, v2, provoking_vertex ); 225 END_PROFILE( ctx->LineTime, ctx->LineCount, 1 ) 226 } 227 228 229 230 /* 231 * Compute Z offsets for a polygon with plane defined by (A,B,C,D) 232 * D is not needed. 233 */ 234 static void offset_polygon( GLcontext *ctx, GLfloat a, GLfloat b, GLfloat c ) 235 { 236 GLfloat ac, bc, m; 237 GLfloat offset; 238 239 if (c<0.001F && c>-0.001F) { 240 /* to prevent underflow problems */ 241 offset = 0.0F; 242 } 243 else { 244 ac = a / c; 245 bc = b / c; 246 if (ac<0.0F) ac = -ac; 247 if (bc<0.0F) bc = -bc; 248 m = MAX2( ac, bc ); 249 /* m = sqrt( ac*ac + bc*bc ); */ 250 251 offset = m * ctx->Polygon.OffsetFactor + ctx->Polygon.OffsetUnits; 252 } 253 254 ctx->PointZoffset = ctx->Polygon.OffsetPoint ? offset : 0.0F; 255 ctx->LineZoffset = ctx->Polygon.OffsetLine ? offset : 0.0F; 256 ctx->PolygonZoffset = ctx->Polygon.OffsetFill ? offset : 0.0F; 257 } 258 259 260 261 /* 262 * When glPolygonMode() is used to specify that the front/back rendering 263 * mode for polygons is not GL_FILL we end up calling this function. 264 */ 265 static void unfilled_polygon( GLcontext *ctx, 266 GLuint n, GLuint vlist[], 267 GLuint pv, GLuint facing ) 268 { 269 GLenum mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode; 270 struct vertex_buffer *VB = ctx->VB; 271 272 if (mode==GL_POINT) { 273 GLint i, j; 274 GLboolean edge; 275 276 if ( ctx->Primitive==GL_TRIANGLES 277 || ctx->Primitive==GL_QUADS 278 || ctx->Primitive==GL_POLYGON) { 279 edge = GL_FALSE; 280 } 281 else { 282 edge = GL_TRUE; 283 } 284 285 for (i=0;i<n;i++) { 286 j = vlist[i]; 287 if (edge || VB->Edgeflag[j]) { 288 (*ctx->Driver.PointsFunc)( ctx, j, j ); 289 } 290 } 291 } 292 else if (mode==GL_LINE) { 293 GLuint i, j0, j1; 294 GLboolean edge; 295 296 ctx->StippleCounter = 0; 297 298 if ( ctx->Primitive==GL_TRIANGLES 299 || ctx->Primitive==GL_QUADS 300 || ctx->Primitive==GL_POLYGON) { 301 edge = GL_FALSE; 302 } 303 else { 304 edge = GL_TRUE; 305 } 306 307 /* draw the edges */ 308 for (i=0;i<n;i++) { 309 j0 = (i==0) ? vlist[n-1] : vlist[i-1]; 310 j1 = vlist[i]; 311 if (edge || VB->Edgeflag[j0]) { 312 START_PROFILE 313 (*ctx->Driver.LineFunc)( ctx, j0, j1, pv ); 314 END_PROFILE( ctx->LineTime, ctx->LineCount, 1 ) 315 } 316 } 317 } 318 else { 319 /* Fill the polygon */ 320 GLuint j0, i; 321 j0 = vlist[0]; 322 for (i=2;i<n;i++) { 323 START_PROFILE 324 (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv ); 325 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 ) 326 } 327 } 328 } 329 330 331 /* 332 * Compute signed area of the n-sided polgyon specified by vertices vb->Win[] 333 * and vertex list vlist[]. 334 * A clockwise polygon will return a negative area. 335 * A counter-clockwise polygon will return a positive area. 336 */ 337 static GLfloat polygon_area( const struct vertex_buffer *vb, 338 GLuint n, const GLuint vlist[] ) 339 { 340 GLfloat area = 0.0F; 341 GLint i; 342 for (i=0;i<n;i++) { 343 /* area = sum of trapezoids */ 344 GLuint j0 = vlist[i]; 345 GLuint j1 = vlist[(i+1)%n]; 346 GLfloat x0 = vb->Win[j0][0]; 347 GLfloat y0 = vb->Win[j0][1]; 348 GLfloat x1 = vb->Win[j1][0]; 349 GLfloat y1 = vb->Win[j1][1]; 350 GLfloat trapArea = (x0-x1)*(y0+y1); /* Note: no divide by two here! */ 351 area += trapArea; 352 } 353 return area * 0.5F; /* divide by two now! */ 354 } 355 356 357 /* 358 * Render a polygon in which doesn't have to be clipped. 359 * Input: n - number of vertices 360 * vlist - list of vertices in the polygon. 361 */ 362 static void render_polygon( GLcontext *ctx, GLuint n, GLuint vlist[] ) 363 { 364 struct vertex_buffer *VB = ctx->VB; 365 GLuint pv; 366 367 /* which vertex dictates the color when flat shading: */ 368 pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1]; 369 370 /* Compute orientation of polygon, do cull test, offset, etc */ 371 { 372 GLuint facing; /* 0=front, 1=back */ 373 GLfloat area = polygon_area( VB, n, vlist ); 374 375 if (area==0.0F) { 376 /* polygon has zero area, don't draw it */ 377 return; 378 } 379 380 facing = (area<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW); 381 382 if ((facing+1) & ctx->Polygon.CullBits) { 383 return; /* culled */ 384 } 385 386 if (ctx->Polygon.OffsetAny) { 387 /* compute plane equation of polygon, apply offset */ 388 GLuint j0 = vlist[0]; 389 GLuint j1 = vlist[1]; 390 GLuint j2 = vlist[2]; 391 GLuint j3 = vlist[ (n==3) ? 0 : 3 ]; 392 GLfloat ex = VB->Win[j1][0] - VB->Win[j3][0]; 393 GLfloat ey = VB->Win[j1][1] - VB->Win[j3][1]; 394 GLfloat ez = VB->Win[j1][2] - VB->Win[j3][2]; 395 GLfloat fx = VB->Win[j2][0] - VB->Win[j0][0]; 396 GLfloat fy = VB->Win[j2][1] - VB->Win[j0][1]; 397 GLfloat fz = VB->Win[j2][2] - VB->Win[j0][2]; 398 GLfloat a = ey*fz-ez*fy; 399 GLfloat b = ez*fx-ex*fz; 400 GLfloat c = ex*fy-ey*fx; 401 offset_polygon( ctx, a, b, c ); 402 } 403 404 if (ctx->LightTwoSide) { 405 if (facing==1) { 406 /* use back color or index */ 407 VB->Color = VB->Bcolor; 408 VB->Index = VB->Bindex; 409 } 410 else { 411 /* use front color or index */ 412 VB->Color = VB->Fcolor; 413 VB->Index = VB->Findex; 414 } 415 } 416 417 /* Render the polygon! */ 418 if (ctx->Polygon.Unfilled) { 419 unfilled_polygon( ctx, n, vlist, pv, facing ); 420 } 421 else { 422 /* Draw filled polygon as a triangle fan */ 423 GLint i; 424 GLuint j0 = vlist[0]; 425 for (i=2;i<n;i++) { 426 START_PROFILE 427 (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv ); 428 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 ) 429 } 430 } 431 } 432 } 433 434 435 436 /* 437 * Render a polygon in which at least one vertex has to be clipped. 438 * Input: n - number of vertices 439 * vlist - list of vertices in the polygon. 440 * CCW order = front facing. 441 */ 442 static void render_clipped_polygon( GLcontext *ctx, GLuint n, GLuint vlist[] ) 443 { 444 GLuint pv; 445 struct vertex_buffer *VB = ctx->VB; 446 GLfloat (*win)[3] = VB->Win; 447 448 /* which vertex dictates the color when flat shading: */ 449 pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1]; 450 451 /* 452 * Clipping may introduce new vertices. New vertices will be stored 453 * in the vertex buffer arrays starting with location VB->Free. After 454 * we've rendered the polygon, these extra vertices can be overwritten. 455 */ 456 VB->Free = VB_MAX; 457 458 /* Clip against user clipping planes in eye coord space. */ 459 if (ctx->Transform.AnyClip) { 460 GLfloat *proj = ctx->ProjectionMatrix; 461 GLuint i; 462 n = gl_userclip_polygon( ctx, n, vlist ); 463 if (n<3) 464 return; 465 /* Transform vertices from eye to clip coordinates: clip = Proj * eye */ 466 for (i=0;i<n;i++) { 467 GLuint j = vlist[i]; 468 TRANSFORM_POINT( VB->Clip[j], proj, VB->Eye[j] ); 469 } 470 } 471 472 /* Clip against view volume in clip coord space */ 473 n = gl_viewclip_polygon( ctx, n, vlist ); 474 if (n<3) 475 return; 476 477 /* Transform new vertices from clip to ndc to window coords. */ 478 /* ndc = clip / W window = viewport_mapping(ndc) */ 479 /* Note that window Z values are scaled to the range of integer */ 480 /* depth buffer values. */ 481 { 482 GLfloat sx = ctx->Viewport.Sx; 483 GLfloat tx = ctx->Viewport.Tx; 484 GLfloat sy = ctx->Viewport.Sy; 485 GLfloat ty = ctx->Viewport.Ty; 486 GLfloat sz = ctx->Viewport.Sz; 487 GLfloat tz = ctx->Viewport.Tz; 488 GLuint i; 489 /* Only need to compute window coords for new vertices */ 490 for (i=VB_MAX; i<VB->Free; i++) { 491 if (VB->Clip[i][3] != 0.0F) { 492 GLfloat wInv = 1.0F / VB->Clip[i][3]; 493 win[i][0] = VB->Clip[i][0] * wInv * sx + tx; 494 win[i][1] = VB->Clip[i][1] * wInv * sy + ty; 495 win[i][2] = VB->Clip[i][2] * wInv * sz + tz; 496 } 497 else { 498 /* Can't divide by zero, so... */ 499 win[i][0] = win[i][1] = win[i][2] = 0.0F; 500 } 501 } 502 if (ctx->Driver.RasterSetup && (VB->Free > VB_MAX)) { 503 /* Device driver raster setup for newly introduced vertices */ 504 (*ctx->Driver.RasterSetup)(ctx, VB_MAX, VB->Free); 505 } 506 507 #ifdef DEBUG 508 { 509 int i, j; 510 for (i=0;i<n;i++) { 511 j = vlist[i]; 512 if (VB->ClipMask[j]) { 513 /* Uh oh! There should be no clip bits set in final polygon! */ 514 int k, l; 515 printf("CLIPMASK %d %d %02x\n", i, j, VB->ClipMask[j]); 516 printf("%f %f %f %f\n", VB->Eye[j][0], VB->Eye[j][1], 517 VB->Eye[j][2], VB->Eye[j][3]); 518 printf("%f %f %f %f\n", VB->Clip[j][0], VB->Clip[j][1], 519 VB->Clip[j][2], VB->Clip[j][3]); 520 for (k=0;k<n;k++) { 521 l = vlist[k]; 522 printf("%d %d %02x\n", k, l, VB->ClipMask[l]); 523 } 524 } 525 } 526 } 527 #endif 528 } 529 530 /* Compute orientation of polygon, do cull test, offset, etc */ 531 { 532 GLuint facing; /* 0=front, 1=back */ 533 GLfloat area = polygon_area( VB, n, vlist ); 534 535 if (area==0.0F) { 536 /* polygon has zero area, don't draw it */ 537 return; 538 } 539 540 facing = (area<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW); 541 542 if ((facing+1) & ctx->Polygon.CullBits) { 543 return; /* culled */ 544 } 545 546 if (ctx->Polygon.OffsetAny) { 547 /* compute plane equation of polygon, apply offset */ 548 GLuint j0 = vlist[0]; 549 GLuint j1 = vlist[1]; 550 GLuint j2 = vlist[2]; 551 GLuint j3 = vlist[ (n==3) ? 0 : 3 ]; 552 GLfloat ex = win[j1][0] - win[j3][0]; 553 GLfloat ey = win[j1][1] - win[j3][1]; 554 GLfloat ez = win[j1][2] - win[j3][2]; 555 GLfloat fx = win[j2][0] - win[j0][0]; 556 GLfloat fy = win[j2][1] - win[j0][1]; 557 GLfloat fz = win[j2][2] - win[j0][2]; 558 GLfloat a = ey*fz-ez*fy; 559 GLfloat b = ez*fx-ex*fz; 560 GLfloat c = ex*fy-ey*fx; 561 offset_polygon( ctx, a, b, c ); 562 } 563 564 if (ctx->LightTwoSide) { 565 if (facing==1) { 566 /* use back color or index */ 567 VB->Color = VB->Bcolor; 568 VB->Index = VB->Bindex; 569 } 570 else { 571 /* use front color or index */ 572 VB->Color = VB->Fcolor; 573 VB->Index = VB->Findex; 574 } 575 } 576 577 /* Render the polygon! */ 578 if (ctx->Polygon.Unfilled) { 579 unfilled_polygon( ctx, n, vlist, pv, facing ); 580 } 581 else { 582 /* Draw filled polygon as a triangle fan */ 583 GLint i; 584 GLuint j0 = vlist[0]; 585 for (i=2;i<n;i++) { 586 START_PROFILE 587 (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv ); 588 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 ) 589 } 590 } 591 } 592 } 593 594 595 596 /* 597 * Render an un-clipped triangle. 598 * v0, v1, v2 - vertex indexes. CCW order = front facing 599 * pv - provoking vertex 600 */ 601 static void render_triangle( GLcontext *ctx, 602 GLuint v0, GLuint v1, GLuint v2, GLuint pv ) 603 { 604 struct vertex_buffer *VB = ctx->VB; 605 GLfloat ex, ey, fx, fy, c; 606 GLuint facing; /* 0=front, 1=back */ 607 GLfloat (*win)[3] = VB->Win; 608 609 /* Compute orientation of triangle */ 610 ex = win[v1][0] - win[v0][0]; 611 ey = win[v1][1] - win[v0][1]; 612 fx = win[v2][0] - win[v0][0]; 613 fy = win[v2][1] - win[v0][1]; 614 c = ex*fy-ey*fx; 615 616 if (c==0.0F) { 617 /* polygon is perpindicular to view plane, don't draw it */ 618 return; 619 } 620 621 facing = (c<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW); 622 623 if ((facing+1) & ctx->Polygon.CullBits) { 624 return; /* culled */ 625 } 626 627 if (ctx->Polygon.OffsetAny) { 628 /* finish computing plane equation of polygon, compute offset */ 629 GLfloat fz = win[v2][2] - win[v0][2]; 630 GLfloat ez = win[v1][2] - win[v0][2]; 631 GLfloat a = ey*fz-ez*fy; 632 GLfloat b = ez*fx-ex*fz; 633 offset_polygon( ctx, a, b, c ); 634 } 635 636 if (ctx->LightTwoSide) { 637 if (facing==1) { 638 /* use back color or index */ 639 VB->Color = VB->Bcolor; 640 VB->Index = VB->Bindex; 641 } 642 else { 643 /* use front color or index */ 644 VB->Color = VB->Fcolor; 645 VB->Index = VB->Findex; 646 } 647 } 648 649 if (ctx->Polygon.Unfilled) { 650 GLuint vlist[3]; 651 vlist[0] = v0; 652 vlist[1] = v1; 653 vlist[2] = v2; 654 unfilled_polygon( ctx, 3, vlist, pv, facing ); 655 } 656 else { 657 START_PROFILE 658 (*ctx->Driver.TriangleFunc)( ctx, v0, v1, v2, pv ); 659 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 ) 660 } 661 } 662 663 664 665 /* 666 * Render an un-clipped quadrilateral. 667 * v0, v1, v2, v3 : CCW order = front facing 668 * pv - provoking vertex 669 */ 670 static void render_quad( GLcontext *ctx, GLuint v0, GLuint v1, 671 GLuint v2, GLuint v3, GLuint pv ) 672 { 673 struct vertex_buffer *VB = ctx->VB; 674 GLfloat ex, ey, fx, fy, c; 675 GLuint facing; /* 0=front, 1=back */ 676 GLfloat (*win)[3] = VB->Win; 677 678 /* Compute polygon orientation */ 679 ex = win[v2][0] - win[v0][0]; 680 ey = win[v2][1] - win[v0][1]; 681 fx = win[v3][0] - win[v1][0]; 682 fy = win[v3][1] - win[v1][1]; 683 c = ex*fy-ey*fx; 684 685 if (c==0.0F) { 686 /* polygon is perpindicular to view plane, don't draw it */ 687 return; 688 } 689 690 facing = (c<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW); 691 692 if ((facing+1) & ctx->Polygon.CullBits) { 693 return; /* culled */ 694 } 695 696 if (ctx->Polygon.OffsetAny) { 697 /* finish computing plane equation of polygon, compute offset */ 698 GLfloat ez = win[v2][2] - win[v0][2]; 699 GLfloat fz = win[v3][2] - win[v1][2]; 700 GLfloat a = ey*fz-ez*fy; 701 GLfloat b = ez*fx-ex*fz; 702 offset_polygon( ctx, a, b, c ); 703 } 704 705 if (ctx->LightTwoSide) { 706 if (facing==1) { 707 /* use back color or index */ 708 VB->Color = VB->Bcolor; 709 VB->Index = VB->Bindex; 710 } 711 else { 712 /* use front color or index */ 713 VB->Color = VB->Fcolor; 714 VB->Index = VB->Findex; 715 } 716 } 717 718 /* Render the quad! */ 719 if (ctx->Polygon.Unfilled) { 720 GLuint vlist[4]; 721 vlist[0] = v0; 722 vlist[1] = v1; 723 vlist[2] = v2; 724 vlist[3] = v3; 725 unfilled_polygon( ctx, 4, vlist, pv, facing ); 726 } 727 else { 728 START_PROFILE 729 (*ctx->Driver.QuadFunc)( ctx, v0, v1, v2, v3, pv ); 730 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 ) 731 } 732 } 733 734 735 736 /* 737 * When the vertex buffer is full, we transform/render it. Sometimes we 738 * have to copy the last vertex (or two) to the front of the vertex list 739 * to "continue" the primitive. For example: line or triangle strips. 740 * This function is a helper for that. 741 */ 742 static void copy_vertex( struct vertex_buffer *vb, GLuint dst, GLuint src ) 743 { 744 COPY_4V( vb->Clip[dst], vb->Clip[src] ); 745 COPY_4V( vb->Eye[dst], vb->Eye[src] ); 746 COPY_3V( vb->Win[dst], vb->Win[src] ); 747 COPY_4V( vb->Fcolor[dst], vb->Fcolor[src] ); 748 COPY_4V( vb->Bcolor[dst], vb->Bcolor[src] ); 749 COPY_4V( vb->TexCoord[dst], vb->TexCoord[src] ); 750 vb->Findex[dst] = vb->Findex[src]; 751 vb->Bindex[dst] = vb->Bindex[src]; 752 vb->Edgeflag[dst] = vb->Edgeflag[src]; 753 vb->ClipMask[dst] = vb->ClipMask[src]; 754 vb->MaterialMask[dst] = vb->MaterialMask[src]; 755 vb->Material[dst][0] = vb->Material[src][0]; 756 vb->Material[dst][1] = vb->Material[src][1]; 757 } 758 759 760 761 762 /* 763 * Either the vertex buffer is full (VB->Count==VB_MAX) or glEnd() has been 764 * called. Render the primitives defined by the vertices and reset the 765 * buffer. 766 * 767 * This function won't be called if the device driver implements a 768 * RenderVB() function. If the device driver renders the vertex buffer 769 * then the driver must also call gl_reset_vb()! 770 * 771 * Input: allDone - GL_TRUE = caller is glEnd() 772 * GL_FALSE = calling because buffer is full. 773 */ 774 void gl_render_vb( GLcontext *ctx, GLboolean allDone ) 775 { 776 struct vertex_buffer *VB = ctx->VB; 777 GLuint vlist[VB_SIZE]; 778 779 switch (ctx->Primitive) { 780 case GL_POINTS: 781 START_PROFILE 782 (*ctx->Driver.PointsFunc)( ctx, 0, VB->Count-1 ); 783 END_PROFILE( ctx->PointTime, ctx->PointCount, VB->Count ) 784 break; 785 786 case GL_LINES: 787 if (VB->ClipOrMask) { 788 GLuint i; 789 for (i=1;i<VB->Count;i+=2) { 790 if (VB->ClipMask[i-1] | VB->ClipMask[i]) { 791 render_clipped_line( ctx, i-1, i ); 792 } 793 else { 794 START_PROFILE 795 (*ctx->Driver.LineFunc)( ctx, i-1, i, i ); 796 END_PROFILE( ctx->LineTime, ctx->LineCount, 1 ) 797 } 798 ctx->StippleCounter = 0; 799 } 800 } 801 else { 802 GLuint i; 803 for (i=1;i<VB->Count;i+=2) { 804 START_PROFILE 805 (*ctx->Driver.LineFunc)( ctx, i-1, i, i ); 806 END_PROFILE( ctx->LineTime, ctx->LineCount, 1 ) 807 ctx->StippleCounter = 0; 808 } 809 } 810 break; 811 812 case GL_LINE_STRIP: 813 if (VB->ClipOrMask) { 814 GLuint i; 815 for (i=1;i<VB->Count;i++) { 816 if (VB->ClipMask[i-1] | VB->ClipMask[i]) { 817 render_clipped_line( ctx, i-1, i ); 818 } 819 else { 820 START_PROFILE 821 (*ctx->Driver.LineFunc)( ctx, i-1, i, i ); 822 END_PROFILE( ctx->LineTime, ctx->LineCount, 1 ) 823 } 824 } 825 } 826 else { 827 /* no clipping needed */ 828 GLuint i; 829 for (i=1;i<VB->Count;i++) { 830 START_PROFILE 831 (*ctx->Driver.LineFunc)( ctx, i-1, i, i ); 832 END_PROFILE( ctx->LineTime, ctx->LineCount, 1 ) 833 } 834 } 835 break; 836 837 case GL_LINE_LOOP: 838 { 839 GLuint i; 840 if (VB->Start==0) { 841 i = 1; /* start at 0th vertex */ 842 } 843 else { 844 i = 2; /* skip first vertex, we're saving it until glEnd */ 845 } 846 while (i<VB->Count) { 847 if (VB->ClipMask[i-1] | VB->ClipMask[i]) { 848 render_clipped_line( ctx, i-1, i ); 849 } 850 else { 851 START_PROFILE 852 (*ctx->Driver.LineFunc)( ctx, i-1, i, i ); 853 END_PROFILE( ctx->LineTime, ctx->LineCount, 1 ) 854 } 855 i++; 856 } 857 } 858 break; 859 860 case GL_TRIANGLES: 861 if (VB->ClipOrMask) { 862 GLuint i; 863 for (i=2;i<VB->Count;i+=3) { 864 if (VB->ClipMask[i-2] & VB->ClipMask[i-1] 865 & VB->ClipMask[i] & CLIP_ALL_BITS) { 866 /* all points clipped by common plane */ 867 continue; 868 } 869 else if (VB->ClipMask[i-2] | VB->ClipMask[i-1] | VB->ClipMask[i]) { 870 vlist[0] = i-2; 871 vlist[1] = i-1; 872 vlist[2] = i-0; 873 render_clipped_polygon( ctx, 3, vlist ); 874 } 875 else { 876 if (ctx->DirectTriangles) { 877 START_PROFILE 878 (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i ); 879 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 ) 880 } 881 else { 882 render_triangle( ctx, i-2, i-1, i, i ); 883 } 884 } 885 } 886 } 887 else { 888 /* no clipping needed */ 889 GLuint i; 890 if (ctx->DirectTriangles) { 891 for (i=2;i<VB->Count;i+=3) { 892 START_PROFILE 893 (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i ); 894 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 ) 895 } 896 } 897 else { 898 for (i=2;i<VB->Count;i+=3) { 899 render_triangle( ctx, i-2, i-1, i, i ); 900 } 901 } 902 } 903 break; 904 905 case GL_TRIANGLE_STRIP: 906 if (VB->ClipOrMask) { 907 GLuint i; 908 for (i=2;i<VB->Count;i++) { 909 if (VB->ClipMask[i-2] & VB->ClipMask[i-1] 910 & VB->ClipMask[i] & CLIP_ALL_BITS) { 911 /* all points clipped by common plane */ 912 continue; 913 } 914 else if (VB->ClipMask[i-2] | VB->ClipMask[i-1] | VB->ClipMask[i]) { 915 if (i&1) { 916 /* reverse vertex order */ 917 vlist[0] = i-1; 918 vlist[1] = i-2; 919 vlist[2] = i-0; 920 render_clipped_polygon( ctx, 3, vlist ); 921 } 922 else { 923 vlist[0] = i-2; 924 vlist[1] = i-1; 925 vlist[2] = i-0; 926 render_clipped_polygon( ctx, 3, vlist ); 927 } 928 } 929 else { 930 if (ctx->DirectTriangles) { 931 START_PROFILE 932 (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i ); 933 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 ) 934 } 935 else { 936 if (i&1) 937 render_triangle( ctx, i, i-1, i-2, i ); 938 else 939 render_triangle( ctx, i-2, i-1, i, i ); 940 } 941 } 942 } 943 } 944 else { 945 /* no vertices were clipped */ 946 GLuint i; 947 if (ctx->DirectTriangles) { 948 for (i=2;i<VB->Count;i++) { 949 START_PROFILE 950 (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i ); 951 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 ) 952 } 953 } 954 else { 955 for (i=2;i<VB->Count;i++) { 956 if (i&1) 957 render_triangle( ctx, i, i-1, i-2, i ); 958 else 959 render_triangle( ctx, i-2, i-1, i, i ); 960 } 961 } 962 } 963 break; 964 965 case GL_TRIANGLE_FAN: 966 if (VB->ClipOrMask) { 967 GLuint i; 968 for (i=2;i<VB->Count;i++) { 969 if (VB->ClipMask[0] & VB->ClipMask[i-1] & VB->ClipMask[i] 970 & CLIP_ALL_BITS) { 971 /* all points clipped by common plane */ 972 continue; 973 } 974 else if (VB->ClipMask[0] | VB->ClipMask[i-1] | VB->ClipMask[i]) { 975 vlist[0] = 0; 976 vlist[1] = i-1; 977 vlist[2] = i; 978 render_clipped_polygon( ctx, 3, vlist ); 979 } 980 else { 981 if (ctx->DirectTriangles) { 982 START_PROFILE 983 (*ctx->Driver.TriangleFunc)( ctx, 0, i-1, i, i ); 984 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 ) 985 } 986 else { 987 render_triangle( ctx, 0, i-1, i, i ); 988 } 989 } 990 } 991 } 992 else { 993 /* no clipping needed */ 994 GLuint i; 995 if (ctx->DirectTriangles) { 996 for (i=2;i<VB->Count;i++) { 997 START_PROFILE 998 (*ctx->Driver.TriangleFunc)( ctx, 0, i-1, i, i ); 999 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 ) 1000 } 1001 } 1002 else { 1003 for (i=2;i<VB->Count;i++) { 1004 render_triangle( ctx, 0, i-1, i, i ); 1005 } 1006 } 1007 } 1008 break; 1009 1010 case GL_QUADS: 1011 if (VB->ClipOrMask) { 1012 GLuint i; 1013 for (i=3;i<VB->Count;i+=4) { 1014 if (VB->ClipMask[i-3] & VB->ClipMask[i-2] 1015 & VB->ClipMask[i-1] & VB->ClipMask[i] & CLIP_ALL_BITS) { 1016 /* all points clipped by common plane */ 1017 continue; 1018 } 1019 else if (VB->ClipMask[i-3] | VB->ClipMask[i-2] 1020 | VB->ClipMask[i-1] | VB->ClipMask[i]) { 1021 vlist[0] = i-3; 1022 vlist[1] = i-2; 1023 vlist[2] = i-1; 1024 vlist[3] = i-0; 1025 render_clipped_polygon( ctx, 4, vlist ); 1026 } 1027 else { 1028 if (ctx->DirectTriangles) { 1029 START_PROFILE 1030 (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i-1, i, i ); 1031 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 ) 1032 } 1033 else { 1034 render_quad( ctx, i-3, i-2, i-1, i, i ); 1035 } 1036 } 1037 } 1038 } 1039 else { 1040 /* no vertices were clipped */ 1041 GLuint i; 1042 if (ctx->DirectTriangles) { 1043 for (i=3;i<VB->Count;i+=4) { 1044 START_PROFILE 1045 (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i-1, i, i ); 1046 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 ) 1047 } 1048 } 1049 else { 1050 for (i=3;i<VB->Count;i+=4) { 1051 render_quad( ctx, i-3, i-2, i-1, i, i ); 1052 } 1053 } 1054 } 1055 break; 1056 1057 case GL_QUAD_STRIP: 1058 if (VB->ClipOrMask) { 1059 GLuint i; 1060 for (i=3;i<VB->Count;i+=2) { 1061 if (VB->ClipMask[i-2] & VB->ClipMask[i-3] 1062 & VB->ClipMask[i-1] & VB->ClipMask[i] & CLIP_ALL_BITS) { 1063 /* all points clipped by common plane */ 1064 continue; 1065 } 1066 else if (VB->ClipMask[i-2] | VB->ClipMask[i-3] 1067 | VB->ClipMask[i-1] | VB->ClipMask[i]) { 1068 vlist[0] = i-1; 1069 vlist[1] = i-3; 1070 vlist[2] = i-2; 1071 vlist[3] = i-0; 1072 render_clipped_polygon( ctx, 4, vlist ); 1073 } 1074 else { 1075 if (ctx->DirectTriangles) { 1076 START_PROFILE 1077 (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i, i-1, i ); 1078 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 ) 1079 } 1080 else { 1081 render_quad( ctx, i-3, i-2, i, i-1, i ); 1082 } 1083 } 1084 } 1085 } 1086 else { 1087 /* no clipping needed */ 1088 GLuint i; 1089 if (ctx->DirectTriangles) { 1090 for (i=3;i<VB->Count;i+=2) { 1091 START_PROFILE 1092 (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i, i-1, i ); 1093 END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 ) 1094 } 1095 } 1096 else { 1097 for (i=3;i<VB->Count;i+=2) { 1098 render_quad( ctx, i-3, i-2, i, i-1, i ); 1099 } 1100 } 1101 } 1102 break; 1103 1104 case GL_POLYGON: 1105 if (VB->Count>2) { 1106 if (VB->ClipAndMask & CLIP_ALL_BITS) { 1107 /* all points clipped by common plane, draw nothing */ 1108 break; 1109 } 1110 if (VB->ClipOrMask) { 1111 /* need clipping */ 1112 GLuint i; 1113 for (i=0;i<VB->Count;i++) { 1114 vlist[i] = i; 1115 } 1116 render_clipped_polygon( ctx, VB->Count, vlist ); 1117 } 1118 else { 1119 /* no clipping needed */ 1120 static GLuint const_vlist[VB_SIZE]; 1121 static GLboolean initFlag = GL_TRUE; 1122 if (initFlag) { 1123 /* vertex list always the same, never changes */ 1124 GLuint i; 1125 for (i=0;i<VB_SIZE;i++) { 1126 const_vlist[i] = i; 1127 } 1128 initFlag = GL_FALSE; 1129 } 1130 render_polygon( ctx, VB->Count, const_vlist ); 1131 } 1132 } 1133 break; 1134 1135 default: 1136 /* should never get here */ 1137 gl_problem( ctx, "invalid mode in gl_render_vb" ); 1138 } 1139 1140 gl_reset_vb( ctx, allDone ); 1141 } 1142 1143 1144 #define CLIP_ALL_BITS 0x3f 1145 1146 1147 /* 1148 * After we've rendered the primitives in the vertex buffer we call 1149 * this function to reset the vertex buffer. That is, we prepare it 1150 * for the next batch of vertices. 1151 * Input: ctx - the context 1152 * allDone - GL_TRUE = glEnd() was called 1153 * GL_FALSE = buffer was filled, more vertices to come 1154 */ 1155 void gl_reset_vb( GLcontext *ctx, GLboolean allDone ) 1156 { 1157 struct vertex_buffer *VB = ctx->VB; 1158 1159 /* save a few VB values for the end of this function */ 1160 int oldCount = VB->Count; 1161 GLubyte clipOrMask = VB->ClipOrMask; 1162 GLboolean monoMaterial = VB->MonoMaterial; 1163 GLuint vertexSizeMask = VB->VertexSizeMask; 1164 1165 /* Special case for GL_LINE_LOOP */ 1166 if (ctx->Primitive==GL_LINE_LOOP && allDone) { 1167 if (VB->ClipMask[VB->Count-1] | VB->ClipMask[0]) { 1168 render_clipped_line( ctx, VB->Count-1, 0 ); 1169 } 1170 else { 1171 START_PROFILE 1172 (*ctx->Driver.LineFunc)( ctx, VB->Count-1, 0, 0 ); 1173 END_PROFILE( ctx->LineTime, ctx->LineCount, 1 ) 1174 } 1175 } 1176 1177 if (allDone) { 1178 /* glEnd() was called so reset Vertex Buffer to default, empty state */ 1179 VB->Start = VB->Count = 0; 1180 VB->ClipOrMask = 0; 1181 VB->ClipAndMask = CLIP_ALL_BITS; 1182 VB->MonoMaterial = GL_TRUE; 1183 VB->MonoNormal = GL_TRUE; 1184 VB->MonoColor = GL_TRUE; 1185 VB->VertexSizeMask = VERTEX3_BIT; 1186 if (VB->TexCoordSize!=2) { 1187 GLint i, n = VB->Count; 1188 for (i=0;i<n;i++) { 1189 VB->TexCoord[i][2] = 0.0F; 1190 VB->TexCoord[i][3] = 1.0F; 1191 } 1192 } 1193 if (ctx->Current.TexCoord[2]==0.0F && ctx->Current.TexCoord[3]==1.0F) { 1194 VB->TexCoordSize = 2; 1195 } 1196 else { 1197 VB->TexCoordSize = 4; 1198 } 1199 } 1200 else { 1201 /* The vertex buffer was filled but we didn't get a glEnd() call yet 1202 * have to "re-cycle" the vertex buffer. 1203 */ 1204 switch (ctx->Primitive) { 1205 case GL_POINTS: 1206 ASSERT(VB->Start==0); 1207 VB->Start = VB->Count = 0; 1208 VB->ClipOrMask = 0; 1209 VB->ClipAndMask = CLIP_ALL_BITS; 1210 VB->MonoMaterial = GL_TRUE; 1211 VB->MonoNormal = GL_TRUE; 1212 break; 1213 case GL_LINES: 1214 ASSERT(VB->Start==0); 1215 VB->Start = VB->Count = 0; 1216 VB->ClipOrMask = 0; 1217 VB->ClipAndMask = CLIP_ALL_BITS; 1218 VB->MonoMaterial = GL_TRUE; 1219 VB->MonoNormal = GL_TRUE; 1220 break; 1221 case GL_LINE_STRIP: 1222 copy_vertex( VB, 0, VB->Count-1 ); /* copy last vertex to front */ 1223 VB->Start = VB->Count = 1; 1224 VB->ClipOrMask = VB->ClipMask[0]; 1225 VB->ClipAndMask = VB->ClipMask[0]; 1226 VB->MonoMaterial = VB->MaterialMask[0] ? GL_FALSE : GL_TRUE; 1227 break; 1228 case GL_LINE_LOOP: 1229 ASSERT(VB->Count==VB_MAX); 1230 copy_vertex( VB, 1, VB_MAX-1 ); 1231 VB->Start = VB->Count = 2; 1232 VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1]; 1233 VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1]; 1234 VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]); 1235 break; 1236 case GL_TRIANGLES: 1237 ASSERT(VB->Start==0); 1238 VB->Start = VB->Count = 0; 1239 VB->ClipOrMask = 0; 1240 VB->ClipAndMask = CLIP_ALL_BITS; 1241 VB->MonoMaterial = GL_TRUE; 1242 VB->MonoNormal = GL_TRUE; 1243 break; 1244 case GL_TRIANGLE_STRIP: 1245 copy_vertex( VB, 0, VB_MAX-2 ); 1246 copy_vertex( VB, 1, VB_MAX-1 ); 1247 VB->Start = VB->Count = 2; 1248 VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1]; 1249 VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1]; 1250 VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]); 1251 break; 1252 case GL_TRIANGLE_FAN: 1253 copy_vertex( VB, 1, VB_MAX-1 ); 1254 VB->Start = VB->Count = 2; 1255 VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1]; 1256 VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1]; 1257 VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]); 1258 break; 1259 case GL_QUADS: 1260 ASSERT(VB->Start==0); 1261 VB->Start = VB->Count = 0; 1262 VB->ClipOrMask = 0; 1263 VB->ClipAndMask = CLIP_ALL_BITS; 1264 VB->MonoMaterial = GL_TRUE; 1265 VB->MonoNormal = GL_TRUE; 1266 break; 1267 case GL_QUAD_STRIP: 1268 copy_vertex( VB, 0, VB_MAX-2 ); 1269 copy_vertex( VB, 1, VB_MAX-1 ); 1270 VB->Start = VB->Count = 2; 1271 VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1]; 1272 VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1]; 1273 VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]); 1274 break; 1275 case GL_POLYGON: 1276 copy_vertex( VB, 1, VB_MAX-1 ); 1277 VB->Start = VB->Count = 2; 1278 VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1]; 1279 VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1]; 1280 VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]); 1281 break; 1282 default: 1283 /* should never get here */ 1284 gl_problem(ctx, "Bad primitive type in gl_reset_vb()"); 1285 } 1286 } 1287 1288 if (clipOrMask) { 1289 /* reset clip masks to zero */ 1290 MEMSET( VB->ClipMask + VB->Start, 0, 1291 (oldCount - VB->Start) * sizeof(VB->ClipMask[0]) ); 1292 } 1293 1294 if (!monoMaterial) { 1295 /* reset material masks to zero */ 1296 MEMSET( VB->MaterialMask + VB->Start, 0, 1297 (oldCount - VB->Start) * sizeof(VB->MaterialMask[0]) ); 1298 gl_update_lighting(ctx); 1299 } 1300 1301 if (vertexSizeMask!=VERTEX3_BIT) { 1302 /* reset object W coords to one */ 1303 GLint i, n; 1304 GLfloat (*obj)[4] = VB->Obj + VB->Start; 1305 n = oldCount - VB->Start; 1306 for (i=0; i<n; i++) { 1307 obj[i][3] = 1.0F; 1308 } 1309 } 1310 } 1311