Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv30/nv30_push.c
4574 views
1
/*
2
* Copyright 2012 Red Hat Inc.
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
13
*
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
* OTHER DEALINGS IN THE SOFTWARE.
21
*
22
* Authors: Ben Skeggs
23
*
24
*/
25
26
#include "pipe/p_context.h"
27
#include "pipe/p_state.h"
28
#include "util/u_inlines.h"
29
#include "util/format/u_format.h"
30
#include "translate/translate.h"
31
32
#include "nv_object.xml.h"
33
#include "nv30/nv30-40_3d.xml.h"
34
#include "nv30/nv30_context.h"
35
#include "nv30/nv30_resource.h"
36
37
struct push_context {
38
struct nouveau_pushbuf *push;
39
40
const void *idxbuf;
41
42
float edgeflag;
43
int edgeflag_attr;
44
45
uint32_t vertex_words;
46
uint32_t packet_vertex_limit;
47
48
struct translate *translate;
49
50
bool primitive_restart;
51
uint32_t prim;
52
uint32_t restart_index;
53
};
54
55
static inline unsigned
56
prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index)
57
{
58
unsigned i;
59
for (i = 0; i < push; ++i)
60
if (elts[i] == index)
61
break;
62
return i;
63
}
64
65
static inline unsigned
66
prim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index)
67
{
68
unsigned i;
69
for (i = 0; i < push; ++i)
70
if (elts[i] == index)
71
break;
72
return i;
73
}
74
75
static inline unsigned
76
prim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index)
77
{
78
unsigned i;
79
for (i = 0; i < push; ++i)
80
if (elts[i] == index)
81
break;
82
return i;
83
}
84
85
static void
86
emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)
87
{
88
uint8_t *elts = (uint8_t *)ctx->idxbuf + start;
89
90
while (count) {
91
unsigned push = MIN2(count, ctx->packet_vertex_limit);
92
unsigned size, nr;
93
94
nr = push;
95
if (ctx->primitive_restart)
96
nr = prim_restart_search_i08(elts, push, ctx->restart_index);
97
98
size = ctx->vertex_words * nr;
99
100
BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);
101
102
ctx->translate->run_elts8(ctx->translate, elts, nr, 0, 0, ctx->push->cur);
103
104
ctx->push->cur += size;
105
count -= nr;
106
elts += nr;
107
108
if (nr != push) {
109
BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1);
110
PUSH_DATA (ctx->push, ctx->restart_index);
111
count--;
112
elts++;
113
}
114
}
115
}
116
117
static void
118
emit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)
119
{
120
uint16_t *elts = (uint16_t *)ctx->idxbuf + start;
121
122
while (count) {
123
unsigned push = MIN2(count, ctx->packet_vertex_limit);
124
unsigned size, nr;
125
126
nr = push;
127
if (ctx->primitive_restart)
128
nr = prim_restart_search_i16(elts, push, ctx->restart_index);
129
130
size = ctx->vertex_words * nr;
131
132
BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);
133
134
ctx->translate->run_elts16(ctx->translate, elts, nr, 0, 0, ctx->push->cur);
135
136
ctx->push->cur += size;
137
count -= nr;
138
elts += nr;
139
140
if (nr != push) {
141
BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1);
142
PUSH_DATA (ctx->push, ctx->restart_index);
143
count--;
144
elts++;
145
}
146
}
147
}
148
149
static void
150
emit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)
151
{
152
uint32_t *elts = (uint32_t *)ctx->idxbuf + start;
153
154
while (count) {
155
unsigned push = MIN2(count, ctx->packet_vertex_limit);
156
unsigned size, nr;
157
158
nr = push;
159
if (ctx->primitive_restart)
160
nr = prim_restart_search_i32(elts, push, ctx->restart_index);
161
162
size = ctx->vertex_words * nr;
163
164
BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);
165
166
ctx->translate->run_elts(ctx->translate, elts, nr, 0, 0, ctx->push->cur);
167
168
ctx->push->cur += size;
169
count -= nr;
170
elts += nr;
171
172
if (nr != push) {
173
BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1);
174
PUSH_DATA (ctx->push, ctx->restart_index);
175
count--;
176
elts++;
177
}
178
}
179
}
180
181
static void
182
emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)
183
{
184
while (count) {
185
unsigned push = MIN2(count, ctx->packet_vertex_limit);
186
unsigned size = ctx->vertex_words * push;
187
188
BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);
189
190
ctx->translate->run(ctx->translate, start, push, 0, 0, ctx->push->cur);
191
ctx->push->cur += size;
192
count -= push;
193
start += push;
194
}
195
}
196
197
void
198
nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info,
199
const struct pipe_draw_start_count_bias *draw)
200
{
201
struct push_context ctx;
202
unsigned i, index_size;
203
bool apply_bias = info->index_size && draw->index_bias;
204
205
ctx.push = nv30->base.pushbuf;
206
ctx.translate = nv30->vertex->translate;
207
ctx.packet_vertex_limit = nv30->vertex->vtx_per_packet_max;
208
ctx.vertex_words = nv30->vertex->vtx_size;
209
210
for (i = 0; i < nv30->num_vtxbufs; ++i) {
211
uint8_t *data;
212
struct pipe_vertex_buffer *vb = &nv30->vtxbuf[i];
213
struct nv04_resource *res = nv04_resource(vb->buffer.resource);
214
215
if (!vb->buffer.resource) {
216
continue;
217
}
218
219
data = nouveau_resource_map_offset(&nv30->base, res,
220
vb->buffer_offset, NOUVEAU_BO_RD);
221
222
if (apply_bias)
223
data += draw->index_bias * vb->stride;
224
225
ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
226
}
227
228
if (info->index_size) {
229
if (!info->has_user_indices)
230
ctx.idxbuf = nouveau_resource_map_offset(&nv30->base,
231
nv04_resource(info->index.resource), draw->start * info->index_size,
232
NOUVEAU_BO_RD);
233
else
234
ctx.idxbuf = (char*)info->index.user + draw->start * info->index_size;
235
if (!ctx.idxbuf) {
236
nv30_state_release(nv30);
237
return;
238
}
239
index_size = info->index_size;
240
ctx.primitive_restart = info->primitive_restart;
241
ctx.restart_index = info->restart_index;
242
} else {
243
ctx.idxbuf = NULL;
244
index_size = 0;
245
ctx.primitive_restart = false;
246
ctx.restart_index = 0;
247
}
248
249
if (nv30->screen->eng3d->oclass >= NV40_3D_CLASS) {
250
BEGIN_NV04(ctx.push, NV40_3D(PRIM_RESTART_ENABLE), 2);
251
PUSH_DATA (ctx.push, info->primitive_restart);
252
PUSH_DATA (ctx.push, info->restart_index);
253
nv30->state.prim_restart = info->primitive_restart;
254
}
255
256
ctx.prim = nv30_prim_gl(info->mode);
257
258
PUSH_RESET(ctx.push, BUFCTX_IDXBUF);
259
BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1);
260
PUSH_DATA (ctx.push, ctx.prim);
261
switch (index_size) {
262
case 0:
263
emit_vertices_seq(&ctx, draw->start, draw->count);
264
break;
265
case 1:
266
emit_vertices_i08(&ctx, draw->start, draw->count);
267
break;
268
case 2:
269
emit_vertices_i16(&ctx, draw->start, draw->count);
270
break;
271
case 4:
272
emit_vertices_i32(&ctx, draw->start, draw->count);
273
break;
274
default:
275
assert(0);
276
break;
277
}
278
BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1);
279
PUSH_DATA (ctx.push, NV30_3D_VERTEX_BEGIN_END_STOP);
280
281
if (info->index_size && !info->has_user_indices)
282
nouveau_resource_unmap(nv04_resource(info->index.resource));
283
284
for (i = 0; i < nv30->num_vtxbufs; ++i) {
285
if (nv30->vtxbuf[i].buffer.resource) {
286
nouveau_resource_unmap(nv04_resource(nv30->vtxbuf[i].buffer.resource));
287
}
288
}
289
290
nv30_state_release(nv30);
291
}
292
293