Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * OTHER DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Keith Whitwell <keith@tungstengraphics.com>
  26.  */
  27.  
  28.  
  29. /* Template for building functions to plug into the driver interface
  30.  * of t_vb_render.c:
  31.  *     ctx->Driver.QuadFunc
  32.  *     ctx->Driver.TriangleFunc
  33.  *     ctx->Driver.LineFunc
  34.  *     ctx->Driver.PointsFunc
  35.  *
  36.  * DO_TWOSIDE:   Plug back-color values from the VB into backfacing triangles,
  37.  *               and restore vertices afterwards.
  38.  * DO_OFFSET:    Calculate offset for triangles and adjust vertices.  Restore
  39.  *               vertices after rendering.
  40.  * DO_FLAT:      For hardware without native flatshading, copy provoking colors
  41.  *               into the other vertices.  Restore after rendering.
  42.  * DO_UNFILLED:  Decompose triangles to lines and points where appropriate.
  43.  * DO_TWOSTENCIL:Gross hack for two-sided stencil.
  44.  *
  45.  * HAVE_SPEC: Vertices have secondary rgba values.
  46.  *
  47.  * VERT_X(v): Alias for vertex x value.
  48.  * VERT_Y(v): Alias for vertex y value.
  49.  * VERT_Z(v): Alias for vertex z value.
  50.  * DEPTH_SCALE: Scale for constant offset.
  51.  * REVERSE_DEPTH: Viewport depth range reversed.
  52.  *
  53.  * VERTEX: Hardware vertex type.
  54.  * GET_VERTEX(n): Retreive vertex with index n.
  55.  * AREA_IS_CCW(a): Return true if triangle with signed area a is ccw.
  56.  *
  57.  * VERT_SET_RGBA: Assign vertex rgba from VB color.
  58.  * VERT_COPY_RGBA: Copy vertex rgba another vertex.
  59.  * VERT_SAVE_RGBA: Save vertex rgba to a local variable.
  60.  * VERT_RESTORE_RGBA: Restore vertex rgba from a local variable.
  61.  *   --> Similar for SPEC.
  62.  *
  63.  * LOCAL_VARS(n): (At least) define local vars for save/restore rgba.
  64.  *
  65.  */
  66.  
  67. #if HAVE_BACK_COLORS
  68. #define VERT_SET_RGBA( v, c )
  69. #endif
  70.  
  71. #if !HAVE_SPEC
  72. #define VERT_SET_SPEC( v, c ) (void) c
  73. #define VERT_COPY_SPEC( v0, v1 )
  74. #define VERT_SAVE_SPEC( idx )
  75. #define VERT_RESTORE_SPEC( idx )
  76. #if HAVE_BACK_COLORS
  77. #define VERT_COPY_SPEC1( v )
  78. #endif
  79. #else
  80. #if HAVE_BACK_COLORS
  81. #define VERT_SET_SPEC( v, c )
  82. #endif
  83. #endif
  84.  
  85. #if !HAVE_BACK_COLORS
  86. #define VERT_COPY_SPEC1( v )
  87. #define VERT_COPY_RGBA1( v )
  88. #endif
  89.  
  90. #ifndef INSANE_VERTICES
  91. #define VERT_SET_Z(v,val) VERT_Z(v) = val
  92. #define VERT_Z_ADD(v,val) VERT_Z(v) += val
  93. #endif
  94.  
  95. #ifndef REVERSE_DEPTH
  96. #define REVERSE_DEPTH 0
  97. #endif
  98.  
  99. /* disable twostencil for un-aware drivers */
  100. #ifndef HAVE_STENCIL_TWOSIDE
  101. #define HAVE_STENCIL_TWOSIDE 0
  102. #endif
  103. #ifndef DO_TWOSTENCIL
  104. #define DO_TWOSTENCIL 0
  105. #endif
  106. #ifndef SETUP_STENCIL
  107. #define SETUP_STENCIL(f)
  108. #endif
  109. #ifndef UNSET_STENCIL
  110. #define UNSET_STENCIL(f)
  111. #endif
  112.  
  113. #if DO_TRI
  114. static void TAG(triangle)( struct gl_context *ctx, GLuint e0, GLuint e1, GLuint e2 )
  115. {
  116.    struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
  117.    VERTEX *v[3];
  118.    GLfloat offset = 0;
  119.    GLfloat z[3] = { 0 };
  120.    GLenum mode = GL_FILL;
  121.    GLuint facing = 0;
  122.    LOCAL_VARS(3);
  123.  
  124. /*     fprintf(stderr, "%s\n", __FUNCTION__); */
  125.  
  126.    v[0] = (VERTEX *)GET_VERTEX(e0);
  127.    v[1] = (VERTEX *)GET_VERTEX(e1);
  128.    v[2] = (VERTEX *)GET_VERTEX(e2);
  129.  
  130.    if (DO_TWOSIDE || DO_OFFSET || DO_UNFILLED || DO_TWOSTENCIL)
  131.    {
  132.       GLfloat ex = VERT_X(v[0]) - VERT_X(v[2]);
  133.       GLfloat ey = VERT_Y(v[0]) - VERT_Y(v[2]);
  134.       GLfloat fx = VERT_X(v[1]) - VERT_X(v[2]);
  135.       GLfloat fy = VERT_Y(v[1]) - VERT_Y(v[2]);
  136.       GLfloat cc = ex*fy - ey*fx;
  137.  
  138.       if (DO_TWOSIDE || DO_UNFILLED || DO_TWOSTENCIL)
  139.       {
  140.          facing = AREA_IS_CCW( cc ) ^ ctx->Polygon._FrontBit;
  141.  
  142.          if (DO_UNFILLED) {
  143.             if (facing) {
  144.                mode = ctx->Polygon.BackMode;
  145.                if (ctx->Polygon.CullFlag &&
  146.                    ctx->Polygon.CullFaceMode != GL_FRONT) {
  147.                   return;
  148.                }
  149.             } else {
  150.                mode = ctx->Polygon.FrontMode;
  151.                if (ctx->Polygon.CullFlag &&
  152.                    ctx->Polygon.CullFaceMode != GL_BACK) {
  153.                   return;
  154.                }
  155.             }
  156.          }
  157.  
  158.          if (DO_TWOSIDE && facing == 1) {
  159.             if (HAVE_BACK_COLORS) {
  160.                if (!DO_FLAT) {
  161.                   VERT_SAVE_RGBA( 0 );
  162.                   VERT_SAVE_RGBA( 1 );
  163.                   VERT_COPY_RGBA1( v[0] );
  164.                   VERT_COPY_RGBA1( v[1] );
  165.                }
  166.                VERT_SAVE_RGBA( 2 );
  167.                VERT_COPY_RGBA1( v[2] );
  168.                if (HAVE_SPEC) {
  169.                   if (!DO_FLAT) {
  170.                      VERT_SAVE_SPEC( 0 );
  171.                      VERT_SAVE_SPEC( 1 );
  172.                      VERT_COPY_SPEC1( v[0] );
  173.                      VERT_COPY_SPEC1( v[1] );
  174.                   }
  175.                   VERT_SAVE_SPEC( 2 );
  176.                   VERT_COPY_SPEC1( v[2] );
  177.                }
  178.             }
  179.             else {
  180.                GLfloat (*vbcolor)[4] = VB->BackfaceColorPtr->data;
  181.                (void) vbcolor;
  182.  
  183.                if (!DO_FLAT) {
  184.                   VERT_SAVE_RGBA( 0 );
  185.                   VERT_SAVE_RGBA( 1 );
  186.                }
  187.                VERT_SAVE_RGBA( 2 );
  188.  
  189.                if (VB->BackfaceColorPtr->stride) {
  190.                   ASSERT(VB->BackfaceColorPtr->stride == 4*sizeof(GLfloat));
  191.  
  192.                   if (!DO_FLAT) {
  193.                      VERT_SET_RGBA( v[0], vbcolor[e0] );
  194.                      VERT_SET_RGBA( v[1], vbcolor[e1] );
  195.                   }
  196.                   VERT_SET_RGBA( v[2], vbcolor[e2] );
  197.                }
  198.                else {
  199.                   if (!DO_FLAT) {
  200.                      VERT_SET_RGBA( v[0], vbcolor[0] );
  201.                      VERT_SET_RGBA( v[1], vbcolor[0] );
  202.                   }
  203.                   VERT_SET_RGBA( v[2], vbcolor[0] );
  204.                }
  205.  
  206.                if (HAVE_SPEC && VB->BackfaceSecondaryColorPtr) {
  207.                   GLfloat (*vbspec)[4] = VB->BackfaceSecondaryColorPtr->data;
  208.                   ASSERT(VB->BackfaceSecondaryColorPtr->stride == 4*sizeof(GLfloat));
  209.  
  210.                   if (!DO_FLAT) {
  211.                      VERT_SAVE_SPEC( 0 );
  212.                      VERT_SAVE_SPEC( 1 );
  213.                      VERT_SET_SPEC( v[0], vbspec[e0] );
  214.                      VERT_SET_SPEC( v[1], vbspec[e1] );
  215.                   }
  216.                   VERT_SAVE_SPEC( 2 );
  217.                   VERT_SET_SPEC( v[2], vbspec[e2] );
  218.                }
  219.             }
  220.          }
  221.       }
  222.  
  223.  
  224.       if (DO_OFFSET)
  225.       {
  226.          offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
  227.          z[0] = VERT_Z(v[0]);
  228.          z[1] = VERT_Z(v[1]);
  229.          z[2] = VERT_Z(v[2]);
  230.          if (cc * cc > 1e-16) {
  231.             GLfloat ic  = 1.0 / cc;
  232.             GLfloat ez  = z[0] - z[2];
  233.             GLfloat fz  = z[1] - z[2];
  234.             GLfloat a   = ey*fz - ez*fy;
  235.             GLfloat b   = ez*fx - ex*fz;
  236.             GLfloat ac  = a * ic;
  237.             GLfloat bc  = b * ic;
  238.             if ( ac < 0.0f ) ac = -ac;
  239.             if ( bc < 0.0f ) bc = -bc;
  240.             offset += MAX2( ac, bc ) * ctx->Polygon.OffsetFactor / ctx->DrawBuffer->_MRD;
  241.          }
  242.          offset *= ctx->DrawBuffer->_MRD * (REVERSE_DEPTH ? -1.0 : 1.0);
  243.       }
  244.    }
  245.  
  246.    if (DO_FLAT) {
  247.       VERT_SAVE_RGBA( 0 );
  248.       VERT_SAVE_RGBA( 1 );
  249.       VERT_COPY_RGBA( v[0], v[2] );
  250.       VERT_COPY_RGBA( v[1], v[2] );
  251.       if (HAVE_SPEC && VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
  252.          VERT_SAVE_SPEC( 0 );
  253.          VERT_SAVE_SPEC( 1 );
  254.          VERT_COPY_SPEC( v[0], v[2] );
  255.          VERT_COPY_SPEC( v[1], v[2] );
  256.       }
  257.    }
  258.  
  259.    if (mode == GL_POINT) {
  260.       if (DO_OFFSET && ctx->Polygon.OffsetPoint) {
  261.          VERT_Z_ADD(v[0], offset);
  262.          VERT_Z_ADD(v[1], offset);
  263.          VERT_Z_ADD(v[2], offset);
  264.       }
  265.       if (DO_TWOSTENCIL && !HAVE_STENCIL_TWOSIDE && ctx->Stencil.TestTwoSide) {
  266.          SETUP_STENCIL(facing);
  267.          UNFILLED_TRI( ctx, GL_POINT, e0, e1, e2 );
  268.          UNSET_STENCIL(facing);
  269.       } else {
  270.          UNFILLED_TRI( ctx, GL_POINT, e0, e1, e2 );
  271.       }
  272.    } else if (mode == GL_LINE) {
  273.       if (DO_OFFSET && ctx->Polygon.OffsetLine) {
  274.          VERT_Z_ADD(v[0], offset);
  275.          VERT_Z_ADD(v[1], offset);
  276.          VERT_Z_ADD(v[2], offset);
  277.       }
  278.       if (DO_TWOSTENCIL && !HAVE_STENCIL_TWOSIDE && ctx->Stencil.TestTwoSide) {
  279.          SETUP_STENCIL(facing);
  280.          UNFILLED_TRI( ctx, GL_LINE, e0, e1, e2 );
  281.          UNSET_STENCIL(facing);
  282.       } else {
  283.          UNFILLED_TRI( ctx, GL_LINE, e0, e1, e2 );
  284.       }
  285.    } else {
  286.       if (DO_OFFSET && ctx->Polygon.OffsetFill) {
  287.          VERT_Z_ADD(v[0], offset);
  288.          VERT_Z_ADD(v[1], offset);
  289.          VERT_Z_ADD(v[2], offset);
  290.       }
  291.       if (DO_UNFILLED) {
  292.          RASTERIZE( GL_TRIANGLES );
  293.       }
  294.       if (DO_TWOSTENCIL && !HAVE_STENCIL_TWOSIDE && ctx->Stencil.TestTwoSide) {
  295.          SETUP_STENCIL(facing);
  296.          TRI( v[0], v[1], v[2] );
  297.          UNSET_STENCIL(facing);
  298.       } else {
  299.          TRI( v[0], v[1], v[2] );
  300.       }
  301.    }
  302.  
  303.    if (DO_OFFSET)
  304.    {
  305.       VERT_SET_Z(v[0], z[0]);
  306.       VERT_SET_Z(v[1], z[1]);
  307.       VERT_SET_Z(v[2], z[2]);
  308.    }
  309.  
  310.    if (DO_TWOSIDE && facing == 1) {
  311.       if (!DO_FLAT) {
  312.          VERT_RESTORE_RGBA( 0 );
  313.          VERT_RESTORE_RGBA( 1 );
  314.       }
  315.       VERT_RESTORE_RGBA( 2 );
  316.       if (HAVE_SPEC) {
  317.          if (!DO_FLAT) {
  318.             VERT_RESTORE_SPEC( 0 );
  319.             VERT_RESTORE_SPEC( 1 );
  320.          }
  321.          VERT_RESTORE_SPEC( 2 );
  322.       }
  323.    }
  324.  
  325.  
  326.    if (DO_FLAT) {
  327.          VERT_RESTORE_RGBA( 0 );
  328.          VERT_RESTORE_RGBA( 1 );
  329.          if (HAVE_SPEC && VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
  330.             VERT_RESTORE_SPEC( 0 );
  331.             VERT_RESTORE_SPEC( 1 );
  332.          }
  333.    }
  334. }
  335. #endif
  336.  
  337. #if DO_QUAD
  338. #if DO_FULL_QUAD
  339. static void TAG(quadr)( struct gl_context *ctx,
  340.                        GLuint e0, GLuint e1, GLuint e2, GLuint e3 )
  341. {
  342.    struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
  343.    VERTEX *v[4];
  344.    GLfloat offset = 0;
  345.    GLfloat z[4] = { 0 };
  346.    GLenum mode = GL_FILL;
  347.    GLuint facing = 0;
  348.    LOCAL_VARS(4);
  349.  
  350.    v[0] = (VERTEX *)GET_VERTEX(e0);
  351.    v[1] = (VERTEX *)GET_VERTEX(e1);
  352.    v[2] = (VERTEX *)GET_VERTEX(e2);
  353.    v[3] = (VERTEX *)GET_VERTEX(e3);
  354.  
  355.    if (DO_TWOSIDE || DO_OFFSET || DO_UNFILLED || DO_TWOSTENCIL)
  356.    {
  357.       GLfloat ex = VERT_X(v[2]) - VERT_X(v[0]);
  358.       GLfloat ey = VERT_Y(v[2]) - VERT_Y(v[0]);
  359.       GLfloat fx = VERT_X(v[3]) - VERT_X(v[1]);
  360.       GLfloat fy = VERT_Y(v[3]) - VERT_Y(v[1]);
  361.       GLfloat cc = ex*fy - ey*fx;
  362.  
  363.       if (DO_TWOSIDE || DO_UNFILLED || DO_TWOSTENCIL)
  364.       {
  365.          facing = AREA_IS_CCW( cc ) ^ ctx->Polygon._FrontBit;
  366.  
  367.          if (DO_UNFILLED) {
  368.             if (facing) {
  369.                mode = ctx->Polygon.BackMode;
  370.                if (ctx->Polygon.CullFlag &&
  371.                    ctx->Polygon.CullFaceMode != GL_FRONT) {
  372.                   return;
  373.                }
  374.             } else {
  375.                mode = ctx->Polygon.FrontMode;
  376.                if (ctx->Polygon.CullFlag &&
  377.                    ctx->Polygon.CullFaceMode != GL_BACK) {
  378.                   return;
  379.                }
  380.             }
  381.          }
  382.  
  383.          if (DO_TWOSIDE && facing == 1) {
  384.             GLfloat (*vbcolor)[4] = VB->BackfaceColorPtr->data;
  385.             (void)vbcolor;
  386.  
  387.             if (HAVE_BACK_COLORS) {
  388.                if (!DO_FLAT) {
  389.                   VERT_SAVE_RGBA( 0 );
  390.                   VERT_SAVE_RGBA( 1 );
  391.                   VERT_SAVE_RGBA( 2 );
  392.                   VERT_COPY_RGBA1( v[0] );
  393.                   VERT_COPY_RGBA1( v[1] );
  394.                   VERT_COPY_RGBA1( v[2] );
  395.                }
  396.                VERT_SAVE_RGBA( 3 );
  397.                VERT_COPY_RGBA1( v[3] );
  398.                if (HAVE_SPEC) {
  399.                   if (!DO_FLAT) {
  400.                      VERT_SAVE_SPEC( 0 );
  401.                      VERT_SAVE_SPEC( 1 );
  402.                      VERT_SAVE_SPEC( 2 );
  403.                      VERT_COPY_SPEC1( v[0] );
  404.                      VERT_COPY_SPEC1( v[1] );
  405.                      VERT_COPY_SPEC1( v[2] );
  406.                   }
  407.                   VERT_SAVE_SPEC( 3 );
  408.                   VERT_COPY_SPEC1( v[3] );
  409.                }
  410.             }
  411.             else {
  412.                if (!DO_FLAT) {
  413.                   VERT_SAVE_RGBA( 0 );
  414.                   VERT_SAVE_RGBA( 1 );
  415.                   VERT_SAVE_RGBA( 2 );
  416.                }
  417.                VERT_SAVE_RGBA( 3 );
  418.  
  419.                if (VB->BackfaceColorPtr->stride) {
  420.                   if (!DO_FLAT) {
  421.                      VERT_SET_RGBA( v[0], vbcolor[e0] );
  422.                      VERT_SET_RGBA( v[1], vbcolor[e1] );
  423.                      VERT_SET_RGBA( v[2], vbcolor[e2] );
  424.                   }
  425.                   VERT_SET_RGBA( v[3], vbcolor[e3] );
  426.                }
  427.                else {
  428.                   if (!DO_FLAT) {
  429.                      VERT_SET_RGBA( v[0], vbcolor[0] );
  430.                      VERT_SET_RGBA( v[1], vbcolor[0] );
  431.                      VERT_SET_RGBA( v[2], vbcolor[0] );
  432.                   }
  433.                   VERT_SET_RGBA( v[3], vbcolor[0] );
  434.                }
  435.  
  436.                if (HAVE_SPEC && VB->BackfaceSecondaryColorPtr) {
  437.                   GLfloat (*vbspec)[4] = VB->BackfaceSecondaryColorPtr->data;
  438.                   ASSERT(VB->BackfaceSecondaryColorPtr->stride==4*sizeof(GLfloat));
  439.  
  440.                   if (!DO_FLAT) {
  441.                      VERT_SAVE_SPEC( 0 );
  442.                      VERT_SAVE_SPEC( 1 );
  443.                      VERT_SAVE_SPEC( 2 );
  444.                      VERT_SET_SPEC( v[0], vbspec[e0] );
  445.                      VERT_SET_SPEC( v[1], vbspec[e1] );
  446.                      VERT_SET_SPEC( v[2], vbspec[e2] );
  447.                   }
  448.                   VERT_SAVE_SPEC( 3 );
  449.                   VERT_SET_SPEC( v[3], vbspec[e3] );
  450.                }
  451.             }
  452.          }
  453.       }
  454.  
  455.  
  456.       if (DO_OFFSET)
  457.       {
  458.          offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
  459.          z[0] = VERT_Z(v[0]);
  460.          z[1] = VERT_Z(v[1]);
  461.          z[2] = VERT_Z(v[2]);
  462.          z[3] = VERT_Z(v[3]);
  463.          if (cc * cc > 1e-16) {
  464.             GLfloat ez = z[2] - z[0];
  465.             GLfloat fz = z[3] - z[1];
  466.             GLfloat a   = ey*fz - ez*fy;
  467.             GLfloat b   = ez*fx - ex*fz;
  468.             GLfloat ic  = 1.0 / cc;
  469.             GLfloat ac  = a * ic;
  470.             GLfloat bc  = b * ic;
  471.             if ( ac < 0.0f ) ac = -ac;
  472.             if ( bc < 0.0f ) bc = -bc;
  473.             offset += MAX2( ac, bc ) * ctx->Polygon.OffsetFactor / ctx->DrawBuffer->_MRD;
  474.          }
  475.          offset *= ctx->DrawBuffer->_MRD * (REVERSE_DEPTH ? -1.0 : 1.0);
  476.       }
  477.    }
  478.  
  479.    if (DO_FLAT) {
  480.          VERT_SAVE_RGBA( 0 );
  481.          VERT_SAVE_RGBA( 1 );
  482.          VERT_SAVE_RGBA( 2 );
  483.          VERT_COPY_RGBA( v[0], v[3] );
  484.          VERT_COPY_RGBA( v[1], v[3] );
  485.          VERT_COPY_RGBA( v[2], v[3] );
  486.          if (HAVE_SPEC && VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
  487.             VERT_SAVE_SPEC( 0 );
  488.             VERT_SAVE_SPEC( 1 );
  489.             VERT_SAVE_SPEC( 2 );
  490.             VERT_COPY_SPEC( v[0], v[3] );
  491.             VERT_COPY_SPEC( v[1], v[3] );
  492.             VERT_COPY_SPEC( v[2], v[3] );
  493.          }
  494.    }
  495.  
  496.    if (mode == GL_POINT) {
  497.       if (( DO_OFFSET) && ctx->Polygon.OffsetPoint) {
  498.          VERT_Z_ADD(v[0], offset);
  499.          VERT_Z_ADD(v[1], offset);
  500.          VERT_Z_ADD(v[2], offset);
  501.          VERT_Z_ADD(v[3], offset);
  502.       }
  503.       if (DO_TWOSTENCIL && !HAVE_STENCIL_TWOSIDE && ctx->Stencil.TestTwoSide) {
  504.          SETUP_STENCIL(facing);
  505.          UNFILLED_QUAD( ctx, GL_POINT, e0, e1, e2, e3 );
  506.          UNSET_STENCIL(facing);
  507.       } else {
  508.          UNFILLED_QUAD( ctx, GL_POINT, e0, e1, e2, e3 );
  509.       }
  510.    } else if (mode == GL_LINE) {
  511.       if (DO_OFFSET && ctx->Polygon.OffsetLine) {
  512.          VERT_Z_ADD(v[0], offset);
  513.          VERT_Z_ADD(v[1], offset);
  514.          VERT_Z_ADD(v[2], offset);
  515.          VERT_Z_ADD(v[3], offset);
  516.       }
  517.       if (DO_TWOSTENCIL && !HAVE_STENCIL_TWOSIDE && ctx->Stencil.TestTwoSide) {
  518.          SETUP_STENCIL(facing);
  519.          UNFILLED_QUAD( ctx, GL_LINE, e0, e1, e2, e3 );
  520.          UNSET_STENCIL(facing);
  521.       } else {
  522.          UNFILLED_QUAD( ctx, GL_LINE, e0, e1, e2, e3 );
  523.       }
  524.    } else {
  525.       if (DO_OFFSET && ctx->Polygon.OffsetFill) {
  526.          VERT_Z_ADD(v[0], offset);
  527.          VERT_Z_ADD(v[1], offset);
  528.          VERT_Z_ADD(v[2], offset);
  529.          VERT_Z_ADD(v[3], offset);
  530.       }
  531.       RASTERIZE( GL_QUADS );
  532.       if (DO_TWOSTENCIL && !HAVE_STENCIL_TWOSIDE && ctx->Stencil.TestTwoSide) {
  533.          SETUP_STENCIL(facing);
  534.          QUAD( (v[0]), (v[1]), (v[2]), (v[3]) );
  535.          UNSET_STENCIL(facing);
  536.       } else {
  537.          QUAD( (v[0]), (v[1]), (v[2]), (v[3]) );
  538.       }
  539.    }
  540.  
  541.    if (DO_OFFSET)
  542.    {
  543.       VERT_SET_Z(v[0], z[0]);
  544.       VERT_SET_Z(v[1], z[1]);
  545.       VERT_SET_Z(v[2], z[2]);
  546.       VERT_SET_Z(v[3], z[3]);
  547.    }
  548.  
  549.    if (DO_TWOSIDE && facing == 1) {
  550.       if (!DO_FLAT) {
  551.          VERT_RESTORE_RGBA( 0 );
  552.          VERT_RESTORE_RGBA( 1 );
  553.          VERT_RESTORE_RGBA( 2 );
  554.       }
  555.       VERT_RESTORE_RGBA( 3 );
  556.       if (HAVE_SPEC) {
  557.          if (!DO_FLAT) {
  558.             VERT_RESTORE_SPEC( 0 );
  559.             VERT_RESTORE_SPEC( 1 );
  560.             VERT_RESTORE_SPEC( 2 );
  561.          }
  562.          VERT_RESTORE_SPEC( 3 );
  563.       }
  564.    }
  565.  
  566.  
  567.    if (DO_FLAT) {
  568.          VERT_RESTORE_RGBA( 0 );
  569.          VERT_RESTORE_RGBA( 1 );
  570.          VERT_RESTORE_RGBA( 2 );
  571.          if (HAVE_SPEC && VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
  572.             VERT_RESTORE_SPEC( 0 );
  573.             VERT_RESTORE_SPEC( 1 );
  574.             VERT_RESTORE_SPEC( 2 );
  575.          }
  576.    }
  577. }
  578. #else
  579. static void TAG(quadr)( struct gl_context *ctx, GLuint e0,
  580.                        GLuint e1, GLuint e2, GLuint e3 )
  581. {
  582.    if (DO_UNFILLED) {
  583.       struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
  584.       GLubyte ef1 = VB->EdgeFlag[e1];
  585.       GLubyte ef3 = VB->EdgeFlag[e3];
  586.       VB->EdgeFlag[e1] = 0;
  587.       TAG(triangle)( ctx, e0, e1, e3 );
  588.       VB->EdgeFlag[e1] = ef1;
  589.       VB->EdgeFlag[e3] = 0;
  590.       TAG(triangle)( ctx, e1, e2, e3 );
  591.       VB->EdgeFlag[e3] = ef3;
  592.    } else {
  593.       TAG(triangle)( ctx, e0, e1, e3 );
  594.       TAG(triangle)( ctx, e1, e2, e3 );
  595.    }
  596. }
  597. #endif
  598. #endif
  599.  
  600. #if DO_LINE
  601. static void TAG(line)( struct gl_context *ctx, GLuint e0, GLuint e1 )
  602. {
  603.    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
  604.    VERTEX *v[2];
  605.    LOCAL_VARS(2);
  606.  
  607.    v[0] = (VERTEX *)GET_VERTEX(e0);
  608.    v[1] = (VERTEX *)GET_VERTEX(e1);
  609.  
  610.    if (DO_FLAT) {
  611.          VERT_SAVE_RGBA( 0 );
  612.          VERT_COPY_RGBA( v[0], v[1] );
  613.          if (HAVE_SPEC && VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
  614.             VERT_SAVE_SPEC( 0 );
  615.             VERT_COPY_SPEC( v[0], v[1] );
  616.          }
  617.    }
  618.  
  619.    LINE( v[0], v[1] );
  620.  
  621.    if (DO_FLAT) {
  622.          VERT_RESTORE_RGBA( 0 );
  623.  
  624.          if (HAVE_SPEC && VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
  625.             VERT_RESTORE_SPEC( 0 );
  626.          }
  627.    }
  628. }
  629. #endif
  630.  
  631. #if DO_POINTS
  632. static void TAG(points)( struct gl_context *ctx, GLuint first, GLuint last )
  633. {
  634.    struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
  635.    GLuint i;
  636.    LOCAL_VARS(1);
  637.  
  638.    if (VB->Elts == 0) {
  639.       for ( i = first ; i < last ; i++ ) {
  640.          if ( VB->ClipMask[i] == 0 ) {
  641.             VERTEX *v = (VERTEX *)GET_VERTEX(i);
  642.             POINT( v );
  643.          }
  644.       }
  645.    } else {
  646.       for ( i = first ; i < last ; i++ ) {
  647.          GLuint e = VB->Elts[i];
  648.          if ( VB->ClipMask[e] == 0 ) {
  649.             VERTEX *v = (VERTEX *)GET_VERTEX(e);
  650.             POINT( v );
  651.          }
  652.       }
  653.    }
  654. }
  655. #endif
  656.  
  657. static void TAG(init)( void )
  658. {
  659. #if DO_QUAD
  660.    TAB[IND].quad = TAG(quadr);
  661. #endif
  662. #if DO_TRI
  663.    TAB[IND].triangle = TAG(triangle);
  664. #endif
  665. #if DO_LINE
  666.    TAB[IND].line = TAG(line);
  667. #endif
  668. #if DO_POINTS
  669.    TAB[IND].points = TAG(points);
  670. #endif
  671. }
  672.  
  673. #undef IND
  674. #undef TAG
  675.  
  676. #if HAVE_BACK_COLORS
  677. #undef VERT_SET_RGBA
  678. #endif
  679.  
  680. #if !HAVE_SPEC
  681. #undef VERT_SET_SPEC
  682. #undef VERT_COPY_SPEC
  683. #undef VERT_SAVE_SPEC
  684. #undef VERT_RESTORE_SPEC
  685. #if HAVE_BACK_COLORS
  686. #undef VERT_COPY_SPEC1
  687. #endif
  688. #else
  689. #if HAVE_BACK_COLORS
  690. #undef VERT_SET_SPEC
  691. #endif
  692. #endif
  693.  
  694. #if !HAVE_BACK_COLORS
  695. #undef VERT_COPY_SPEC1
  696. #undef VERT_COPY_RGBA1
  697. #endif
  698.  
  699. #ifndef INSANE_VERTICES
  700. #undef VERT_SET_Z
  701. #undef VERT_Z_ADD
  702. #endif
  703.