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 26static void 27FUNC(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 if (prim == PIPE_PRIM_PATCHES) { 44 first = vsplit->draw->pt.vertices_per_patch; 45 incr = vsplit->draw->pt.vertices_per_patch; 46 } else 47 draw_pt_split_prim(prim, &first, &incr); 48 /* sanitize primitive length */ 49 count = draw_pt_trim_count(count, first, incr); 50 if (count < first) 51 return; 52 53 /* try flushing the entire primitive */ 54 if (PRIMITIVE(start, count)) 55 return; 56 57 /* must be able to at least flush two complete primitives */ 58 assert(max_count_simple >= first + incr && 59 max_count_loop >= first + incr && 60 max_count_fan >= first + incr); 61 62 /* no splitting required */ 63 if (count <= max_count_simple) { 64 SEGMENT_SIMPLE(0x0, start, count); 65 } 66 else { 67 const unsigned rollback = first - incr; 68 unsigned flags = DRAW_SPLIT_AFTER, seg_start = 0, seg_max; 69 70 /* 71 * Both count and seg_max below are explicitly trimmed. Because 72 * 73 * seg_start = N * (seg_max - rollback) = N' * incr, 74 * 75 * we have 76 * 77 * remaining = count - seg_start = first + N'' * incr. 78 * 79 * That is, remaining is implicitly trimmed. 80 */ 81 switch (prim) { 82 case PIPE_PRIM_PATCHES: 83 case PIPE_PRIM_POINTS: 84 case PIPE_PRIM_LINES: 85 case PIPE_PRIM_LINE_STRIP: 86 case PIPE_PRIM_TRIANGLES: 87 case PIPE_PRIM_TRIANGLE_STRIP: 88 case PIPE_PRIM_QUADS: 89 case PIPE_PRIM_QUAD_STRIP: 90 case PIPE_PRIM_LINES_ADJACENCY: 91 case PIPE_PRIM_LINE_STRIP_ADJACENCY: 92 case PIPE_PRIM_TRIANGLES_ADJACENCY: 93 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 94 seg_max = 95 draw_pt_trim_count(MIN2(max_count_simple, count), first, incr); 96 if (prim == PIPE_PRIM_TRIANGLE_STRIP || 97 prim == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY) { 98 /* make sure we flush even number of triangles at a time */ 99 if (seg_max < count && !(((seg_max - first) / incr) & 1)) 100 seg_max -= incr; 101 } 102 103 do { 104 const unsigned remaining = count - seg_start; 105 106 if (remaining > seg_max) { 107 SEGMENT_SIMPLE(flags, start + seg_start, seg_max); 108 seg_start += seg_max - rollback; 109 110 flags |= DRAW_SPLIT_BEFORE; 111 } 112 else { 113 flags &= ~DRAW_SPLIT_AFTER; 114 115 SEGMENT_SIMPLE(flags, start + seg_start, remaining); 116 seg_start += remaining; 117 } 118 } while (seg_start < count); 119 break; 120 121 case PIPE_PRIM_LINE_LOOP: 122 seg_max = 123 draw_pt_trim_count(MIN2(max_count_loop, count), first, incr); 124 125 do { 126 const unsigned remaining = count - seg_start; 127 128 if (remaining > seg_max) { 129 SEGMENT_LOOP(flags, start + seg_start, seg_max, start); 130 seg_start += seg_max - rollback; 131 132 flags |= DRAW_SPLIT_BEFORE; 133 } 134 else { 135 flags &= ~DRAW_SPLIT_AFTER; 136 137 SEGMENT_LOOP(flags, start + seg_start, remaining, start); 138 seg_start += remaining; 139 } 140 } while (seg_start < count); 141 break; 142 143 case PIPE_PRIM_TRIANGLE_FAN: 144 case PIPE_PRIM_POLYGON: 145 seg_max = 146 draw_pt_trim_count(MIN2(max_count_fan, count), first, incr); 147 148 do { 149 const unsigned remaining = count - seg_start; 150 151 if (remaining > seg_max) { 152 SEGMENT_FAN(flags, start + seg_start, seg_max, start); 153 seg_start += seg_max - rollback; 154 155 flags |= DRAW_SPLIT_BEFORE; 156 } 157 else { 158 flags &= ~DRAW_SPLIT_AFTER; 159 160 SEGMENT_FAN(flags, start + seg_start, remaining, start); 161 seg_start += remaining; 162 } 163 } while (seg_start < count); 164 break; 165 166 default: 167 assert(0); 168 break; 169 } 170 } 171} 172 173#undef FUNC 174#undef FUNC_VARS 175#undef LOCAL_VARS 176 177#undef PRIMITIVE 178#undef SEGMENT_SIMPLE 179#undef SEGMENT_LOOP 180#undef SEGMENT_FAN 181