draw_pt_vsplit_tmp.h revision a072f0e186522f9de2848989422ad0244f65c961
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.9 4 * 5 * Copyright 2007-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 27#define CONCAT2(name, elt_type) name ## elt_type 28#define CONCAT(name, elt_type) CONCAT2(name, elt_type) 29 30#ifdef ELT_TYPE 31 32/** 33 * Fetch all elements in [min_index, max_index] with bias, and use the 34 * (rebased) index buffer as the draw elements. 35 */ 36static boolean 37CONCAT(vsplit_primitive_, ELT_TYPE)(struct vsplit_frontend *vsplit, 38 unsigned istart, unsigned icount) 39{ 40 struct draw_context *draw = vsplit->draw; 41 const ELT_TYPE *ib = (const ELT_TYPE *) draw->pt.user.elts; 42 const unsigned min_index = draw->pt.user.min_index; 43 const unsigned max_index = draw->pt.user.max_index; 44 const int elt_bias = draw->pt.user.eltBias; 45 unsigned fetch_start, fetch_count; 46 const ushort *draw_elts = NULL; 47 unsigned i; 48 49 /* use the ib directly */ 50 if (min_index == 0 && sizeof(ib[0]) == sizeof(draw_elts[0])) { 51 if (icount > vsplit->max_vertices) 52 return FALSE; 53 54 for (i = 0; i < icount; i++) { 55 ELT_TYPE idx = ib[istart + i]; 56 assert(idx >= min_index && idx <= max_index); 57 } 58 draw_elts = (const ushort *) ib; 59 } 60 else { 61 /* have to go through vsplit->draw_elts */ 62 if (icount > vsplit->segment_size) 63 return FALSE; 64 } 65 66 /* this is faster only when we fetch less elements than the normal path */ 67 if (max_index - min_index > icount - 1) 68 return FALSE; 69 70 if (elt_bias < 0 && min_index < -elt_bias) 71 return FALSE; 72 73 /* why this check? */ 74 for (i = 0; i < draw->pt.nr_vertex_elements; i++) { 75 if (draw->pt.vertex_element[i].instance_divisor) 76 return FALSE; 77 } 78 79 fetch_start = min_index + elt_bias; 80 fetch_count = max_index - min_index + 1; 81 82 if (!draw_elts) { 83 if (min_index == 0) { 84 for (i = 0; i < icount; i++) { 85 ELT_TYPE idx = ib[istart + i]; 86 87 assert(idx >= min_index && idx <= max_index); 88 vsplit->draw_elts[i] = (ushort) idx; 89 } 90 } 91 else { 92 for (i = 0; i < icount; i++) { 93 ELT_TYPE idx = ib[istart + i]; 94 95 assert(idx >= min_index && idx <= max_index); 96 vsplit->draw_elts[i] = (ushort) (idx - min_index); 97 } 98 } 99 100 draw_elts = vsplit->draw_elts; 101 } 102 103 return vsplit->middle->run_linear_elts(vsplit->middle, 104 fetch_start, fetch_count, 105 draw_elts, icount, 0x0); 106} 107 108/** 109 * Use the cache to prepare the fetch and draw elements, and flush. 110 * 111 * When spoken is TRUE, ispoken replaces istart; When close is TRUE, iclose is 112 * appended. 113 */ 114static INLINE void 115CONCAT(vsplit_segment_cache_, ELT_TYPE)(struct vsplit_frontend *vsplit, 116 unsigned flags, 117 unsigned istart, unsigned icount, 118 boolean spoken, unsigned ispoken, 119 boolean close, unsigned iclose) 120{ 121 struct draw_context *draw = vsplit->draw; 122 const ELT_TYPE *ib = (const ELT_TYPE *) draw->pt.user.elts; 123 const int ibias = draw->pt.user.eltBias; 124 unsigned i; 125 126 assert(icount + !!close <= vsplit->segment_size); 127 128 vsplit_clear_cache(vsplit); 129 130 spoken = !!spoken; 131 if (ibias == 0) { 132 if (spoken) 133 ADD_CACHE(vsplit, ib[ispoken]); 134 135 for (i = spoken; i < icount; i++) 136 ADD_CACHE(vsplit, ib[istart + i]); 137 138 if (close) 139 ADD_CACHE(vsplit, ib[iclose]); 140 } 141 else if (ibias > 0) { 142 if (spoken) 143 ADD_CACHE(vsplit, (uint) ib[ispoken] + ibias); 144 145 for (i = spoken; i < icount; i++) 146 ADD_CACHE(vsplit, (uint) ib[istart + i] + ibias); 147 148 if (close) 149 ADD_CACHE(vsplit, (uint) ib[iclose] + ibias); 150 } 151 else { 152 if (spoken) { 153 if (ib[ispoken] < -ibias) 154 return; 155 ADD_CACHE(vsplit, ib[ispoken] + ibias); 156 } 157 158 for (i = spoken; i < icount; i++) { 159 if (ib[istart + i] < -ibias) 160 return; 161 ADD_CACHE(vsplit, ib[istart + i] + ibias); 162 } 163 164 if (close) { 165 if (ib[iclose] < -ibias) 166 return; 167 ADD_CACHE(vsplit, ib[iclose] + ibias); 168 } 169 } 170 171 vsplit_flush_cache(vsplit, flags); 172} 173 174static void 175CONCAT(vsplit_segment_simple_, ELT_TYPE)(struct vsplit_frontend *vsplit, 176 unsigned flags, 177 unsigned istart, 178 unsigned icount) 179{ 180 CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit, 181 flags, istart, icount, FALSE, 0, FALSE, 0); 182} 183 184static void 185CONCAT(vsplit_segment_loop_, ELT_TYPE)(struct vsplit_frontend *vsplit, 186 unsigned flags, 187 unsigned istart, 188 unsigned icount, 189 unsigned i0) 190{ 191 const boolean close_loop = ((flags) == DRAW_SPLIT_BEFORE); 192 193 CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit, 194 flags, istart, icount, FALSE, 0, close_loop, i0); 195} 196 197static void 198CONCAT(vsplit_segment_fan_, ELT_TYPE)(struct vsplit_frontend *vsplit, 199 unsigned flags, 200 unsigned istart, 201 unsigned icount, 202 unsigned i0) 203{ 204 const boolean use_spoken = (((flags) & DRAW_SPLIT_BEFORE) != 0); 205 206 CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit, 207 flags, istart, icount, use_spoken, i0, FALSE, 0); 208} 209 210#define LOCAL_VARS \ 211 struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend; \ 212 const unsigned prim = vsplit->prim; \ 213 const unsigned max_count_simple = vsplit->segment_size; \ 214 const unsigned max_count_loop = vsplit->segment_size - 1; \ 215 const unsigned max_count_fan = vsplit->segment_size; 216 217#define PRIMITIVE(istart, icount) \ 218 CONCAT(vsplit_primitive_, ELT_TYPE)(vsplit, istart, icount) 219 220#else /* ELT_TYPE */ 221 222static void 223vsplit_segment_simple_linear(struct vsplit_frontend *vsplit, unsigned flags, 224 unsigned istart, unsigned icount) 225{ 226 assert(icount <= vsplit->max_vertices); 227 vsplit->middle->run_linear(vsplit->middle, istart, icount, flags); 228} 229 230static void 231vsplit_segment_loop_linear(struct vsplit_frontend *vsplit, unsigned flags, 232 unsigned istart, unsigned icount, unsigned i0) 233{ 234 boolean close_loop = (flags == DRAW_SPLIT_BEFORE); 235 unsigned nr; 236 237 assert(icount + !!close_loop <= vsplit->segment_size); 238 239 if (close_loop) { 240 for (nr = 0; nr < icount; nr++) 241 vsplit->fetch_elts[nr] = istart + nr; 242 vsplit->fetch_elts[nr++] = i0; 243 244 vsplit->middle->run(vsplit->middle, vsplit->fetch_elts, nr, 245 vsplit->identity_draw_elts, nr, flags); 246 } 247 else { 248 vsplit->middle->run_linear(vsplit->middle, istart, icount, flags); 249 } 250} 251 252static void 253vsplit_segment_fan_linear(struct vsplit_frontend *vsplit, unsigned flags, 254 unsigned istart, unsigned icount, unsigned i0) 255{ 256 boolean use_spoken = ((flags & DRAW_SPLIT_BEFORE) != 0); 257 unsigned nr = 0, i; 258 259 assert(icount + !!use_spoken <= vsplit->segment_size); 260 261 if (use_spoken) { 262 vsplit->fetch_elts[nr++] = i0; 263 for (i = 1 ; i < icount; i++) 264 vsplit->fetch_elts[nr++] = istart + i; 265 266 vsplit->middle->run(vsplit->middle, vsplit->fetch_elts, nr, 267 vsplit->identity_draw_elts, nr, flags); 268 } 269 else { 270 vsplit->middle->run_linear(vsplit->middle, istart, icount, flags); 271 } 272} 273 274#define LOCAL_VARS \ 275 struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend; \ 276 const unsigned prim = vsplit->prim; \ 277 const unsigned max_count_simple = vsplit->max_vertices; \ 278 const unsigned max_count_loop = vsplit->segment_size - 1; \ 279 const unsigned max_count_fan = vsplit->segment_size; 280 281#define PRIMITIVE(istart, icount) FALSE 282 283#define ELT_TYPE linear 284 285#endif /* ELT_TYPE */ 286 287#define FUNC_VARS \ 288 struct draw_pt_front_end *frontend, \ 289 unsigned start, \ 290 unsigned count 291 292#define SEGMENT_SIMPLE(flags, istart, icount) \ 293 CONCAT(vsplit_segment_simple_, ELT_TYPE)(vsplit, flags, istart, icount) 294 295#define SEGMENT_LOOP(flags, istart, icount, i0) \ 296 CONCAT(vsplit_segment_loop_, ELT_TYPE)(vsplit, flags, istart, icount, i0) 297 298#define SEGMENT_FAN(flags, istart, icount, i0) \ 299 CONCAT(vsplit_segment_fan_, ELT_TYPE)(vsplit, flags, istart, icount, i0) 300 301#include "draw_split_tmp.h" 302 303#undef CONCAT2 304#undef CONCAT 305 306#undef ELT_TYPE 307#undef ADD_CACHE 308