[OPENGL32][MESA] Downgrade Mesa library to version 2.6
[reactos.git] / dll / opengl / mesa / vbrender.c
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 }