Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**********************************************************
  2.  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person
  5.  * obtaining a copy of this software and associated documentation
  6.  * files (the "Software"), to deal in the Software without
  7.  * restriction, including without limitation the rights to use, copy,
  8.  * modify, merge, publish, distribute, sublicense, and/or sell copies
  9.  * of the Software, and to permit persons to whom the Software is
  10.  * furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice shall be
  13.  * included in all copies or substantial portions of the Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18.  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19.  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20.  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22.  * SOFTWARE.
  23.  *
  24.  **********************************************************/
  25.  
  26. #include "svga_cmd.h"
  27.  
  28. #include "util/u_inlines.h"
  29. #include "indices/u_indices.h"
  30.  
  31. #include "svga_hw_reg.h"
  32. #include "svga_draw.h"
  33. #include "svga_draw_private.h"
  34. #include "svga_context.h"
  35.  
  36.  
  37. #define DBG 0
  38.  
  39.  
  40. static enum pipe_error
  41. generate_indices(struct svga_hwtnl *hwtnl,
  42.                  unsigned nr,
  43.                  unsigned index_size,
  44.                  u_generate_func generate, struct pipe_resource **out_buf)
  45. {
  46.    struct pipe_context *pipe = &hwtnl->svga->pipe;
  47.    struct pipe_transfer *transfer;
  48.    unsigned size = index_size * nr;
  49.    struct pipe_resource *dst = NULL;
  50.    void *dst_map = NULL;
  51.  
  52.    dst = pipe_buffer_create(pipe->screen,
  53.                             PIPE_BIND_INDEX_BUFFER, PIPE_USAGE_DEFAULT, size);
  54.    if (dst == NULL)
  55.       goto fail;
  56.  
  57.    dst_map = pipe_buffer_map(pipe, dst, PIPE_TRANSFER_WRITE, &transfer);
  58.    if (dst_map == NULL)
  59.       goto fail;
  60.  
  61.    generate(0, nr, dst_map);
  62.  
  63.    pipe_buffer_unmap(pipe, transfer);
  64.  
  65.    *out_buf = dst;
  66.    return PIPE_OK;
  67.  
  68. fail:
  69.    if (dst_map)
  70.       pipe_buffer_unmap(pipe, transfer);
  71.  
  72.    if (dst)
  73.       pipe->screen->resource_destroy(pipe->screen, dst);
  74.  
  75.    return PIPE_ERROR_OUT_OF_MEMORY;
  76. }
  77.  
  78.  
  79. static boolean
  80. compare(unsigned cached_nr, unsigned nr, unsigned type)
  81. {
  82.    if (type == U_GENERATE_REUSABLE)
  83.       return cached_nr >= nr;
  84.    else
  85.       return cached_nr == nr;
  86. }
  87.  
  88.  
  89. static enum pipe_error
  90. retrieve_or_generate_indices(struct svga_hwtnl *hwtnl,
  91.                              unsigned prim,
  92.                              unsigned gen_type,
  93.                              unsigned gen_nr,
  94.                              unsigned gen_size,
  95.                              u_generate_func generate,
  96.                              struct pipe_resource **out_buf)
  97. {
  98.    enum pipe_error ret = PIPE_OK;
  99.    int i;
  100.  
  101.    for (i = 0; i < IDX_CACHE_MAX; i++) {
  102.       if (hwtnl->index_cache[prim][i].buffer != NULL &&
  103.           hwtnl->index_cache[prim][i].generate == generate) {
  104.          if (compare(hwtnl->index_cache[prim][i].gen_nr, gen_nr, gen_type)) {
  105.             pipe_resource_reference(out_buf,
  106.                                     hwtnl->index_cache[prim][i].buffer);
  107.  
  108.             if (DBG)
  109.                debug_printf("%s retrieve %d/%d\n", __FUNCTION__, i, gen_nr);
  110.  
  111.             return PIPE_OK;
  112.          }
  113.          else if (gen_type == U_GENERATE_REUSABLE) {
  114.             pipe_resource_reference(&hwtnl->index_cache[prim][i].buffer,
  115.                                     NULL);
  116.  
  117.             if (DBG)
  118.                debug_printf("%s discard %d/%d\n", __FUNCTION__,
  119.                             i, hwtnl->index_cache[prim][i].gen_nr);
  120.  
  121.             break;
  122.          }
  123.       }
  124.    }
  125.  
  126.    if (i == IDX_CACHE_MAX) {
  127.       unsigned smallest = 0;
  128.       unsigned smallest_size = ~0;
  129.  
  130.       for (i = 0; i < IDX_CACHE_MAX && smallest_size; i++) {
  131.          if (hwtnl->index_cache[prim][i].buffer == NULL) {
  132.             smallest = i;
  133.             smallest_size = 0;
  134.          }
  135.          else if (hwtnl->index_cache[prim][i].gen_nr < smallest) {
  136.             smallest = i;
  137.             smallest_size = hwtnl->index_cache[prim][i].gen_nr;
  138.          }
  139.       }
  140.  
  141.       assert(smallest != IDX_CACHE_MAX);
  142.  
  143.       pipe_resource_reference(&hwtnl->index_cache[prim][smallest].buffer,
  144.                               NULL);
  145.  
  146.       if (DBG)
  147.          debug_printf("%s discard smallest %d/%d\n", __FUNCTION__,
  148.                       smallest, smallest_size);
  149.  
  150.       i = smallest;
  151.    }
  152.  
  153.    ret = generate_indices(hwtnl, gen_nr, gen_size, generate, out_buf);
  154.    if (ret != PIPE_OK)
  155.       return ret;
  156.  
  157.    hwtnl->index_cache[prim][i].generate = generate;
  158.    hwtnl->index_cache[prim][i].gen_nr = gen_nr;
  159.    pipe_resource_reference(&hwtnl->index_cache[prim][i].buffer, *out_buf);
  160.  
  161.    if (DBG)
  162.       debug_printf("%s cache %d/%d\n", __FUNCTION__,
  163.                    i, hwtnl->index_cache[prim][i].gen_nr);
  164.  
  165.    return PIPE_OK;
  166. }
  167.  
  168.  
  169. static enum pipe_error
  170. simple_draw_arrays(struct svga_hwtnl *hwtnl,
  171.                    unsigned prim, unsigned start, unsigned count)
  172. {
  173.    SVGA3dPrimitiveRange range;
  174.    unsigned hw_prim;
  175.    unsigned hw_count;
  176.  
  177.    hw_prim = svga_translate_prim(prim, count, &hw_count);
  178.    if (hw_count == 0)
  179.       return PIPE_ERROR_BAD_INPUT;
  180.  
  181.    range.primType = hw_prim;
  182.    range.primitiveCount = hw_count;
  183.    range.indexArray.surfaceId = SVGA3D_INVALID_ID;
  184.    range.indexArray.offset = 0;
  185.    range.indexArray.stride = 0;
  186.    range.indexWidth = 0;
  187.    range.indexBias = start;
  188.  
  189.    /* Min/max index should be calculated prior to applying bias, so we
  190.     * end up with min_index = 0, max_index = count - 1 and everybody
  191.     * looking at those numbers knows to adjust them by
  192.     * range.indexBias.
  193.     */
  194.    return svga_hwtnl_prim(hwtnl, &range, 0, count - 1, NULL);
  195. }
  196.  
  197.  
  198. enum pipe_error
  199. svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
  200.                        unsigned prim, unsigned start, unsigned count)
  201. {
  202.    unsigned gen_prim, gen_size, gen_nr, gen_type;
  203.    u_generate_func gen_func;
  204.    enum pipe_error ret = PIPE_OK;
  205.  
  206.    if (hwtnl->api_fillmode != PIPE_POLYGON_MODE_FILL &&
  207.        prim >= PIPE_PRIM_TRIANGLES) {
  208.       /* Convert unfilled polygons into points, lines, triangles */
  209.       gen_type = u_unfilled_generator(prim,
  210.                                       start,
  211.                                       count,
  212.                                       hwtnl->api_fillmode,
  213.                                       &gen_prim,
  214.                                       &gen_size, &gen_nr, &gen_func);
  215.    }
  216.    else {
  217.       /* Convert PIPE_PRIM_LINE_LOOP to PIPE_PRIM_LINESTRIP,
  218.        * convert PIPE_PRIM_POLYGON to PIPE_PRIM_TRIANGLE_FAN,
  219.        * etc, if needed (as determined by svga_hw_prims mask).
  220.        */
  221.       gen_type = u_index_generator(svga_hw_prims,
  222.                                    prim,
  223.                                    start,
  224.                                    count,
  225.                                    hwtnl->api_pv,
  226.                                    hwtnl->hw_pv,
  227.                                    &gen_prim, &gen_size, &gen_nr, &gen_func);
  228.    }
  229.  
  230.    if (gen_type == U_GENERATE_LINEAR) {
  231.       return simple_draw_arrays(hwtnl, gen_prim, start, count);
  232.    }
  233.    else {
  234.       struct pipe_resource *gen_buf = NULL;
  235.  
  236.       /* Need to draw as indexed primitive.
  237.        * Potentially need to run the gen func to build an index buffer.
  238.        */
  239.       ret = retrieve_or_generate_indices(hwtnl,
  240.                                          prim,
  241.                                          gen_type,
  242.                                          gen_nr,
  243.                                          gen_size, gen_func, &gen_buf);
  244.       if (ret != PIPE_OK)
  245.          goto done;
  246.  
  247.       ret = svga_hwtnl_simple_draw_range_elements(hwtnl,
  248.                                                   gen_buf,
  249.                                                   gen_size,
  250.                                                   start,
  251.                                                   0,
  252.                                                   count - 1,
  253.                                                   gen_prim, 0, gen_nr);
  254.  
  255.       if (ret != PIPE_OK)
  256.          goto done;
  257.  
  258. done:
  259.       if (gen_buf)
  260.          pipe_resource_reference(&gen_buf, NULL);
  261.  
  262.       return ret;
  263.    }
  264. }
  265.