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