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

Last change on this file since 3582 was 2962, checked in by jeroen, 25 years ago

* empty log message *

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