Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
 
2
#include "pipe/p_state.h"
3
#include "util/u_inlines.h"
4
#include "util/u_format.h"
5
#include "translate/translate.h"
6
7
 
8
#include "nvc0/nvc0_resource.h"
9
10
 
11
12
 
13
   struct nouveau_pushbuf *push;
14
15
 
16
   void *dest;
17
   const void *idxbuf;
18
19
 
20
   uint32_t restart_index;
21
   uint32_t instance_id;
22
23
 
24
   boolean need_vertex_id;
25
26
 
27
      boolean enabled;
28
      boolean value;
29
      unsigned stride;
30
      const uint8_t *data;
31
   } edgeflag;
32
};
33
34
 
35
                                        struct nvc0_context *,
36
                                        const struct pipe_draw_info *);
37
38
 
39
nvc0_push_context_init(struct nvc0_context *nvc0, struct push_context *ctx)
40
{
41
   ctx->push = nvc0->base.pushbuf;
42
43
 
44
   ctx->vertex_size = nvc0->vertex->size;
45
46
 
47
      nvc0->vertprog->vp.need_vertex_id && (nvc0->vertex->num_elements < 32);
48
49
 
50
   ctx->edgeflag.enabled = nvc0->vertprog->vp.edgeflag < PIPE_MAX_ATTRIBS;
51
52
 
53
   ctx->edgeflag.data = NULL;
54
   ctx->edgeflag.stride = 0;
55
}
56
57
 
58
nvc0_vertex_configure_translate(struct nvc0_context *nvc0, int32_t index_bias)
59
{
60
   struct translate *translate = nvc0->vertex->translate;
61
   unsigned i;
62
63
 
64
      const uint8_t *map;
65
      const struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[i];
66
67
 
68
         map = (const uint8_t *)vb->user_buffer;
69
      else
70
         map = nouveau_resource_map_offset(&nvc0->base,
71
            nv04_resource(vb->buffer), vb->buffer_offset, NOUVEAU_BO_RD);
72
73
 
74
         map += (intptr_t)index_bias * vb->stride;
75
76
 
77
   }
78
}
79
80
 
81
nvc0_push_map_idxbuf(struct push_context *ctx, struct nvc0_context *nvc0)
82
{
83
   if (nvc0->idxbuf.buffer) {
84
      struct nv04_resource *buf = nv04_resource(nvc0->idxbuf.buffer);
85
      ctx->idxbuf = nouveau_resource_map_offset(&nvc0->base,
86
         buf, nvc0->idxbuf.offset, NOUVEAU_BO_RD);
87
   } else {
88
      ctx->idxbuf = nvc0->idxbuf.user_buffer;
89
   }
90
}
91
92
 
93
nvc0_push_map_edgeflag(struct push_context *ctx, struct nvc0_context *nvc0,
94
                       int32_t index_bias)
95
{
96
   unsigned attr = nvc0->vertprog->vp.edgeflag;
97
   struct pipe_vertex_element *ve = &nvc0->vertex->element[attr].pipe;
98
   struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[ve->vertex_buffer_index];
99
   struct nv04_resource *buf = nv04_resource(vb->buffer);
100
101
 
102
   if (buf) {
103
      unsigned offset = vb->buffer_offset + ve->src_offset;
104
      ctx->edgeflag.data = nouveau_resource_map_offset(&nvc0->base,
105
                           buf, offset, NOUVEAU_BO_RD);
106
   } else {
107
      ctx->edgeflag.data = (const uint8_t *)vb->user_buffer + ve->src_offset;
108
   }
109
110
 
111
      ctx->edgeflag.data += (intptr_t)index_bias * vb->stride;
112
}
113
114
 
115
prim_restart_search_i08(const uint8_t *elts, unsigned push, uint8_t index)
116
{
117
   unsigned i;
118
   for (i = 0; i < push && elts[i] != index; ++i);
119
   return i;
120
}
121
122
 
123
prim_restart_search_i16(const uint16_t *elts, unsigned push, uint16_t index)
124
{
125
   unsigned i;
126
   for (i = 0; i < push && elts[i] != index; ++i);
127
   return i;
128
}
129
130
 
131
prim_restart_search_i32(const uint32_t *elts, unsigned push, uint32_t index)
132
{
133
   unsigned i;
134
   for (i = 0; i < push && elts[i] != index; ++i);
135
   return i;
136
}
137
138
 
