Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2009 VMware, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the "Software"),
  7.  * to deal in the Software without restriction, including without limitation
  8.  * on the rights to use, copy, modify, merge, publish, distribute, sub
  9.  * license, and/or sell copies of the Software, and to permit persons to whom
  10.  * the Software is furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the next
  13.  * paragraph) shall be included in all copies or substantial portions of the
  14.  * Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
  19.  * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  20.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  21.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  22.  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25. #include "u_indices.h"
  26. #include "u_indices_priv.h"
  27.  
  28. static void translate_memcpy_ushort( const void *in,
  29.                                      unsigned start,
  30.                                      unsigned in_nr,
  31.                                      unsigned out_nr,
  32.                                      unsigned restart_index,
  33.                                      void *out )
  34. {
  35.    memcpy(out, &((short *)in)[start], out_nr*sizeof(short));
  36. }
  37.                              
  38. static void translate_memcpy_uint( const void *in,
  39.                                    unsigned start,
  40.                                    unsigned in_nr,
  41.                                    unsigned out_nr,
  42.                                    unsigned restart_index,
  43.                                    void *out )
  44. {
  45.    memcpy(out, &((int *)in)[start], out_nr*sizeof(int));
  46. }
  47.                              
  48.  
  49. /**
  50.  * Translate indexes when a driver can't support certain types
  51.  * of drawing.  Example include:
  52.  * - Translate 1-byte indexes into 2-byte indexes
  53.  * - Translate PIPE_PRIM_QUADS into PIPE_PRIM_TRIANGLES when the hardware
  54.  *   doesn't support the former.
  55.  * - Translate from first provoking vertex to last provoking vertex and
  56.  *   vice versa.
  57.  *
  58.  * \param hw_mask  mask of (1 << PIPE_PRIM_x) flags indicating which types
  59.  *                 of primitives are supported by the hardware.
  60.  * \param prim  incoming PIPE_PRIM_x
  61.  * \param in_index_size  bytes per index value (1, 2 or 4)
  62.  * \param nr  number of incoming vertices
  63.  * \param in_pv  incoming provoking vertex convention (PV_FIRST or PV_LAST)
  64.  * \param out_pv  desired provoking vertex convention (PV_FIRST or PV_LAST)
  65.  * \param prim_restart  whether primitive restart is disable or enabled
  66.  * \param out_prim  returns new PIPE_PRIM_x we'll translate to
  67.  * \param out_index_size  returns bytes per new index value (2 or 4)
  68.  * \param out_nr  returns number of new vertices
  69.  * \param out_translate  returns the translation function to use by the caller
  70.  */
  71. int u_index_translator( unsigned hw_mask,
  72.                         unsigned prim,
  73.                         unsigned in_index_size,
  74.                         unsigned nr,
  75.                         unsigned in_pv,
  76.                         unsigned out_pv,
  77.                         unsigned prim_restart,
  78.                         unsigned *out_prim,
  79.                         unsigned *out_index_size,
  80.                         unsigned *out_nr,
  81.                         u_translate_func *out_translate )
  82. {
  83.    unsigned in_idx;
  84.    unsigned out_idx;
  85.    int ret = U_TRANSLATE_NORMAL;
  86.  
  87.    assert(in_index_size == 1 ||
  88.           in_index_size == 2 ||
  89.           in_index_size == 4);
  90.  
  91.    u_index_init();
  92.  
  93.    in_idx = in_size_idx(in_index_size);
  94.    *out_index_size = (in_index_size == 4) ? 4 : 2;
  95.    out_idx = out_size_idx(*out_index_size);
  96.  
  97.    if ((hw_mask & (1<<prim)) &&
  98.        in_index_size == *out_index_size &&
  99.        in_pv == out_pv)
  100.    {
  101.       /* Index translation not really needed */
  102.       if (in_index_size == 4)
  103.          *out_translate = translate_memcpy_uint;
  104.       else
  105.          *out_translate = translate_memcpy_ushort;
  106.  
  107.       *out_prim = prim;
  108.       *out_nr = nr;
  109.  
  110.       return U_TRANSLATE_MEMCPY;
  111.    }
  112.    else {
  113.       switch (prim) {
  114.       case PIPE_PRIM_POINTS:
  115.          *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
  116.          *out_prim = PIPE_PRIM_POINTS;
  117.          *out_nr = nr;
  118.          break;
  119.  
  120.       case PIPE_PRIM_LINES:
  121.          *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
  122.          *out_prim = PIPE_PRIM_LINES;
  123.          *out_nr = nr;
  124.          break;
  125.  
  126.       case PIPE_PRIM_LINE_STRIP:
  127.          *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
  128.          *out_prim = PIPE_PRIM_LINES;
  129.          *out_nr = (nr - 1) * 2;
  130.          break;
  131.  
  132.       case PIPE_PRIM_LINE_LOOP:
  133.          *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
  134.          *out_prim = PIPE_PRIM_LINES;
  135.          *out_nr = nr * 2;
  136.          break;
  137.  
  138.       case PIPE_PRIM_TRIANGLES:
  139.          *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
  140.          *out_prim = PIPE_PRIM_TRIANGLES;
  141.          *out_nr = nr;
  142.          break;
  143.  
  144.       case PIPE_PRIM_TRIANGLE_STRIP:
  145.          *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
  146.          *out_prim = PIPE_PRIM_TRIANGLES;
  147.          *out_nr = (nr - 2) * 3;
  148.          break;
  149.  
  150.       case PIPE_PRIM_TRIANGLE_FAN:
  151.          *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
  152.          *out_prim = PIPE_PRIM_TRIANGLES;
  153.          *out_nr = (nr - 2) * 3;
  154.          break;
  155.  
  156.       case PIPE_PRIM_QUADS:
  157.          *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
  158.          *out_prim = PIPE_PRIM_TRIANGLES;
  159.          *out_nr = (nr / 4) * 6;
  160.          break;
  161.  
  162.       case PIPE_PRIM_QUAD_STRIP:
  163.          *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
  164.          *out_prim = PIPE_PRIM_TRIANGLES;
  165.          *out_nr = (nr - 2) * 3;
  166.          break;
  167.  
  168.       case PIPE_PRIM_POLYGON:
  169.          *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
  170.          *out_prim = PIPE_PRIM_TRIANGLES;
  171.          *out_nr = (nr - 2) * 3;
  172.          break;
  173.  
  174.       default:
  175.          assert(0);
  176.          *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
  177.          *out_prim = PIPE_PRIM_POINTS;
  178.          *out_nr = nr;
  179.          return U_TRANSLATE_ERROR;
  180.       }
  181.    }
  182.  
  183.    return ret;
  184. }
  185.  
  186.  
  187. /**
  188.  * If a driver does not support a particular gallium primitive type
  189.  * (such as PIPE_PRIM_QUAD_STRIP) this function can be used to help
  190.  * convert the primitive into a simpler type (like PIPE_PRIM_TRIANGLES).
  191.  *
  192.  * The generator functions generates a number of ushort or uint indexes
  193.  * for drawing the new type of primitive.
  194.  *
  195.  * \param hw_mask  a bitmask of (1 << PIPE_PRIM_x) values that indicates
  196.  *                 kind of primitives are supported by the driver.
  197.  * \param prim  the PIPE_PRIM_x that the user wants to draw
  198.  * \param start  index of first vertex to draw
  199.  * \param nr  number of vertices to draw
  200.  * \param in_pv  user's provoking vertex (PV_FIRST/LAST)
  201.  * \param out_pv  desired proking vertex for the hardware (PV_FIRST/LAST)
  202.  * \param out_prim  returns the new primitive type for the driver
  203.  * \param out_index_size  returns OUT_USHORT or OUT_UINT
  204.  * \param out_nr  returns new number of vertices to draw
  205.  * \param out_generate  returns pointer to the generator function
  206.  */
  207. int u_index_generator( unsigned hw_mask,
  208.                        unsigned prim,
  209.                        unsigned start,
  210.                        unsigned nr,
  211.                        unsigned in_pv,
  212.                        unsigned out_pv,
  213.                        unsigned *out_prim,
  214.                        unsigned *out_index_size,
  215.                        unsigned *out_nr,
  216.                        u_generate_func *out_generate )
  217.  
  218. {
  219.    unsigned out_idx;
  220.  
  221.    u_index_init();
  222.  
  223.    *out_index_size = ((start + nr) > 0xfffe) ? 4 : 2;
  224.    out_idx = out_size_idx(*out_index_size);
  225.  
  226.    if ((hw_mask & (1<<prim)) &&
  227.        (in_pv == out_pv)) {
  228.        
  229.       *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];
  230.       *out_prim = prim;
  231.       *out_nr = nr;
  232.       return U_GENERATE_LINEAR;
  233.    }
  234.    else {
  235.       switch (prim) {
  236.       case PIPE_PRIM_POINTS:
  237.          *out_generate = generate[out_idx][in_pv][out_pv][prim];
  238.          *out_prim = PIPE_PRIM_POINTS;
  239.          *out_nr = nr;
  240.          return U_GENERATE_REUSABLE;
  241.  
  242.       case PIPE_PRIM_LINES:
  243.          *out_generate = generate[out_idx][in_pv][out_pv][prim];
  244.          *out_prim = PIPE_PRIM_LINES;
  245.          *out_nr = nr;
  246.          return U_GENERATE_REUSABLE;
  247.  
  248.       case PIPE_PRIM_LINE_STRIP:
  249.          *out_generate = generate[out_idx][in_pv][out_pv][prim];
  250.          *out_prim = PIPE_PRIM_LINES;
  251.          *out_nr = (nr - 1) * 2;
  252.          return U_GENERATE_REUSABLE;
  253.  
  254.       case PIPE_PRIM_LINE_LOOP:
  255.          *out_generate = generate[out_idx][in_pv][out_pv][prim];
  256.          *out_prim = PIPE_PRIM_LINES;
  257.          *out_nr = nr * 2;
  258.          return U_GENERATE_ONE_OFF;
  259.  
  260.       case PIPE_PRIM_TRIANGLES:
  261.          *out_generate = generate[out_idx][in_pv][out_pv][prim];
  262.          *out_prim = PIPE_PRIM_TRIANGLES;
  263.          *out_nr = nr;
  264.          return U_GENERATE_REUSABLE;
  265.  
  266.       case PIPE_PRIM_TRIANGLE_STRIP:
  267.          *out_generate = generate[out_idx][in_pv][out_pv][prim];
  268.          *out_prim = PIPE_PRIM_TRIANGLES;
  269.          *out_nr = (nr - 2) * 3;
  270.          return U_GENERATE_REUSABLE;
  271.  
  272.       case PIPE_PRIM_TRIANGLE_FAN:
  273.          *out_generate = generate[out_idx][in_pv][out_pv][prim];
  274.          *out_prim = PIPE_PRIM_TRIANGLES;
  275.          *out_nr = (nr - 2) * 3;
  276.          return U_GENERATE_REUSABLE;
  277.  
  278.       case PIPE_PRIM_QUADS:
  279.          *out_generate = generate[out_idx][in_pv][out_pv][prim];
  280.          *out_prim = PIPE_PRIM_TRIANGLES;
  281.          *out_nr = (nr / 4) * 6;
  282.          return U_GENERATE_REUSABLE;
  283.  
  284.       case PIPE_PRIM_QUAD_STRIP:
  285.          *out_generate = generate[out_idx][in_pv][out_pv][prim];
  286.          *out_prim = PIPE_PRIM_TRIANGLES;
  287.          *out_nr = (nr - 2) * 3;
  288.          return U_GENERATE_REUSABLE;
  289.  
  290.       case PIPE_PRIM_POLYGON:
  291.          *out_generate = generate[out_idx][in_pv][out_pv][prim];
  292.          *out_prim = PIPE_PRIM_TRIANGLES;
  293.          *out_nr = (nr - 2) * 3;
  294.          return U_GENERATE_REUSABLE;
  295.  
  296.       default:
  297.          assert(0);
  298.          *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];
  299.          *out_prim = PIPE_PRIM_POINTS;
  300.          *out_nr = nr;
  301.          return U_TRANSLATE_ERROR;
  302.       }
  303.    }
  304. }
  305.