2
* Mesa 3-D graphics library
5
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6
* Copyright (C) 2010 LunarG Inc.
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:
15
* The above copyright notice and this permission notice shall be included
16
* in all copies or substantial portions of the Software.
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.
27
#define CONCAT2(name, elt_type) name ## elt_type
28
#define CONCAT(name, elt_type) CONCAT2(name, elt_type)
33
* Fetch all elements in [min_index, max_index] with bias, and use the
34
* (rebased) index buffer as the draw elements.
37
CONCAT(vsplit_primitive_, ELT_TYPE)(struct vsplit_frontend *vsplit,
38
unsigned istart, unsigned icount)
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;
50
/* use the ib directly */
51
if (min_index == 0 && sizeof(ib[0]) == sizeof(draw_elts[0])) {
52
if (icount > vsplit->max_vertices)
55
for (i = 0; i < icount; i++) {
56
ELT_TYPE idx = ib[istart + i];
57
assert(idx >= min_index && idx <= max_index);
59
draw_elts = (const ushort *) ib;
62
/* have to go through vsplit->draw_elts */
63
if (icount > vsplit->segment_size)
67
/* this is faster only when we fetch less elements than the normal path */
68
if (max_index - min_index > icount - 1)
71
if (elt_bias < 0 && min_index < -elt_bias)
75
for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
76
if (draw->pt.vertex_element[i].instance_divisor)
80
fetch_start = min_index + elt_bias;
81
fetch_count = max_index - min_index + 1;
85
for (i = 0; i < icount; i++) {
86
ELT_TYPE idx = ib[istart + i];
88
assert(idx >= min_index && idx <= max_index);
89
vsplit->draw_elts[i] = (ushort) idx;
93
for (i = 0; i < icount; i++) {
94
ELT_TYPE idx = ib[istart + i];
96
assert(idx >= min_index && idx <= max_index);
97
vsplit->draw_elts[i] = (ushort) (idx - min_index);
101
draw_elts = vsplit->draw_elts;
104
return vsplit->middle->run_linear_elts(vsplit->middle,
105
fetch_start, fetch_count,
106
draw_elts, icount, 0x0);
110
* Use the cache to prepare the fetch and draw elements, and flush.
112
* When spoken is TRUE, ispoken replaces istart; When close is TRUE, iclose is
116
CONCAT(vsplit_segment_cache_, ELT_TYPE)(struct vsplit_frontend *vsplit,
118
unsigned istart, unsigned icount,
119
boolean spoken, unsigned ispoken,
120
boolean close, unsigned iclose)
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;
128
assert(icount + !!close <= vsplit->segment_size);
130
vsplit_clear_cache(vsplit);
135
ADD_CACHE(vsplit, ib[ispoken]);
137
for (i = spoken; i < icount; i++)
138
ADD_CACHE(vsplit, ib[istart + i]);
141
ADD_CACHE(vsplit, ib[iclose]);
143
else if (ibias > 0) {
145
ADD_CACHE(vsplit, (uint) ib[ispoken] + ibias);
147
for (i = spoken; i < icount; i++)
148
ADD_CACHE(vsplit, (uint) ib[istart + i] + ibias);
151
ADD_CACHE(vsplit, (uint) ib[iclose] + ibias);
155
if (ib[ispoken] < -ibias)
157
ADD_CACHE(vsplit, ib[ispoken] + ibias);
160
for (i = spoken; i < icount; i++) {
161
if (ib[istart + i] < -ibias)
163
ADD_CACHE(vsplit, ib[istart + i] + ibias);
167
if (ib[iclose] < -ibias)
169
ADD_CACHE(vsplit, ib[iclose] + ibias);
173
vsplit_flush_cache(vsplit, flags);
177
CONCAT(vsplit_segment_simple_, ELT_TYPE)(struct vsplit_frontend *vsplit,
182
CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
183
flags, istart, icount, FALSE, 0, FALSE, 0);
187
CONCAT(vsplit_segment_loop_, ELT_TYPE)(struct vsplit_frontend *vsplit,
193
const boolean close_loop = ((flags) == DRAW_SPLIT_BEFORE);
195
CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
196
flags, istart, icount, FALSE, 0, close_loop, i0);
200
CONCAT(vsplit_segment_fan_, ELT_TYPE)(struct vsplit_frontend *vsplit,
206
const boolean use_spoken = (((flags) & DRAW_SPLIT_BEFORE) != 0);
208
CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
209
flags, istart, icount, use_spoken, i0, FALSE, 0);
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;
219
#define PRIMITIVE(istart, icount) \
220
CONCAT(vsplit_primitive_, ELT_TYPE)(vsplit, istart, icount)
225
vsplit_segment_simple_linear(struct vsplit_frontend *vsplit, unsigned flags,
226
unsigned istart, unsigned icount)
228
assert(icount <= vsplit->max_vertices);
229
vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
233
vsplit_segment_loop_linear(struct vsplit_frontend *vsplit, unsigned flags,
234
unsigned istart, unsigned icount, unsigned i0)
236
boolean close_loop = (flags == DRAW_SPLIT_BEFORE);
239
assert(icount + !!close_loop <= vsplit->segment_size);
242
for (nr = 0; nr < icount; nr++)
243
vsplit->fetch_elts[nr] = istart + nr;
244
vsplit->fetch_elts[nr++] = i0;
246
vsplit->middle->run(vsplit->middle, vsplit->fetch_elts, nr,
247
vsplit->identity_draw_elts, nr, flags);
250
vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
255
vsplit_segment_fan_linear(struct vsplit_frontend *vsplit, unsigned flags,
256
unsigned istart, unsigned icount, unsigned i0)
258
boolean use_spoken = ((flags & DRAW_SPLIT_BEFORE) != 0);
261
assert(icount + !!use_spoken <= vsplit->segment_size);
264
vsplit->fetch_elts[nr++] = i0;
265
for (i = 1 ; i < icount; i++)
266
vsplit->fetch_elts[nr++] = istart + i;
268
vsplit->middle->run(vsplit->middle, vsplit->fetch_elts, nr,
269
vsplit->identity_draw_elts, nr, flags);
272
vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
277
struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend; \
278
const unsigned prim = vsplit->prim; \
279
const unsigned max_count_simple = vsplit->max_vertices; \
280
const unsigned max_count_loop = vsplit->segment_size - 1; \
281
const unsigned max_count_fan = vsplit->segment_size;
283
#define PRIMITIVE(istart, icount) FALSE
285
#define ELT_TYPE linear
287
#endif /* ELT_TYPE */
290
struct draw_pt_front_end *frontend, \
294
#define SEGMENT_SIMPLE(flags, istart, icount) \
295
CONCAT(vsplit_segment_simple_, ELT_TYPE)(vsplit, flags, istart, icount)
297
#define SEGMENT_LOOP(flags, istart, icount, i0) \
298
CONCAT(vsplit_segment_loop_, ELT_TYPE)(vsplit, flags, istart, icount, i0)
300
#define SEGMENT_FAN(flags, istart, icount, i0) \
301
CONCAT(vsplit_segment_fan_, ELT_TYPE)(vsplit, flags, istart, icount, i0)
303
#include "draw_split_tmp.h"