139
ef_value(const struct push_context *ctx, uint32_t index)
140
{
141
   float *pf = (float *)&ctx->edgeflag.data[index * ctx->edgeflag.stride];
142
   return *pf ? TRUE : FALSE;
143
}
144
145
 
146
ef_toggle(struct push_context *ctx)
147
{
148
   ctx->edgeflag.value = !ctx->edgeflag.value;
149
   return ctx->edgeflag.value;
150
}
151
152
 
153
ef_toggle_search_i08(struct push_context *ctx, const uint8_t *elts, unsigned n)
154
{
155
   unsigned i;
156
   for (i = 0; i < n && ef_value(ctx, elts[i]) == ctx->edgeflag.value; ++i);
157
   return i;
158
}
159
160
 
161
ef_toggle_search_i16(struct push_context *ctx, const uint16_t *elts, unsigned n)
162
{
163
   unsigned i;
164
   for (i = 0; i < n && ef_value(ctx, elts[i]) == ctx->edgeflag.value; ++i);
165
   return i;
166
}
167
168
 
169
ef_toggle_search_i32(struct push_context *ctx, const uint32_t *elts, unsigned n)
170
{
171
   unsigned i;
172
   for (i = 0; i < n && ef_value(ctx, elts[i]) == ctx->edgeflag.value; ++i);
173
   return i;
174
}
175
176
 
177
ef_toggle_search_seq(struct push_context *ctx, unsigned start, unsigned n)
178
{
179
   unsigned i;
180
   for (i = 0; i < n && ef_value(ctx, start++) == ctx->edgeflag.value; ++i);
181
   return i;
182
}
183
184
 
185
nvc0_push_setup_vertex_array(struct nvc0_context *nvc0, const unsigned count)
186
{
187
   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
188
   struct nouveau_bo *bo;
189
   uint64_t va;
190
   const unsigned size = count * nvc0->vertex->size;
191
192
 
193
194
 
195
   PUSH_DATAh(push, va);
196
   PUSH_DATA (push, va);
197
   BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(0)), 2);
198
   PUSH_DATAh(push, va + size - 1);
199
   PUSH_DATA (push, va + size - 1);
200
201
 
202
                bo);
203
   nouveau_pushbuf_validate(push);
204
205
 
206
}
207
208
 
209
disp_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)
210
{
211
   struct nouveau_pushbuf *push = ctx->push;
212
   struct translate *translate = ctx->translate;
213
   const uint8_t *restrict elts = (uint8_t *)ctx->idxbuf + start;
214
   unsigned pos = 0;
215
216
 
217
      unsigned nR = count;
218
219
 
220
         nR = prim_restart_search_i08(elts, nR, ctx->restart_index);
221
222
 
223
      count -= nR;
224
      ctx->dest += nR * ctx->vertex_size;
225
226
 
227
         unsigned nE = nR;
228
229
 
230
            nE = ef_toggle_search_i08(ctx, elts, nR);
231
232
 
233
         if (likely(nE >= 2)) {
234
            BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2);
235
            PUSH_DATA (push, pos);
236
            PUSH_DATA (push, nE);
237
         } else
238
         if (nE) {
239
            if (pos <= 0xff) {
240
               IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_U32), pos);
241
            } else {
242
               BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1);
243
               PUSH_DATA (push, pos);
244
            }
245
         }
246
         if (unlikely(nE != nR))
247
            IMMED_NVC0(push, NVC0_3D(EDGEFLAG), ef_toggle(ctx));
248
249
 
250
         elts += nE;
251
         nR -= nE;
252
      }
253
      if (count) {
254
         BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1);
255
         PUSH_DATA (push, 0xffffffff);
256
         ++elts;
257
         ctx->dest += ctx->vertex_size;
258
         ++pos;
259
         --count;
260
      }
261
   } while (count);
262
}
263
264
 
