Merge remote branch 'origin/nvc0'
[mesa.git] / src / gallium / drivers / nv50 / nv50_vbo.c
1 /*
2 * Copyright 2010 Christoph Bumiller
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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include "pipe/p_context.h"
24 #include "pipe/p_state.h"
25 #include "util/u_inlines.h"
26 #include "util/u_format.h"
27 #include "translate/translate.h"
28
29 #include "nv50_context.h"
30 #include "nv50_resource.h"
31
32 #include "nv50_3d.xml.h"
33
34 void
35 nv50_vertex_state_delete(struct pipe_context *pipe,
36 void *hwcso)
37 {
38 struct nv50_vertex_stateobj *so = hwcso;
39
40 if (so->translate)
41 so->translate->release(so->translate);
42 FREE(hwcso);
43 }
44
45 void *
46 nv50_vertex_state_create(struct pipe_context *pipe,
47 unsigned num_elements,
48 const struct pipe_vertex_element *elements)
49 {
50 struct nv50_vertex_stateobj *so;
51 struct translate_key transkey;
52 unsigned i;
53
54 assert(num_elements);
55
56 so = MALLOC(sizeof(*so) +
57 (num_elements - 1) * sizeof(struct nv50_vertex_element));
58 if (!so)
59 return NULL;
60 so->num_elements = num_elements;
61 so->instance_elts = 0;
62 so->instance_bufs = 0;
63 so->need_conversion = FALSE;
64
65 transkey.nr_elements = 0;
66 transkey.output_stride = 0;
67
68 for (i = 0; i < num_elements; ++i) {
69 const struct pipe_vertex_element *ve = &elements[i];
70 const unsigned vbi = ve->vertex_buffer_index;
71 enum pipe_format fmt = ve->src_format;
72
73 so->element[i].pipe = elements[i];
74 so->element[i].state = nv50_format_table[fmt].vtx;
75
76 if (!so->element[i].state) {
77 switch (util_format_get_nr_components(fmt)) {
78 case 1: fmt = PIPE_FORMAT_R32_FLOAT; break;
79 case 2: fmt = PIPE_FORMAT_R32G32_FLOAT; break;
80 case 3: fmt = PIPE_FORMAT_R32G32B32_FLOAT; break;
81 case 4: fmt = PIPE_FORMAT_R32G32B32A32_FLOAT; break;
82 default:
83 assert(0);
84 return NULL;
85 }
86 so->element[i].state = nv50_format_table[fmt].vtx;
87 so->need_conversion = TRUE;
88 }
89 so->element[i].state |= i;
90
91 if (1) {
92 unsigned j = transkey.nr_elements++;
93
94 transkey.element[j].type = TRANSLATE_ELEMENT_NORMAL;
95 transkey.element[j].input_format = ve->src_format;
96 transkey.element[j].input_buffer = vbi;
97 transkey.element[j].input_offset = ve->src_offset;
98 transkey.element[j].instance_divisor = ve->instance_divisor;
99
100 transkey.element[j].output_format = fmt;
101 transkey.element[j].output_offset = transkey.output_stride;
102 transkey.output_stride += (util_format_get_stride(fmt, 1) + 3) & ~3;
103
104 if (unlikely(ve->instance_divisor)) {
105 so->instance_elts |= 1 << i;
106 so->instance_bufs |= 1 << vbi;
107 }
108 }
109 }
110
111 so->translate = translate_create(&transkey);
112 so->vertex_size = transkey.output_stride / 4;
113 so->packet_vertex_limit = NV04_PFIFO_MAX_PACKET_LEN /
114 MAX2(so->vertex_size, 1);
115
116 return so;
117 }
118
119 #define NV50_3D_VERTEX_ATTRIB_INACTIVE \
120 NV50_3D_VERTEX_ARRAY_ATTRIB_TYPE_FLOAT | \
121 NV50_3D_VERTEX_ARRAY_ATTRIB_FORMAT_32_32_32_32 | \
122 NV50_3D_VERTEX_ARRAY_ATTRIB_CONST
123
124 static void
125 nv50_emit_vtxattr(struct nv50_context *nv50, struct pipe_vertex_buffer *vb,
126 struct pipe_vertex_element *ve, unsigned attr)
127 {
128 const void *data;
129 struct nouveau_channel *chan = nv50->screen->base.channel;
130 struct nv04_resource *res = nv04_resource(vb->buffer);
131 float v[4];
132 const unsigned nc = util_format_get_nr_components(ve->src_format);
133
134 data = nouveau_resource_map_offset(&nv50->base, res, vb->buffer_offset +
135 ve->src_offset, NOUVEAU_BO_RD);
136
137 util_format_read_4f(ve->src_format, v, 0, data, 0, 0, 0, 1, 1);
138
139 switch (nc) {
140 case 4:
141 BEGIN_RING(chan, RING_3D(VTX_ATTR_4F_X(attr)), 4);
142 OUT_RINGf (chan, v[0]);
143 OUT_RINGf (chan, v[1]);
144 OUT_RINGf (chan, v[2]);
145 OUT_RINGf (chan, v[3]);
146 break;
147 case 3:
148 BEGIN_RING(chan, RING_3D(VTX_ATTR_3F_X(attr)), 3);
149 OUT_RINGf (chan, v[0]);
150 OUT_RINGf (chan, v[1]);
151 OUT_RINGf (chan, v[2]);
152 break;
153 case 2:
154 BEGIN_RING(chan, RING_3D(VTX_ATTR_2F_X(attr)), 2);
155 OUT_RINGf (chan, v[0]);
156 OUT_RINGf (chan, v[1]);
157 break;
158 case 1:
159 if (attr == nv50->vertprog->vp.edgeflag) {
160 BEGIN_RING(chan, RING_3D(EDGEFLAG_ENABLE), 1);
161 OUT_RING (chan, v[0] ? 1 : 0);
162 }
163 BEGIN_RING(chan, RING_3D(VTX_ATTR_1F(attr)), 1);
164 OUT_RINGf (chan, v[0]);
165 break;
166 default:
167 assert(0);
168 break;
169 }
170 }
171
172 static INLINE void
173 nv50_vbuf_range(struct nv50_context *nv50, int vbi,
174 uint32_t *base, uint32_t *size)
175 {
176 if (unlikely(nv50->vertex->instance_bufs & (1 << vbi))) {
177 /* TODO: use min and max instance divisor to get a proper range */
178 *base = 0;
179 *size = nv50->vtxbuf[vbi].buffer->width0;
180 } else {
181 assert(nv50->vbo_max_index != ~0);
182 *base = nv50->vbo_min_index * nv50->vtxbuf[vbi].stride;
183 *size = (nv50->vbo_max_index -
184 nv50->vbo_min_index + 1) * nv50->vtxbuf[vbi].stride;
185 }
186 }
187
188 static void
189 nv50_prevalidate_vbufs(struct nv50_context *nv50)
190 {
191 struct pipe_vertex_buffer *vb;
192 struct nv04_resource *buf;
193 int i;
194 uint32_t base, size;
195
196 nv50->vbo_fifo = nv50->vbo_user = 0;
197
198 nv50_bufctx_reset(nv50, NV50_BUFCTX_VERTEX);
199
200 for (i = 0; i < nv50->num_vtxbufs; ++i) {
201 vb = &nv50->vtxbuf[i];
202 if (!vb->stride)
203 continue;
204 buf = nv04_resource(vb->buffer);
205
206 /* NOTE: user buffers with temporary storage count as mapped by GPU */
207 if (!nouveau_resource_mapped_by_gpu(vb->buffer)) {
208 if (nv50->vbo_push_hint) {
209 nv50->vbo_fifo = ~0;
210 continue;
211 } else {
212 if (buf->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY) {
213 nv50->vbo_user |= 1 << i;
214 assert(vb->stride > vb->buffer_offset);
215 nv50_vbuf_range(nv50, i, &base, &size);
216 nouveau_user_buffer_upload(buf, base, size);
217 } else {
218 nouveau_buffer_migrate(&nv50->base, buf, NOUVEAU_BO_GART);
219 }
220 nv50->base.vbo_dirty = TRUE;
221 }
222 }
223 nv50_bufctx_add_resident(nv50, NV50_BUFCTX_VERTEX, buf, NOUVEAU_BO_RD);
224 nouveau_buffer_adjust_score(&nv50->base, buf, 1);
225 }
226 }
227
228 static void
229 nv50_update_user_vbufs(struct nv50_context *nv50)
230 {
231 struct nouveau_channel *chan = nv50->screen->base.channel;
232 uint32_t base, offset, size;
233 int i;
234 uint32_t written = 0;
235
236 for (i = 0; i < nv50->vertex->num_elements; ++i) {
237 struct pipe_vertex_element *ve = &nv50->vertex->element[i].pipe;
238 const int b = ve->vertex_buffer_index;
239 struct pipe_vertex_buffer *vb = &nv50->vtxbuf[b];
240 struct nv04_resource *buf = nv04_resource(vb->buffer);
241
242 if (!(nv50->vbo_user & (1 << b)))
243 continue;
244
245 if (!vb->stride) {
246 nv50_emit_vtxattr(nv50, vb, ve, i);
247 continue;
248 }
249 nv50_vbuf_range(nv50, b, &base, &size);
250
251 if (!(written & (1 << b))) {
252 written |= 1 << b;
253 nouveau_user_buffer_upload(buf, base, size);
254 }
255 offset = vb->buffer_offset + ve->src_offset;
256
257 MARK_RING (chan, 6, 4);
258 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_LIMIT_HIGH(i)), 2);
259 OUT_RESRCh(chan, buf, base + size - 1, NOUVEAU_BO_RD);
260 OUT_RESRCl(chan, buf, base + size - 1, NOUVEAU_BO_RD);
261 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_START_HIGH(i)), 2);
262 OUT_RESRCh(chan, buf, offset, NOUVEAU_BO_RD);
263 OUT_RESRCl(chan, buf, offset, NOUVEAU_BO_RD);
264 }
265 nv50->base.vbo_dirty = TRUE;
266 }
267
268 static INLINE void
269 nv50_release_user_vbufs(struct nv50_context *nv50)
270 {
271 uint32_t vbo_user = nv50->vbo_user;
272
273 while (vbo_user) {
274 int i = ffs(vbo_user) - 1;
275 vbo_user &= ~(1 << i);
276
277 nouveau_buffer_release_gpu_storage(nv04_resource(nv50->vtxbuf[i].buffer));
278 }
279 }
280
281 void
282 nv50_vertex_arrays_validate(struct nv50_context *nv50)
283 {
284 struct nouveau_channel *chan = nv50->screen->base.channel;
285 struct nv50_vertex_stateobj *vertex = nv50->vertex;
286 struct pipe_vertex_buffer *vb;
287 struct nv50_vertex_element *ve;
288 unsigned i;
289
290 if (unlikely(vertex->need_conversion)) {
291 nv50->vbo_fifo = ~0;
292 nv50->vbo_user = 0;
293 } else {
294 nv50_prevalidate_vbufs(nv50);
295 }
296
297 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_ATTRIB(0)), vertex->num_elements);
298 for (i = 0; i < vertex->num_elements; ++i) {
299 ve = &vertex->element[i];
300 vb = &nv50->vtxbuf[ve->pipe.vertex_buffer_index];
301
302 if (likely(vb->stride) || nv50->vbo_fifo) {
303 OUT_RING(chan, ve->state);
304 } else {
305 OUT_RING(chan, ve->state | NV50_3D_VERTEX_ARRAY_ATTRIB_CONST);
306 nv50->vbo_fifo &= ~(1 << i);
307 }
308 }
309
310 for (i = 0; i < vertex->num_elements; ++i) {
311 struct nv04_resource *res;
312 unsigned size, offset;
313
314 ve = &vertex->element[i];
315 vb = &nv50->vtxbuf[ve->pipe.vertex_buffer_index];
316
317 if (unlikely(ve->pipe.instance_divisor)) {
318 if (!(nv50->state.instance_elts & (1 << i))) {
319 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_PER_INSTANCE(i)), 1);
320 OUT_RING (chan, 1);
321 }
322 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_DIVISOR(i)), 1);
323 OUT_RING (chan, ve->pipe.instance_divisor);
324 } else
325 if (unlikely(nv50->state.instance_elts & (1 << i))) {
326 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_PER_INSTANCE(i)), 1);
327 OUT_RING (chan, 0);
328 }
329
330 res = nv04_resource(vb->buffer);
331
332 if (nv50->vbo_fifo || unlikely(vb->stride == 0)) {
333 if (!nv50->vbo_fifo)
334 nv50_emit_vtxattr(nv50, vb, &ve->pipe, i);
335 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_FETCH(i)), 1);
336 OUT_RING (chan, 0);
337 continue;
338 }
339
340 size = vb->buffer->width0;
341 offset = ve->pipe.src_offset + vb->buffer_offset;
342
343 MARK_RING (chan, 8, 4);
344 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_FETCH(i)), 1);
345 OUT_RING (chan, NV50_3D_VERTEX_ARRAY_FETCH_ENABLE | vb->stride);
346 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_LIMIT_HIGH(i)), 2);
347 OUT_RESRCh(chan, res, size - 1, NOUVEAU_BO_RD);
348 OUT_RESRCl(chan, res, size - 1, NOUVEAU_BO_RD);
349 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_START_HIGH(i)), 2);
350 OUT_RESRCh(chan, res, offset, NOUVEAU_BO_RD);
351 OUT_RESRCl(chan, res, offset, NOUVEAU_BO_RD);
352 }
353 for (; i < nv50->state.num_vtxelts; ++i) {
354 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_ATTRIB(i)), 1);
355 OUT_RING (chan, NV50_3D_VERTEX_ATTRIB_INACTIVE);
356 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_FETCH(i)), 1);
357 OUT_RING (chan, 0);
358 }
359
360 nv50->state.num_vtxelts = vertex->num_elements;
361 nv50->state.instance_elts = vertex->instance_elts;
362 }
363
364 #define NV50_PRIM_GL_CASE(n) \
365 case PIPE_PRIM_##n: return NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n
366
367 static INLINE unsigned
368 nv50_prim_gl(unsigned prim)
369 {
370 switch (prim) {
371 NV50_PRIM_GL_CASE(POINTS);
372 NV50_PRIM_GL_CASE(LINES);
373 NV50_PRIM_GL_CASE(LINE_LOOP);
374 NV50_PRIM_GL_CASE(LINE_STRIP);
375 NV50_PRIM_GL_CASE(TRIANGLES);
376 NV50_PRIM_GL_CASE(TRIANGLE_STRIP);
377 NV50_PRIM_GL_CASE(TRIANGLE_FAN);
378 NV50_PRIM_GL_CASE(QUADS);
379 NV50_PRIM_GL_CASE(QUAD_STRIP);
380 NV50_PRIM_GL_CASE(POLYGON);
381 NV50_PRIM_GL_CASE(LINES_ADJACENCY);
382 NV50_PRIM_GL_CASE(LINE_STRIP_ADJACENCY);
383 NV50_PRIM_GL_CASE(TRIANGLES_ADJACENCY);
384 NV50_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY);
385 default:
386 return NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS;
387 break;
388 }
389 }
390
391 static void
392 nv50_draw_vbo_flush_notify(struct nouveau_channel *chan)
393 {
394 struct nv50_context *nv50 = chan->user_private;
395
396 nouveau_fence_update(&nv50->screen->base, TRUE);
397
398 nv50_bufctx_emit_relocs(nv50);
399 }
400
401 static void
402 nv50_draw_arrays(struct nv50_context *nv50,
403 unsigned mode, unsigned start, unsigned count,
404 unsigned instance_count)
405 {
406 struct nouveau_channel *chan = nv50->screen->base.channel;
407 unsigned prim;
408
409 chan->flush_notify = nv50_draw_vbo_flush_notify;
410 chan->user_private = nv50;
411
412 prim = nv50_prim_gl(mode);
413
414 while (instance_count--) {
415 BEGIN_RING(chan, RING_3D(VERTEX_BEGIN_GL), 1);
416 OUT_RING (chan, prim);
417 BEGIN_RING(chan, RING_3D(VERTEX_BUFFER_FIRST), 2);
418 OUT_RING (chan, start);
419 OUT_RING (chan, count);
420 BEGIN_RING(chan, RING_3D(VERTEX_END_GL), 1);
421 OUT_RING (chan, 0);
422
423 prim |= NV50_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
424 }
425
426 chan->flush_notify = nv50_default_flush_notify;
427 }
428
429 static void
430 nv50_draw_elements_inline_u08(struct nouveau_channel *chan, uint8_t *map,
431 unsigned start, unsigned count)
432 {
433 map += start;
434
435 if (count & 3) {
436 unsigned i;
437 BEGIN_RING_NI(chan, RING_3D(VB_ELEMENT_U32), count & 3);
438 for (i = 0; i < (count & 3); ++i)
439 OUT_RING(chan, *map++);
440 count &= ~3;
441 }
442 while (count) {
443 unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 4) / 4;
444
445 BEGIN_RING_NI(chan, RING_3D(VB_ELEMENT_U8), nr);
446 for (i = 0; i < nr; ++i) {
447 OUT_RING(chan,
448 (map[3] << 24) | (map[2] << 16) | (map[1] << 8) | map[0]);
449 map += 4;
450 }
451 count -= nr * 4;
452 }
453 }
454
455 static void
456 nv50_draw_elements_inline_u16(struct nouveau_channel *chan, uint16_t *map,
457 unsigned start, unsigned count)
458 {
459 map += start;
460
461 if (count & 1) {
462 count &= ~1;
463 BEGIN_RING(chan, RING_3D(VB_ELEMENT_U32), 1);
464 OUT_RING (chan, *map++);
465 }
466 while (count) {
467 unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 2) / 2;
468
469 BEGIN_RING_NI(chan, RING_3D(VB_ELEMENT_U16), nr);
470 for (i = 0; i < nr; ++i) {
471 OUT_RING(chan, (map[1] << 16) | map[0]);
472 map += 2;
473 }
474 count -= nr * 2;
475 }
476 }
477
478 static void
479 nv50_draw_elements_inline_u32(struct nouveau_channel *chan, uint32_t *map,
480 unsigned start, unsigned count)
481 {
482 map += start;
483
484 while (count) {
485 const unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
486
487 BEGIN_RING_NI(chan, RING_3D(VB_ELEMENT_U32), nr);
488 OUT_RINGp (chan, map, nr);
489
490 map += nr;
491 count -= nr;
492 }
493 }
494
495 static void
496 nv50_draw_elements_inline_u32_short(struct nouveau_channel *chan, uint32_t *map,
497 unsigned start, unsigned count)
498 {
499 map += start;
500
501 if (count & 1) {
502 count--;
503 BEGIN_RING(chan, RING_3D(VB_ELEMENT_U32), 1);
504 OUT_RING (chan, *map++);
505 }
506 while (count) {
507 unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 2) / 2;
508
509 BEGIN_RING_NI(chan, RING_3D(VB_ELEMENT_U16), nr);
510 for (i = 0; i < nr; ++i) {
511 OUT_RING(chan, (map[1] << 16) | map[0]);
512 map += 2;
513 }
514 count -= nr * 2;
515 }
516 }
517
518 static void
519 nv50_draw_elements(struct nv50_context *nv50, boolean shorten,
520 unsigned mode, unsigned start, unsigned count,
521 unsigned instance_count, int32_t index_bias)
522 {
523 struct nouveau_channel *chan = nv50->screen->base.channel;
524 void *data;
525 unsigned prim;
526 const unsigned index_size = nv50->idxbuf.index_size;
527
528 chan->flush_notify = nv50_draw_vbo_flush_notify;
529 chan->user_private = nv50;
530
531 prim = nv50_prim_gl(mode);
532
533 if (index_bias != nv50->state.index_bias) {
534 BEGIN_RING(chan, RING_3D(VB_ELEMENT_BASE), 1);
535 OUT_RING (chan, index_bias);
536 nv50->state.index_bias = index_bias;
537 }
538
539 if (nouveau_resource_mapped_by_gpu(nv50->idxbuf.buffer)) {
540 struct nv04_resource *res = nv04_resource(nv50->idxbuf.buffer);
541
542 start += nv50->idxbuf.offset >> (index_size >> 1);
543
544 nouveau_buffer_adjust_score(&nv50->base, res, 1);
545
546 while (instance_count--) {
547 BEGIN_RING(chan, RING_3D(VERTEX_BEGIN_GL), 1);
548 OUT_RING (chan, mode);
549
550 switch (index_size) {
551 case 4:
552 {
553 WAIT_RING (chan, 2);
554 BEGIN_RING(chan, RING_3D(VB_ELEMENT_U32) | 0x30000, 0);
555 OUT_RING (chan, count);
556 nouveau_pushbuf_submit(chan, res->bo, res->offset + start * 4,
557 count * 4);
558 }
559 break;
560 case 2:
561 {
562 unsigned pb_start = (start & ~1);
563 unsigned pb_words = (((start + count + 1) & ~1) - pb_start) >> 1;
564
565 BEGIN_RING(chan, RING_3D(VB_ELEMENT_U16_SETUP), 1);
566 OUT_RING (chan, (start << 31) | count);
567 WAIT_RING (chan, 2);
568 BEGIN_RING(chan, RING_3D(VB_ELEMENT_U16) | 0x30000, 0);
569 OUT_RING (chan, pb_words);
570 nouveau_pushbuf_submit(chan, res->bo, res->offset + pb_start * 2,
571 pb_words * 4);
572 BEGIN_RING(chan, RING_3D(VB_ELEMENT_U16_SETUP), 1);
573 OUT_RING (chan, 0);
574 break;
575 }
576 case 1:
577 {
578 unsigned pb_start = (start & ~3);
579 unsigned pb_words = (((start + count + 3) & ~3) - pb_start) >> 1;
580
581 BEGIN_RING(chan, RING_3D(VB_ELEMENT_U8_SETUP), 1);
582 OUT_RING (chan, (start << 30) | count);
583 WAIT_RING (chan, 2);
584 BEGIN_RING(chan, RING_3D(VB_ELEMENT_U8) | 0x30000, 0);
585 OUT_RING (chan, pb_words);
586 nouveau_pushbuf_submit(chan, res->bo, res->offset + pb_start,
587 pb_words * 4);
588 BEGIN_RING(chan, RING_3D(VB_ELEMENT_U8_SETUP), 1);
589 OUT_RING (chan, 0);
590 break;
591 }
592 default:
593 assert(0);
594 return;
595 }
596 BEGIN_RING(chan, RING_3D(VERTEX_END_GL), 1);
597 OUT_RING (chan, 0);
598
599 nv50_resource_fence(res, NOUVEAU_BO_RD);
600
601 mode |= NV50_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
602 }
603 } else {
604 data = nouveau_resource_map_offset(&nv50->base,
605 nv04_resource(nv50->idxbuf.buffer),
606 nv50->idxbuf.offset, NOUVEAU_BO_RD);
607 if (!data)
608 return;
609
610 while (instance_count--) {
611 BEGIN_RING(chan, RING_3D(VERTEX_BEGIN_GL), 1);
612 OUT_RING (chan, prim);
613 switch (index_size) {
614 case 1:
615 nv50_draw_elements_inline_u08(chan, data, start, count);
616 break;
617 case 2:
618 nv50_draw_elements_inline_u16(chan, data, start, count);
619 break;
620 case 4:
621 if (shorten)
622 nv50_draw_elements_inline_u32_short(chan, data, start, count);
623 else
624 nv50_draw_elements_inline_u32(chan, data, start, count);
625 break;
626 default:
627 assert(0);
628 return;
629 }
630 BEGIN_RING(chan, RING_3D(VERTEX_END_GL), 1);
631 OUT_RING (chan, 0);
632
633 prim |= NV50_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
634 }
635 }
636
637 chan->flush_notify = nv50_default_flush_notify;
638 }
639
640 void
641 nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
642 {
643 struct nv50_context *nv50 = nv50_context(pipe);
644 struct nouveau_channel *chan = nv50->screen->base.channel;
645
646 /* For picking only a few vertices from a large user buffer, push is better,
647 * if index count is larger and we expect repeated vertices, suggest upload.
648 */
649 nv50->vbo_push_hint = /* the 64 is heuristic */
650 !(info->indexed &&
651 ((info->max_index - info->min_index + 64) < info->count));
652
653 nv50->vbo_min_index = info->min_index;
654 nv50->vbo_max_index = info->max_index;
655
656 if (nv50->vbo_push_hint != !!nv50->vbo_fifo)
657 nv50->dirty |= NV50_NEW_ARRAYS;
658
659 if (nv50->vbo_user && !(nv50->dirty & (NV50_NEW_VERTEX | NV50_NEW_ARRAYS)))
660 nv50_update_user_vbufs(nv50);
661
662 nv50_state_validate(nv50);
663
664 if (nv50->vbo_fifo) {
665 nv50_push_vbo(nv50, info);
666 return;
667 }
668
669 if (nv50->state.instance_base != info->start_instance) {
670 nv50->state.instance_base = info->start_instance;
671 /* NOTE: this does not affect the shader input, should it ? */
672 BEGIN_RING(chan, RING_3D(VB_INSTANCE_BASE), 1);
673 OUT_RING (chan, info->start_instance);
674 }
675
676 if (nv50->base.vbo_dirty) {
677 BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_FLUSH), 1);
678 OUT_RING (chan, 0);
679 nv50->base.vbo_dirty = FALSE;
680 }
681
682 if (!info->indexed) {
683 nv50_draw_arrays(nv50,
684 info->mode, info->start, info->count,
685 info->instance_count);
686 } else {
687 boolean shorten = info->max_index <= 65535;
688
689 assert(nv50->idxbuf.buffer);
690
691 if (info->primitive_restart != nv50->state.prim_restart) {
692 if (info->primitive_restart) {
693 BEGIN_RING(chan, RING_3D(PRIM_RESTART_ENABLE), 2);
694 OUT_RING (chan, 1);
695 OUT_RING (chan, info->restart_index);
696
697 if (info->restart_index > 65535)
698 shorten = FALSE;
699 } else {
700 BEGIN_RING(chan, RING_3D(PRIM_RESTART_ENABLE), 1);
701 OUT_RING (chan, 0);
702 }
703 nv50->state.prim_restart = info->primitive_restart;
704 } else
705 if (info->primitive_restart) {
706 BEGIN_RING(chan, RING_3D(PRIM_RESTART_INDEX), 1);
707 OUT_RING (chan, info->restart_index);
708
709 if (info->restart_index > 65535)
710 shorten = FALSE;
711 }
712
713 nv50_draw_elements(nv50, shorten,
714 info->mode, info->start, info->count,
715 info->instance_count, info->index_bias);
716 }
717
718 nv50_release_user_vbufs(nv50);
719 }