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