Subversion Repositories Kolibri OS

Rev

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

  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 "draw/draw_context.h"
  27. #include "draw/draw_vertex.h"
  28. #include "draw/draw_pipe.h"
  29. #include "draw/draw_vbuf.h"
  30. #include "draw/draw_private.h"
  31.  
  32. #include "nouveau/nv_object.xml.h"
  33. #include "nv30-40_3d.xml.h"
  34. #include "nv30_context.h"
  35. #include "nv30_format.h"
  36.  
  37. struct nv30_render {
  38.    struct vbuf_render base;
  39.    struct nv30_context *nv30;
  40.  
  41.    struct pipe_transfer *transfer;
  42.    struct pipe_resource *buffer;
  43.    unsigned offset;
  44.    unsigned length;
  45.  
  46.    struct vertex_info vertex_info;
  47.  
  48.    struct nouveau_heap *vertprog;
  49.    uint32_t vtxprog[16][4];
  50.    uint32_t vtxfmt[16];
  51.    uint32_t vtxptr[16];
  52.    uint32_t prim;
  53. };
  54.  
  55. static INLINE struct nv30_render *
  56. nv30_render(struct vbuf_render *render)
  57. {
  58.    return (struct nv30_render *)render;
  59. }
  60.  
  61. static const struct vertex_info *
  62. nv30_render_get_vertex_info(struct vbuf_render *render)
  63. {
  64.    return &nv30_render(render)->vertex_info;
  65. }
  66.  
  67. static boolean
  68. nv30_render_allocate_vertices(struct vbuf_render *render,
  69.                               ushort vertex_size, ushort nr_vertices)
  70. {
  71.    struct nv30_render *r = nv30_render(render);
  72.    struct nv30_context *nv30 = r->nv30;
  73.  
  74.    r->length = vertex_size * nr_vertices;
  75.  
  76.    if (r->offset + r->length >= render->max_vertex_buffer_bytes) {
  77.       pipe_resource_reference(&r->buffer, NULL);
  78.       r->buffer = pipe_buffer_create(&nv30->screen->base.base,
  79.                                      PIPE_BIND_VERTEX_BUFFER, 0,
  80.                                      render->max_vertex_buffer_bytes);
  81.       if (!r->buffer)
  82.          return FALSE;
  83.  
  84.       r->offset = 0;
  85.    }
  86.  
  87.    return TRUE;
  88. }
  89.  
  90. static void *
  91. nv30_render_map_vertices(struct vbuf_render *render)
  92. {
  93.    struct nv30_render *r = nv30_render(render);
  94.    char *map = pipe_buffer_map(&r->nv30->base.pipe, r->buffer,
  95.                                PIPE_TRANSFER_WRITE |
  96.                                PIPE_TRANSFER_UNSYNCHRONIZED, &r->transfer);
  97.    return map + r->offset;
  98. }
  99.  
  100. static void
  101. nv30_render_unmap_vertices(struct vbuf_render *render,
  102.                            ushort min_index, ushort max_index)
  103. {
  104.    struct nv30_render *r = nv30_render(render);
  105.    pipe_buffer_unmap(&r->nv30->base.pipe, r->transfer);
  106. }
  107.  
  108. static void
  109. nv30_render_set_primitive(struct vbuf_render *render, unsigned prim)
  110. {
  111.    struct nv30_render *r = nv30_render(render);
  112.  
  113.    r->prim = nv30_prim_gl(prim);
  114. }
  115.  
  116. static void
  117. nv30_render_draw_elements(struct vbuf_render *render,
  118.                           const ushort *indices, uint count)
  119. {
  120.    struct nv30_render *r = nv30_render(render);
  121.    struct nv30_context *nv30 = r->nv30;
  122.    struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;
  123.    unsigned i;
  124.  
  125.    BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);
  126.    for (i = 0; i < r->vertex_info.num_attribs; i++) {
  127.       PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP,
  128.                        nv04_resource(r->buffer), r->offset + r->vtxptr[i],
  129.                        NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
  130.    }
  131.  
  132.    if (!nv30_state_validate(nv30, FALSE))
  133.       return;
  134.  
  135.    BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
  136.    PUSH_DATA (push, r->prim);
  137.  
  138.    if (count & 1) {
  139.       BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
  140.       PUSH_DATA (push, *indices++);
  141.    }
  142.  
  143.    count >>= 1;
  144.    while (count) {
  145.       unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
  146.       count -= npush;
  147.  
  148.       BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
  149.       while (npush--) {
  150.          PUSH_DATA(push, (indices[1] << 16) | indices[0]);
  151.          indices += 2;
  152.       }
  153.    }
  154.  
  155.    BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
  156.    PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
  157.    PUSH_RESET(push, BUFCTX_VTXTMP);
  158. }
  159.  
  160. static void
  161. nv30_render_draw_arrays(struct vbuf_render *render, unsigned start, uint nr)
  162. {
  163.    struct nv30_render *r = nv30_render(render);
  164.    struct nv30_context *nv30 = r->nv30;
  165.    struct nouveau_pushbuf *push = nv30->base.pushbuf;
  166.    unsigned fn = nr >> 8, pn = nr & 0xff;
  167.    unsigned ps = fn + (pn ? 1 : 0);
  168.    unsigned i;
  169.  
  170.    BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);
  171.    for (i = 0; i < r->vertex_info.num_attribs; i++) {
  172.       PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP,
  173.                        nv04_resource(r->buffer), r->offset + r->vtxptr[i],
  174.                        NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
  175.    }
  176.  
  177.    if (!nv30_state_validate(nv30, FALSE))
  178.       return;
  179.  
  180.    BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
  181.    PUSH_DATA (push, r->prim);
  182.  
  183.    BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), ps);
  184.    while (fn--) {
  185.       PUSH_DATA (push, 0xff000000 | start);
  186.       start += 256;
  187.    }
  188.  
  189.    if (pn)
  190.       PUSH_DATA (push, ((pn - 1) << 24) | start);
  191.  
  192.    BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
  193.    PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
  194.    PUSH_RESET(push, BUFCTX_VTXTMP);
  195. }
  196.  
  197. static void
  198. nv30_render_release_vertices(struct vbuf_render *render)
  199. {
  200.    struct nv30_render *r = nv30_render(render);
  201.    r->offset += r->length;
  202. }
  203.  
  204. static const struct {
  205.    unsigned emit;
  206.    unsigned interp;
  207.    unsigned vp30;
  208.    unsigned vp40;
  209.    unsigned ow40;
  210. } vroute [] = {
  211.    [TGSI_SEMANTIC_POSITION] = { EMIT_4F, INTERP_PERSPECTIVE, 0, 0, 0x00000000 },
  212.    [TGSI_SEMANTIC_COLOR   ] = { EMIT_4F, INTERP_LINEAR     , 3, 1, 0x00000001 },
  213.    [TGSI_SEMANTIC_BCOLOR  ] = { EMIT_4F, INTERP_LINEAR     , 1, 3, 0x00000004 },
  214.    [TGSI_SEMANTIC_FOG     ] = { EMIT_4F, INTERP_PERSPECTIVE, 5, 5, 0x00000010 },
  215.    [TGSI_SEMANTIC_PSIZE   ] = { EMIT_1F_PSIZE, INTERP_POS  , 6, 6, 0x00000020 },
  216.    [TGSI_SEMANTIC_GENERIC ] = { EMIT_4F, INTERP_PERSPECTIVE, 8, 7, 0x00004000 }
  217. };
  218.  
  219. static boolean
  220. vroute_add(struct nv30_render *r, uint attrib, uint sem, uint *idx)
  221. {
  222.    struct pipe_screen *pscreen = &r->nv30->screen->base.base;
  223.    struct nv30_fragprog *fp = r->nv30->fragprog.program;
  224.    struct vertex_info *vinfo = &r->vertex_info;
  225.    enum pipe_format format;
  226.    uint emit = EMIT_OMIT;
  227.    uint result = *idx;
  228.  
  229.    if (sem == TGSI_SEMANTIC_GENERIC && result >= 8) {
  230.       for (result = 0; result < 8; result++) {
  231.          if (fp->texcoord[result] == *idx) {
  232.             emit = vroute[sem].emit;
  233.             break;
  234.          }
  235.       }
  236.    } else {
  237.       emit = vroute[sem].emit;
  238.    }
  239.  
  240.    if (emit == EMIT_OMIT)
  241.       return FALSE;
  242.  
  243.    draw_emit_vertex_attr(vinfo, emit, vroute[sem].interp, attrib);
  244.    format = draw_translate_vinfo_format(emit);
  245.  
  246.    r->vtxfmt[attrib] = nv30_vtxfmt(pscreen, format)->hw;
  247.    r->vtxptr[attrib] = vinfo->size | NV30_3D_VTXBUF_DMA1;
  248.    vinfo->size += draw_translate_vinfo_size(emit);
  249.  
  250.    if (nv30_screen(pscreen)->eng3d->oclass < NV40_3D_CLASS) {
  251.       r->vtxprog[attrib][0] = 0x001f38d8;
  252.       r->vtxprog[attrib][1] = 0x0080001b | (attrib << 9);
  253.       r->vtxprog[attrib][2] = 0x0836106c;
  254.       r->vtxprog[attrib][3] = 0x2000f800 | (result + vroute[sem].vp30) << 2;
  255.    } else {
  256.       r->vtxprog[attrib][0] = 0x401f9c6c;
  257.       r->vtxprog[attrib][1] = 0x0040000d | (attrib << 8);
  258.       r->vtxprog[attrib][2] = 0x8106c083;
  259.       r->vtxprog[attrib][3] = 0x6041ff80 | (result + vroute[sem].vp40) << 2;
  260.    }
  261.  
  262.    *idx = vroute[sem].ow40 << result;
  263.    return TRUE;
  264. }
  265.  
  266. static boolean
  267. nv30_render_validate(struct nv30_context *nv30)
  268. {
  269.    struct nv30_render *r = nv30_render(nv30->draw->render);
  270.    struct nv30_rasterizer_stateobj *rast = nv30->rast;
  271.    struct pipe_screen *pscreen = &nv30->screen->base.base;
  272.    struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;
  273.    struct nouveau_object *eng3d = nv30->screen->eng3d;
  274.    struct nv30_vertprog *vp = nv30->vertprog.program;
  275.    struct vertex_info *vinfo = &r->vertex_info;
  276.    unsigned vp_attribs = 0;
  277.    unsigned vp_results = 0;
  278.    unsigned attrib = 0;
  279.    unsigned pntc;
  280.    int i;
  281.  
  282.    if (!r->vertprog) {
  283.       struct nouveau_heap *heap = nv30_screen(pscreen)->vp_exec_heap;
  284.       if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog)) {
  285.          while (heap->next && heap->size < 16) {
  286.             struct nouveau_heap **evict = heap->next->priv;
  287.             nouveau_heap_free(evict);
  288.          }
  289.  
  290.          if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog))
  291.             return FALSE;
  292.       }
  293.    }
  294.  
  295.    vinfo->num_attribs = 0;
  296.    vinfo->size = 0;
  297.  
  298.    /* setup routing for all necessary vp outputs */
  299.    for (i = 0; i < vp->info.num_outputs && attrib < 16; i++) {
  300.       uint semantic = vp->info.output_semantic_name[i];
  301.       uint index = vp->info.output_semantic_index[i];
  302.       if (vroute_add(r, attrib, semantic, &index)) {
  303.          vp_attribs |= (1 << attrib++);
  304.          vp_results |= index;
  305.       }
  306.    }
  307.  
  308.    /* setup routing for replaced point coords not written by vp */
  309.    if (rast && rast->pipe.point_quad_rasterization)
  310.       pntc = rast->pipe.sprite_coord_enable & 0x000002ff;
  311.    else
  312.       pntc = 0;
  313.  
  314.    while (pntc && attrib < 16) {
  315.       uint index = ffs(pntc) - 1; pntc &= ~(1 << index);
  316.       if (vroute_add(r, attrib, TGSI_SEMANTIC_GENERIC, &index)) {
  317.          vp_attribs |= (1 << attrib++);
  318.          vp_results |= index;
  319.       }
  320.    }
  321.  
  322.    /* modify vertex format for correct stride, and stub out unused ones */
  323.    BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1);
  324.    PUSH_DATA (push, r->vertprog->start);
  325.    r->vtxprog[attrib - 1][3] |= 1;
  326.    for (i = 0; i < attrib; i++) {
  327.       BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);
  328.       PUSH_DATAp(push, r->vtxprog[i], 4);
  329.       r->vtxfmt[i] |= vinfo->size << 8;
  330.    }
  331.    for (; i < 16; i++)
  332.       r->vtxfmt[i]  = NV30_3D_VTXFMT_TYPE_V32_FLOAT;
  333.  
  334.    BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);
  335.    PUSH_DATAf(push, 0.0);
  336.    PUSH_DATAf(push, 0.0);
  337.    PUSH_DATAf(push, 0.0);
  338.    PUSH_DATAf(push, 0.0);
  339.    PUSH_DATAf(push, 1.0);
  340.    PUSH_DATAf(push, 1.0);
  341.    PUSH_DATAf(push, 1.0);
  342.    PUSH_DATAf(push, 1.0);
  343.    BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);
  344.    PUSH_DATAf(push, 0.0);
  345.    PUSH_DATAf(push, 1.0);
  346.  
  347.    BEGIN_NV04(push, NV30_3D(VTXFMT(0)), 16);
  348.    PUSH_DATAp(push, r->vtxfmt, 16);
  349.  
  350.    BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1);
  351.    PUSH_DATA (push, r->vertprog->start);
  352.    BEGIN_NV04(push, NV30_3D(ENGINE), 1);
  353.    PUSH_DATA (push, 0x00000103);
  354.    if (eng3d->oclass >= NV40_3D_CLASS) {
  355.       BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2);
  356.       PUSH_DATA (push, vp_attribs);
  357.       PUSH_DATA (push, vp_results);
  358.    }
  359.  
  360.    vinfo->size /= 4;
  361.    return TRUE;
  362. }
  363.  
  364. void
  365. nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
  366. {
  367.    struct nv30_context *nv30 = nv30_context(pipe);
  368.    struct draw_context *draw = nv30->draw;
  369.    struct pipe_transfer *transfer[PIPE_MAX_ATTRIBS] = {NULL};
  370.    struct pipe_transfer *transferi = NULL;
  371.    int i;
  372.  
  373.    nv30_render_validate(nv30);
  374.  
  375.    if (nv30->draw_dirty & NV30_NEW_VIEWPORT)
  376.       draw_set_viewport_states(draw, 0, 1, &nv30->viewport);
  377.    if (nv30->draw_dirty & NV30_NEW_RASTERIZER)
  378.       draw_set_rasterizer_state(draw, &nv30->rast->pipe, NULL);
  379.    if (nv30->draw_dirty & NV30_NEW_CLIP)
  380.       draw_set_clip_state(draw, &nv30->clip);
  381.    if (nv30->draw_dirty & NV30_NEW_ARRAYS) {
  382.       draw_set_vertex_buffers(draw, 0, nv30->num_vtxbufs, nv30->vtxbuf);
  383.       draw_set_vertex_elements(draw, nv30->vertex->num_elements, nv30->vertex->pipe);
  384.    }
  385.    if (nv30->draw_dirty & NV30_NEW_FRAGPROG) {
  386.       struct nv30_fragprog *fp = nv30->fragprog.program;
  387.       if (!fp->draw)
  388.          fp->draw = draw_create_fragment_shader(draw, &fp->pipe);
  389.       draw_bind_fragment_shader(draw, fp->draw);
  390.    }
  391.    if (nv30->draw_dirty & NV30_NEW_VERTPROG) {
  392.       struct nv30_vertprog *vp = nv30->vertprog.program;
  393.       if (!vp->draw)
  394.          vp->draw = draw_create_vertex_shader(draw, &vp->pipe);
  395.       draw_bind_vertex_shader(draw, vp->draw);
  396.    }
  397.    if (nv30->draw_dirty & NV30_NEW_VERTCONST) {
  398.       if (nv30->vertprog.constbuf) {
  399.          void *map = nv04_resource(nv30->vertprog.constbuf)->data;
  400.          draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0,
  401.                                          map, nv30->vertprog.constbuf_nr);
  402.       }
  403.    }
  404.  
  405.    for (i = 0; i < nv30->num_vtxbufs; i++) {
  406.       const void *map = nv30->vtxbuf[i].user_buffer;
  407.       if (!map) {
  408.          if (!nv30->vtxbuf[i].buffer) {
  409.             continue;
  410.          }
  411.          map = pipe_buffer_map(pipe, nv30->vtxbuf[i].buffer,
  412.                                   PIPE_TRANSFER_UNSYNCHRONIZED |
  413.                                   PIPE_TRANSFER_READ, &transfer[i]);
  414.       }
  415.       draw_set_mapped_vertex_buffer(draw, i, map, ~0);
  416.    }
  417.  
  418.    if (info->indexed) {
  419.       const void *map = nv30->idxbuf.user_buffer;
  420.       if (!map)
  421.          pipe_buffer_map(pipe, nv30->idxbuf.buffer,
  422.                                   PIPE_TRANSFER_UNSYNCHRONIZED |
  423.                                   PIPE_TRANSFER_READ, &transferi);
  424.       draw_set_indexes(draw,
  425.                        (ubyte *) map + nv30->idxbuf.offset,
  426.                        nv30->idxbuf.index_size, ~0);
  427.    } else {
  428.       draw_set_indexes(draw, NULL, 0, 0);
  429.    }
  430.  
  431.    draw_vbo(draw, info);
  432.    draw_flush(draw);
  433.  
  434.    if (info->indexed && transferi)
  435.       pipe_buffer_unmap(pipe, transferi);
  436.    for (i = 0; i < nv30->num_vtxbufs; i++)
  437.       if (transfer[i])
  438.          pipe_buffer_unmap(pipe, transfer[i]);
  439.  
  440.    nv30->draw_dirty = 0;
  441.    nv30_state_release(nv30);
  442. }
  443.  
  444. static void
  445. nv30_render_destroy(struct vbuf_render *render)
  446. {
  447.    FREE(render);
  448. }
  449.  
  450. static struct vbuf_render *
  451. nv30_render_create(struct nv30_context *nv30)
  452. {
  453.    struct nv30_render *r = CALLOC_STRUCT(nv30_render);
  454.    if (!r)
  455.       return NULL;
  456.  
  457.    r->nv30 = nv30;
  458.    r->offset = 1 * 1024 * 1024;
  459.  
  460.    r->base.max_indices = 16 * 1024;
  461.    r->base.max_vertex_buffer_bytes = r->offset;
  462.  
  463.    r->base.get_vertex_info = nv30_render_get_vertex_info;
  464.    r->base.allocate_vertices = nv30_render_allocate_vertices;
  465.    r->base.map_vertices = nv30_render_map_vertices;
  466.    r->base.unmap_vertices = nv30_render_unmap_vertices;
  467.    r->base.set_primitive = nv30_render_set_primitive;
  468.    r->base.draw_elements = nv30_render_draw_elements;
  469.    r->base.draw_arrays = nv30_render_draw_arrays;
  470.    r->base.release_vertices = nv30_render_release_vertices;
  471.    r->base.destroy = nv30_render_destroy;
  472.    return &r->base;
  473. }
  474.  
  475. void
  476. nv30_draw_init(struct pipe_context *pipe)
  477. {
  478.    struct nv30_context *nv30 = nv30_context(pipe);
  479.    struct vbuf_render *render;
  480.    struct draw_context *draw;
  481.    struct draw_stage *stage;
  482.  
  483.    draw = draw_create(pipe);
  484.    if (!draw)
  485.       return;
  486.  
  487.    render = nv30_render_create(nv30);
  488.    if (!render) {
  489.       draw_destroy(draw);
  490.       return;
  491.    }
  492.  
  493.    stage = draw_vbuf_stage(draw, render);
  494.    if (!stage) {
  495.       render->destroy(render);
  496.       draw_destroy(draw);
  497.       return;
  498.    }
  499.  
  500.    draw_set_render(draw, render);
  501.    draw_set_rasterize_stage(draw, stage);
  502.    draw_wide_line_threshold(draw, 10000000.f);
  503.    draw_wide_point_threshold(draw, 10000000.f);
  504.    draw_wide_point_sprites(draw, TRUE);
  505.    nv30->draw = draw;
  506. }
  507.