265
disp_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)
266
{
267
   struct nouveau_pushbuf *push = ctx->push;
268
   struct translate *translate = ctx->translate;
269
   const uint16_t *restrict elts = (uint16_t *)ctx->idxbuf + start;
270
   unsigned pos = 0;
271
272
 
273
      unsigned nR = count;
274
275
 
276
         nR = prim_restart_search_i16(elts, nR, ctx->restart_index);
277
278
 
279
      count -= nR;
280
      ctx->dest += nR * ctx->vertex_size;
281
282
 
283
         unsigned nE = nR;
284
285
 
286
            nE = ef_toggle_search_i16(ctx, elts, nR);
287
288
 
289
         if (likely(nE >= 2)) {
290
            BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2);
291
            PUSH_DATA (push, pos);
292
            PUSH_DATA (push, nE);
293
         } else
294
         if (nE) {
295
            if (pos <= 0xff) {
296
               IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_U32), pos);
297
            } else {
298
               BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1);
299
               PUSH_DATA (push, pos);
300
            }
301
         }
302
         if (unlikely(nE != nR))
303
            IMMED_NVC0(push, NVC0_3D(EDGEFLAG), ef_toggle(ctx));
304
305
 
306
         elts += nE;
307
         nR -= nE;
308
      }
309
      if (count) {
310
         BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1);
311
         PUSH_DATA (push, 0xffffffff);
312
         ++elts;
313
         ctx->dest += ctx->vertex_size;
314
         ++pos;
315
         --count;
316
      }
317
   } while (count);
318
}
319
320
 
321
disp_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)
322
{
323
   struct nouveau_pushbuf *push = ctx->push;
324
   struct translate *translate = ctx->translate;
325
   const uint32_t *restrict elts = (uint32_t *)ctx->idxbuf + start;
326
   unsigned pos = 0;
327
328
 
329
      unsigned nR = count;
330
331
 
332
         nR = prim_restart_search_i32(elts, nR, ctx->restart_index);
333
334
 
335
      count -= nR;
336
      ctx->dest += nR * ctx->vertex_size;
337
338
 
339
         unsigned nE = nR;
340
341
 
342
            nE = ef_toggle_search_i32(ctx, elts, nR);
343
344
 
345
         if (likely(nE >= 2)) {
346
            BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2);
347
            PUSH_DATA (push, pos);
348
            PUSH_DATA (push, nE);
349
         } else
350
         if (nE) {
351
            if (pos <= 0xff) {
352
               IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_U32), pos);
353
            } else {
354
               BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1);
355
               PUSH_DATA (push, pos);
356
            }
357
         }
358
         if (unlikely(nE != nR))
359
            IMMED_NVC0(push, NVC0_3D(EDGEFLAG), ef_toggle(ctx));
360
361
 
362
         elts += nE;
363
         nR -= nE;
364
      }
365
      if (count) {
366
         BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1);
367
         PUSH_DATA (push, 0xffffffff);
368
         ++elts;
369
         ctx->dest += ctx->vertex_size;
370
         ++pos;
371
         --count;
372
      }
373
   } while (count);
374
}
375
376
 
377
disp_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)
378
{
379
   struct nouveau_pushbuf *push = ctx->push;
380
   struct translate *translate = ctx->translate;
381
   unsigned pos = 0;
382
383
 
384
    *  maybe we should avoid that ?
385
    */
386
   translate->run(translate, start, count, 0, ctx->instance_id, ctx->dest);
387
   do {
388
      unsigned nr = count;
389
390
 
391
         nr = ef_toggle_search_seq(ctx, start + pos, nr);
392
393
 
394
      if (likely(nr)) {
395
         BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2);
396
         PUSH_DATA (push, pos);
397
         PUSH_DATA (push, nr);
398
      }
399
      if (unlikely(nr != count))
400
         IMMED_NVC0(push, NVC0_3D(EDGEFLAG), ef_toggle(ctx));
401
402
 
403
      count -= nr;
404
   } while (count);
405
}
406
407
 
408
 
409
   case PIPE_PRIM_##n: return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n
410
411
 
