Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/auxiliary/draw/draw_pt_vsplit.c
4565 views
1
/*
2
* Mesa 3-D graphics library
3
*
4
* Copyright 2007-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
26
#include "util/u_math.h"
27
#include "util/u_memory.h"
28
29
#include "draw/draw_context.h"
30
#include "draw/draw_private.h"
31
#include "draw/draw_pt.h"
32
33
#define SEGMENT_SIZE 1024
34
#define MAP_SIZE 256
35
36
/* The largest possible index within an index buffer */
37
#define MAX_ELT_IDX 0xffffffff
38
39
struct vsplit_frontend {
40
struct draw_pt_front_end base;
41
struct draw_context *draw;
42
43
unsigned prim;
44
45
struct draw_pt_middle_end *middle;
46
47
unsigned max_vertices;
48
ushort segment_size;
49
50
/* buffers for splitting */
51
unsigned fetch_elts[SEGMENT_SIZE];
52
ushort draw_elts[SEGMENT_SIZE];
53
ushort identity_draw_elts[SEGMENT_SIZE];
54
55
struct {
56
/* map a fetch element to a draw element */
57
unsigned fetches[MAP_SIZE];
58
ushort draws[MAP_SIZE];
59
boolean has_max_fetch;
60
61
ushort num_fetch_elts;
62
ushort num_draw_elts;
63
} cache;
64
};
65
66
67
static void
68
vsplit_clear_cache(struct vsplit_frontend *vsplit)
69
{
70
memset(vsplit->cache.fetches, 0xff, sizeof(vsplit->cache.fetches));
71
vsplit->cache.has_max_fetch = FALSE;
72
vsplit->cache.num_fetch_elts = 0;
73
vsplit->cache.num_draw_elts = 0;
74
}
75
76
static void
77
vsplit_flush_cache(struct vsplit_frontend *vsplit, unsigned flags)
78
{
79
vsplit->middle->run(vsplit->middle,
80
vsplit->fetch_elts, vsplit->cache.num_fetch_elts,
81
vsplit->draw_elts, vsplit->cache.num_draw_elts, flags);
82
}
83
84
/**
85
* Add a fetch element and add it to the draw elements.
86
*/
87
static inline void
88
vsplit_add_cache(struct vsplit_frontend *vsplit, unsigned fetch)
89
{
90
unsigned hash;
91
92
hash = fetch % MAP_SIZE;
93
94
/* If the value isn't in the cache or it's an overflow due to the
95
* element bias */
96
if (vsplit->cache.fetches[hash] != fetch) {
97
/* update cache */
98
vsplit->cache.fetches[hash] = fetch;
99
vsplit->cache.draws[hash] = vsplit->cache.num_fetch_elts;
100
101
/* add fetch */
102
assert(vsplit->cache.num_fetch_elts < vsplit->segment_size);
103
vsplit->fetch_elts[vsplit->cache.num_fetch_elts++] = fetch;
104
}
105
106
vsplit->draw_elts[vsplit->cache.num_draw_elts++] = vsplit->cache.draws[hash];
107
}
108
109
/**
110
* Returns the base index to the elements array.
111
* The value is checked for integer overflow (not sure it can happen?).
112
*/
113
static inline unsigned
114
vsplit_get_base_idx(unsigned start, unsigned fetch)
115
{
116
return draw_overflow_uadd(start, fetch, MAX_ELT_IDX);
117
}
118
119
120
static inline void
121
vsplit_add_cache_ubyte(struct vsplit_frontend *vsplit, const ubyte *elts,
122
unsigned start, unsigned fetch, int elt_bias)
123
{
124
struct draw_context *draw = vsplit->draw;
125
unsigned elt_idx;
126
elt_idx = vsplit_get_base_idx(start, fetch);
127
elt_idx = (unsigned)((int)(DRAW_GET_IDX(elts, elt_idx)) + elt_bias);
128
/* unlike the uint case this can only happen with elt_bias */
129
if (elt_bias && elt_idx == DRAW_MAX_FETCH_IDX && !vsplit->cache.has_max_fetch) {
130
unsigned hash = elt_idx % MAP_SIZE;
131
vsplit->cache.fetches[hash] = 0;
132
vsplit->cache.has_max_fetch = TRUE;
133
}
134
vsplit_add_cache(vsplit, elt_idx);
135
}
136
137
static inline void
138
vsplit_add_cache_ushort(struct vsplit_frontend *vsplit, const ushort *elts,
139
unsigned start, unsigned fetch, int elt_bias)
140
{
141
struct draw_context *draw = vsplit->draw;
142
unsigned elt_idx;
143
elt_idx = vsplit_get_base_idx(start, fetch);
144
elt_idx = (unsigned)((int)(DRAW_GET_IDX(elts, elt_idx)) + elt_bias);
145
/* unlike the uint case this can only happen with elt_bias */
146
if (elt_bias && elt_idx == DRAW_MAX_FETCH_IDX && !vsplit->cache.has_max_fetch) {
147
unsigned hash = elt_idx % MAP_SIZE;
148
vsplit->cache.fetches[hash] = 0;
149
vsplit->cache.has_max_fetch = TRUE;
150
}
151
vsplit_add_cache(vsplit, elt_idx);
152
}
153
154
155
/**
156
* Add a fetch element and add it to the draw elements. The fetch element is
157
* in full range (uint).
158
*/
159
static inline void
160
vsplit_add_cache_uint(struct vsplit_frontend *vsplit, const uint *elts,
161
unsigned start, unsigned fetch, int elt_bias)
162
{
163
struct draw_context *draw = vsplit->draw;
164
unsigned elt_idx;
165
/*
166
* The final element index is just element index plus element bias.
167
*/
168
elt_idx = vsplit_get_base_idx(start, fetch);
169
elt_idx = (unsigned)((int)(DRAW_GET_IDX(elts, elt_idx)) + elt_bias);
170
/* Take care for DRAW_MAX_FETCH_IDX (since cache is initialized to -1). */
171
if (elt_idx == DRAW_MAX_FETCH_IDX && !vsplit->cache.has_max_fetch) {
172
unsigned hash = elt_idx % MAP_SIZE;
173
/* force update - any value will do except DRAW_MAX_FETCH_IDX */
174
vsplit->cache.fetches[hash] = 0;
175
vsplit->cache.has_max_fetch = TRUE;
176
}
177
vsplit_add_cache(vsplit, elt_idx);
178
}
179
180
181
#define FUNC vsplit_run_linear
182
#include "draw_pt_vsplit_tmp.h"
183
184
#define FUNC vsplit_run_ubyte
185
#define ELT_TYPE ubyte
186
#define ADD_CACHE(vsplit, ib, start, fetch, bias) vsplit_add_cache_ubyte(vsplit,ib,start,fetch,bias)
187
#include "draw_pt_vsplit_tmp.h"
188
189
#define FUNC vsplit_run_ushort
190
#define ELT_TYPE ushort
191
#define ADD_CACHE(vsplit, ib, start, fetch, bias) vsplit_add_cache_ushort(vsplit,ib,start,fetch, bias)
192
#include "draw_pt_vsplit_tmp.h"
193
194
#define FUNC vsplit_run_uint
195
#define ELT_TYPE uint
196
#define ADD_CACHE(vsplit, ib, start, fetch, bias) vsplit_add_cache_uint(vsplit, ib, start, fetch, bias)
197
#include "draw_pt_vsplit_tmp.h"
198
199
200
static void vsplit_prepare(struct draw_pt_front_end *frontend,
201
unsigned in_prim,
202
struct draw_pt_middle_end *middle,
203
unsigned opt)
204
{
205
struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;
206
207
switch (vsplit->draw->pt.user.eltSize) {
208
case 0:
209
vsplit->base.run = vsplit_run_linear;
210
break;
211
case 1:
212
vsplit->base.run = vsplit_run_ubyte;
213
break;
214
case 2:
215
vsplit->base.run = vsplit_run_ushort;
216
break;
217
case 4:
218
vsplit->base.run = vsplit_run_uint;
219
break;
220
default:
221
assert(0);
222
break;
223
}
224
225
/* split only */
226
vsplit->prim = in_prim;
227
228
vsplit->middle = middle;
229
middle->prepare(middle, vsplit->prim, opt, &vsplit->max_vertices);
230
231
vsplit->segment_size = MIN2(SEGMENT_SIZE, vsplit->max_vertices);
232
}
233
234
235
static void vsplit_flush(struct draw_pt_front_end *frontend, unsigned flags)
236
{
237
struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;
238
239
if (flags & DRAW_FLUSH_STATE_CHANGE) {
240
vsplit->middle->finish(vsplit->middle);
241
vsplit->middle = NULL;
242
}
243
}
244
245
246
static void vsplit_destroy(struct draw_pt_front_end *frontend)
247
{
248
FREE(frontend);
249
}
250
251
252
struct draw_pt_front_end *draw_pt_vsplit(struct draw_context *draw)
253
{
254
struct vsplit_frontend *vsplit = CALLOC_STRUCT(vsplit_frontend);
255
ushort i;
256
257
if (!vsplit)
258
return NULL;
259
260
vsplit->base.prepare = vsplit_prepare;
261
vsplit->base.run = NULL;
262
vsplit->base.flush = vsplit_flush;
263
vsplit->base.destroy = vsplit_destroy;
264
vsplit->draw = draw;
265
266
for (i = 0; i < SEGMENT_SIZE; i++)
267
vsplit->identity_draw_elts[i] = i;
268
269
return &vsplit->base;
270
}
271
272