source: trunk/src/opengl/mesa/vbcull.c@ 3721

Last change on this file since 3721 was 3598, checked in by jeroen, 25 years ago

* empty log message *

File size: 29.9 KB
Line 
1/* $Id: vbcull.c,v 1.3 2000-05-23 20:41:01 jeroen Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27/*
28 * New (3.1) transformation code written by Keith Whitwell.
29 */
30
31
32#ifdef PC_HEADER
33#include "all.h"
34#else
35#include "glheader.h"
36#include "types.h"
37#include "context.h"
38#include "macros.h"
39#include "vb.h"
40#include "vbcull.h"
41#include "vbrender.h"
42#include "xform.h"
43#include "mem.h"
44#endif
45
46
47/* Culling for vertices and primitives.
48 * (C) Keith Whitwell, December 1998.
49 *
50 * These functions build bitmasks which can be used to shortcircuit
51 * lighting, fogging and texture calculations, and to convert
52 * two-sided lighting into one-sided on a per-vertex basis.
53 *
54 * Each of these functions returns a value 'cullcount'. The meaning
55 * of this value just has to satisfy the requirements:
56 *
57 * cullcount == VB->Count implies the entire vb has been culled and
58 * can be discarded.
59 *
60 * cullcount == 0 implies that every vertex in the buffer is required
61 * and that the cullmask can be ignored for transformation
62 * and lighting.
63 *
64 */
65
66
67const char *gl_prim_name[GL_POLYGON+2] = {
68 "GL_POINTS",
69 "GL_LINES",
70 "GL_LINE_LOOP",
71 "GL_LINE_STRIP",
72 "GL_TRIANGLES",
73 "GL_TRIANGLE_STRIP",
74 "GL_TRIANGLE_FAN",
75 "GL_QUADS",
76 "GL_QUAD_STRIP",
77 "GL_POLYGON",
78 "culled primitive"
79};
80
81static GLuint gl_cull_points( struct vertex_buffer *VB,
82 GLuint start,
83 GLuint count,
84 GLuint parity,
85 CONST GLfloat (*proj)[4])
86{
87 const GLubyte *clipmask = VB->ClipMask;
88 GLubyte *cullmask = VB->CullMask;
89 GLuint i, cullcount = 0;
90
91 (void) parity;
92 (void) proj;
93
94 /* This is pretty pointless. (arf arf)
95 */
96 for (i=start+1;i<count;i++) {
97 if (clipmask[i] == 0)
98 cullmask[i] = VERT_FACE_FRONT | PRIM_FACE_FRONT;
99 else {
100 cullcount++;
101 }
102 }
103 return cullcount;
104}
105
106
107/* Covers all the non-polygonal primitives when only area culling is
108 * activated.
109 */
110static GLuint gl_cull_points_neither( struct vertex_buffer *VB,
111 GLuint start,
112 GLuint count,
113 GLuint parity,
114 CONST GLfloat (*proj)[4])
115{
116 GLubyte unculled_prim = VERT_FACE_FRONT|PRIM_FACE_FRONT;
117 (void) parity;
118 (void) proj;
119 MEMSET(VB->CullMask+start, unculled_prim, (count-start)*sizeof(GLubyte));
120 return 0;
121}
122
123
124
125#define CULL_LINE( i1, i, nr ) \
126do { \
127 GLubyte ClipOr = VB->ClipMask[i1] | VB->ClipMask[i]; \
128 \
129 if (ClipOr) { \
130 if (VB->ClipMask[i1] & VB->ClipMask[i] & CLIP_ALL_BITS) { \
131 cullcount+=nr; \
132 } \
133 else { \
134 cullmask[i1] |= VERT_FACE_FRONT; \
135 cullmask[i] |= VERT_FACE_FRONT | PRIM_FACE_FRONT | PRIM_CLIPPED; \
136 } \
137 } else { \
138 cullmask[i1] |= VERT_FACE_FRONT; \
139 cullmask[i] |= VERT_FACE_FRONT | PRIM_FACE_FRONT; \
140 } \
141} while (0)
142
143
144
145static GLuint gl_cull_lines( struct vertex_buffer *VB,
146 GLuint start,
147 GLuint count,
148 GLuint parity,
149 CONST GLfloat (*proj)[4])
150{
151 GLubyte *cullmask = VB->CullMask;
152 GLuint cullcount = 0;
153 GLuint i;
154 GLuint last = count - 1;
155
156 (void) parity;
157 (void) proj;
158
159 for (i = start; i < last ; i += 2) {
160 CULL_LINE(i, i+1, 2);
161 }
162
163 if (i != last)
164 cullcount++;
165
166 return cullcount;
167}
168
169
170static GLuint gl_cull_line_strip( struct vertex_buffer *VB,
171 GLuint start,
172 GLuint count,
173 GLuint parity,
174 CONST GLfloat (*proj)[4])
175{
176 GLubyte *cullmask = VB->CullMask;
177 GLuint cullcount = 0;
178 GLuint i;
179 GLuint last = count - 1;
180 GLuint nr = 2;
181
182 (void) parity;
183 (void) proj;
184
185 for (i = start; i < last ; i++, nr = 1) {
186 CULL_LINE(i, i+1, nr);
187 }
188
189 if (i != last)
190 cullcount++;
191
192 return cullcount;
193}
194
195
196static GLuint gl_cull_line_loop( struct vertex_buffer *VB,
197 GLuint start,
198 GLuint count,
199 GLuint parity,
200 CONST GLfloat (*proj)[4])
201{
202 GLuint cullcount = 0;
203 GLubyte *cullmask = VB->CullMask;
204 GLuint i, last = count - 1;
205 (void) parity;
206 (void) proj;
207 if (count - start < 2)
208 return count - start;
209
210 for (i = start; i < last ; i++) {
211 CULL_LINE(i, i+1, 1);
212 }
213
214 CULL_LINE(last, start, 1);
215
216 return cullcount;
217}
218
219
220#define CULL_TRI( do_clip, do_area, i2, i1, i0, parity, nr ) \
221do { \
222 GLubyte ClipOr = 0; \
223 if (do_clip) { \
224 ClipOr = (VB->ClipMask[i2] | \
225 VB->ClipMask[i1] | \
226 VB->ClipMask[i0]); \
227 } \
228 \
229 if (do_clip && (ClipOr&CLIP_ALL_BITS)) \
230 { \
231 if (VB->ClipMask[i2] & VB->ClipMask[i1] & VB->ClipMask[i0] & \
232 CLIP_ALL_BITS) \
233 { \
234 cullcount+=nr; \
235 } \
236 else \
237 { \
238 cullmask[i0] = cull_faces | PRIM_CLIPPED; \
239 cullmask[i1] |= cull_faces; \
240 cullmask[i2] |= cull_faces; \
241 } \
242 } \
243 else \
244 { \
245 GLfloat area; \
246 GLubyte face_flags; \
247 \
248 if (do_area) { \
249 area = ((proj[i2][0] - proj[i0][0]) * \
250 (proj[i1][1] - proj[i0][1]) - \
251 (proj[i2][1] - proj[i0][1]) * \
252 (proj[i1][0] - proj[i0][0])); \
253 \
254 face_flags = (((area<0.0F) ^ parity) + 1) & cull_faces; \
255 } else { \
256 face_flags = cull_faces; \
257 } \
258 \
259 if (!do_area || face_flags) \
260 { \
261 cullmask[i0] = face_flags | (face_flags << PRIM_FLAG_SHIFT); \
262 cullmask[i1] |= face_flags; \
263 cullmask[i2] |= face_flags; \
264 if (do_clip && ClipOr) cullmask[i0] |= PRIM_CLIPPED; \
265 } \
266 else \
267 { \
268 cullcount+=nr; \
269 } \
270 } \
271} while (0)
272
273
274
275
276
277#define CULL_QUAD( do_clip, do_area, i3, i2, i1, i, nr ) \
278do { \
279 GLubyte ClipOr = 0; \
280 \
281 if (do_clip) { \
282 ClipOr = (VB->ClipMask[i3] | \
283 VB->ClipMask[i2] | \
284 VB->ClipMask[i1] | \
285 VB->ClipMask[i]); \
286 } \
287 \
288 if (do_clip && (ClipOr&CLIP_ALL_BITS)) \
289 { \
290 if (VB->ClipMask[i3] & VB->ClipMask[i2] & \
291 VB->ClipMask[i1] & VB->ClipMask[i] & \
292 CLIP_ALL_BITS) \
293 { \
294 cullcount+=nr; \
295 } \
296 else \
297 { \
298 cullmask[i] = cull_faces | PRIM_CLIPPED; \
299 cullmask[i1] = cull_faces | PRIM_CLIPPED; \
300 cullmask[i2] |= cull_faces; \
301 cullmask[i3] |= cull_faces; \
302 } \
303 } \
304 else \
305 { \
306 GLfloat area; \
307 GLubyte face_flags; \
308 \
309 if (do_area) { \
310 area = ((proj[i1][0] - proj[i3][0]) * /* ex */ \
311 (proj[i ][1] - proj[i2][1]) - /* fy */ \
312 (proj[i1][1] - proj[i3][1]) * /* ey */ \
313 (proj[i ][0] - proj[i2][0])); /* fx */ \
314 \
315 face_flags = (((area<0.0F) ^ face_bit) + 1) & cull_faces; \
316 } else { \
317 face_flags = cull_faces; \
318 } \
319 \
320 if (do_area && !face_flags) \
321 { \
322 cullcount+=nr; \
323 } \
324 else \
325 { \
326 cullmask[i] = face_flags | (face_flags<<PRIM_FLAG_SHIFT); \
327 cullmask[i1] = face_flags | (face_flags<<PRIM_FLAG_SHIFT); \
328 cullmask[i2] |= face_flags; \
329 cullmask[i3] |= face_flags; \
330 if (ClipOr) \
331 cullmask[i] |= PRIM_CLIPPED; \
332 } \
333 } \
334} while(0)
335
336
337#define DO_AREA 1
338#define DO_CLIP 1
339#define TAG(x) x
340#include "cull_tmp.h"
341
342
343#define DO_AREA 1
344#define DO_CLIP 0
345#define TAG(x) x##_area
346#include "cull_tmp.h"
347
348#define DO_AREA 0
349#define DO_CLIP 1
350#define TAG(x) x##_clip
351#include "cull_tmp.h"
352
353
354
355static GLuint gl_cull_dummy_prim( struct vertex_buffer *VB,
356 GLuint start,
357 GLuint count,
358 GLuint parity,
359 CONST GLfloat (*proj)[4])
360{
361 (void) VB;
362 (void) parity;
363 (void) proj;
364 return count - start;
365}
366
367
368/* KW: Force the vertices which are used in both this and the
369 * next vertex buffer to be fully transformed on their first
370 * appearance. Need to do this because otherwise I would have
371 * to try to copy the un-transformed (Obj, Normal) data. This
372 * is difficult in the case of shared normals, and seems
373 * to be quite complex in the immediate mode case. For now,
374 * just force the copied vertices to be transformed.
375 *
376 * KW: Copy now organized to grow towards zero.
377 */
378static GLuint gl_copy_last_cull( struct vertex_buffer *VB,
379 GLuint start, GLuint count,
380 GLuint ovf, CONST GLfloat (*proj)[4])
381{
382 const GLcontext *ctx = VB->ctx;
383 GLubyte *cullmask = VB->CullMask;
384 GLuint rv = 0;
385 (void) start;
386 (void) ovf;
387 if (cullmask[count-1] == 0) {
388 rv++;
389 cullmask[count-1] = ctx->Polygon.CullBits;
390 }
391 VB->CopyCount = 1;
392 VB->Copy[2] = count-1;
393 COPY_4FV(VB->CopyProj[2], proj[count-1]);
394 return rv;
395}
396
397static GLuint gl_copy_first_and_last_cull( struct vertex_buffer *VB,
398 GLuint start,
399 GLuint count, GLuint ovf,
400 CONST GLfloat (*proj)[4] )
401{
402 const GLcontext *ctx = VB->ctx;
403 GLuint rv = 0;
404 GLubyte *cullmask = VB->CullMask;
405 (void) ovf;
406 if (cullmask[count-1] == 0) {
407 rv++;
408 cullmask[count-1] = ctx->Polygon.CullBits;
409 }
410 if (cullmask[start] == 0) {
411 rv++;
412 cullmask[start] = ctx->Polygon.CullBits;
413 }
414 VB->CopyCount = 2;
415 VB->Copy[1] = start;
416 VB->Copy[2] = count-1;
417 COPY_4FV(VB->CopyProj[1], proj[start]);
418 COPY_4FV(VB->CopyProj[2], proj[count-1]);
419 return rv;
420}
421
422/* Must be able to cope with zero or one overflow
423 *
424 */
425static GLuint gl_copy_last_two_cull( struct vertex_buffer *VB,
426 GLuint start,
427 GLuint count, GLuint ovf,
428 CONST GLfloat (*proj)[4] )
429{
430 const GLcontext *ctx = VB->ctx;
431 GLubyte *cullmask = VB->CullMask;
432 GLuint rv = 0;
433 (void) start;
434 if (cullmask[count-1] == 0) {
435 rv++;
436 cullmask[count-1] = ctx->Polygon.CullBits;
437 }
438 if (cullmask[count-2] == 0) {
439 rv++;
440 cullmask[count-2] = ctx->Polygon.CullBits;
441 }
442
443 VB->CopyCount = 2;
444 VB->Copy[1] = count-2;
445 VB->Copy[2] = count-1;
446 COPY_4FV(VB->CopyProj[1], proj[count-2]);
447 COPY_4FV(VB->CopyProj[2], proj[count-1]);
448
449 if (ovf == 1) {
450 if (cullmask[count-3] == 0) {
451 rv++;
452 cullmask[count-3] = ctx->Polygon.CullBits;
453 }
454 VB->CopyCount = 3;
455 VB->Copy[0] = count-3;
456 COPY_4FV(VB->CopyProj[0], proj[count-3]);
457 }
458
459 return rv;
460}
461
462
463/* Eg, quads - just copy the overflow, guarenteed to all be culled.
464 */
465static GLuint gl_copy_overflow_cull( struct vertex_buffer *VB,
466 GLuint start, GLuint count,
467 GLuint ovf, CONST GLfloat (*proj)[4] )
468{
469 const GLcontext *ctx = VB->ctx;
470 GLubyte *cullmask = VB->CullMask;
471 GLuint src_offset = count - ovf;
472 GLuint dst_offset = 3 - ovf;
473 GLuint i;
474 (void) start;
475 VB->CopyCount = ovf;
476 for (i = 0 ; i < ovf ; i++) {
477 cullmask[i+src_offset] = ctx->Polygon.CullBits;
478 VB->Copy[i+dst_offset] = i+src_offset;
479 COPY_4FV(VB->CopyProj[i+dst_offset], proj[i+src_offset]);
480 }
481 return ovf;
482}
483
484
485static GLuint gl_copy_last( struct vertex_buffer *VB,
486 GLuint start, GLuint count,
487 GLuint ovf, CONST GLfloat (*proj)[4])
488{
489 (void) start;
490 (void) ovf;
491 VB->CopyCount = 1;
492 VB->Copy[2] = count-1;
493 COPY_4FV(VB->CopyProj[2], proj[count-1]);
494 return 0;
495}
496
497static GLuint gl_copy_first_and_last( struct vertex_buffer *VB,
498 GLuint start,
499 GLuint count,
500 GLuint ovf, CONST GLfloat (*proj)[4])
501{
502 (void) ovf;
503 VB->CopyCount = 2;
504 VB->Copy[1] = start;
505 VB->Copy[2] = count-1;
506 COPY_4FV(VB->CopyProj[1], proj[start]);
507 COPY_4FV(VB->CopyProj[2], proj[count-1]);
508 return 0;
509}
510
511static GLuint gl_copy_last_two( struct vertex_buffer *VB,
512 GLuint start, GLuint count,
513 GLuint ovf, CONST GLfloat (*proj)[4])
514{
515 (void) start;
516 VB->CopyCount = 2;
517 VB->Copy[1] = count-2;
518 VB->Copy[2] = count-1;
519 COPY_4FV(VB->CopyProj[1], proj[count-2]);
520 COPY_4FV(VB->CopyProj[2], proj[count-1]);
521
522 if (ovf == 1) {
523 VB->CopyCount = 3;
524 VB->Copy[0] = count-3;
525 COPY_4FV(VB->CopyProj[0], proj[count-3]);
526 }
527
528 return 0;
529}
530
531static GLuint gl_copy_overflow( struct vertex_buffer *VB,
532 GLuint start,
533 GLuint count,
534 GLuint ovf,
535 CONST GLfloat (*proj)[4] )
536{
537 GLuint src_offset = count - ovf;
538 GLuint dst_offset = 3 - ovf;
539 GLuint i;
540 (void) start;
541 VB->CopyCount = ovf;
542 for (i = 0 ; i < ovf ; i++) {
543 VB->Copy[i+dst_offset] = i+src_offset;
544 COPY_4FV(VB->CopyProj[i+dst_offset], proj[i+src_offset]);
545 }
546
547 return 0;
548}
549
550
551
552
553
554
555static void gl_fast_copy_noop( struct vertex_buffer *VB,
556 GLuint start, GLuint count,
557 GLuint ovf)
558{
559 (void) start;
560 (void) ovf;
561 (void) VB;
562 (void) count;
563}
564
565static void gl_fast_copy_last( struct vertex_buffer *VB,
566 GLuint start, GLuint count,
567 GLuint ovf)
568{
569 (void) start;
570 (void) ovf;
571 VB->CopyCount = 1;
572 VB->Copy[2] = count-1;
573}
574
575static void gl_fast_copy_first_and_last( struct vertex_buffer *VB,
576 GLuint start,
577 GLuint count,
578 GLuint ovf)
579{
580 (void) ovf;
581 VB->CopyCount = 2;
582 VB->Copy[1] = start;
583 VB->Copy[2] = count-1;
584}
585
586static void gl_fast_copy_last_two( struct vertex_buffer *VB,
587 GLuint start, GLuint count,
588 GLuint ovf )
589{
590 (void) start;
591 VB->CopyCount = 2;
592 VB->Copy[1] = count-2;
593 VB->Copy[2] = count-1;
594
595 if (ovf == 1) {
596 VB->CopyCount = 3;
597 VB->Copy[0] = count-3;
598 }
599}
600
601static void gl_fast_copy_overflow( struct vertex_buffer *VB,
602 GLuint start,
603 GLuint count,
604 GLuint ovf )
605{
606 GLuint src_offset = count - ovf;
607 GLuint dst_offset = 3 - ovf;
608 GLuint i;
609 (void) start;
610 VB->CopyCount = ovf;
611 for (i = 0 ; i < ovf ; i++)
612 VB->Copy[i+dst_offset] = i+src_offset;
613}
614
615
616typedef void (*fast_copy_func)( struct vertex_buffer *VB,
617 GLuint start,
618 GLuint count,
619 GLuint ovf );
620
621
622
623
624typedef GLuint (*cull_func)( struct vertex_buffer *VB,
625 GLuint start,
626 GLuint count,
627 GLuint parity,
628 CONST GLfloat (*proj)[4]);
629
630
631typedef GLuint (*copy_func)( struct vertex_buffer *VB,
632 GLuint start,
633 GLuint end,
634 GLuint ovf,
635 CONST GLfloat (*proj)[4] );
636
637
638
639static cull_func cull_tab_both[GL_POLYGON+2] =
640{
641 gl_cull_points,
642 gl_cull_lines,
643 gl_cull_line_loop,
644 gl_cull_line_strip,
645 gl_cull_triangles,
646 gl_cull_triangle_strip,
647 gl_cull_triangle_fan,
648 gl_cull_quads,
649 gl_cull_quad_strip,
650 gl_cull_triangle_fan,
651 gl_cull_dummy_prim
652};
653
654static cull_func cull_tab_area[GL_POLYGON+2] =
655{
656 gl_cull_points_neither,
657 gl_cull_points_neither,
658 gl_cull_points_neither,
659 gl_cull_points_neither,
660 gl_cull_triangles_area,
661 gl_cull_triangle_strip_area,
662 gl_cull_triangle_fan_area,
663 gl_cull_quads_area,
664 gl_cull_quad_strip_area,
665 gl_cull_triangle_fan_area,
666 gl_cull_dummy_prim
667};
668
669static cull_func cull_tab_clip[GL_POLYGON+2] =
670{
671 gl_cull_points,
672 gl_cull_lines,
673 gl_cull_line_loop,
674 gl_cull_line_strip,
675 gl_cull_triangles_clip,
676 gl_cull_triangle_strip_clip,
677 gl_cull_triangle_fan_clip,
678 gl_cull_quads_clip,
679 gl_cull_quad_strip_clip,
680 gl_cull_triangle_fan_clip,
681 gl_cull_dummy_prim
682};
683
684static cull_func *cull_tab[4] =
685{
686 0,
687 cull_tab_area,
688 cull_tab_clip,
689 cull_tab_both
690};
691
692
693static copy_func copy_tab_cull[GL_POLYGON+2] =
694{
695 0,
696 gl_copy_overflow_cull,
697 gl_copy_first_and_last_cull,
698 gl_copy_last_cull,
699 gl_copy_overflow_cull,
700 gl_copy_last_two_cull,
701 gl_copy_first_and_last_cull,
702 gl_copy_overflow_cull,
703 gl_copy_last_two_cull,
704 gl_copy_first_and_last_cull,
705 0,
706};
707
708
709static copy_func copy_tab_no_cull[GL_POLYGON+2] =
710{
711 0,
712 gl_copy_overflow,
713 gl_copy_first_and_last,
714 gl_copy_last,
715 gl_copy_overflow,
716 gl_copy_last_two,
717 gl_copy_first_and_last,
718 gl_copy_overflow,
719 gl_copy_last_two,
720 gl_copy_first_and_last,
721 0,
722};
723
724
725static fast_copy_func fast_copy_tab[GL_POLYGON+2] =
726{
727 gl_fast_copy_noop,
728 gl_fast_copy_overflow,
729 gl_fast_copy_first_and_last,
730 gl_fast_copy_last,
731 gl_fast_copy_overflow,
732 gl_fast_copy_last_two,
733 gl_fast_copy_first_and_last,
734 gl_fast_copy_overflow,
735 gl_fast_copy_last_two,
736 gl_fast_copy_first_and_last,
737 gl_fast_copy_noop,
738};
739
740
741
742
743
744/* Do this after (?) primitive fixup on buffers containing unwanted
745 * eval coords. No early culling will be done on these vertices (it's
746 * a degenerate case & not worth the code), and the vertices will be
747 * rendered by a special 'indirect' case in gl_render_vb. Otherwise,
748 * the cullmask will force (some) transforms to skip these vertices.
749 */
750void gl_purge_vertices( struct vertex_buffer *VB )
751{
752 GLuint *flags = VB->Flag;
753 GLubyte *cullmask = VB->CullMask;
754 GLuint *indirect = VB->Indirect = VB->EltPtr->start;
755 GLuint *in_prim = VB->Primitive;
756 GLuint *out_prim = VB->IM->Primitive;
757 GLuint *in_nextprim = VB->NextPrimitive;
758 GLuint *out_nextprim = VB->IM->NextPrimitive;
759 GLuint count = VB->Count;
760 GLuint purge = VB->PurgeFlags;
761 GLuint next, start;
762 GLuint j;
763
764 /*
765 */
766 for ( j = start = VB->CopyStart ; start < count ; start = next ) {
767 GLuint startj = j;
768 GLuint i;
769
770 next = in_nextprim[start];
771 out_prim[j] = in_prim[start];
772
773 for ( i = start ; i < next ; i++) {
774 if (~(flags[i] & purge)) {
775 indirect[j] = i;
776 cullmask[i] = PRIM_CLIPPED; /* nonzero */
777 j++;
778 }
779
780 }
781
782 out_nextprim[startj] = j;
783 }
784
785 VB->Primitive = out_prim;
786 VB->NextPrimitive = out_nextprim;
787 VB->IndirectCount = j;
788}
789
790#define VERT_NOT_CLIPPED 0x80
791
792static void build_clip_vert_bits( GLubyte *clipmask, const GLubyte *cullmask,
793 GLuint count )
794{
795 GLuint i = 0;
796 for (;;)
797 if (cullmask[++i]==0) {
798 clipmask[i] |= CLIP_CULLED_BIT;
799 if (&cullmask[i] == &cullmask[count]) return;
800 }
801}
802
803GLuint gl_cull_vb( struct vertex_buffer *VB )
804{
805 const GLcontext *ctx = VB->ctx;
806 GLuint i, next, prim, n;
807 GLfloat (*proj)[4] = VB->Projected->data;
808 GLuint *in_prim = VB->Primitive;
809 GLuint *out_prim = VB->IM->Primitive;
810 GLuint cullcount = 0;
811 GLuint lastprim = in_prim[VB->LastPrimitive];
812 GLuint first = VB->CopyStart;
813 GLuint parity = VB->Parity;
814 cull_func *cull_funcs;
815 GLuint idx = 0;
816
817 if (VB->CullDone)
818 return 0;
819
820 if (VB->ClipOrMask)
821 idx |= 0x2;
822
823 if (ctx->IndirectTriangles & DD_ANY_CULL)
824 idx |= 0x1;
825
826 cull_funcs = cull_tab[idx];
827
828 for (i = VB->CopyStart ; i < VB->Start ; i++) {
829 COPY_4FV(proj[i], VB->CopyProj[i]);
830 }
831
832 VB->CopyCount = 0;
833
834 MEMSET(VB->CullMask, 0, (VB->Count+1) * sizeof(GLubyte));
835
836 for ( i = VB->CopyStart ; i < VB->Count ; i = next, parity = 0 )
837 {
838 first = i;
839 next = VB->NextPrimitive[i];
840 prim = in_prim[i];
841 n = cull_funcs[prim]( VB, i, next, parity, (const GLfloat (*)[4])proj );
842
843 if (n == next - i)
844 out_prim[i] = GL_POLYGON+1;
845 else
846 out_prim[i] = prim;
847
848 cullcount += n;
849 }
850
851
852 if (VB->LastPrimitive < VB->Count) {
853 if (copy_tab_cull[lastprim])
854 cullcount -= copy_tab_cull[prim]( VB,
855 first,
856 VB->Count,
857 VB->Ovf,
858 (const GLfloat (*)[4])proj );
859 }
860
861 VB->Primitive = out_prim;
862
863 VB->CullFlag[0] = VB->CullFlag[1] = (GLubyte) 0;
864
865 if (cullcount > 0 || (ctx->IndirectTriangles & DD_LIGHTING_CULL)) {
866 VB->CullMode |= CULL_MASK_ACTIVE;
867 VB->CullFlag[0] = VB->CullFlag[1] = CLIP_CULLED_BIT&ctx->AllowVertexCull;
868
869 if (cullcount < VB->Count)
870 build_clip_vert_bits( VB->ClipMask, VB->CullMask, VB->Count );
871
872 }
873 if (VB->ClipOrMask) {
874 VB->CullMode |= CLIP_MASK_ACTIVE;
875 VB->CullFlag[1] |= (CLIP_ALL_BITS|CLIP_USER_BIT) & ctx->AllowVertexCull;
876 }
877
878 VB->CullDone = 1;
879 return cullcount;
880}
881
882
883/* Need to set up to copy some vertices at the end of the buffer, even
884 * if culling is disabled or the entire vb has been culled by clipping.
885 */
886void gl_dont_cull_vb( struct vertex_buffer *VB )
887{
888 GLfloat (*proj)[4] = VB->Projected->data;
889 GLuint i;
890
891 if (VB->CullDone)
892 return;
893
894 for (i = VB->CopyStart ; i < VB->Start ; i++)
895 COPY_4FV(proj[i], VB->CopyProj[i]);
896
897 VB->CopyCount = 0;
898
899 if (VB->LastPrimitive < VB->Count)
900 {
901 GLuint first = VB->LastPrimitive;
902 GLuint prim = VB->Primitive[first];
903
904 if (first == VB_START)
905 first = VB->Start;
906
907 if (copy_tab_no_cull[prim])
908 copy_tab_no_cull[prim]( VB,
909 first,
910 VB->Count,
911 VB->Ovf,
912 (const GLfloat (*)[4])proj );
913 }
914
915 VB->CullDone = 1;
916}
917
918void gl_fast_copy_vb( struct vertex_buffer *VB )
919{
920 VB->CopyCount = 0;
921
922 if (VB->LastPrimitive < VB->Count)
923 {
924 GLuint first = VB->LastPrimitive;
925 GLuint prim = VB->Primitive[first];
926
927 if (first == VB_START)
928 first = VB->Start;
929
930 fast_copy_tab[prim]( VB, first, VB->Count, VB->Ovf );
931 }
932
933 VB->CullDone = 1;
934}
935
936
937
938
939
940void gl_make_normal_cullmask( struct vertex_buffer *VB )
941{
942 GLuint i;
943
944 if (VB->CullMode & COMPACTED_NORMALS) {
945 /* The shared normals case - never for cva.
946 */
947 MEMSET(VB->NormCullMask, 0, VB->Count * sizeof(GLubyte));
948 VB->NormCullStart = VB->NormCullMask + VB->Start;
949
950 if (VB->CullMode & CULL_MASK_ACTIVE) {
951 GLubyte *lastnorm = VB->NormCullStart;
952
953 for (i = VB->Start ;;) {
954 *lastnorm |= VB->CullMask[i];
955 if (VB->Flag[++i] & (VERT_NORM|VERT_END_VB)) {
956 lastnorm = &VB->NormCullMask[i];
957 if (VB->Flag[i] & VERT_END_VB) return;
958 }
959 }
960 } else {
961 VB->NormCullMask[VB->Start] = ~0;
962 for (i = VB->Start ;; )
963 if (VB->Flag[++i] & (VERT_NORM|VERT_END_VB)) {
964 VB->NormCullMask[i] = ~0;
965 if (VB->Flag[i] & VERT_END_VB) return;
966 }
967 }
968 } else {
969 /* Non-shared normals.
970 */
971 VB->NormCullStart = VB->CullMask + VB->Start;
972 }
973}
974
975
976
977
Note: See TracBrowser for help on using the repository browser.