Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  5.  * Copyright (C) 2010 LunarG Inc.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23.  * DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26. #define CONCAT2(name, elt_type) name ## elt_type
  27. #define CONCAT(name, elt_type) CONCAT2(name, elt_type)
  28.  
  29. #ifdef ELT_TYPE
  30.  
  31. /**
  32.  * Fetch all elements in [min_index, max_index] with bias, and use the
  33.  * (rebased) index buffer as the draw elements.
  34.  */
  35. static boolean
  36. CONCAT(vsplit_primitive_, ELT_TYPE)(struct vsplit_frontend *vsplit,
  37.                                     unsigned istart, unsigned icount)
  38. {
  39.    struct draw_context *draw = vsplit->draw;
  40.    const ELT_TYPE *ib = (const ELT_TYPE *) draw->pt.user.elts;
  41.    const unsigned min_index = draw->pt.user.min_index;
  42.    const unsigned max_index = draw->pt.user.max_index;
  43.    const int elt_bias = draw->pt.user.eltBias;
  44.    unsigned fetch_start, fetch_count;
  45.    const ushort *draw_elts = NULL;
  46.    unsigned i;
  47.    const unsigned start = istart;
  48.    const unsigned end = istart + icount;
  49.  
  50.    /* If the index buffer overflows we'll need to run
  51.     * through the normal paths */
  52.    if (start >= draw->pt.user.eltMax ||
  53.        end > draw->pt.user.eltMax ||
  54.        end < istart || end < icount)
  55.       return FALSE;
  56.  
  57.    /* use the ib directly */
  58.    if (min_index == 0 && sizeof(ib[0]) == sizeof(draw_elts[0])) {
  59.       if (icount > vsplit->max_vertices)
  60.          return FALSE;
  61.  
  62.       for (i = 0; i < icount; i++) {
  63.          ELT_TYPE idx = DRAW_GET_IDX(ib, start + i);
  64.          if (idx < min_index || idx > max_index) {
  65.             debug_printf("warning: index out of range\n");
  66.          }
  67.       }
  68.       draw_elts = (const ushort *) (ib + istart);
  69.    }
  70.    else {
  71.       /* have to go through vsplit->draw_elts */
  72.       if (icount > vsplit->segment_size)
  73.          return FALSE;
  74.    }
  75.  
  76.    /* this is faster only when we fetch less elements than the normal path */
  77.    if (max_index - min_index > icount - 1)
  78.       return FALSE;
  79.  
  80.    if (elt_bias < 0 && (int) min_index < -elt_bias)
  81.       return FALSE;
  82.  
  83.    /* why this check? */
  84.    for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
  85.       if (draw->pt.vertex_element[i].instance_divisor)
  86.          return FALSE;
  87.    }
  88.  
  89.    fetch_start = min_index + elt_bias;
  90.    fetch_count = max_index - min_index + 1;
  91.  
  92.    /* Check for overflow in the fetch_start */
  93.    if (fetch_start < min_index || fetch_start < elt_bias)
  94.       return FALSE;
  95.  
  96.    if (!draw_elts) {
  97.       if (min_index == 0) {
  98.          for (i = 0; i < icount; i++) {
  99.             ELT_TYPE idx = DRAW_GET_IDX(ib, i + start);
  100.  
  101.             if (idx < min_index || idx > max_index) {
  102.                debug_printf("warning: index out of range\n");
  103.             }
  104.             vsplit->draw_elts[i] = (ushort) idx;
  105.          }
  106.       }
  107.       else {
  108.          for (i = 0; i < icount; i++) {
  109.             ELT_TYPE idx = DRAW_GET_IDX(ib, i + start);
  110.  
  111.             if (idx < min_index || idx > max_index) {
  112.                debug_printf("warning: index out of range\n");
  113.             }
  114.             vsplit->draw_elts[i] = (ushort) (idx - min_index);
  115.          }
  116.       }
  117.  
  118.       draw_elts = vsplit->draw_elts;
  119.    }
  120.  
  121.    return vsplit->middle->run_linear_elts(vsplit->middle,
  122.                                           fetch_start, fetch_count,
  123.                                           draw_elts, icount, 0x0);
  124. }
  125.  
  126. /**
  127.  * Use the cache to prepare the fetch and draw elements, and flush.
  128.  *
  129.  * When spoken is TRUE, ispoken replaces istart;  When close is TRUE, iclose is
  130.  * appended.
  131.  */
  132. static INLINE void
  133. CONCAT(vsplit_segment_cache_, ELT_TYPE)(struct vsplit_frontend *vsplit,
  134.                                         unsigned flags,
  135.                                         unsigned istart, unsigned icount,
  136.                                         boolean spoken, unsigned ispoken,
  137.                                         boolean close, unsigned iclose)
  138. {
  139.    struct draw_context *draw = vsplit->draw;
  140.    const ELT_TYPE *ib = (const ELT_TYPE *) draw->pt.user.elts;
  141.    const int ibias = draw->pt.user.eltBias;
  142.    unsigned i;
  143.  
  144.    assert(icount + !!close <= vsplit->segment_size);
  145.  
  146.    vsplit_clear_cache(vsplit);
  147.  
  148.    spoken = !!spoken;
  149.    if (ibias == 0) {
  150.       if (spoken)
  151.          ADD_CACHE(vsplit, ib, 0, ispoken, 0);
  152.  
  153.       for (i = spoken; i < icount; i++) {
  154.          ADD_CACHE(vsplit, ib, istart, i, 0);
  155.       }
  156.  
  157.       if (close)
  158.          ADD_CACHE(vsplit, ib, 0, iclose, 0);
  159.    }
  160.    else if (ibias > 0) {
  161.       if (spoken)
  162.          ADD_CACHE(vsplit, ib, 0, ispoken, ibias);
  163.  
  164.       for (i = spoken; i < icount; i++)
  165.          ADD_CACHE(vsplit, ib, istart, i, ibias);
  166.  
  167.       if (close)
  168.          ADD_CACHE(vsplit, ib, 0, iclose, ibias);
  169.    }
  170.    else {
  171.       if (spoken) {
  172.          ADD_CACHE(vsplit, ib, 0, ispoken, ibias);
  173.       }
  174.  
  175.       for (i = spoken; i < icount; i++) {
  176.          ADD_CACHE(vsplit, ib, istart, i, ibias);
  177.       }
  178.  
  179.       if (close) {
  180.          ADD_CACHE(vsplit, ib, 0, iclose, ibias);
  181.       }
  182.    }
  183.  
  184.    vsplit_flush_cache(vsplit, flags);
  185. }
  186.  
  187. static void
  188. CONCAT(vsplit_segment_simple_, ELT_TYPE)(struct vsplit_frontend *vsplit,
  189.                                          unsigned flags,
  190.                                          unsigned istart,
  191.                                          unsigned icount)
  192. {
  193.    CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
  194.          flags, istart, icount, FALSE, 0, FALSE, 0);
  195. }
  196.  
  197. static void
  198. CONCAT(vsplit_segment_loop_, ELT_TYPE)(struct vsplit_frontend *vsplit,
  199.                                        unsigned flags,
  200.                                        unsigned istart,
  201.                                        unsigned icount,
  202.                                        unsigned i0)
  203. {
  204.    const boolean close_loop = ((flags) == DRAW_SPLIT_BEFORE);
  205.  
  206.    CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
  207.          flags, istart, icount, FALSE, 0, close_loop, i0);
  208. }
  209.  
  210. static void
  211. CONCAT(vsplit_segment_fan_, ELT_TYPE)(struct vsplit_frontend *vsplit,
  212.                                       unsigned flags,
  213.                                       unsigned istart,
  214.                                       unsigned icount,
  215.                                       unsigned i0)
  216. {
  217.    const boolean use_spoken = (((flags) & DRAW_SPLIT_BEFORE) != 0);
  218.  
  219.    CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
  220.          flags, istart, icount, use_spoken, i0, FALSE, 0);
  221. }
  222.  
  223. #define LOCAL_VARS                                                         \
  224.    struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;   \
  225.    const unsigned prim = vsplit->prim;                                     \
  226.    const unsigned max_count_simple = vsplit->segment_size;                 \
  227.    const unsigned max_count_loop = vsplit->segment_size - 1;               \
  228.    const unsigned max_count_fan = vsplit->segment_size;
  229.  
  230. #define PRIMITIVE(istart, icount)   \
  231.    CONCAT(vsplit_primitive_, ELT_TYPE)(vsplit, istart, icount)
  232.  
  233. #else /* ELT_TYPE */
  234.  
  235. static void
  236. vsplit_segment_simple_linear(struct vsplit_frontend *vsplit, unsigned flags,
  237.                              unsigned istart, unsigned icount)
  238. {
  239.    assert(icount <= vsplit->max_vertices);
  240.    vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
  241. }
  242.  
  243. static void
  244. vsplit_segment_loop_linear(struct vsplit_frontend *vsplit, unsigned flags,
  245.                            unsigned istart, unsigned icount, unsigned i0)
  246. {
  247.    boolean close_loop = (flags == DRAW_SPLIT_BEFORE);
  248.    unsigned nr;
  249.  
  250.    assert(icount + !!close_loop <= vsplit->segment_size);
  251.  
  252.    if (close_loop) {
  253.       for (nr = 0; nr < icount; nr++)
  254.          vsplit->fetch_elts[nr] = istart + nr;
  255.       vsplit->fetch_elts[nr++] = i0;
  256.  
  257.       vsplit->middle->run(vsplit->middle, vsplit->fetch_elts, nr,
  258.             vsplit->identity_draw_elts, nr, flags);
  259.    }
  260.    else {
  261.       vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
  262.    }
  263. }
  264.  
  265. static void
  266. vsplit_segment_fan_linear(struct vsplit_frontend *vsplit, unsigned flags,
  267.                           unsigned istart, unsigned icount, unsigned i0)
  268. {
  269.    boolean use_spoken = ((flags & DRAW_SPLIT_BEFORE) != 0);
  270.    unsigned nr = 0, i;
  271.  
  272.    assert(icount <= vsplit->segment_size);
  273.  
  274.    if (use_spoken) {
  275.       /* replace istart by i0 */
  276.       vsplit->fetch_elts[nr++] = i0;
  277.       for (i = 1 ; i < icount; i++)
  278.          vsplit->fetch_elts[nr++] = istart + i;
  279.  
  280.       vsplit->middle->run(vsplit->middle, vsplit->fetch_elts, nr,
  281.             vsplit->identity_draw_elts, nr, flags);
  282.    }
  283.    else {
  284.       vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
  285.    }
  286. }
  287.  
  288. #define LOCAL_VARS                                                         \
  289.    struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;   \
  290.    const unsigned prim = vsplit->prim;                                     \
  291.    const unsigned max_count_simple = vsplit->max_vertices;                 \
  292.    const unsigned max_count_loop = vsplit->segment_size - 1;               \
  293.    const unsigned max_count_fan = vsplit->segment_size;
  294.  
  295. #define PRIMITIVE(istart, icount) FALSE
  296.  
  297. #define ELT_TYPE linear
  298.  
  299. #endif /* ELT_TYPE */
  300.  
  301. #define FUNC_VARS                      \
  302.    struct draw_pt_front_end *frontend, \
  303.    unsigned start,                     \
  304.    unsigned count
  305.  
  306. #define SEGMENT_SIMPLE(flags, istart, icount)   \
  307.    CONCAT(vsplit_segment_simple_, ELT_TYPE)(vsplit, flags, istart, icount)
  308.  
  309. #define SEGMENT_LOOP(flags, istart, icount, i0) \
  310.    CONCAT(vsplit_segment_loop_, ELT_TYPE)(vsplit, flags, istart, icount, i0)
  311.  
  312. #define SEGMENT_FAN(flags, istart, icount, i0)  \
  313.    CONCAT(vsplit_segment_fan_, ELT_TYPE)(vsplit, flags, istart, icount, i0)
  314.  
  315. #include "draw_split_tmp.h"
  316.  
  317. #undef CONCAT2
  318. #undef CONCAT
  319.  
  320. #undef ELT_TYPE
  321. #undef ADD_CACHE
  322.