412
nvc0_prim_gl(unsigned prim)
413
{
414
   switch (prim) {
415
   NVC0_PRIM_GL_CASE(POINTS);
416
   NVC0_PRIM_GL_CASE(LINES);
417
   NVC0_PRIM_GL_CASE(LINE_LOOP);
418
   NVC0_PRIM_GL_CASE(LINE_STRIP);
419
   NVC0_PRIM_GL_CASE(TRIANGLES);
420
   NVC0_PRIM_GL_CASE(TRIANGLE_STRIP);
421
   NVC0_PRIM_GL_CASE(TRIANGLE_FAN);
422
   NVC0_PRIM_GL_CASE(QUADS);
423
   NVC0_PRIM_GL_CASE(QUAD_STRIP);
424
   NVC0_PRIM_GL_CASE(POLYGON);
425
   NVC0_PRIM_GL_CASE(LINES_ADJACENCY);
426
   NVC0_PRIM_GL_CASE(LINE_STRIP_ADJACENCY);
427
   NVC0_PRIM_GL_CASE(TRIANGLES_ADJACENCY);
428
   NVC0_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY);
429
   /*
430
   NVC0_PRIM_GL_CASE(PATCHES); */
431
   default:
432
      return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS;
433
   }
434
}
435
436
 
437
nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
438
{
439
   struct push_context ctx;
440
   unsigned i, index_size;
441
   unsigned inst_count = info->instance_count;
442
   unsigned vert_count = info->count;
443
   unsigned prim;
444
445
 
446
447
 
448
449
 
450
      /* this is already taken care of by translate */
451
      IMMED_NVC0(ctx.push, NVC0_3D(VB_ELEMENT_BASE), 0);
452
      nvc0->state.index_bias = 0;
453
   }
454
455
 
456
      nvc0_push_map_edgeflag(&ctx, nvc0, info->index_bias);
457
458
 
459
   ctx.restart_index = info->restart_index;
460
461
 
462
      /* NOTE: I hope we won't ever need that last index (~0).
463
       * If we do, we have to disable primitive restart here always and
464
       * use END,BEGIN to restart. (XXX: would that affect PrimitiveID ?)
465
       * We could also deactive PRIM_RESTART_WITH_DRAW_ARRAYS temporarily,
466
       * and add manual restart to disp_vertices_seq.
467
       */
468
      BEGIN_NVC0(ctx.push, NVC0_3D(PRIM_RESTART_ENABLE), 2);
469
      PUSH_DATA (ctx.push, 1);
470
      PUSH_DATA (ctx.push, info->indexed ? 0xffffffff : info->restart_index);
471
   } else
472
   if (nvc0->state.prim_restart) {
473
      IMMED_NVC0(ctx.push, NVC0_3D(PRIM_RESTART_ENABLE), 0);
474
   }
475
   nvc0->state.prim_restart = info->primitive_restart;
476
477
 
478
      nvc0_push_map_idxbuf(&ctx, nvc0);
479
      index_size = nvc0->idxbuf.index_size;
480
   } else {
481
      if (unlikely(info->count_from_stream_output)) {
482
         struct pipe_context *pipe = &nvc0->base.pipe;
483
         struct nvc0_so_target *targ;
484
         targ = nvc0_so_target(info->count_from_stream_output);
485
         pipe->get_query_result(pipe, targ->pq, TRUE, (void *)&vert_count);
486
         vert_count /= targ->stride;
487
      }
488
      ctx.idxbuf = NULL; /* shut up warnings */
489
      index_size = 0;
490
   }
491
492
 
493
494
 
495
   do {
496
      PUSH_SPACE(ctx.push, 9);
497
498
 
499
      if (unlikely(!ctx.dest))
500
         break;
501
502
 
503
         nvc0_push_upload_vertex_ids(&ctx, nvc0, info);
504
505
 
506
         IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0);
507
      BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_BEGIN_GL), 1);
508
      PUSH_DATA (ctx.push, prim);
509
      switch (index_size) {
510
      case 1:
511
         disp_vertices_i08(&ctx, info->start, vert_count);
512
         break;
513
      case 2:
514
         disp_vertices_i16(&ctx, info->start, vert_count);
515
         break;
516
      case 4:
517
         disp_vertices_i32(&ctx, info->start, vert_count);
518
         break;
519
      default:
520
         assert(index_size == 0);
521
         disp_vertices_seq(&ctx, info->start, vert_count);
522
         break;
523
      }
524
      PUSH_SPACE(ctx.push, 1);
525
      IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_END_GL), 0);
526
527
 
528
         prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
529
         ++ctx.instance_id;
530
      }
531
      nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_VTX_TMP);
532
      nouveau_scratch_done(&nvc0->base);
533
   } while (inst_count);
534
535
 
536
 
537
538
 
539
      PUSH_SPACE(ctx.push, 1);
