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 "nvc0_context.h"
  9. #include "nvc0_resource.h"
  10.  
  11. #include "nvc0_3d.xml.h"
  12.  
  13. struct push_context {
  14.    struct nouveau_pushbuf *push;
  15.  
  16.    void *idxbuf;
  17.  
  18.    uint32_t vertex_words;
  19.    uint32_t packet_vertex_limit;
  20.  
  21.    struct translate *translate;
  22.  
  23.    boolean primitive_restart;
  24.    boolean need_vertex_id;
  25.    uint32_t prim;
  26.    uint32_t restart_index;
  27.    uint32_t instance_id;
  28.  
  29.    struct {
  30.       int buffer;
  31.       float value;
  32.       uint8_t *data;
  33.       unsigned offset;
  34.       unsigned stride;
  35.    } edgeflag;
  36. };
  37.  
  38. static void
  39. init_push_context(struct nvc0_context *nvc0, struct push_context *ctx)
  40. {
  41.    struct pipe_vertex_element *ve;
  42.  
  43.    ctx->push = nvc0->base.pushbuf;
  44.    ctx->translate = nvc0->vertex->translate;
  45.  
  46.    if (likely(nvc0->vertex->num_elements < 32))
  47.       ctx->need_vertex_id = nvc0->vertprog->vp.need_vertex_id;
  48.    else
  49.       ctx->need_vertex_id = FALSE;
  50.  
  51.    ctx->edgeflag.buffer = -1;
  52.    ctx->edgeflag.value = 0.5f;
  53.  
  54.    if (unlikely(nvc0->vertprog->vp.edgeflag < PIPE_MAX_ATTRIBS)) {
  55.       ve = &nvc0->vertex->element[nvc0->vertprog->vp.edgeflag].pipe;
  56.       ctx->edgeflag.buffer = ve->vertex_buffer_index;
  57.       ctx->edgeflag.offset = ve->src_offset;
  58.       ctx->packet_vertex_limit = 1;
  59.    } else {
  60.       ctx->packet_vertex_limit = nvc0->vertex->vtx_per_packet_max;
  61.       if (unlikely(ctx->need_vertex_id))
  62.          ctx->packet_vertex_limit = 1;
  63.    }
  64.  
  65.    ctx->vertex_words = nvc0->vertex->vtx_size;
  66. }
  67.  
  68. static INLINE void
  69. set_edgeflag(struct push_context *ctx, unsigned vtx_id)
  70. {
  71.    float f = *(float *)(ctx->edgeflag.data + vtx_id * ctx->edgeflag.stride);
  72.  
  73.    if (ctx->edgeflag.value != f) {
  74.       ctx->edgeflag.value = f;
  75.       IMMED_NVC0(ctx->push, NVC0_3D(EDGEFLAG), f ? 1 : 0);
  76.    }
  77. }
  78.  
  79. static INLINE void
  80. set_vertexid(struct push_context *ctx, uint32_t vtx_id)
  81. {
  82. #if 0
  83.    BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_ID), 1); /* broken on nvc0 */
  84. #else
  85.    BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_DATA), 1); /* as last attribute */
  86. #endif
  87.    PUSH_DATA (ctx->push, vtx_id);
  88. }
  89.  
  90. static INLINE unsigned
  91. prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index)
  92. {
  93.    unsigned i;
  94.    for (i = 0; i < push; ++i)
  95.       if (elts[i] == index)
  96.          break;
  97.    return i;
  98. }
  99.  
  100. static INLINE unsigned
  101. prim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index)
  102. {
  103.    unsigned i;
  104.    for (i = 0; i < push; ++i)
  105.       if (elts[i] == index)
  106.          break;
  107.    return i;
  108. }
  109.  
  110. static INLINE unsigned
  111. prim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index)
  112. {
  113.    unsigned i;
  114.    for (i = 0; i < push; ++i)
  115.       if (elts[i] == index)
  116.          break;
  117.    return i;
  118. }
  119.  
  120. static void
  121. emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)
  122. {
  123.    uint8_t *restrict elts = (uint8_t *)ctx->idxbuf + start;
  124.  
  125.    while (count) {
  126.       unsigned push = MIN2(count, ctx->packet_vertex_limit);
  127.       unsigned size, nr;
  128.  
  129.       nr = push;
  130.       if (ctx->primitive_restart)
  131.          nr = prim_restart_search_i08(elts, push, ctx->restart_index);
  132.  
  133.       if (unlikely(ctx->edgeflag.buffer >= 0) && likely(nr))
  134.          set_edgeflag(ctx, elts[0]);
  135.  
  136.       size = ctx->vertex_words * nr;
  137.  
  138.       BEGIN_NIC0(ctx->push, NVC0_3D(VERTEX_DATA), size);
  139.  
  140.       ctx->translate->run_elts8(ctx->translate, elts, nr, 0, ctx->instance_id,
  141.                                 ctx->push->cur);
  142.       ctx->push->cur += size;
  143.  
  144.       if (unlikely(ctx->need_vertex_id) && likely(size))
  145.          set_vertexid(ctx, elts[0]);
  146.  
  147.       count -= nr;
  148.       elts += nr;
  149.  
  150.       if (nr != push) {
  151.          count--;
  152.          elts++;
  153.          BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_END_GL), 2);
  154.          PUSH_DATA (ctx->push, 0);
  155.          PUSH_DATA (ctx->push, NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_CONT |
  156.                     (ctx->prim & ~NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT));
  157.       }
  158.    }
  159. }
  160.  
  161. static void
  162. emit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)
  163. {
  164.    uint16_t *restrict elts = (uint16_t *)ctx->idxbuf + start;
  165.  
  166.    while (count) {
  167.       unsigned push = MIN2(count, ctx->packet_vertex_limit);
  168.       unsigned size, nr;
  169.  
  170.       nr = push;
  171.       if (ctx->primitive_restart)
  172.          nr = prim_restart_search_i16(elts, push, ctx->restart_index);
  173.  
  174.       if (unlikely(ctx->edgeflag.buffer >= 0) && likely(nr))
  175.          set_edgeflag(ctx, elts[0]);
  176.  
  177.       size = ctx->vertex_words * nr;
  178.  
  179.       BEGIN_NIC0(ctx->push, NVC0_3D(VERTEX_DATA), size);
  180.  
  181.       ctx->translate->run_elts16(ctx->translate, elts, nr, 0, ctx->instance_id,
  182.                                  ctx->push->cur);
  183.       ctx->push->cur += size;
  184.  
  185.       if (unlikely(ctx->need_vertex_id))
  186.          set_vertexid(ctx, elts[0]);
  187.  
  188.       count -= nr;
  189.       elts += nr;
  190.  
  191.       if (nr != push) {
  192.          count--;
  193.          elts++;
  194.          BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_END_GL), 2);
  195.          PUSH_DATA (ctx->push, 0);
  196.          PUSH_DATA (ctx->push, NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_CONT |
  197.                     (ctx->prim & ~NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT));
  198.       }
  199.    }
  200. }
  201.  
  202. static void
  203. emit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)
  204. {
  205.    uint32_t *restrict elts = (uint32_t *)ctx->idxbuf + start;
  206.  
  207.    while (count) {
  208.       unsigned push = MIN2(count, ctx->packet_vertex_limit);
  209.       unsigned size, nr;
  210.  
  211.       nr = push;
  212.       if (ctx->primitive_restart)
  213.          nr = prim_restart_search_i32(elts, push, ctx->restart_index);
  214.  
  215.       if (unlikely(ctx->edgeflag.buffer >= 0) && likely(nr))
  216.          set_edgeflag(ctx, elts[0]);
  217.  
  218.       size = ctx->vertex_words * nr;
  219.  
  220.       BEGIN_NIC0(ctx->push, NVC0_3D(VERTEX_DATA), size);
  221.  
  222.       ctx->translate->run_elts(ctx->translate, elts, nr, 0, ctx->instance_id,
  223.                                ctx->push->cur);
  224.       ctx->push->cur += size;
  225.  
  226.       if (unlikely(ctx->need_vertex_id))
  227.          set_vertexid(ctx, elts[0]);
  228.  
  229.       count -= nr;
  230.       elts += nr;
  231.  
  232.       if (nr != push) {
  233.          count--;
  234.          elts++;
  235.          BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_END_GL), 2);
  236.          PUSH_DATA (ctx->push, 0);
  237.          PUSH_DATA (ctx->push, NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_CONT |
  238.                     (ctx->prim & ~NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT));
  239.       }
  240.    }
  241. }
  242.  
  243. static void
  244. emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)
  245. {
  246.    while (count) {
  247.       unsigned push = MIN2(count, ctx->packet_vertex_limit);
  248.       unsigned size = ctx->vertex_words * push;
  249.  
  250.       if (unlikely(ctx->edgeflag.buffer >= 0))
  251.          set_edgeflag(ctx, start);
  252.  
  253.       BEGIN_NIC0(ctx->push, NVC0_3D(VERTEX_DATA), size);
  254.  
  255.       ctx->translate->run(ctx->translate, start, push, 0, ctx->instance_id,
  256.                           ctx->push->cur);
  257.       ctx->push->cur += size;
  258.  
  259.       if (unlikely(ctx->need_vertex_id))
  260.          set_vertexid(ctx, start);
  261.  
  262.       count -= push;
  263.       start += push;
  264.    }
  265. }
  266.  
  267.  
  268. #define NVC0_PRIM_GL_CASE(n) \
  269.    case PIPE_PRIM_##n: return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n
  270.  
  271. static INLINE unsigned
  272. nvc0_prim_gl(unsigned prim)
  273. {
  274.    switch (prim) {
  275.    NVC0_PRIM_GL_CASE(POINTS);
  276.    NVC0_PRIM_GL_CASE(LINES);
  277.    NVC0_PRIM_GL_CASE(LINE_LOOP);
  278.    NVC0_PRIM_GL_CASE(LINE_STRIP);
  279.    NVC0_PRIM_GL_CASE(TRIANGLES);
  280.    NVC0_PRIM_GL_CASE(TRIANGLE_STRIP);
  281.    NVC0_PRIM_GL_CASE(TRIANGLE_FAN);
  282.    NVC0_PRIM_GL_CASE(QUADS);
  283.    NVC0_PRIM_GL_CASE(QUAD_STRIP);
  284.    NVC0_PRIM_GL_CASE(POLYGON);
  285.    NVC0_PRIM_GL_CASE(LINES_ADJACENCY);
  286.    NVC0_PRIM_GL_CASE(LINE_STRIP_ADJACENCY);
  287.    NVC0_PRIM_GL_CASE(TRIANGLES_ADJACENCY);
  288.    NVC0_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY);
  289.    /*
  290.    NVC0_PRIM_GL_CASE(PATCHES); */
  291.    default:
  292.       return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS;
  293.       break;
  294.    }
  295. }
  296.  
  297. void
  298. nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
  299. {
  300.    struct push_context ctx;
  301.    unsigned i, index_size;
  302.    unsigned inst_count = info->instance_count;
  303.    unsigned vert_count = info->count;
  304.    boolean apply_bias = info->indexed && info->index_bias;
  305.  
  306.    init_push_context(nvc0, &ctx);
  307.  
  308.    for (i = 0; i < nvc0->num_vtxbufs; ++i) {
  309.       uint8_t *data;
  310.       struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[i];
  311.       struct nv04_resource *res = nv04_resource(vb->buffer);
  312.  
  313.       data = nouveau_resource_map_offset(&nvc0->base, res,
  314.                                          vb->buffer_offset, NOUVEAU_BO_RD);
  315.  
  316.       if (apply_bias && likely(!(nvc0->vertex->instance_bufs & (1 << i))))
  317.          data += info->index_bias * vb->stride;
  318.  
  319.       ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
  320.  
  321.       if (unlikely(i == ctx.edgeflag.buffer)) {
  322.          ctx.edgeflag.data = data + ctx.edgeflag.offset;
  323.          ctx.edgeflag.stride = vb->stride;
  324.       }
  325.    }
  326.  
  327.    if (info->indexed) {
  328.       ctx.idxbuf =
  329.          nouveau_resource_map_offset(&nvc0->base,
  330.                                      nv04_resource(nvc0->idxbuf.buffer),
  331.                                      nvc0->idxbuf.offset, NOUVEAU_BO_RD);
  332.       if (!ctx.idxbuf)
  333.          return;
  334.       index_size = nvc0->idxbuf.index_size;
  335.       ctx.primitive_restart = info->primitive_restart;
  336.       ctx.restart_index = info->restart_index;
  337.    } else {
  338.       ctx.idxbuf = NULL;
  339.       index_size = 0;
  340.       ctx.primitive_restart = FALSE;
  341.       ctx.restart_index = 0;
  342.  
  343.       if (info->count_from_stream_output) {
  344.          struct pipe_context *pipe = &nvc0->base.pipe;
  345.          struct nvc0_so_target *targ;
  346.          targ = nvc0_so_target(info->count_from_stream_output);
  347.          pipe->get_query_result(pipe, targ->pq, TRUE, (void*)&vert_count);
  348.          vert_count /= targ->stride;
  349.       }
  350.    }
  351.  
  352.    ctx.instance_id = info->start_instance;
  353.    ctx.prim = nvc0_prim_gl(info->mode);
  354.  
  355.    if (unlikely(ctx.need_vertex_id)) {
  356.       const unsigned a = nvc0->vertex->num_elements;
  357.       BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ATTRIB_FORMAT(a)), 1);
  358.       PUSH_DATA (ctx.push, (a << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT) |
  359.                  NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT |
  360.                  NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32);
  361.       BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ID_REPLACE), 1);
  362.       PUSH_DATA (ctx.push, (((0x80 + a * 0x10) / 4) << 4) | 1);
  363.    }
  364.  
  365.    while (inst_count--) {
  366.       BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_BEGIN_GL), 1);
  367.       PUSH_DATA (ctx.push, ctx.prim);
  368.       switch (index_size) {
  369.       case 0:
  370.          emit_vertices_seq(&ctx, info->start, vert_count);
  371.          break;
  372.       case 1:
  373.          emit_vertices_i08(&ctx, info->start, vert_count);
  374.          break;
  375.       case 2:
  376.          emit_vertices_i16(&ctx, info->start, vert_count);
  377.          break;
  378.       case 4:
  379.          emit_vertices_i32(&ctx, info->start, vert_count);
  380.          break;
  381.       default:
  382.          assert(0);
  383.          break;
  384.       }
  385.       IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_END_GL), 0);
  386.  
  387.       ctx.instance_id++;
  388.       ctx.prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
  389.    }
  390.  
  391.    if (unlikely(ctx.edgeflag.value == 0.0f))
  392.       IMMED_NVC0(ctx.push, NVC0_3D(EDGEFLAG), 1);
  393.  
  394.    if (unlikely(ctx.need_vertex_id)) {
  395.       const unsigned a = nvc0->vertex->num_elements;
  396.       IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ID_REPLACE), 0);
  397.       BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ATTRIB_FORMAT(a)), 1);
  398.       PUSH_DATA (ctx.push,
  399.                  NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST |
  400.                  NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT |
  401.                  NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32);
  402.    }
  403.  
  404.    if (info->indexed)
  405.       nouveau_resource_unmap(nv04_resource(nvc0->idxbuf.buffer));
  406.  
  407.    for (i = 0; i < nvc0->num_vtxbufs; ++i)
  408.       nouveau_resource_unmap(nv04_resource(nvc0->vtxbuf[i].buffer));
  409. }
  410.