Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright 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.  * Authors:
  26.   *   Keith Whitwell <keith@tungstengraphics.com>
  27.  *    Chia-I Wu <olv@lunarg.com>
  28.  */
  29.  
  30. /* these macros are optional */
  31. #ifndef LOCAL_VARS
  32. #define LOCAL_VARS
  33. #endif
  34. #ifndef FUNC_ENTER
  35. #define FUNC_ENTER do {} while (0)
  36. #endif
  37. #ifndef FUNC_EXIT
  38. #define FUNC_EXIT do {} while (0)
  39. #endif
  40. #ifndef LINE_ADJ
  41. #define LINE_ADJ(flags, a0, i0, i1, a1) LINE(flags, i0, i1)
  42. #endif
  43. #ifndef TRIANGLE_ADJ
  44. #define TRIANGLE_ADJ(flags, i0, a0, i1, a1, i2, a2) TRIANGLE(flags, i0, i1, i2)
  45. #endif
  46.  
  47. static void
  48. FUNC(FUNC_VARS)
  49. {
  50.    unsigned idx[6], i;
  51.    ushort flags;
  52.    LOCAL_VARS
  53.  
  54.    FUNC_ENTER;
  55.  
  56.    /* prim, prim_flags, count, and last_vertex_last should have been defined */
  57.    if (0) {
  58.       debug_printf("%s: prim 0x%x, prim_flags 0x%x, count %d, last_vertex_last %d\n",
  59.             __FUNCTION__, prim, prim_flags, count, last_vertex_last);
  60.    }
  61.  
  62.    switch (prim) {
  63.    case PIPE_PRIM_POINTS:
  64.       for (i = 0; i < count; i++) {
  65.          idx[0] = GET_ELT(i);
  66.          POINT(idx[0]);
  67.       }
  68.       break;
  69.  
  70.    case PIPE_PRIM_LINES:
  71.       flags = DRAW_PIPE_RESET_STIPPLE;
  72.       for (i = 0; i + 1 < count; i += 2) {
  73.          idx[0] = GET_ELT(i);
  74.          idx[1] = GET_ELT(i + 1);
  75.          LINE(flags, idx[0], idx[1]);
  76.       }
  77.       break;
  78.  
  79.    case PIPE_PRIM_LINE_LOOP:
  80.    case PIPE_PRIM_LINE_STRIP:
  81.       if (count >= 2) {
  82.          flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
  83.          idx[1] = GET_ELT(0);
  84.          idx[2] = idx[1];
  85.  
  86.          for (i = 1; i < count; i++, flags = 0) {
  87.             idx[0] = idx[1];
  88.             idx[1] = GET_ELT(i);
  89.             LINE(flags, idx[0], idx[1]);
  90.          }
  91.          /* close the loop */
  92.          if (prim == PIPE_PRIM_LINE_LOOP && !prim_flags)
  93.             LINE(flags, idx[1], idx[2]);
  94.       }
  95.       break;
  96.  
  97.    case PIPE_PRIM_TRIANGLES:
  98.       flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
  99.       for (i = 0; i + 2 < count; i += 3) {
  100.          idx[0] = GET_ELT(i);
  101.          idx[1] = GET_ELT(i + 1);
  102.          idx[2] = GET_ELT(i + 2);
  103.          TRIANGLE(flags, idx[0], idx[1], idx[2]);
  104.       }
  105.       break;
  106.  
  107.    case PIPE_PRIM_TRIANGLE_STRIP:
  108.       if (count >= 3) {
  109.          flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
  110.          idx[1] = GET_ELT(0);
  111.          idx[2] = GET_ELT(1);
  112.  
  113.          if (last_vertex_last) {
  114.             for (i = 0; i + 2 < count; i++) {
  115.                idx[0] = idx[1];
  116.                idx[1] = idx[2];
  117.                idx[2] = GET_ELT(i + 2);
  118.                /* always emit idx[2] last */
  119.                if (i & 1)
  120.                   TRIANGLE(flags, idx[1], idx[0], idx[2]);
  121.                else
  122.                   TRIANGLE(flags, idx[0], idx[1], idx[2]);
  123.             }
  124.          }
  125.          else {
  126.             for (i = 0; i + 2 < count; i++) {
  127.                idx[0] = idx[1];
  128.                idx[1] = idx[2];
  129.                idx[2] = GET_ELT(i + 2);
  130.                /* always emit idx[0] first */
  131.                if (i & 1)
  132.                   TRIANGLE(flags, idx[0], idx[2], idx[1]);
  133.                else
  134.                   TRIANGLE(flags, idx[0], idx[1], idx[2]);
  135.             }
  136.          }
  137.       }
  138.       break;
  139.  
  140.    case PIPE_PRIM_TRIANGLE_FAN:
  141.       if (count >= 3) {
  142.          flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
  143.          idx[0] = GET_ELT(0);
  144.          idx[2] = GET_ELT(1);
  145.  
  146.          /* idx[0] is neither the first nor the last vertex */
  147.          if (last_vertex_last) {
  148.             for (i = 0; i + 2 < count; i++) {
  149.                idx[1] = idx[2];
  150.                idx[2] = GET_ELT(i + 2);
  151.                /* always emit idx[2] last */
  152.                TRIANGLE(flags, idx[0], idx[1], idx[2]);
  153.             }
  154.          }
  155.          else {
  156.             for (i = 0; i + 2 < count; i++) {
  157.                idx[1] = idx[2];
  158.                idx[2] = GET_ELT(i + 2);
  159.                /* always emit idx[1] first */
  160.                TRIANGLE(flags, idx[1], idx[2], idx[0]);
  161.             }
  162.          }
  163.       }
  164.       break;
  165.  
  166.    case PIPE_PRIM_QUADS:
  167.       if (last_vertex_last) {
  168.          for (i = 0; i + 3 < count; i += 4) {
  169.             idx[0] = GET_ELT(i);
  170.             idx[1] = GET_ELT(i + 1);
  171.             idx[2] = GET_ELT(i + 2);
  172.             idx[3] = GET_ELT(i + 3);
  173.  
  174.             flags = DRAW_PIPE_RESET_STIPPLE |
  175.                     DRAW_PIPE_EDGE_FLAG_0 |
  176.                     DRAW_PIPE_EDGE_FLAG_2;
  177.             /* always emit idx[3] last */
  178.             TRIANGLE(flags, idx[0], idx[1], idx[3]);
  179.  
  180.             flags = DRAW_PIPE_EDGE_FLAG_0 |
  181.                     DRAW_PIPE_EDGE_FLAG_1;
  182.             TRIANGLE(flags, idx[1], idx[2], idx[3]);
  183.          }
  184.       }
  185.       else {
  186.          for (i = 0; i + 3 < count; i += 4) {
  187.             idx[0] = GET_ELT(i);
  188.             idx[1] = GET_ELT(i + 1);
  189.             idx[2] = GET_ELT(i + 2);
  190.             idx[3] = GET_ELT(i + 3);
  191.  
  192.             flags = DRAW_PIPE_RESET_STIPPLE |
  193.                     DRAW_PIPE_EDGE_FLAG_0 |
  194.                     DRAW_PIPE_EDGE_FLAG_1;
  195.             /* always emit idx[3] / idx[0] first */
  196.             if (quads_flatshade_last)
  197.                TRIANGLE(flags, idx[3], idx[0], idx[1]);
  198.             else
  199.                TRIANGLE(flags, idx[0], idx[1], idx[2]);
  200.  
  201.             flags = DRAW_PIPE_EDGE_FLAG_1 |
  202.                     DRAW_PIPE_EDGE_FLAG_2;
  203.             if (quads_flatshade_last)
  204.                TRIANGLE(flags, idx[3], idx[1], idx[2]);
  205.             else
  206.                TRIANGLE(flags, idx[0], idx[2], idx[3]);
  207.          }
  208.       }
  209.       break;
  210.  
  211.    case PIPE_PRIM_QUAD_STRIP:
  212.       if (count >= 4) {
  213.          idx[2] = GET_ELT(0);
  214.          idx[3] = GET_ELT(1);
  215.  
  216.          if (last_vertex_last) {
  217.             for (i = 0; i + 3 < count; i += 2) {
  218.                idx[0] = idx[2];
  219.                idx[1] = idx[3];
  220.                idx[2] = GET_ELT(i + 2);
  221.                idx[3] = GET_ELT(i + 3);
  222.  
  223.                /* always emit idx[3] last */
  224.                flags = DRAW_PIPE_RESET_STIPPLE |
  225.                        DRAW_PIPE_EDGE_FLAG_0 |
  226.                        DRAW_PIPE_EDGE_FLAG_2;
  227.                TRIANGLE(flags, idx[2], idx[0], idx[3]);
  228.  
  229.                flags = DRAW_PIPE_EDGE_FLAG_0 |
  230.                        DRAW_PIPE_EDGE_FLAG_1;
  231.                TRIANGLE(flags, idx[0], idx[1], idx[3]);
  232.             }
  233.          }
  234.          else {
  235.             for (i = 0; i + 3 < count; i += 2) {
  236.                idx[0] = idx[2];
  237.                idx[1] = idx[3];
  238.                idx[2] = GET_ELT(i + 2);
  239.                idx[3] = GET_ELT(i + 3);
  240.  
  241.                flags = DRAW_PIPE_RESET_STIPPLE |
  242.                        DRAW_PIPE_EDGE_FLAG_0 |
  243.                        DRAW_PIPE_EDGE_FLAG_1;
  244.                /* always emit idx[3] / idx[0 first */
  245.                if (quads_flatshade_last)
  246.                   TRIANGLE(flags, idx[3], idx[2], idx[0]);
  247.                else
  248.                   TRIANGLE(flags, idx[0], idx[3], idx[2]);
  249.  
  250.                flags = DRAW_PIPE_EDGE_FLAG_1 |
  251.                        DRAW_PIPE_EDGE_FLAG_2;
  252.                if (quads_flatshade_last)
  253.                   TRIANGLE(flags, idx[3], idx[0], idx[1]);
  254.                else
  255.                   TRIANGLE(flags, idx[0], idx[1], idx[3]);
  256.             }
  257.          }
  258.       }
  259.       break;
  260.  
  261.    case PIPE_PRIM_POLYGON:
  262.       if (count >= 3) {
  263.          ushort edge_next, edge_finish;
  264.  
  265.          if (last_vertex_last) {
  266.             flags = (DRAW_PIPE_RESET_STIPPLE |
  267.                      DRAW_PIPE_EDGE_FLAG_0);
  268.             if (!(prim_flags & DRAW_SPLIT_BEFORE))
  269.                flags |= DRAW_PIPE_EDGE_FLAG_2;
  270.  
  271.             edge_next = DRAW_PIPE_EDGE_FLAG_0;
  272.             edge_finish =
  273.                (prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_1;
  274.          }
  275.          else {
  276.             flags = (DRAW_PIPE_RESET_STIPPLE |
  277.                      DRAW_PIPE_EDGE_FLAG_1);
  278.             if (!(prim_flags & DRAW_SPLIT_BEFORE))
  279.                flags |= DRAW_PIPE_EDGE_FLAG_0;
  280.  
  281.             edge_next = DRAW_PIPE_EDGE_FLAG_1;
  282.             edge_finish =
  283.                (prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_2;
  284.          }
  285.  
  286.          idx[0] = GET_ELT(0);
  287.          idx[2] = GET_ELT(1);
  288.  
  289.          for (i = 0; i + 2 < count; i++, flags = edge_next) {
  290.             idx[1] = idx[2];
  291.             idx[2] = GET_ELT(i + 2);
  292.  
  293.             if (i + 3 == count)
  294.                flags |= edge_finish;
  295.  
  296.             /* idx[0] is both the first and the last vertex */
  297.             if (last_vertex_last)
  298.                TRIANGLE(flags, idx[1], idx[2], idx[0]);
  299.             else
  300.                TRIANGLE(flags, idx[0], idx[1], idx[2]);
  301.          }
  302.       }
  303.       break;
  304.  
  305.    case PIPE_PRIM_LINES_ADJACENCY:
  306.       flags = DRAW_PIPE_RESET_STIPPLE;
  307.       for (i = 0; i + 3 < count; i += 4) {
  308.          idx[0] = GET_ELT(i);
  309.          idx[1] = GET_ELT(i + 1);
  310.          idx[2] = GET_ELT(i + 2);
  311.          idx[3] = GET_ELT(i + 3);
  312.          LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
  313.       }
  314.       break;
  315.  
  316.    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
  317.       if (count >= 4) {
  318.          flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
  319.          idx[1] = GET_ELT(0);
  320.          idx[2] = GET_ELT(1);
  321.          idx[3] = GET_ELT(2);
  322.  
  323.          for (i = 1; i + 2 < count; i++, flags = 0) {
  324.             idx[0] = idx[1];
  325.             idx[1] = idx[2];
  326.             idx[2] = idx[3];
  327.             idx[3] = GET_ELT(i + 2);
  328.             LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
  329.          }
  330.       }
  331.       break;
  332.  
  333.    case PIPE_PRIM_TRIANGLES_ADJACENCY:
  334.       flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
  335.       for (i = 0; i + 5 < count; i += 6) {
  336.          idx[0] = GET_ELT(i);
  337.          idx[1] = GET_ELT(i + 1);
  338.          idx[2] = GET_ELT(i + 2);
  339.          idx[3] = GET_ELT(i + 3);
  340.          idx[4] = GET_ELT(i + 4);
  341.          idx[5] = GET_ELT(i + 5);
  342.          TRIANGLE_ADJ(flags, idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
  343.       }
  344.       break;
  345.  
  346.    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
  347.       if (count >= 6) {
  348.          flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
  349.          idx[0] = GET_ELT(1);
  350.          idx[2] = GET_ELT(0);
  351.          idx[4] = GET_ELT(2);
  352.          idx[3] = GET_ELT(4);
  353.  
  354.          /*
  355.           * The vertices of the i-th triangle are stored in
  356.           * idx[0,2,4] = { 2*i, 2*i+2, 2*i+4 };
  357.           *
  358.           * The adjacent vertices are stored in
  359.           * idx[1,3,5] = { 2*i-2, 2*i+6, 2*i+3 }.
  360.           *
  361.           * However, there are two exceptions:
  362.           *
  363.           * For the first triangle, idx[1] = 1;
  364.           * For the  last triangle, idx[3] = 2*i+5.
  365.           */
  366.          if (last_vertex_last) {
  367.             for (i = 0; i + 5 < count; i += 2) {
  368.                idx[1] = idx[0];
  369.  
  370.                idx[0] = idx[2];
  371.                idx[2] = idx[4];
  372.                idx[4] = idx[3];
  373.  
  374.                idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
  375.                idx[5] = GET_ELT(i + 3);
  376.  
  377.                /*
  378.                 * alternate the first two vertices (idx[0] and idx[2]) and the
  379.                 * corresponding adjacent vertices (idx[3] and idx[5]) to have
  380.                 * the correct orientation
  381.                 */
  382.                if (i & 2) {
  383.                   TRIANGLE_ADJ(flags,
  384.                         idx[2], idx[1], idx[0], idx[5], idx[4], idx[3]);
  385.                }
  386.                else {
  387.                   TRIANGLE_ADJ(flags,
  388.                         idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
  389.                }
  390.             }
  391.          }
  392.          else {
  393.             for (i = 0; i + 5 < count; i += 2) {
  394.                idx[1] = idx[0];
  395.  
  396.                idx[0] = idx[2];
  397.                idx[2] = idx[4];
  398.                idx[4] = idx[3];
  399.  
  400.                idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
  401.                idx[5] = GET_ELT(i + 3);
  402.  
  403.                /*
  404.                 * alternate the last two vertices (idx[2] and idx[4]) and the
  405.                 * corresponding adjacent vertices (idx[1] and idx[5]) to have
  406.                 * the correct orientation
  407.                 */
  408.                if (i & 2) {
  409.                   TRIANGLE_ADJ(flags,
  410.                         idx[0], idx[5], idx[4], idx[3], idx[2], idx[1]);
  411.                }
  412.                else {
  413.                   TRIANGLE_ADJ(flags,
  414.                         idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
  415.                }
  416.             }
  417.          }
  418.       }
  419.       break;
  420.  
  421.    default:
  422.       assert(0);
  423.       break;
  424.    }
  425.  
  426.    FUNC_EXIT;
  427. }
  428.  
  429. #undef LOCAL_VARS
  430. #undef FUNC_ENTER
  431. #undef FUNC_EXIT
  432. #undef LINE_ADJ
  433. #undef TRIANGLE_ADJ
  434.  
  435. #undef FUNC
  436. #undef FUNC_VARS
  437. #undef GET_ELT
  438. #undef POINT
  439. #undef LINE
  440. #undef TRIANGLE
  441.