540
      IMMED_NVC0(ctx.push, NVC0_3D(EDGEFLAG), 1);
541
   }
542
543
 
544
      PUSH_SPACE(ctx.push, 4);
545
      IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ID_REPLACE), 0);
546
      BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ATTRIB_FORMAT(1)), 1);
547
      PUSH_DATA (ctx.push,
548
                 NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST |
549
                 NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT |
550
                 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32);
551
      IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ARRAY_FETCH(1)), 0);
552
   }
553
554
 
555
      nouveau_resource_unmap(nv04_resource(nvc0->idxbuf.buffer));
556
   for (i = 0; i < nvc0->num_vtxbufs; ++i)
557
      nouveau_resource_unmap(nv04_resource(nvc0->vtxbuf[i].buffer));
558
559
 
560
}
561
562
 
563
copy_indices_u8(uint32_t *dst, const uint8_t *elts, uint32_t bias, unsigned n)
564
{
565
   unsigned i;
566
   for (i = 0; i < n; ++i)
567
      dst[i] = elts[i] + bias;
568
}
569
570
 
571
copy_indices_u16(uint32_t *dst, const uint16_t *elts, uint32_t bias, unsigned n)
572
{
573
   unsigned i;
574
   for (i = 0; i < n; ++i)
575
      dst[i] = elts[i] + bias;
576
}
577
578
 
579
copy_indices_u32(uint32_t *dst, const uint32_t *elts, uint32_t bias, unsigned n)
580
{
581
   unsigned i;
582
   for (i = 0; i < n; ++i)
583
      dst[i] = elts[i] + bias;
584
}
585
586
 
587
nvc0_push_upload_vertex_ids(struct push_context *ctx,
588
                            struct nvc0_context *nvc0,
589
                            const struct pipe_draw_info *info)
590
591
 
592
   struct nouveau_pushbuf *push = ctx->push;
593
   struct nouveau_bo *bo;
594
   uint64_t va;
595
   uint32_t *data;
596
   uint32_t format;
597
   unsigned index_size = nvc0->idxbuf.index_size;
598
   unsigned i;
599
   unsigned a = nvc0->vertex->num_elements;
600
601
 
602
      index_size = 4;
603
   data = (uint32_t *)nouveau_scratch_get(&nvc0->base,
604
                                          info->count * index_size, &va, &bo);
605
606
 
607
                bo);
608
   nouveau_pushbuf_validate(push);
609
610
 
611
      if (!info->index_bias) {
612
         memcpy(data, ctx->idxbuf, info->count * index_size);
613
      } else {
614
         switch (nvc0->idxbuf.index_size) {
615
         case 1:
616
            copy_indices_u8(data, ctx->idxbuf, info->index_bias, info->count);
617
            break;
618
         case 2:
619
            copy_indices_u16(data, ctx->idxbuf, info->index_bias, info->count);
620
            break;
621
         default:
622
            copy_indices_u32(data, ctx->idxbuf, info->index_bias, info->count);
623
            break;
624
         }
625
      }
626
   } else {
627
      for (i = 0; i < info->count; ++i)
628
         data[i] = i + (info->start + info->index_bias);
629
   }
630
631
 
632
      NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_UINT;
633
634
 
635
   case 1:
636
      format |= NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_8;
637
      break;
638
   case 2:
639
      format |= NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_16;
640
      break;
641
   default:
642
      format |= NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32;
643
      break;
644
   }
645
646
 
647
648
 
649
      nvc0->state.instance_elts &= ~2;
650
      IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_PER_INSTANCE(1)), 0);
651
   }
652
653
 
654
   PUSH_DATA (push, format);
655
656
 
657
   PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | index_size);
658
   PUSH_DATAh(push, va);
659
   PUSH_DATA (push, va);
660
   BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(1)), 2);
661
   PUSH_DATAh(push, va + info->count * index_size - 1);
662
   PUSH_DATA (push, va + info->count * index_size - 1);
663
664
 
665
   (((0x80 + (a) * 0x10) / 4) << NVC0_3D_VERTEX_ID_REPLACE_SOURCE__SHIFT)
666
667
 
668
   PUSH_DATA (push, NVC0_3D_VERTEX_ID_REPLACE_SOURCE_ATTR_X(a) | 1);
669
}
670