Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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 generate_indices( struct svga_hwtnl *hwtnl,
  41.                                          unsigned nr,
  42.                                          unsigned index_size,
  43.                                          u_generate_func generate,
  44.                                          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,
  54.                              PIPE_USAGE_STATIC,
  55.                              size );
  56.    if (dst == NULL)
  57.       goto fail;
  58.  
  59.    dst_map = pipe_buffer_map( pipe, dst, PIPE_TRANSFER_WRITE,
  60.                               &transfer);
  61.    if (dst_map == NULL)
  62.       goto fail;
  63.  
  64.    generate( nr,
  65.              dst_map );
  66.  
  67.    pipe_buffer_unmap( pipe, transfer );
  68.  
  69.    *out_buf = dst;
  70.    return PIPE_OK;
  71.  
  72. fail:
  73.    if (dst_map)
  74.       pipe_buffer_unmap( pipe, transfer );
  75.  
  76.    if (dst)
  77.       pipe->screen->resource_destroy( pipe->screen, dst );
  78.  
  79.    return PIPE_ERROR_OUT_OF_MEMORY;
  80. }
  81.  
  82.  
  83. static boolean compare( unsigned cached_nr,
  84.                         unsigned nr,
  85.                         unsigned type )
  86. {
  87.    if (type == U_GENERATE_REUSABLE)
  88.       return cached_nr >= nr;
  89.    else
  90.       return cached_nr == nr;
  91. }
  92.  
  93.  
  94. static enum pipe_error retrieve_or_generate_indices( struct svga_hwtnl *hwtnl,
  95.                                                      unsigned prim,
  96.                                                      unsigned gen_type,
  97.                                                      unsigned gen_nr,
  98.                                                      unsigned gen_size,
  99.                                                      u_generate_func generate,
  100.                                                      struct pipe_resource **out_buf )
  101. {
  102.    enum pipe_error ret = PIPE_OK;
  103.    int i;
  104.  
  105.    for (i = 0; i < IDX_CACHE_MAX; i++) {
  106.       if (hwtnl->index_cache[prim][i].buffer != NULL &&
  107.           hwtnl->index_cache[prim][i].generate == generate)
  108.       {
  109.          if (compare(hwtnl->index_cache[prim][i].gen_nr, gen_nr, gen_type))
  110.          {
  111.             pipe_resource_reference( out_buf,
  112.                                    hwtnl->index_cache[prim][i].buffer );
  113.  
  114.             if (DBG)
  115.                debug_printf("%s retrieve %d/%d\n", __FUNCTION__, i, gen_nr);
  116.  
  117.             return PIPE_OK;
  118.          }
  119.          else if (gen_type == U_GENERATE_REUSABLE)
  120.          {
  121.             pipe_resource_reference( &hwtnl->index_cache[prim][i].buffer,
  122.                                    NULL );
  123.  
  124.             if (DBG)
  125.                debug_printf("%s discard %d/%d\n", __FUNCTION__,
  126.                             i, hwtnl->index_cache[prim][i].gen_nr);
  127.  
  128.             break;
  129.          }
  130.       }
  131.    }
  132.  
  133.    if (i == IDX_CACHE_MAX)
  134.    {
  135.       unsigned smallest = 0;
  136.       unsigned smallest_size = ~0;
  137.  
  138.       for (i = 0; i < IDX_CACHE_MAX && smallest_size; i++) {
  139.          if (hwtnl->index_cache[prim][i].buffer == NULL)
  140.          {
  141.             smallest = i;
  142.             smallest_size = 0;
  143.          }
  144.          else if (hwtnl->index_cache[prim][i].gen_nr < smallest)
  145.          {
  146.             smallest = i;
  147.             smallest_size = hwtnl->index_cache[prim][i].gen_nr;
  148.          }
  149.       }
  150.  
  151.       assert (smallest != IDX_CACHE_MAX);
  152.  
  153.       pipe_resource_reference( &hwtnl->index_cache[prim][smallest].buffer,
  154.                              NULL );
  155.  
  156.       if (DBG)
  157.          debug_printf("%s discard smallest %d/%d\n", __FUNCTION__,
  158.                       smallest, smallest_size);
  159.  
  160.       i = smallest;
  161.    }
  162.  
  163.    ret = generate_indices( hwtnl,
  164.                            gen_nr,
  165.                            gen_size,
  166.                            generate,
  167.                            out_buf );
  168.    if (ret != PIPE_OK)
  169.       return ret;
  170.  
  171.  
  172.    hwtnl->index_cache[prim][i].generate = generate;
  173.    hwtnl->index_cache[prim][i].gen_nr = gen_nr;
  174.    pipe_resource_reference( &hwtnl->index_cache[prim][i].buffer,
  175.                           *out_buf );
  176.  
  177.    if (DBG)
  178.       debug_printf("%s cache %d/%d\n", __FUNCTION__,
  179.                    i, hwtnl->index_cache[prim][i].gen_nr);
  180.  
  181.    return PIPE_OK;
  182. }
  183.  
  184.  
  185.  
  186. static enum pipe_error
  187. simple_draw_arrays( struct svga_hwtnl *hwtnl,
  188.                     unsigned prim, unsigned start, unsigned count )
  189. {
  190.    SVGA3dPrimitiveRange range;
  191.    unsigned hw_prim;
  192.    unsigned hw_count;
  193.  
  194.    hw_prim = svga_translate_prim(prim, count, &hw_count);
  195.    if (hw_count == 0)
  196.       return PIPE_ERROR_BAD_INPUT;
  197.  
  198.    range.primType = hw_prim;
  199.    range.primitiveCount = hw_count;
  200.    range.indexArray.surfaceId = SVGA3D_INVALID_ID;
  201.    range.indexArray.offset = 0;
  202.    range.indexArray.stride = 0;
  203.    range.indexWidth = 0;
  204.    range.indexBias = start;
  205.  
  206.    /* Min/max index should be calculated prior to applying bias, so we
  207.     * end up with min_index = 0, max_index = count - 1 and everybody
  208.     * looking at those numbers knows to adjust them by
  209.     * range.indexBias.
  210.     */
  211.    return svga_hwtnl_prim( hwtnl, &range, 0, count - 1, NULL );
  212. }
  213.  
  214.  
  215. enum pipe_error
  216. svga_hwtnl_draw_arrays( struct svga_hwtnl *hwtnl,
  217.                         unsigned prim,
  218.                         unsigned start,
  219.                         unsigned count)
  220. {
  221.    unsigned gen_prim, gen_size, gen_nr, gen_type;
  222.    u_generate_func gen_func;
  223.    enum pipe_error ret = PIPE_OK;
  224.  
  225.    if (hwtnl->api_fillmode != PIPE_POLYGON_MODE_FILL &&
  226.        prim >= PIPE_PRIM_TRIANGLES)
  227.    {
  228.       /* Convert unfilled polygons into points, lines, triangles */
  229.       gen_type = u_unfilled_generator( prim,
  230.                                        start,
  231.                                        count,
  232.                                        hwtnl->api_fillmode,
  233.                                        &gen_prim,
  234.                                        &gen_size,
  235.                                        &gen_nr,
  236.                                        &gen_func );
  237.    }
  238.    else {
  239.       /* Convert PIPE_PRIM_LINE_LOOP to PIPE_PRIM_LINESTRIP,
  240.        * convert PIPE_PRIM_POLYGON to PIPE_PRIM_TRIANGLE_FAN,
  241.        * etc, if needed (as determined by svga_hw_prims mask).
  242.        */
  243.       gen_type = u_index_generator( svga_hw_prims,
  244.                                     prim,
  245.                                     start,
  246.                                     count,
  247.                                     hwtnl->api_pv,
  248.                                     hwtnl->hw_pv,
  249.                                     &gen_prim,
  250.                                     &gen_size,
  251.                                     &gen_nr,
  252.                                     &gen_func );
  253.    }
  254.  
  255.    if (gen_type == U_GENERATE_LINEAR) {
  256.       return simple_draw_arrays( hwtnl, gen_prim, start, count );
  257.    }
  258.    else {
  259.       struct pipe_resource *gen_buf = NULL;
  260.  
  261.       /* Need to draw as indexed primitive.
  262.        * Potentially need to run the gen func to build an index buffer.
  263.        */
  264.       ret = retrieve_or_generate_indices( hwtnl,
  265.                                           prim,
  266.                                           gen_type,
  267.                                           gen_nr,
  268.                                           gen_size,
  269.                                           gen_func,
  270.                                           &gen_buf );
  271.       if (ret != PIPE_OK)
  272.          goto done;
  273.  
  274.       ret = svga_hwtnl_simple_draw_range_elements( hwtnl,
  275.                                                    gen_buf,
  276.                                                    gen_size,
  277.                                                    start,
  278.                                                    0,
  279.                                                    count - 1,
  280.                                                    gen_prim,
  281.                                                    0,
  282.                                                    gen_nr );
  283.  
  284.       if (ret != PIPE_OK)
  285.          goto done;
  286.  
  287.    done:
  288.       if (gen_buf)
  289.          pipe_resource_reference( &gen_buf, NULL );
  290.  
  291.       return ret;
  292.    }
  293. }
  294.