1/* 2 * Mesa 3-D graphics library 3 * Version: 7.9 4 * 5 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 6 * Copyright (C) 2010 LunarG Inc. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 * DEALINGS IN THE SOFTWARE. 25 */ 26 27static void 28FUNC(FUNC_VARS) 29{ 30 unsigned first, incr; 31 LOCAL_VARS 32 33 /* 34 * prim, start, count, and max_count_{simple,loop,fan} should have been 35 * defined 36 */ 37 if (0) { 38 debug_printf("%s: prim 0x%x, start %d, count %d, max_count_simple %d, " 39 "max_count_loop %d, max_count_fan %d\n", 40 __FUNCTION__, prim, start, count, max_count_simple, 41 max_count_loop, max_count_fan); 42 } 43 44 draw_pt_split_prim(prim, &first, &incr); 45 /* sanitize primitive length */ 46 count = draw_pt_trim_count(count, first, incr); 47 if (count < first) 48 return; 49 50 /* try flushing the entire primitive */ 51 if (PRIMITIVE(start, count)) 52 return; 53 54 /* must be able to at least flush two complete primitives */ 55 assert(max_count_simple >= first + incr && 56 max_count_loop >= first + incr && 57 max_count_fan >= first + incr); 58 59 /* no splitting required */ 60 if (count <= max_count_simple) { 61 SEGMENT_SIMPLE(0x0, start, count); 62 } 63 else { 64 const unsigned rollback = first - incr; 65 unsigned flags = DRAW_SPLIT_AFTER, seg_start = 0, seg_max; 66 67 /* 68 * Both count and seg_max below are explicitly trimmed. Because 69 * 70 * seg_start = N * (seg_max - rollback) = N' * incr, 71 * 72 * we have 73 * 74 * remaining = count - seg_start = first + N'' * incr. 75 * 76 * That is, remaining is implicitly trimmed. 77 */ 78 switch (prim) { 79 case PIPE_PRIM_POINTS: 80 case PIPE_PRIM_LINES: 81 case PIPE_PRIM_LINE_STRIP: 82 case PIPE_PRIM_TRIANGLES: 83 case PIPE_PRIM_TRIANGLE_STRIP: 84 case PIPE_PRIM_QUADS: 85 case PIPE_PRIM_QUAD_STRIP: 86 case PIPE_PRIM_LINES_ADJACENCY: 87 case PIPE_PRIM_LINE_STRIP_ADJACENCY: 88 case PIPE_PRIM_TRIANGLES_ADJACENCY: 89 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 90 seg_max = 91 draw_pt_trim_count(MIN2(max_count_simple, count), first, incr); 92 if (prim == PIPE_PRIM_TRIANGLE_STRIP || 93 prim == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY) { 94 /* make sure we flush even number of triangles at a time */ 95 if (seg_max < count && !(((seg_max - first) / incr) & 1)) 96 seg_max -= incr; 97 } 98 99 do { 100 const unsigned remaining = count - seg_start; 101 102 if (remaining > seg_max) { 103 SEGMENT_SIMPLE(flags, start + seg_start, seg_max); 104 seg_start += seg_max - rollback; 105 106 flags |= DRAW_SPLIT_BEFORE; 107 } 108 else { 109 flags &= ~DRAW_SPLIT_AFTER; 110 111 SEGMENT_SIMPLE(flags, start + seg_start, remaining); 112 seg_start += remaining; 113 } 114 } while (seg_start < count); 115 break; 116 117 case PIPE_PRIM_LINE_LOOP: 118 seg_max = 119 draw_pt_trim_count(MIN2(max_count_loop, count), first, incr); 120 121 do { 122 const unsigned remaining = count - seg_start; 123 124 if (remaining > seg_max) { 125 SEGMENT_LOOP(flags, start + seg_start, seg_max, start); 126 seg_start += seg_max - rollback; 127 128 flags |= DRAW_SPLIT_BEFORE; 129 } 130 else { 131 flags &= ~DRAW_SPLIT_AFTER; 132 133 SEGMENT_LOOP(flags, start + seg_start, remaining, start); 134 seg_start += remaining; 135 } 136 } while (seg_start < count); 137 break; 138 139 case PIPE_PRIM_TRIANGLE_FAN: 140 case PIPE_PRIM_POLYGON: 141 seg_max = 142 draw_pt_trim_count(MIN2(max_count_fan, count), first, incr); 143 144 do { 145 const unsigned remaining = count - seg_start; 146 147 if (remaining > seg_max) { 148 SEGMENT_FAN(flags, start + seg_start, seg_max, start); 149 seg_start += seg_max - rollback; 150 151 flags |= DRAW_SPLIT_BEFORE; 152 } 153 else { 154 flags &= ~DRAW_SPLIT_AFTER; 155 156 SEGMENT_FAN(flags, start + seg_start, remaining, start); 157 seg_start += remaining; 158 } 159 } while (seg_start < count); 160 break; 161 162 default: 163 assert(0); 164 break; 165 } 166 } 167} 168 169#undef FUNC 170#undef FUNC_VARS 171#undef LOCAL_VARS 172 173#undef PRIMITIVE 174#undef SEGMENT_SIMPLE 175#undef SEGMENT_LOOP 176#undef SEGMENT_FAN 177