home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src / vbrender.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  38.1 KB  |  1,300 lines

  1. /* $Id: vbrender.c,v 1.16 1997/11/20 00:00:47 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.5
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: vbrender.c,v $
  26.  * Revision 1.16  1997/11/20 00:00:47  brianp
  27.  * only call Driver.RasterSetup() once in render_clipped_polygon()
  28.  *
  29.  * Revision 1.15  1997/09/18 01:32:47  brianp
  30.  * fixed divide by zero problem for "weird" projection matrices
  31.  *
  32.  * Revision 1.14  1997/08/13 01:31:41  brianp
  33.  * cleaned up code involving LightTwoSide
  34.  *
  35.  * Revision 1.13  1997/07/24 01:25:27  brianp
  36.  * changed precompiled header symbol from PCH to PC_HEADER
  37.  *
  38.  * Revision 1.12  1997/07/11 02:19:52  brianp
  39.  * flat-shaded quads in a strip were miscolored if clipped (Randy Frank)
  40.  *
  41.  * Revision 1.11  1997/05/28 03:26:49  brianp
  42.  * added precompiled header (PCH) support
  43.  *
  44.  * Revision 1.10  1997/05/16 02:09:26  brianp
  45.  * clipped GL_TRIANGLE_STRIP triangles sometimes got wrong provoking vertex
  46.  *
  47.  * Revision 1.9  1997/04/30 02:20:00  brianp
  48.  * fixed a line clipping bug in GL_LINE_LOOPs
  49.  *
  50.  * Revision 1.8  1997/04/29 01:31:07  brianp
  51.  * added RasterSetup() function to device driver
  52.  *
  53.  * Revision 1.7  1997/04/24 00:30:17  brianp
  54.  * optimized glTexCoord2() code
  55.  *
  56.  * Revision 1.6  1997/04/20 19:47:06  brianp
  57.  * fixed an error message, added a comment
  58.  *
  59.  * Revision 1.5  1997/04/20 15:59:30  brianp
  60.  * removed VERTEX2_BIT stuff
  61.  *
  62.  * Revision 1.4  1997/04/20 15:27:34  brianp
  63.  * removed odd_flag from all polygon rendering functions
  64.  *
  65.  * Revision 1.3  1997/04/12 12:26:06  brianp
  66.  * now directly call ctx->Driver.Points/Line/Triangle/QuadFunc
  67.  *
  68.  * Revision 1.2  1997/04/07 03:01:11  brianp
  69.  * optimized vertex[234] code
  70.  *
  71.  * Revision 1.1  1997/04/02 03:14:14  brianp
  72.  * Initial revision
  73.  *
  74.  */
  75.  
  76.  
  77. /*
  78.  * Render points, lines, and polygons.  The only entry point to this
  79.  * file is the gl_render_vb() function.  This function is called after
  80.  * the vertex buffer has filled up or glEnd() has been called.
  81.  *
  82.  * This file basically only makes calls to the clipping functions and
  83.  * the point, line and triangle rasterizers via the function pointers.
  84.  *    context->Driver.PointsFunc()
  85.  *    context->Driver.LineFunc()
  86.  *    context->Driver.TriangleFunc()
  87.  */
  88.  
  89.  
  90. #ifdef PC_HEADER
  91. #include "all.h"
  92. #else
  93. #include <stdio.h>
  94. #include "clip.h"
  95. #include "context.h"
  96. #include "macros.h"
  97. #include "matrix.h"
  98. #include "pb.h"
  99. #include "types.h"
  100. #include "vb.h"
  101. #include "vbrender.h"
  102. #include "xform.h"
  103. #endif
  104.  
  105.  
  106. /*
  107.  * This file implements rendering of points, lines and polygons defined by
  108.  * vertices in the vertex buffer.
  109.  */
  110.  
  111.  
  112.  
  113. #ifdef PROFILE
  114. #  define START_PROFILE                         \
  115.         {                                       \
  116.            GLdouble t0 = gl_time();
  117.  
  118. #  define END_PROFILE( TIMER, COUNTER, INCR )   \
  119.            TIMER += (gl_time() - t0);           \
  120.            COUNTER += INCR;                     \
  121.         }
  122. #else
  123. #  define START_PROFILE
  124. #  define END_PROFILE( TIMER, COUNTER, INCR )
  125. #endif
  126.  
  127.  
  128.  
  129.  
  130. /*
  131.  * Render a line segment from VB[v1] to VB[v2] when either one or both
  132.  * endpoints must be clipped.
  133.  */
  134. static void render_clipped_line( GLcontext *ctx, GLuint v1, GLuint v2 )
  135. {
  136.    GLfloat ndc_x, ndc_y, ndc_z;
  137.    GLuint provoking_vertex;
  138.    struct vertex_buffer *VB = ctx->VB;
  139.  
  140.    /* which vertex dictates the color when flat shading: */
  141.    provoking_vertex = v2;
  142.  
  143.    /*
  144.     * Clipping may introduce new vertices.  New vertices will be stored
  145.     * in the vertex buffer arrays starting with location VB->Free.  After
  146.     * we've rendered the line, these extra vertices can be overwritten.
  147.     */
  148.    VB->Free = VB_MAX;
  149.  
  150.    /* Clip against user clipping planes */
  151.    if (ctx->Transform.AnyClip) {
  152.       GLuint orig_v1 = v1, orig_v2 = v2;
  153.       if (gl_userclip_line( ctx, &v1, &v2 )==0)
  154.         return;
  155.       /* Apply projection matrix:  clip = Proj * eye */
  156.       if (v1!=orig_v1) {
  157.          TRANSFORM_POINT( VB->Clip[v1], ctx->ProjectionMatrix, VB->Eye[v1] );
  158.       }
  159.       if (v2!=orig_v2) {
  160.          TRANSFORM_POINT( VB->Clip[v2], ctx->ProjectionMatrix, VB->Eye[v2] );
  161.       }
  162.    }
  163.  
  164.    /* Clip against view volume */
  165.    if (gl_viewclip_line( ctx, &v1, &v2 )==0)
  166.       return;
  167.  
  168.    /* Transform from clip coords to ndc:  ndc = clip / W */
  169.    if (VB->Clip[v1][3] != 0.0F) {
  170.       GLfloat wInv = 1.0F / VB->Clip[v1][3];
  171.       ndc_x = VB->Clip[v1][0] * wInv;
  172.       ndc_y = VB->Clip[v1][1] * wInv;
  173.       ndc_z = VB->Clip[v1][2] * wInv;
  174.    }
  175.    else {
  176.       /* Can't divide by zero, so... */
  177.       ndc_x = ndc_y = ndc_z = 0.0F;
  178.    }
  179.  
  180.    /* Map ndc coord to window coords. */
  181.    VB->Win[v1][0] = ndc_x * ctx->Viewport.Sx + ctx->Viewport.Tx;
  182.    VB->Win[v1][1] = ndc_y * ctx->Viewport.Sy + ctx->Viewport.Ty;
  183.    VB->Win[v1][2] = ndc_z * ctx->Viewport.Sz + ctx->Viewport.Tz;
  184.  
  185.    /* Transform from clip coords to ndc:  ndc = clip / W */
  186.    if (VB->Clip[v2][3] != 0.0F) {
  187.       GLfloat wInv = 1.0F / VB->Clip[v2][3];
  188.       ndc_x = VB->Clip[v2][0] * wInv;
  189.       ndc_y = VB->Clip[v2][1] * wInv;
  190.       ndc_z = VB->Clip[v2][2] * wInv;
  191.    }
  192.    else {
  193.       /* Can't divide by zero, so... */
  194.       ndc_x = ndc_y = ndc_z = 0.0F;
  195.    }
  196.  
  197.    /* Map ndc coord to window coords. */
  198.    VB->Win[v2][0] = ndc_x * ctx->Viewport.Sx + ctx->Viewport.Tx;
  199.    VB->Win[v2][1] = ndc_y * ctx->Viewport.Sy + ctx->Viewport.Ty;
  200.    VB->Win[v2][2] = ndc_z * ctx->Viewport.Sz + ctx->Viewport.Tz;
  201.  
  202.    if (ctx->Driver.RasterSetup) {
  203.       /* Device driver rasterization setup */
  204.       (*ctx->Driver.RasterSetup)( ctx, v1, v1+1 );
  205.       (*ctx->Driver.RasterSetup)( ctx, v2, v2+1 );
  206.    }
  207.  
  208.    START_PROFILE
  209.    (*ctx->Driver.LineFunc)( ctx, v1, v2, provoking_vertex );
  210.    END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  211. }
  212.  
  213.  
  214.  
  215. /*
  216.  * Compute Z offsets for a polygon with plane defined by (A,B,C,D)
  217.  * D is not needed.
  218.  */
  219. static void offset_polygon( GLcontext *ctx, GLfloat a, GLfloat b, GLfloat c )
  220. {
  221.    GLfloat ac, bc, m;
  222.    GLfloat offset;
  223.  
  224.    if (c<0.001F && c>-0.001F) {
  225.       /* to prevent underflow problems */
  226.       offset = 0.0F;
  227.    }
  228.    else {
  229.       ac = a / c;
  230.       bc = b / c;
  231.       if (ac<0.0F)  ac = -ac;
  232.       if (bc<0.0F)  bc = -bc;
  233.       m = MAX2( ac, bc );
  234.       /* m = sqrt( ac*ac + bc*bc ); */
  235.  
  236.       offset = m * ctx->Polygon.OffsetFactor + ctx->Polygon.OffsetUnits;
  237.    }
  238.  
  239.    ctx->PointZoffset   = ctx->Polygon.OffsetPoint ? offset : 0.0F;
  240.    ctx->LineZoffset    = ctx->Polygon.OffsetLine  ? offset : 0.0F;
  241.    ctx->PolygonZoffset = ctx->Polygon.OffsetFill  ? offset : 0.0F;
  242. }
  243.  
  244.  
  245.  
  246. /*
  247.  * When glPolygonMode() is used to specify that the front/back rendering
  248.  * mode for polygons is not GL_FILL we end up calling this function.
  249.  */
  250. static void unfilled_polygon( GLcontext *ctx,
  251.                               GLuint n, GLuint vlist[],
  252.                               GLuint pv, GLuint facing )
  253. {
  254.    GLenum mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;
  255.    struct vertex_buffer *VB = ctx->VB;
  256.  
  257.    if (mode==GL_POINT) {
  258.       GLint i, j;
  259.       GLboolean edge;
  260.  
  261.       if (   ctx->Primitive==GL_TRIANGLES
  262.           || ctx->Primitive==GL_QUADS
  263.           || ctx->Primitive==GL_POLYGON) {
  264.          edge = GL_FALSE;
  265.       }
  266.       else {
  267.          edge = GL_TRUE;
  268.       }
  269.  
  270.       for (i=0;i<n;i++) {
  271.          j = vlist[i];
  272.          if (edge || VB->Edgeflag[j]) {
  273.             (*ctx->Driver.PointsFunc)( ctx, j, j );
  274.          }
  275.       }
  276.    }
  277.    else if (mode==GL_LINE) {
  278.       GLuint i, j0, j1;
  279.       GLboolean edge;
  280.  
  281.       ctx->StippleCounter = 0;
  282.  
  283.       if (   ctx->Primitive==GL_TRIANGLES
  284.           || ctx->Primitive==GL_QUADS
  285.           || ctx->Primitive==GL_POLYGON) {
  286.          edge = GL_FALSE;
  287.       }
  288.       else {
  289.          edge = GL_TRUE;
  290.       }
  291.  
  292.       /* draw the edges */
  293.       for (i=0;i<n;i++) {
  294.          j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  295.          j1 = vlist[i];
  296.          if (edge || VB->Edgeflag[j0]) {
  297.             START_PROFILE
  298.             (*ctx->Driver.LineFunc)( ctx, j0, j1, pv );
  299.             END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  300.          }
  301.       }
  302.    }
  303.    else {
  304.       /* Fill the polygon */
  305.       GLuint j0, i;
  306.       j0 = vlist[0];
  307.       for (i=2;i<n;i++) {
  308.          START_PROFILE
  309.          (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv );
  310.          END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  311.       }
  312.    }
  313. }
  314.  
  315.  
  316. /*
  317.  * Compute signed area of the n-sided polgyon specified by vertices vb->Win[]
  318.  * and vertex list vlist[].
  319.  * A clockwise polygon will return a negative area.
  320.  * A counter-clockwise polygon will return a positive area.
  321.  */
  322. static GLfloat polygon_area( const struct vertex_buffer *vb,
  323.                              GLuint n, const GLuint vlist[] )
  324. {
  325.    GLfloat area = 0.0F;
  326.    GLint i;
  327.    for (i=0;i<n;i++) {
  328.       /* area = sum of trapezoids */
  329.       GLuint j0 = vlist[i];
  330.       GLuint j1 = vlist[(i+1)%n];
  331.       GLfloat x0 = vb->Win[j0][0];
  332.       GLfloat y0 = vb->Win[j0][1];
  333.       GLfloat x1 = vb->Win[j1][0];
  334.       GLfloat y1 = vb->Win[j1][1];
  335.       GLfloat trapArea = (x0-x1)*(y0+y1);  /* Note: no divide by two here! */
  336.       area += trapArea;
  337.    }
  338.    return area * 0.5F;     /* divide by two now! */
  339. }
  340.  
  341.  
  342. /*
  343.  * Render a polygon in which doesn't have to be clipped.
  344.  * Input:  n - number of vertices
  345.  *         vlist - list of vertices in the polygon.
  346.  */
  347. static void render_polygon( GLcontext *ctx, GLuint n, GLuint vlist[] )
  348. {
  349.    struct vertex_buffer *VB = ctx->VB;
  350.    GLuint pv;
  351.  
  352.    /* which vertex dictates the color when flat shading: */
  353.    pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1];
  354.  
  355.    /* Compute orientation of polygon, do cull test, offset, etc */
  356.    {
  357.       GLuint facing;   /* 0=front, 1=back */
  358.       GLfloat area = polygon_area( VB, n, vlist );
  359.  
  360.       if (area==0.0F) {
  361.          /* polygon has zero area, don't draw it */
  362.          return;
  363.       }
  364.  
  365.       facing = (area<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
  366.  
  367.       if ((facing+1) & ctx->Polygon.CullBits) {
  368.          return;   /* culled */
  369.       }
  370.  
  371.       if (ctx->Polygon.OffsetAny) {
  372.          /* compute plane equation of polygon, apply offset */
  373.          GLuint j0 = vlist[0];
  374.          GLuint j1 = vlist[1];
  375.          GLuint j2 = vlist[2];
  376.          GLuint j3 = vlist[ (n==3) ? 0 : 3 ];
  377.          GLfloat ex = VB->Win[j1][0] - VB->Win[j3][0];
  378.          GLfloat ey = VB->Win[j1][1] - VB->Win[j3][1];
  379.          GLfloat ez = VB->Win[j1][2] - VB->Win[j3][2];
  380.          GLfloat fx = VB->Win[j2][0] - VB->Win[j0][0];
  381.          GLfloat fy = VB->Win[j2][1] - VB->Win[j0][1];
  382.          GLfloat fz = VB->Win[j2][2] - VB->Win[j0][2];
  383.          GLfloat a = ey*fz-ez*fy;
  384.          GLfloat b = ez*fx-ex*fz;
  385.          GLfloat c = ex*fy-ey*fx;
  386.          offset_polygon( ctx, a, b, c );
  387.       }
  388.  
  389.       if (ctx->LightTwoSide) {
  390.          if (facing==1) {
  391.             /* use back color or index */
  392.             VB->Color = VB->Bcolor;
  393.             VB->Index = VB->Bindex;
  394.          }
  395.          else {
  396.             /* use front color or index */
  397.             VB->Color = VB->Fcolor;
  398.             VB->Index = VB->Findex;
  399.          }
  400.       }
  401.  
  402.       /* Render the polygon! */
  403.       if (ctx->Polygon.Unfilled) {
  404.          unfilled_polygon( ctx, n, vlist, pv, facing );
  405.       }
  406.       else {
  407.          /* Draw filled polygon as a triangle fan */
  408.          GLint i;
  409.          GLuint j0 = vlist[0];
  410.          for (i=2;i<n;i++) {
  411.             START_PROFILE
  412.             (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv );
  413.             END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  414.          }
  415.       }
  416.    }
  417. }
  418.  
  419.  
  420.  
  421. /*
  422.  * Render a polygon in which at least one vertex has to be clipped.
  423.  * Input:  n - number of vertices
  424.  *         vlist - list of vertices in the polygon.
  425.  *                 CCW order = front facing.
  426.  */
  427. static void render_clipped_polygon( GLcontext *ctx, GLuint n, GLuint vlist[] )
  428. {
  429.    GLuint pv;
  430.    struct vertex_buffer *VB = ctx->VB;
  431. #ifndef __STORM__
  432.    GLfloat (*win)[3] = VB->Win;
  433. #else
  434.    float (*win)[3] = VB->Win;
  435. #endif
  436.    /* which vertex dictates the color when flat shading: */
  437.    pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1];
  438.  
  439.    /*
  440.     * Clipping may introduce new vertices.  New vertices will be stored
  441.     * in the vertex buffer arrays starting with location VB->Free.  After
  442.     * we've rendered the polygon, these extra vertices can be overwritten.
  443.     */
  444.    VB->Free = VB_MAX;
  445.  
  446.    /* Clip against user clipping planes in eye coord space. */
  447.    if (ctx->Transform.AnyClip) {
  448.       GLfloat *proj = ctx->ProjectionMatrix;
  449.       GLuint i;
  450.       n = gl_userclip_polygon( ctx, n, vlist );
  451.       if (n<3)
  452.          return;
  453.       /* Transform vertices from eye to clip coordinates:  clip = Proj * eye */
  454.       for (i=0;i<n;i++) {
  455.          GLuint j = vlist[i];
  456.          TRANSFORM_POINT( VB->Clip[j], proj, VB->Eye[j] );
  457.       }
  458.    }
  459.  
  460.    /* Clip against view volume in clip coord space */
  461.    n = gl_viewclip_polygon( ctx, n, vlist );
  462.    if (n<3)
  463.       return;
  464.  
  465.    /* Transform vertices from clip to ndc to window coords.        */
  466.    /* ndc = clip / W    window = viewport_mapping(ndc)             */
  467.    /* Note that window Z values are scaled to the range of integer */
  468.    /* depth buffer values.                                         */
  469.    {
  470.       GLfloat sx = ctx->Viewport.Sx;
  471.       GLfloat tx = ctx->Viewport.Tx;
  472.       GLfloat sy = ctx->Viewport.Sy;
  473.       GLfloat ty = ctx->Viewport.Ty;
  474.       GLfloat sz = ctx->Viewport.Sz;
  475.       GLfloat tz = ctx->Viewport.Tz;
  476.       GLuint i;
  477.       for (i=0;i<n;i++) {
  478.          GLuint j = vlist[i];
  479.          if (VB->Clip[j][3] != 0.0F) {
  480.             GLfloat wInv = 1.0F / VB->Clip[j][3];
  481.             win[j][0] = VB->Clip[j][0] * wInv * sx + tx;
  482.             win[j][1] = VB->Clip[j][1] * wInv * sy + ty;
  483.             win[j][2] = VB->Clip[j][2] * wInv * sz + tz;
  484.          }
  485.          else {
  486.             /* Can't divide by zero, so... */
  487.             win[j][0] = win[j][1] = win[j][2] = 0.0F;
  488.          }
  489.       }
  490.       if (ctx->Driver.RasterSetup && (VB->Free > VB_MAX)) {
  491.          /* Device driver raster setup for newly introduced vertices */
  492.          (*ctx->Driver.RasterSetup)(ctx, VB_MAX, VB->Free);
  493.       }
  494.    }
  495.  
  496.    /* Compute orientation of polygon, do cull test, offset, etc */
  497.    {
  498.       GLuint facing;   /* 0=front, 1=back */
  499.       GLfloat area = polygon_area( VB, n, vlist );
  500.  
  501.       if (area==0.0F) {
  502.          /* polygon has zero area, don't draw it */
  503.          return;
  504.       }
  505.  
  506.       facing = (area<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
  507.  
  508.       if ((facing+1) & ctx->Polygon.CullBits) {
  509.          return;   /* culled */
  510.       }
  511.  
  512.       if (ctx->Polygon.OffsetAny) {
  513.          /* compute plane equation of polygon, apply offset */
  514.          GLuint j0 = vlist[0];
  515.          GLuint j1 = vlist[1];
  516.          GLuint j2 = vlist[2];
  517.          GLuint j3 = vlist[ (n==3) ? 0 : 3 ];
  518.          GLfloat ex = win[j1][0] - win[j3][0];
  519.          GLfloat ey = win[j1][1] - win[j3][1];
  520.          GLfloat ez = win[j1][2] - win[j3][2];
  521.          GLfloat fx = win[j2][0] - win[j0][0];
  522.          GLfloat fy = win[j2][1] - win[j0][1];
  523.          GLfloat fz = win[j2][2] - win[j0][2];
  524.          GLfloat a = ey*fz-ez*fy;
  525.          GLfloat b = ez*fx-ex*fz;
  526.          GLfloat c = ex*fy-ey*fx;
  527.          offset_polygon( ctx, a, b, c );
  528.       }
  529.  
  530.       if (ctx->LightTwoSide) {
  531.          if (facing==1) {
  532.             /* use back color or index */
  533.             VB->Color = VB->Bcolor;
  534.             VB->Index = VB->Bindex;
  535.          }
  536.          else {
  537.             /* use front color or index */
  538.             VB->Color = VB->Fcolor;
  539.             VB->Index = VB->Findex;
  540.          }
  541.       }
  542.  
  543.       /* Render the polygon! */
  544.       if (ctx->Polygon.Unfilled) {
  545.          unfilled_polygon( ctx, n, vlist, pv, facing );
  546.       }
  547.       else {
  548.          /* Draw filled polygon as a triangle fan */
  549.          GLint i;
  550.          GLuint j0 = vlist[0];
  551.          for (i=2;i<n;i++) {
  552.             START_PROFILE
  553.             (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv );
  554.             END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  555.          }
  556.       }
  557.    }
  558. }
  559.  
  560.  
  561.  
  562. /*
  563.  * Render an un-clipped triangle.
  564.  * v0, v1, v2 - vertex indexes.  CCW order = front facing
  565.  * pv - provoking vertex
  566.  */
  567. static void render_triangle( GLcontext *ctx,
  568.                              GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  569. {
  570.    struct vertex_buffer *VB = ctx->VB;
  571.    GLfloat ex, ey, fx, fy, c;
  572.    GLuint facing;  /* 0=front, 1=back */
  573. #ifndef __STORM__
  574.    GLfloat (*win)[3] = VB->Win;
  575. #else
  576.    float (*win)[3] = VB->Win;
  577. #endif
  578.    /* Compute orientation of triangle */
  579.    ex = win[v1][0] - win[v0][0];
  580.    ey = win[v1][1] - win[v0][1];
  581.    fx = win[v2][0] - win[v0][0];
  582.    fy = win[v2][1] - win[v0][1];
  583.    c = ex*fy-ey*fx;
  584.  
  585.    if (c==0.0F) {
  586.       /* polygon is perpindicular to view plane, don't draw it */
  587.       return;
  588.    }
  589.  
  590.    facing = (c<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
  591.  
  592.    if ((facing+1) & ctx->Polygon.CullBits) {
  593.       return;   /* culled */
  594.    }
  595.  
  596.    if (ctx->Polygon.OffsetAny) {
  597.       /* finish computing plane equation of polygon, compute offset */
  598.       GLfloat fz = win[v2][2] - win[v0][2];
  599.       GLfloat ez = win[v1][2] - win[v0][2];
  600.       GLfloat a = ey*fz-ez*fy;
  601.       GLfloat b = ez*fx-ex*fz;
  602.       offset_polygon( ctx, a, b, c );
  603.    }
  604.  
  605.    if (ctx->LightTwoSide) {
  606.       if (facing==1) {
  607.          /* use back color or index */
  608.          VB->Color = VB->Bcolor;
  609.          VB->Index = VB->Bindex;
  610.       }
  611.       else {
  612.          /* use front color or index */
  613.          VB->Color = VB->Fcolor;
  614.          VB->Index = VB->Findex;
  615.       }
  616.    }
  617.  
  618.    if (ctx->Polygon.Unfilled) {
  619.       GLuint vlist[3];
  620.       vlist[0] = v0;
  621.       vlist[1] = v1;
  622.       vlist[2] = v2;
  623.       unfilled_polygon( ctx, 3, vlist, pv, facing );
  624.    }
  625.    else {
  626.       START_PROFILE
  627.       (*ctx->Driver.TriangleFunc)( ctx, v0, v1, v2, pv );
  628.       END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  629.    }
  630. }
  631.  
  632.  
  633.  
  634. /*
  635.  * Render an un-clipped quadrilateral.
  636.  * v0, v1, v2, v3 : CCW order = front facing
  637.  * pv - provoking vertex
  638.  */
  639. static void render_quad( GLcontext *ctx, GLuint v0, GLuint v1,
  640.                          GLuint v2, GLuint v3, GLuint pv )
  641. {
  642.    struct vertex_buffer *VB = ctx->VB;
  643.    GLfloat ex, ey, fx, fy, c;
  644.    GLuint facing;  /* 0=front, 1=back */
  645. #ifndef __STORM__
  646.    GLfloat (*win)[3] = VB->Win;
  647. #else
  648.    float (*win)[3] = VB->Win;
  649. #endif
  650.    /* Compute polygon orientation */
  651.    ex = win[v2][0] - win[v0][0];
  652.    ey = win[v2][1] - win[v0][1];
  653.    fx = win[v3][0] - win[v1][0];
  654.    fy = win[v3][1] - win[v1][1];
  655.    c = ex*fy-ey*fx;
  656.  
  657.    if (c==0.0F) {
  658.       /* polygon is perpindicular to view plane, don't draw it */
  659.       return;
  660.    }
  661.  
  662.    facing = (c<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
  663.  
  664.    if ((facing+1) & ctx->Polygon.CullBits) {
  665.       return;   /* culled */
  666.    }
  667.  
  668.    if (ctx->Polygon.OffsetAny) {
  669.       /* finish computing plane equation of polygon, compute offset */
  670.       GLfloat ez = win[v2][2] - win[v0][2];
  671.       GLfloat fz = win[v3][2] - win[v1][2];
  672.       GLfloat a = ey*fz-ez*fy;
  673.       GLfloat b = ez*fx-ex*fz;
  674.       offset_polygon( ctx, a, b, c );
  675.    }
  676.  
  677.    if (ctx->LightTwoSide) {
  678.       if (facing==1) {
  679.          /* use back color or index */
  680.          VB->Color = VB->Bcolor;
  681.          VB->Index = VB->Bindex;
  682.       }
  683.       else {
  684.          /* use front color or index */
  685.          VB->Color = VB->Fcolor;
  686.          VB->Index = VB->Findex;
  687.       }
  688.    }
  689.  
  690.    /* Render the quad! */
  691.    if (ctx->Polygon.Unfilled) {
  692.       GLuint vlist[4];
  693.       vlist[0] = v0;
  694.       vlist[1] = v1;
  695.       vlist[2] = v2;
  696.       vlist[3] = v3;
  697.       unfilled_polygon( ctx, 4, vlist, pv, facing );
  698.    }
  699.    else {
  700.       START_PROFILE
  701.       (*ctx->Driver.QuadFunc)( ctx, v0, v1, v2, v3, pv );
  702.       END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  703.    }
  704. }
  705.  
  706.  
  707.  
  708. /*
  709.  * When the vertex buffer is full, we transform/render it.  Sometimes we
  710.  * have to copy the last vertex (or two) to the front of the vertex list
  711.  * to "continue" the primitive.  For example:  line or triangle strips.
  712.  * This function is a helper for that.
  713.  */
  714. static void copy_vertex( struct vertex_buffer *vb, GLuint dst, GLuint src )
  715. {
  716.    COPY_4V( vb->Clip[dst], vb->Clip[src] );
  717.    COPY_4V( vb->Eye[dst], vb->Eye[src] );
  718.    COPY_3V( vb->Win[dst], vb->Win[src] );
  719.    COPY_4V( vb->Fcolor[dst], vb->Fcolor[src] );
  720.    COPY_4V( vb->Bcolor[dst], vb->Bcolor[src] );
  721.    COPY_4V( vb->TexCoord[dst], vb->TexCoord[src] );
  722.    vb->Findex[dst] = vb->Findex[src];
  723.    vb->Bindex[dst] = vb->Bindex[src];
  724.    vb->Edgeflag[dst] = vb->Edgeflag[src];
  725.    vb->ClipMask[dst] = vb->ClipMask[src];
  726. }
  727.  
  728.  
  729.  
  730.  
  731. /*
  732.  * Either the vertex buffer is full (VB->Count==VB_MAX) or glEnd() has been
  733.  * called.  Render the primitives defined by the vertices and reset the
  734.  * buffer.
  735.  *
  736.  * This function won't be called if the device driver implements a
  737.  * RenderVB() function.  If the device driver renders the vertex buffer
  738.  * then the driver must also call gl_reset_vb()!
  739.  *
  740.  * Input:  allDone - GL_TRUE = caller is glEnd()
  741.  *                   GL_FALSE = calling because buffer is full.
  742.  */
  743. void gl_render_vb( GLcontext *ctx, GLboolean allDone )
  744. {
  745.    struct vertex_buffer *VB = ctx->VB;
  746.    GLuint vlist[VB_SIZE];
  747.  
  748.    switch (ctx->Primitive) {
  749.       case GL_POINTS:
  750.          START_PROFILE
  751.          (*ctx->Driver.PointsFunc)( ctx, 0, VB->Count-1 );
  752.          END_PROFILE( ctx->PointTime, ctx->PointCount, VB->Count )
  753.          break;
  754.  
  755.       case GL_LINES:
  756.          if (VB->ClipOrMask) {
  757.             GLuint i;
  758.             for (i=1;i<VB->Count;i+=2) {
  759.                if (VB->ClipMask[i-1] | VB->ClipMask[i]) {
  760.                   render_clipped_line( ctx, i-1, i );
  761.                }
  762.                else {
  763.                   START_PROFILE
  764.                   (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  765.                   END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  766.                }
  767.                ctx->StippleCounter = 0;
  768.             }
  769.          }
  770.          else {
  771.             GLuint i;
  772.             for (i=1;i<VB->Count;i+=2) {
  773.                START_PROFILE
  774.                (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  775.                END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  776.                ctx->StippleCounter = 0;
  777.             }
  778.          }
  779.          break;
  780.  
  781.       case GL_LINE_STRIP:
  782.          if (VB->ClipOrMask) {
  783.             GLuint i;
  784.             for (i=1;i<VB->Count;i++) {
  785.                if (VB->ClipMask[i-1] | VB->ClipMask[i]) {
  786.                   render_clipped_line( ctx, i-1, i );
  787.                }
  788.                else {
  789.                   START_PROFILE
  790.                   (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  791.                   END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  792.                }
  793.             }
  794.          }
  795.          else {
  796.             /* no clipping needed */
  797.             GLuint i;
  798.             for (i=1;i<VB->Count;i++) {
  799.                START_PROFILE
  800.                (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  801.                END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  802.             }
  803.          }
  804.          break;
  805.  
  806.       case GL_LINE_LOOP:
  807.          {
  808.             GLuint i;
  809.             if (VB->Start==0) {
  810.                i = 1;  /* start at 0th vertex */
  811.             }
  812.             else {
  813.                i = 2;  /* skip first vertex, we're saving it until glEnd */
  814.             }
  815.             while (i<VB->Count) {
  816.                if (VB->ClipMask[i-1] | VB->ClipMask[i]) {
  817.                   render_clipped_line( ctx, i-1, i );
  818.                }
  819.                else {
  820.                   START_PROFILE
  821.                   (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  822.                   END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  823.                }
  824.                i++;
  825.             }
  826.          }
  827.          break;
  828.  
  829.       case GL_TRIANGLES:
  830.          if (VB->ClipOrMask) {
  831.             GLuint i;
  832.             for (i=2;i<VB->Count;i+=3) {
  833.                if (VB->ClipMask[i-2] | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  834.                   vlist[0] = i-2;
  835.                   vlist[1] = i-1;
  836.                   vlist[2] = i-0;
  837.                   render_clipped_polygon( ctx, 3, vlist );
  838.                }
  839.                else {
  840.                   if (ctx->DirectTriangles) {
  841.                      START_PROFILE
  842.                      (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i );
  843.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  844.                   }
  845.                   else {
  846.                      render_triangle( ctx, i-2, i-1, i, i );
  847.                   }
  848.                }
  849.             }
  850.          }
  851.          else {
  852.             /* no clipping needed */
  853.             GLuint i;
  854.             if (ctx->DirectTriangles) {
  855.                for (i=2;i<VB->Count;i+=3) {
  856.                   START_PROFILE
  857.                   (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i );
  858.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  859.                }
  860.             }
  861.             else {
  862.                for (i=2;i<VB->Count;i+=3) {
  863.                   render_triangle( ctx, i-2, i-1, i, i );
  864.                }
  865.             }
  866.          }
  867.          break;
  868.  
  869.       case GL_TRIANGLE_STRIP:
  870.          if (VB->ClipOrMask) {
  871.             GLuint i;
  872.             for (i=2;i<VB->Count;i++) {
  873.                if (VB->ClipMask[i-2] | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  874.                   if (i&1) {
  875.                      /* reverse vertex order */
  876.                      vlist[0] = i-1;
  877.                      vlist[1] = i-2;
  878.                      vlist[2] = i-0;
  879.                      render_clipped_polygon( ctx, 3, vlist );
  880.                   }
  881.                   else {
  882.                      vlist[0] = i-2;
  883.                      vlist[1] = i-1;
  884.                      vlist[2] = i-0;
  885.                      render_clipped_polygon( ctx, 3, vlist );
  886.                   }
  887.                }
  888.                else {
  889.                   if (ctx->DirectTriangles) {
  890.                      START_PROFILE
  891.                      (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i );
  892.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  893.                   }
  894.                   else {
  895.                      if (i&1)
  896.                         render_triangle( ctx, i, i-1, i-2, i );
  897.                      else
  898.                         render_triangle( ctx, i-2, i-1, i, i );
  899.                   }
  900.                }
  901.             }
  902.          }
  903.          else {
  904.             /* no vertices were clipped */
  905.             GLuint i;
  906.             if (ctx->DirectTriangles) {
  907.                for (i=2;i<VB->Count;i++) {
  908.                   START_PROFILE
  909.                   (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i );
  910.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  911.                }
  912.             }
  913.             else {
  914.                for (i=2;i<VB->Count;i++) {
  915.                   if (i&1)
  916.                      render_triangle( ctx, i, i-1, i-2, i );
  917.                   else
  918.                      render_triangle( ctx, i-2, i-1, i, i );
  919.                }
  920.             }
  921.          }
  922.          break;
  923.  
  924.       case GL_TRIANGLE_FAN:
  925.          if (VB->ClipOrMask) {
  926.             GLuint i;
  927.             for (i=2;i<VB->Count;i++) {
  928.                if (VB->ClipMask[0] | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  929.                   vlist[0] = 0;
  930.                   vlist[1] = i-1;
  931.                   vlist[2] = i;
  932.                   render_clipped_polygon( ctx, 3, vlist );
  933.                }
  934.                else {
  935.                   if (ctx->DirectTriangles) {
  936.                      START_PROFILE
  937.                      (*ctx->Driver.TriangleFunc)( ctx, 0, i-1, i, i );
  938.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  939.                   }
  940.                   else {
  941.                      render_triangle( ctx, 0, i-1, i, i );
  942.                   }
  943.                }
  944.             }
  945.          }
  946.          else {
  947.             /* no clipping needed */
  948.             GLuint i;
  949.             if (ctx->DirectTriangles) {
  950.                for (i=2;i<VB->Count;i++) {
  951.                   START_PROFILE
  952.                   (*ctx->Driver.TriangleFunc)( ctx, 0, i-1, i, i );
  953.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  954.                }
  955.             }
  956.             else {
  957.                for (i=2;i<VB->Count;i++) {
  958.                   render_triangle( ctx, 0, i-1, i, i );
  959.                }
  960.             }
  961.          }
  962.          break;
  963.  
  964.       case GL_QUADS:
  965.          if (VB->ClipOrMask) {
  966.             GLuint i;
  967.             for (i=3;i<VB->Count;i+=4) {
  968.                if (  VB->ClipMask[i-3] | VB->ClipMask[i-2]
  969.                    | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  970.                   vlist[0] = i-3;
  971.                   vlist[1] = i-2;
  972.                   vlist[2] = i-1;
  973.                   vlist[3] = i-0;
  974.                   render_clipped_polygon( ctx, 4, vlist );
  975.                }
  976.                else {
  977.                   if (ctx->DirectTriangles) {
  978.                      START_PROFILE
  979.                      (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i-1, i, i );
  980.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  981.                   }
  982.                   else {
  983.                      render_quad( ctx, i-3, i-2, i-1, i, i );
  984.                   }
  985.                }
  986.             }
  987.          }
  988.          else {
  989.             /* no vertices were clipped */
  990.             GLuint i;
  991.             if (ctx->DirectTriangles) {
  992.                for (i=3;i<VB->Count;i+=4) {
  993.                   START_PROFILE
  994.                   (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i-1, i, i );
  995.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  996.                }
  997.             }
  998.             else {
  999.                for (i=3;i<VB->Count;i+=4) {
  1000.                   render_quad( ctx, i-3, i-2, i-1, i, i );
  1001.                }
  1002.             }
  1003.          }
  1004.          break;
  1005.  
  1006.       case GL_QUAD_STRIP:
  1007.          if (VB->ClipOrMask) {
  1008.             GLuint i;
  1009.             for (i=3;i<VB->Count;i+=2) {
  1010.                if (  VB->ClipMask[i-2] | VB->ClipMask[i-3]
  1011.                    | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  1012.                   vlist[0] = i-1;
  1013.                   vlist[1] = i-3;
  1014.                   vlist[2] = i-2;
  1015.                   vlist[3] = i-0;
  1016.                   render_clipped_polygon( ctx, 4, vlist );
  1017.                }
  1018.                else {
  1019.                   if (ctx->DirectTriangles) {
  1020.                      START_PROFILE
  1021.                      (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i, i-1, i );
  1022.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  1023.                   }
  1024.                   else {
  1025.                      render_quad( ctx, i-3, i-2, i, i-1, i );
  1026.                   }
  1027.                }
  1028.             }
  1029.          }
  1030.          else {
  1031.             /* no clipping needed */
  1032.             GLuint i;
  1033.             if (ctx->DirectTriangles) {
  1034.                for (i=3;i<VB->Count;i+=2) {
  1035.                   START_PROFILE
  1036.                   (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i, i-1, i );
  1037.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  1038.                }
  1039.             }
  1040.             else {
  1041.                for (i=3;i<VB->Count;i+=2) {
  1042.                   render_quad( ctx, i-3, i-2, i, i-1, i );
  1043.                }
  1044.             }
  1045.          }
  1046.          break;
  1047.  
  1048.       case GL_POLYGON:
  1049.          if (VB->Count>2) {
  1050.             GLuint i;
  1051.             for (i=0;i<VB->Count;i++) {
  1052.                vlist[i] = i;
  1053.             }
  1054.             if (VB->ClipOrMask) {
  1055.                render_clipped_polygon( ctx, VB->Count, vlist );
  1056.             }
  1057.             else {
  1058.                render_polygon( ctx, VB->Count, vlist );
  1059.             }
  1060.          }
  1061.          break;
  1062.  
  1063.       default:
  1064.          /* should never get here */
  1065.          gl_problem( ctx, "invalid mode in gl_render_vb" );
  1066.    }
  1067.  
  1068.    gl_reset_vb( ctx, allDone );
  1069. }
  1070.  
  1071.  
  1072. #define CLIP_ALL_BITS    0x3f
  1073.  
  1074.  
  1075. /*
  1076.  * After we've rendered the primitives in the vertex buffer we call
  1077.  * this function to reset the vertex buffer.  That is, we prepare it
  1078.  * for the next batch of vertices.
  1079.  * Input:  ctx - the context
  1080.  *         allDone - GL_TRUE = glEnd() was called
  1081.  *                   GL_FALSE = buffer was filled, more vertices to come
  1082.  */
  1083. void gl_reset_vb( GLcontext *ctx, GLboolean allDone )
  1084. {
  1085.    struct vertex_buffer *VB = ctx->VB;
  1086.  
  1087.    if (ctx->Primitive==GL_LINE_LOOP && allDone) {
  1088.       /* special case */
  1089.       if (VB->ClipMask[VB->Count-1] | VB->ClipMask[0]) {
  1090.          render_clipped_line( ctx, VB->Count-1, 0 );
  1091.       }
  1092.       else {
  1093.          START_PROFILE
  1094.             (*ctx->Driver.LineFunc)( ctx, VB->Count-1, 0, 0 );
  1095.          END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  1096.       }
  1097.    }
  1098.  
  1099.    if (VB->ClipOrMask) {
  1100.       /* reset clip masks to zero */
  1101.       MEMSET( VB->ClipMask + VB->Start, 0,
  1102.               (VB->Count - VB->Start) * sizeof(VB->ClipMask[0]) );
  1103.    }
  1104.  
  1105.    if (!VB->MonoMaterial) {
  1106.       /* reset material masks to zero */
  1107.       MEMSET( VB->MaterialMask + VB->Start, 0,
  1108.               (VB->Count - VB->Start) * sizeof(VB->MaterialMask[0]) );
  1109.    }
  1110.  
  1111.    if (VB->VertexSizeMask!=VERTEX3_BIT) {
  1112.       /* reset object W coords to one */
  1113.       GLint i, n;
  1114. #ifndef __STORM__
  1115.       GLfloat (*obj)[4] = VB->Obj + VB->Start;
  1116. #else
  1117.       float (*obj)[4] = VB->Obj + VB->Start;
  1118. #endif
  1119.       n = VB->Count - VB->Start;
  1120.       for (i=0; i<n; i++) {
  1121.          obj[i][3] = 1.0F;
  1122.       }
  1123.    }
  1124.  
  1125.    if (allDone) {
  1126.       VB->MonoColor = GL_TRUE;
  1127.       VB->VertexSizeMask = VERTEX3_BIT;
  1128.       if (VB->TexCoordSize!=2) {
  1129.          GLint i, n = VB->Count;
  1130.          for (i=0;i<n;i++) {
  1131.             VB->TexCoord[i][2] = 0.0F;
  1132.             VB->TexCoord[i][3] = 1.0F;
  1133.          }
  1134.       }
  1135.       if (ctx->Current.TexCoord[2]==0.0F && ctx->Current.TexCoord[3]==1.0F) {
  1136.          VB->TexCoordSize = 2;
  1137.       }
  1138.       else {
  1139.          VB->TexCoordSize = 4;
  1140.       }
  1141.    }
  1142.  
  1143.    switch (ctx->Primitive) {
  1144.       case GL_POINTS:
  1145.          ASSERT(VB->Start==0);
  1146.          VB->Count = 0;
  1147.          VB->ClipOrMask = 0;
  1148.          VB->ClipAndMask = CLIP_ALL_BITS;
  1149.          VB->MonoMaterial = GL_TRUE;
  1150.          VB->MonoNormal = GL_TRUE;
  1151.          break;
  1152.  
  1153.       case GL_LINES:
  1154.          ASSERT(VB->Start==0);
  1155.          VB->Count = 0;
  1156.          VB->ClipOrMask = 0;
  1157.          VB->ClipAndMask = CLIP_ALL_BITS;
  1158.          VB->MonoMaterial = GL_TRUE;
  1159.          VB->MonoNormal = GL_TRUE;
  1160.          break;
  1161.  
  1162.       case GL_LINE_STRIP:
  1163.          if (allDone) {
  1164.             VB->Count = 0;
  1165.             VB->ClipOrMask = 0;
  1166.             VB->ClipAndMask = CLIP_ALL_BITS;
  1167.             VB->MonoMaterial = GL_TRUE;
  1168.             VB->MonoNormal = GL_TRUE;
  1169.          }
  1170.          else {
  1171.             copy_vertex( VB, 0, VB->Count-1 );  /* copy last vertex to front */
  1172.             VB->Count = 1;
  1173.             VB->ClipOrMask = VB->ClipMask[0];
  1174.             VB->ClipAndMask = VB->ClipMask[0];
  1175.             VB->MonoMaterial = VB->MaterialMask[0] ? GL_FALSE : GL_TRUE;
  1176.          }
  1177.          break;
  1178.  
  1179.       case GL_LINE_LOOP:
  1180.          if (allDone) {
  1181.             VB->Count = 0;
  1182.             VB->ClipOrMask = 0;
  1183.             VB->ClipAndMask = CLIP_ALL_BITS;
  1184.             VB->MonoMaterial = GL_TRUE;
  1185.             VB->MonoNormal = GL_TRUE;
  1186.          }
  1187.          else {
  1188.             ASSERT(VB->Count==VB_MAX);
  1189.             /* recycle the vertex list */
  1190.             copy_vertex( VB, 1, VB_MAX-1 );
  1191.             VB->Count = 2;
  1192.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1193.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1194.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1195.          }
  1196.          break;
  1197.  
  1198.       case GL_TRIANGLES:
  1199.          ASSERT(VB->Start==0);
  1200.          VB->Count = 0;
  1201.          VB->ClipOrMask = 0;
  1202.          VB->ClipAndMask = CLIP_ALL_BITS;
  1203.          VB->MonoMaterial = GL_TRUE;
  1204.          VB->MonoNormal = GL_TRUE;
  1205.          break;
  1206.  
  1207.       case GL_TRIANGLE_STRIP:
  1208.          if (allDone) {
  1209.             VB->Count = 0;
  1210.             VB->ClipOrMask = 0;
  1211.             VB->ClipAndMask = CLIP_ALL_BITS;
  1212.             VB->MonoMaterial = GL_TRUE;
  1213.             VB->MonoNormal = GL_TRUE;
  1214.          }
  1215.          else {
  1216.             /* get ready for more vertices in this triangle strip */
  1217.             copy_vertex( VB, 0, VB_MAX-2 );
  1218.             copy_vertex( VB, 1, VB_MAX-1 );
  1219.             VB->Count = 2;
  1220.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1221.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1222.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1223.          }
  1224.          break;
  1225.  
  1226.       case GL_TRIANGLE_FAN:
  1227.          if (allDone) {
  1228.             VB->Count = 0;
  1229.             VB->ClipOrMask = 0;
  1230.             VB->ClipAndMask = CLIP_ALL_BITS;
  1231.             VB->MonoMaterial = GL_TRUE;
  1232.             VB->MonoNormal = GL_TRUE;
  1233.          }
  1234.          else {
  1235.             /* get ready for more vertices in this triangle fan */
  1236.             copy_vertex( VB, 1, VB_MAX-1 );
  1237.             VB->Count = 2;
  1238.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1239.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1240.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1241.          }
  1242.          break;
  1243.  
  1244.       case GL_QUADS:
  1245.          ASSERT(VB->Start==0);
  1246.          VB->Count = 0;
  1247.          VB->ClipOrMask = 0;
  1248.          VB->ClipAndMask = CLIP_ALL_BITS;
  1249.          VB->MonoMaterial = GL_TRUE;
  1250.          VB->MonoNormal = GL_TRUE;
  1251.          break;
  1252.  
  1253.       case GL_QUAD_STRIP:
  1254.          if (allDone) {
  1255.             VB->Count = 0;
  1256.             VB->ClipOrMask = 0;
  1257.             VB->ClipAndMask = CLIP_ALL_BITS;
  1258.             VB->MonoMaterial = GL_TRUE;
  1259.             VB->MonoNormal = GL_TRUE;
  1260.          }
  1261.          else {
  1262.             /* get ready for more vertices in this quad strip */
  1263.             copy_vertex( VB, 0, VB_MAX-2 );
  1264.             copy_vertex( VB, 1, VB_MAX-1 );
  1265.             VB->Count = 2;
  1266.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1267.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1268.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1269.          }
  1270.          break;
  1271.  
  1272.       case GL_POLYGON:
  1273.          if (allDone) {
  1274.             VB->Count = 0;
  1275.             VB->ClipOrMask = 0;
  1276.             VB->ClipAndMask = CLIP_ALL_BITS;
  1277.             VB->MonoMaterial = GL_TRUE;
  1278.             VB->MonoNormal = GL_TRUE;
  1279.          }
  1280.          else {
  1281.             /* get ready for more vertices just like a triangle fan */
  1282.             copy_vertex( VB, 1, VB_MAX-1 );
  1283.             VB->Count = 2;
  1284.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1285.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1286.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1287.          }
  1288.          break;
  1289.  
  1290.       default:
  1291.          /* should never get here */
  1292.          gl_problem( ctx, "invalid mode in gl_reset_vb" );
  1293.    }
  1294.  
  1295.    /* In any case, Start = first vertex which hasn't been transformed yet */
  1296.    VB->Start = VB->Count;
  1297. }
  1298.  
  1299.  
  1300.