Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1.  
  2. #include "pipe/p_context.h"
  3. #include "pipe/p_state.h"
  4. #include "util/u_inlines.h"
  5. #include "util/u_format.h"
  6. #include "translate/translate.h"
  7.  
  8. #include "nv50_context.h"
  9. #include "nv50_resource.h"
  10.  
  11. #include "nv50_3d.xml.h"
  12.  
  13. struct push_context {
  14.    struct nouveau_pushbuf *push;
  15.  
  16.    const void *idxbuf;
  17.  
  18.    float edgeflag;
  19.    int edgeflag_attr;
  20.  
  21.    uint32_t vertex_words;
  22.    uint32_t packet_vertex_limit;
  23.  
  24.    struct translate *translate;
  25.  
  26.    boolean primitive_restart;
  27.    uint32_t prim;
  28.    uint32_t restart_index;
  29.    uint32_t instance_id;
  30. };
  31.  
  32. static INLINE unsigned
  33. prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index)
  34. {
  35.    unsigned i;
  36.    for (i = 0; i < push; ++i)
  37.       if (elts[i] == index)
  38.          break;
  39.    return i;
  40. }
  41.  
  42. static INLINE unsigned
  43. prim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index)
  44. {
  45.    unsigned i;
  46.    for (i = 0; i < push; ++i)
  47.       if (elts[i] == index)
  48.          break;
  49.    return i;
  50. }
  51.  
  52. static INLINE unsigned
  53. prim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index)
  54. {
  55.    unsigned i;
  56.    for (i = 0; i < push; ++i)
  57.       if (elts[i] == index)
  58.          break;
  59.    return i;
  60. }
  61.  
  62. static void
  63. emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)
  64. {
  65.    uint8_t *elts = (uint8_t *)ctx->idxbuf + start;
  66.  
  67.    while (count) {
  68.       unsigned push = MIN2(count, ctx->packet_vertex_limit);
  69.       unsigned size, nr;
  70.  
  71.       nr = push;
  72.       if (ctx->primitive_restart)
  73.          nr = prim_restart_search_i08(elts, push, ctx->restart_index);
  74.  
  75.       size = ctx->vertex_words * nr;
  76.  
  77.       BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);
  78.  
  79.       ctx->translate->run_elts8(ctx->translate, elts, nr, 0, ctx->instance_id,
  80.                                 ctx->push->cur);
  81.  
  82.       ctx->push->cur += size;
  83.       count -= nr;
  84.       elts += nr;
  85.  
  86.       if (nr != push) {
  87.          count--;
  88.          elts++;
  89.          BEGIN_NV04(ctx->push, NV50_3D(VB_ELEMENT_U32), 1);
  90.          PUSH_DATA (ctx->push, ctx->restart_index);
  91.       }
  92.    }
  93. }
  94.  
  95. static void
  96. emit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)
  97. {
  98.    uint16_t *elts = (uint16_t *)ctx->idxbuf + start;
  99.  
  100.    while (count) {
  101.       unsigned push = MIN2(count, ctx->packet_vertex_limit);
  102.       unsigned size, nr;
  103.  
  104.       nr = push;
  105.       if (ctx->primitive_restart)
  106.          nr = prim_restart_search_i16(elts, push, ctx->restart_index);
  107.  
  108.       size = ctx->vertex_words * nr;
  109.  
  110.       BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);
  111.  
  112.       ctx->translate->run_elts16(ctx->translate, elts, nr, 0, ctx->instance_id,
  113.                                  ctx->push->cur);
  114.  
  115.       ctx->push->cur += size;
  116.       count -= nr;
  117.       elts += nr;
  118.  
  119.       if (nr != push) {
  120.          count--;
  121.          elts++;
  122.          BEGIN_NV04(ctx->push, NV50_3D(VB_ELEMENT_U32), 1);
  123.          PUSH_DATA (ctx->push, ctx->restart_index);
  124.       }
  125.    }
  126. }
  127.  
  128. static void
  129. emit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)
  130. {
  131.    uint32_t *elts = (uint32_t *)ctx->idxbuf + start;
  132.  
  133.    while (count) {
  134.       unsigned push = MIN2(count, ctx->packet_vertex_limit);
  135.       unsigned size, nr;
  136.  
  137.       nr = push;
  138.       if (ctx->primitive_restart)
  139.          nr = prim_restart_search_i32(elts, push, ctx->restart_index);
  140.  
  141.       size = ctx->vertex_words * nr;
  142.  
  143.       BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);
  144.  
  145.       ctx->translate->run_elts(ctx->translate, elts, nr, 0, ctx->instance_id,
  146.                                ctx->push->cur);
  147.  
  148.       ctx->push->cur += size;
  149.       count -= nr;
  150.       elts += nr;
  151.  
  152.       if (nr != push) {
  153.          count--;
  154.          elts++;
  155.          BEGIN_NV04(ctx->push, NV50_3D(VB_ELEMENT_U32), 1);
  156.          PUSH_DATA (ctx->push, ctx->restart_index);
  157.       }
  158.    }
  159. }
  160.  
  161. static void
  162. emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)
  163. {
  164.    while (count) {
  165.       unsigned push = MIN2(count, ctx->packet_vertex_limit);
  166.       unsigned size = ctx->vertex_words * push;
  167.  
  168.       BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);
  169.  
  170.       ctx->translate->run(ctx->translate, start, push, 0, ctx->instance_id,
  171.                           ctx->push->cur);
  172.       ctx->push->cur += size;
  173.       count -= push;
  174.       start += push;
  175.    }
  176. }
  177.  
  178.  
  179. #define NV50_PRIM_GL_CASE(n) \
  180.    case PIPE_PRIM_##n: return NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n
  181.  
  182. static INLINE unsigned
  183. nv50_prim_gl(unsigned prim)
  184. {
  185.    switch (prim) {
  186.    NV50_PRIM_GL_CASE(POINTS);
  187.    NV50_PRIM_GL_CASE(LINES);
  188.    NV50_PRIM_GL_CASE(LINE_LOOP);
  189.    NV50_PRIM_GL_CASE(LINE_STRIP);
  190.    NV50_PRIM_GL_CASE(TRIANGLES);
  191.    NV50_PRIM_GL_CASE(TRIANGLE_STRIP);
  192.    NV50_PRIM_GL_CASE(TRIANGLE_FAN);
  193.    NV50_PRIM_GL_CASE(QUADS);
  194.    NV50_PRIM_GL_CASE(QUAD_STRIP);
  195.    NV50_PRIM_GL_CASE(POLYGON);
  196.    NV50_PRIM_GL_CASE(LINES_ADJACENCY);
  197.    NV50_PRIM_GL_CASE(LINE_STRIP_ADJACENCY);
  198.    NV50_PRIM_GL_CASE(TRIANGLES_ADJACENCY);
  199.    NV50_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY);
  200.    /*
  201.    NV50_PRIM_GL_CASE(PATCHES); */
  202.    default:
  203.       return NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS;
  204.       break;
  205.    }
  206. }
  207.  
  208. void
  209. nv50_push_vbo(struct nv50_context *nv50, const struct pipe_draw_info *info)
  210. {
  211.    struct push_context ctx;
  212.    unsigned i, index_size;
  213.    unsigned inst_count = info->instance_count;
  214.    unsigned vert_count = info->count;
  215.    boolean apply_bias = info->indexed && info->index_bias;
  216.  
  217.    ctx.push = nv50->base.pushbuf;
  218.    ctx.translate = nv50->vertex->translate;
  219.    ctx.packet_vertex_limit = nv50->vertex->packet_vertex_limit;
  220.    ctx.vertex_words = nv50->vertex->vertex_size;
  221.  
  222.    for (i = 0; i < nv50->num_vtxbufs; ++i) {
  223.       const struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i];
  224.       const uint8_t *data;
  225.  
  226.       if (unlikely(vb->buffer))
  227.          data = nouveau_resource_map_offset(&nv50->base,
  228.             nv04_resource(vb->buffer), vb->buffer_offset, NOUVEAU_BO_RD);
  229.       else
  230.          data = vb->user_buffer;
  231.  
  232.       if (apply_bias && likely(!(nv50->vertex->instance_bufs & (1 << i))))
  233.          data += (ptrdiff_t)info->index_bias * vb->stride;
  234.  
  235.       ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
  236.    }
  237.  
  238.    if (info->indexed) {
  239.       if (nv50->idxbuf.buffer) {
  240.          ctx.idxbuf = nouveau_resource_map_offset(&nv50->base,
  241.             nv04_resource(nv50->idxbuf.buffer), nv50->idxbuf.offset,
  242.             NOUVEAU_BO_RD);
  243.       } else {
  244.          ctx.idxbuf = nv50->idxbuf.user_buffer;
  245.       }
  246.       if (!ctx.idxbuf)
  247.          return;
  248.       index_size = nv50->idxbuf.index_size;
  249.       ctx.primitive_restart = info->primitive_restart;
  250.       ctx.restart_index = info->restart_index;
  251.    } else {
  252.       if (unlikely(info->count_from_stream_output)) {
  253.          struct pipe_context *pipe = &nv50->base.pipe;
  254.          struct nv50_so_target *targ;
  255.          targ = nv50_so_target(info->count_from_stream_output);
  256.          if (!targ->pq) {
  257.             NOUVEAU_ERR("draw_stream_output not supported on pre-NVA0 cards\n");
  258.             return;
  259.          }
  260.          pipe->get_query_result(pipe, targ->pq, TRUE, (void *)&vert_count);
  261.          vert_count /= targ->stride;
  262.       }
  263.       ctx.idxbuf = NULL;
  264.       index_size = 0;
  265.       ctx.primitive_restart = FALSE;
  266.       ctx.restart_index = 0;
  267.    }
  268.  
  269.    ctx.instance_id = info->start_instance;
  270.    ctx.prim = nv50_prim_gl(info->mode);
  271.  
  272.    if (info->primitive_restart) {
  273.       BEGIN_NV04(ctx.push, NV50_3D(PRIM_RESTART_ENABLE), 2);
  274.       PUSH_DATA (ctx.push, 1);
  275.       PUSH_DATA (ctx.push, info->restart_index);
  276.    } else
  277.    if (nv50->state.prim_restart) {
  278.       BEGIN_NV04(ctx.push, NV50_3D(PRIM_RESTART_ENABLE), 1);
  279.       PUSH_DATA (ctx.push, 0);
  280.    }
  281.    nv50->state.prim_restart = info->primitive_restart;
  282.  
  283.    while (inst_count--) {
  284.       BEGIN_NV04(ctx.push, NV50_3D(VERTEX_BEGIN_GL), 1);
  285.       PUSH_DATA (ctx.push, ctx.prim);
  286.       switch (index_size) {
  287.       case 0:
  288.          emit_vertices_seq(&ctx, info->start, vert_count);
  289.          break;
  290.       case 1:
  291.          emit_vertices_i08(&ctx, info->start, vert_count);
  292.          break;
  293.       case 2:
  294.          emit_vertices_i16(&ctx, info->start, vert_count);
  295.          break;
  296.       case 4:
  297.          emit_vertices_i32(&ctx, info->start, vert_count);
  298.          break;
  299.       default:
  300.          assert(0);
  301.          break;
  302.       }
  303.       BEGIN_NV04(ctx.push, NV50_3D(VERTEX_END_GL), 1);
  304.       PUSH_DATA (ctx.push, 0);
  305.  
  306.       ctx.instance_id++;
  307.       ctx.prim |= NV50_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
  308.    }
  309. }
  310.