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