home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src / polygons.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  26KB  |  973 lines

  1. /* $Id: polygons.c,v 1.52 1996/03/02 21:58:13 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995-1996  Brian Paul  (brianp@ssec.wisc.edu)
  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: polygons.c,v $
  26.  * Revision 1.52  1996/03/02  21:58:13  brianp
  27.  * only test edge flag for GL_TRIANGLES, GL_QUADS, or GL_POLYGON
  28.  *
  29.  * Revision 1.51  1996/02/12  19:08:45  brianp
  30.  * applied Bill's Feb 8 patches: change eye Z's to clip W's
  31.  *
  32.  * Revision 1.50  1996/02/06  04:14:04  brianp
  33.  * added GL_FRONT_AND_BACK to glCullFace()
  34.  *
  35.  * Revision 1.49  1996/02/06  03:23:54  brianp
  36.  * removed gamma correction code
  37.  *
  38.  * Revision 1.48  1996/02/01  00:55:40  brianp
  39.  * added some DEFARRAY(),UNDEFARRY() macros for Macintosh
  40.  *
  41.  * Revision 1.47  1996/01/30  19:44:05  brianp
  42.  * set U component of texture coords to zero to supress Purify warnings
  43.  *
  44.  * Revision 1.46  1996/01/29  19:06:02  brianp
  45.  * use CC.Orientation in unfilled_polygon()
  46.  *
  47.  * Revision 1.45  1996/01/22  15:34:31  brianp
  48.  * call GL_INTERPOLATE_RGBA() instead of GL_INTERPOLATE_4FIXED()
  49.  *
  50.  * Revision 1.44  1996/01/11  22:51:59  brianp
  51.  * include depth.h added
  52.  *
  53.  * Revision 1.44  1996/01/11  22:51:59  brianp
  54.  * include depth.h added
  55.  *
  56.  * Revision 1.43  1996/01/11  15:48:21  brianp
  57.  * added Y-axis clipping
  58.  * removed obsolete fast_flat/smooth_rgba_z_polygon() functions
  59.  *
  60.  * Revision 1.42  1996/01/02  22:13:40  brianp
  61.  * removed old fixed-point macros
  62.  *
  63.  * Revision 1.41  1995/12/30  17:19:27  brianp
  64.  * use new gl_interp_texcoords function, per Bill Triggs
  65.  *
  66.  * Revision 1.40  1995/12/30  00:59:09  brianp
  67.  * use integer vertex colors instead of floating point
  68.  *
  69.  * Revision 1.38  1995/12/20  15:27:33  brianp
  70.  * VB color indexes changed to GLuint
  71.  *
  72.  * Revision 1.37  1995/12/18  17:26:50  brianp
  73.  * use new GLdepth datatype
  74.  *
  75.  * Revision 1.36  1995/12/14  19:57:44  brianp
  76.  * used new GLfixed type and GL_INTERPOLATE_4FIXED macro for color interp
  77.  *
  78.  * Revision 1.35  1995/12/12  21:48:48  brianp
  79.  * call GL_INTERPOLATE_Z instead of GL_INTERPOLATE_I
  80.  *
  81.  * Revision 1.34  1995/11/30  00:21:55  brianp
  82.  * restored old gl_polygon_edge function
  83.  *
  84.  * Revision 1.33  1995/11/14  21:49:40  brianp
  85.  * optimized polygon rendering setup
  86.  *
  87.  * Revision 1.32  1995/11/04  20:09:07  brianp
  88.  * optimized gl_polygon_edge()
  89.  *
  90.  * Revision 1.31  1995/10/29  19:14:44  brianp
  91.  * added glPolygonOffsetEXT display list support
  92.  *
  93.  * Revision 1.30  1995/10/27  20:30:29  brianp
  94.  * added glPolygonOffsetEXT()
  95.  *
  96.  * Revision 1.29  1995/10/24  20:52:15  brianp
  97.  * renamed COMPUTE_PLANE_Z as gl_compute_z
  98.  * renamed polygon_edge as gl_polygon_edge
  99.  * use new color interpolation based on fixed point arithmetic
  100.  * removed dead code
  101.  *
  102.  * Revision 1.28  1995/10/22  21:20:50  brianp
  103.  * changed 0.5 to 0.5F in COMPUTE_PLANE_Z calls
  104.  *
  105.  * Revision 1.27  1995/10/22  20:29:37  brianp
  106.  * removed dead code
  107.  *
  108.  * Revision 1.26  1995/10/19  15:48:28  brianp
  109.  * added gamma support
  110.  * changed DD.color arguments to GLubytes
  111.  *
  112.  * Revision 1.25  1995/10/17  21:40:04  brianp
  113.  * added fast_flat_rgba_z_polygon() function
  114.  * removed fast_ci/rgb_polygon() functions
  115.  *
  116.  * Revision 1.24  1995/09/20  18:20:39  brianp
  117.  * prototype device driver changes described
  118.  *
  119.  * Revision 1.23  1995/09/13  14:51:05  brianp
  120.  * use CC.NewState convention
  121.  * use DEFARRAY/UNDEFARRAY macros for Mac
  122.  * replaced VB.Vs and VB.Vt with VB.TexCoord
  123.  *
  124.  * Revision 1.22  1995/07/28  21:34:16  brianp
  125.  * support polygons draw in viewport larger than window
  126.  *
  127.  * Revision 1.21  1995/07/15  14:04:50  brianp
  128.  * fixed texture coord interpolation bug
  129.  *
  130.  * Revision 1.20  1995/07/11  17:47:45  brianp
  131.  * round window coords to nearest int, not truncate, in fast_ci|rgba_polygon
  132.  *
  133.  * Revision 1.19  1995/06/20  16:32:40  brianp
  134.  * new depth buffer value computations
  135.  * introduced new triangle rasterizer code, experimental, not used yet
  136.  *
  137.  * Revision 1.18  1995/06/12  15:43:35  brianp
  138.  * changed color arrays to GLubyte
  139.  * new interpolation functions
  140.  *
  141.  * Revision 1.17  1995/06/05  20:27:53  brianp
  142.  * added CC.Polygon.Unfilled stuff
  143.  *
  144.  * Revision 1.16  1995/06/02  13:59:46  brianp
  145.  * added fast_smooth_rgba_z_polygon() function
  146.  *
  147.  * Revision 1.15  1995/05/31  19:34:12  brianp
  148.  * replaced MAX_VERTICES with VB_MAX
  149.  *
  150.  * Revision 1.14  1995/05/22  21:02:41  brianp
  151.  * Release 1.2
  152.  *
  153.  * Revision 1.13  1995/05/12  17:01:05  brianp
  154.  * changed CC.Mode!=0 to INSIDE_BEGIN_END
  155.  *
  156.  * Revision 1.12  1995/04/18  15:48:23  brianp
  157.  * fixed assignment of NULL to function pointers to prevent warnings on Suns
  158.  *
  159.  * Revision 1.11  1995/04/12  15:36:15  brianp
  160.  * updated to use DD.draw_* function pointers
  161.  *
  162.  * Revision 1.10  1995/03/27  20:31:53  brianp
  163.  * new Texture.Enabled scheme
  164.  *
  165.  * Revision 1.9  1995/03/24  19:28:13  brianp
  166.  * introduced VB
  167.  *
  168.  * Revision 1.8  1995/03/07  14:20:59  brianp
  169.  * updated for new XSetForeground/GC scheme
  170.  *
  171.  * Revision 1.7  1995/03/04  19:29:44  brianp
  172.  * 1.1 beta revision
  173.  *
  174.  * Revision 1.6  1995/03/02  19:18:54  brianp
  175.  * new RasterMask logic
  176.  * fixed Vcolor/Vbcolor bug in textured_polygon()
  177.  *
  178.  * Revision 1.5  1995/02/27  22:49:01  brianp
  179.  * modified for PB
  180.  *
  181.  * Revision 1.4  1995/02/27  15:08:17  brianp
  182.  * added Vcolor/Vindex scheme
  183.  *
  184.  * Revision 1.3  1995/02/26  22:58:57  brianp
  185.  * made COMPUTE_PLANE_Z a function w/ FP overflow checking
  186.  *
  187.  * Revision 1.2  1995/02/25  22:07:43  brianp
  188.  * more debugging code
  189.  *
  190.  * Revision 1.1  1995/02/24  14:26:49  brianp
  191.  * Initial revision
  192.  *
  193.  */
  194.  
  195.  
  196. #include <string.h>
  197. #include "context.h"
  198. #include "dd.h"
  199. #include "depth.h"
  200. #include "feedback.h"
  201. #include "interp.h"
  202. #include "lines.h"
  203. #include "list.h"
  204. #include "macros.h"
  205. #include "points.h"
  206. #include "span.h"
  207. #include "vb.h"
  208.  
  209. /*#include "triangle.h"*/
  210.  
  211.  
  212. void glCullFace( GLenum mode )
  213. {
  214.    if (CC.CompileFlag) {
  215.       gl_save_cullface( mode );
  216.    }
  217.    if (CC.ExecuteFlag) {
  218.       if (mode!=GL_FRONT && mode!=GL_BACK && mode!=GL_FRONT_AND_BACK) {
  219.      gl_error( GL_INVALID_ENUM, "glCullFace" );
  220.      return;
  221.       }
  222.       if (INSIDE_BEGIN_END) {
  223.      gl_error( GL_INVALID_OPERATION, "glCullFace" );
  224.      return;
  225.       }
  226.       CC.Polygon.CullFaceMode = mode;
  227.       CC.NewState = GL_TRUE;
  228.    }
  229. }
  230.  
  231.  
  232.  
  233. void glFrontFace( GLenum mode )
  234. {
  235.    if (CC.CompileFlag) {
  236.       gl_save_frontface( mode );
  237.    }
  238.    if (CC.ExecuteFlag) {
  239.       if (INSIDE_BEGIN_END) {
  240.      gl_error( GL_INVALID_OPERATION, "glFrontFace" );
  241.      return;
  242.       }
  243.       if (mode!=GL_CW && mode!=GL_CCW) {
  244.      gl_error( GL_INVALID_ENUM, "glFrontFace" );
  245.      return;
  246.       }
  247.       CC.Polygon.FrontFace = mode;
  248.    }  
  249. }
  250.  
  251.  
  252.  
  253. void glPolygonMode( GLenum face, GLenum mode )
  254. {
  255.    if (CC.CompileFlag) {
  256.       gl_save_polygonmode( face, mode );
  257.    }
  258.    if (CC.ExecuteFlag) {
  259.       if (INSIDE_BEGIN_END) {
  260.      gl_error( GL_INVALID_OPERATION, "glPolygonMode" );
  261.      return;
  262.       }
  263.       if (face!=GL_FRONT && face!=GL_BACK && face!=GL_FRONT_AND_BACK) {
  264.      gl_error( GL_INVALID_ENUM, "glPolygonMode(face)" );
  265.      return;
  266.       }
  267.       else if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) {
  268.      gl_error( GL_INVALID_ENUM, "glPolygonMode(mode)" );
  269.      return;
  270.       }
  271.  
  272.       if (face==GL_FRONT || face==GL_FRONT_AND_BACK) {
  273.      CC.Polygon.FrontMode = mode;
  274.       }
  275.       if (face==GL_BACK || face==GL_FRONT_AND_BACK) {
  276.      CC.Polygon.BackMode = mode;
  277.       }
  278.  
  279.       /* Compute a handy "shortcut" value: */
  280.       if (CC.Polygon.FrontMode!=GL_FILL || CC.Polygon.BackMode!=GL_FILL) {
  281.      CC.Polygon.Unfilled = GL_TRUE;
  282.       }
  283.       else {
  284.      CC.Polygon.Unfilled = GL_FALSE;
  285.       }
  286.  
  287.       CC.NewState = GL_TRUE;
  288.    }
  289. }
  290.  
  291.  
  292.  
  293. void glPolygonStipple( const GLubyte *mask )
  294. {
  295.    if (CC.CompileFlag) {
  296.       /*gl_save_polygon_stipple( mask );*/
  297.    }
  298.    if (CC.ExecuteFlag) {
  299.       /* TODO:  bit twiddling, unpacking */
  300.       if (INSIDE_BEGIN_END) {
  301.      gl_error( GL_INVALID_OPERATION, "glPolygonStipple" );
  302.      return;
  303.       }
  304.       MEMCPY( CC.PolygonStipple, mask, 32*sizeof(GLuint) );
  305.    }
  306. }
  307.  
  308.  
  309.  
  310. void glGetPolygonStipple( GLubyte *mask )
  311. {
  312.    /* TODO */
  313. }
  314.  
  315.  
  316.  
  317. #ifdef GL_EXT_polygon_offset
  318. void glPolygonOffsetEXT( GLfloat factor, GLfloat bias )
  319. {
  320.    if (CC.CompileFlag) {
  321.       gl_save_polygonoffset( factor, bias );
  322.    }
  323.    if (CC.ExecuteFlag) {
  324.       if (INSIDE_BEGIN_END) {
  325.          gl_error( GL_INVALID_OPERATION, "glPolygonOffsetEXT" );
  326.          return;
  327.       }
  328.       CC.Polygon.OffsetFactor = factor;
  329.       CC.Polygon.OffsetBias = bias;
  330.    }
  331. }
  332. #endif
  333.  
  334.  
  335.  
  336. /**********************************************************************/
  337. /*****                    Rasterization                           *****/
  338. /**********************************************************************/
  339.  
  340.  
  341. /*
  342.  * Summary of polygon drawing functions:
  343.  *   feedback_polygon - when rendering mode is GL_FEEDBACK
  344.  *   select_polygon - when rendering mode is GL_SELECT
  345.  *   flat_ci_polygon - flat-shaded, any raster ops, RGBA polygon
  346.  *   smooth_ci_polygon - smooth-shaded, any raster ops, CI polygon
  347.  *   flat_rgba_polygon - flat-shaded, any raster ops, RGBA polygon
  348.  *   smooth_rgba_polygon - smooth-shaded, any raster ops, RGBA polygon
  349.  *   textured_polygon - smooth-shaded, textured RGBA polygon
  350.  */
  351.  
  352.  
  353. /*
  354.  * All polygon drawing functions have the same arguments:
  355.  * n      - number of vertices
  356.  * vlist  - array of indexes into the vertex list
  357.  * pv     - provoking vertex: which vertex color to use for flat shading.
  358.  */
  359.  
  360.  
  361.  
  362.  
  363. /*
  364.  * Put polygon in feedback buffer.
  365.  */
  366. static void feedback_polygon( GLuint n, GLuint vlist[], GLuint pv )
  367. {
  368.    GLuint i;
  369.  
  370.    APPEND_TOKEN( (GLfloat) GL_POLYGON_TOKEN );
  371.    APPEND_TOKEN( (GLfloat) n );
  372.  
  373.    for (i=0;i<n;i++) {
  374.       GLfloat x, y, z, w;
  375.       GLfloat tc[4];
  376.       GLuint j = vlist[i];
  377.       GLfloat color[4];
  378.  
  379.       x = VB.Win[j][0] - CC.RasterOffsetX;
  380.       y = VB.Win[j][1] - CC.RasterOffsetY;
  381.       z = VB.Win[j][2];
  382.       w = VB.Clip[j][3];
  383.  
  384.       /* convert color from integer back to a float in [0,1] */
  385.       color[0] = (GLfloat) VB.Color[j][0] / CC.RedScale;
  386.       color[1] = (GLfloat) VB.Color[j][1] / CC.GreenScale;
  387.       color[2] = (GLfloat) VB.Color[j][2] / CC.BlueScale;
  388.       color[3] = (GLfloat) VB.Color[j][3] / CC.AlphaScale;
  389.  
  390.       tc[0] = VB.TexCoord[j][0];
  391.       tc[1] = VB.TexCoord[j][1];
  392.       tc[2] = 0.0F;          /* TODO: R, Q components */
  393.       tc[3] = 1.0F;
  394.  
  395.       gl_feedback_vertex( x, y, z, w, color, (GLfloat) VB.Index[j], tc );
  396.    }
  397. }
  398.  
  399.  
  400.  
  401. /*
  402.  * Put polygon in selection buffer.
  403.  */
  404. static void select_polygon( GLuint n, GLuint vlist[], GLuint pv )
  405. {
  406.    GLuint i;
  407.  
  408.    CC.HitFlag = GL_TRUE;
  409.    for (i=0;i<n;i++) {
  410.       GLuint j = vlist[i];
  411.       GLfloat wz = VB.Win[j][2];
  412.       if (wz < CC.HitMinZ) {
  413.      CC.HitMinZ = wz;
  414.       }
  415.       if (wz > CC.HitMaxZ) {
  416.      CC.HitMaxZ = wz;
  417.       }
  418.    }
  419. }
  420.  
  421.  
  422.  
  423. /*
  424.  * Left and right boundary values for polygon scan conversion
  425.  */
  426. static GLint lx[MAX_HEIGHT], rx[MAX_HEIGHT];    /* integer X bounds */
  427. static GLint li[MAX_HEIGHT], ri[MAX_HEIGHT];    /* Color Index */
  428. static GLfixed lr[MAX_HEIGHT], rr[MAX_HEIGHT];    /* Red */
  429. static GLfixed lg[MAX_HEIGHT], rg[MAX_HEIGHT];    /* Green */
  430. static GLfixed lb[MAX_HEIGHT], rb[MAX_HEIGHT];    /* Blue */
  431. static GLfixed la[MAX_HEIGHT], ra[MAX_HEIGHT];    /* Alpha */
  432.  
  433.  
  434.  
  435.  
  436. static void flat_ci_polygon( GLuint n, GLuint vlist[], GLuint pv )
  437. {
  438. #define INTERP_Z
  439. #define CLIP_Y
  440.  
  441. #define SETUP_CODE            \
  442.    GLuint index = VB.Index[pv];        \
  443.    if (!VB.MonoColor) {            \
  444.       /* set the color index */        \
  445.       (*DD.index)( index );        \
  446.    }
  447.  
  448. #define INNER_CODE                            \
  449.    GLdepth zspan[MAX_WIDTH];                        \
  450.    GLint i;                                \
  451.    for (i=0;i<len;i++) {                        \
  452.       zspan[i] = FixedToUns(fz);  fz += fdzdx;                \
  453.    }                                    \
  454.    gl_write_monoindex_span( len, xmin, y, zspan, index, GL_POLYGON );
  455.  
  456. #include "polytemp.h"
  457. }
  458.  
  459.  
  460.  
  461. static void smooth_ci_polygon( GLuint n, GLuint vlist[], GLuint pv )
  462. {
  463. #define INTERP_INDEX
  464. #define INTERP_Z
  465. #define CLIP_Y
  466.  
  467. #define INNER_CODE                            \
  468.    GLdepth zspan[MAX_WIDTH];                        \
  469.    GLuint index[MAX_WIDTH];                        \
  470.    GLint i;                                \
  471.    for (i=0;i<len;i++) {                        \
  472.       zspan[i] = FixedToUns(fz);   fz += fdzdx;                \
  473.       index[i] = FixedToInt(fi);     fi += fdidx;            \
  474.    }                                    \
  475.    gl_write_index_span( len, xmin, y, zspan, index, GL_POLYGON );
  476.  
  477. #include "polytemp.h"
  478. }
  479.  
  480.  
  481.  
  482. static void flat_rgba_polygon( GLuint n, GLuint vlist[], GLuint pv )
  483. {
  484. #define INTERP_Z
  485. #define CLIP_Y
  486.  
  487. #define SETUP_CODE                \
  488.    if (!VB.MonoColor) {                \
  489.       /* set the color */            \
  490.       GLubyte r = VB.Color[pv][0];        \
  491.       GLubyte g = VB.Color[pv][1];        \
  492.       GLubyte b = VB.Color[pv][2];        \
  493.       GLubyte a = VB.Color[pv][3];        \
  494.       (*DD.color)( r, g, b, a );        \
  495.    }
  496.  
  497.  
  498. #define INNER_CODE                        \
  499.     GLdepth zspan[MAX_WIDTH];                    \
  500.     GLint i;                            \
  501.     for (i=0;i<len;i++) {                    \
  502.        zspan[i] = FixedToUns(fz);   fz += fdzdx;        \
  503.     }                                \
  504.     gl_write_monocolor_span( len, xmin, y, zspan,        \
  505.                              VB.Color[pv][0], VB.Color[pv][1],    \
  506.                              VB.Color[pv][2], VB.Color[pv][3],    \
  507.                  GL_POLYGON );
  508.  
  509. #include "polytemp.h"
  510. }
  511.  
  512.  
  513.  
  514. static void smooth_rgba_polygon( GLuint n, GLuint vlist[], GLuint pv )
  515. {
  516. #define INTERP_COLOR
  517. #define INTERP_ALPHA
  518. #define INTERP_Z
  519. #define CLIP_Y
  520.  
  521. #define INNER_CODE                        \
  522.    GLdepth zspan[MAX_WIDTH];                    \
  523.    GLubyte red[MAX_WIDTH], green[MAX_WIDTH];            \
  524.    GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];            \
  525.    GLint i;                            \
  526.    for (i=0;i<len;i++) {                    \
  527.       zspan[i] = FixedToUns(fz);    fz += fdzdx;        \
  528.       red[i]   = FixedToInt(fr);    fr += fdrdx;        \
  529.       green[i] = FixedToInt(fg);    fg += fdgdx;        \
  530.       blue[i]  = FixedToInt(fb);    fb += fdbdx;        \
  531.       alpha[i] = FixedToInt(fa);    fa += fdadx;        \
  532.    }                                \
  533.    gl_write_color_span( len, xmin, y, zspan,            \
  534.             red, green, blue, alpha, GL_POLYGON );
  535.  
  536. #include "polytemp.h"
  537. }
  538.  
  539.  
  540.  
  541.  
  542. /* Max number of pixels along a polygon's edge */
  543. #if MAX_WIDTH > MAX_HEIGHT
  544. #  define EDGEMAX MAX_WIDTH
  545. #else
  546. #  define EDGEMAX MAX_HEIGHT
  547. #endif
  548.  
  549. static GLfloat flx[MAX_HEIGHT], frx[MAX_HEIGHT];/* float X bounds */
  550. static GLfloat ls[MAX_HEIGHT], rs[MAX_HEIGHT];    /* S */
  551. static GLfloat lt[MAX_HEIGHT], rt[MAX_HEIGHT];    /* T */
  552. static GLfloat lu[MAX_HEIGHT], ru[MAX_HEIGHT];    /* R */
  553. static GLfloat lv[MAX_HEIGHT], rv[MAX_HEIGHT];    /* Q */
  554.  
  555.  
  556. /*
  557.  * Compute the location of the pixels along the edge of a polygon.
  558.  * Input:  x1,y1, x2,y2 - endpoints of the polygon edge
  559.  * Output:  x, y - array of edge coords
  560.  * Return:  number of elements in x[], and y[]
  561.  *
  562.  * ONLY USED FOR TEXTURED POLYGON FUNCTION AT THIS TIME!
  563.  */
  564. static GLuint gl_polygon_edge( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2,
  565.                                GLfloat x[], GLint y[])
  566. {
  567.    GLint ymin, ymax, iy;
  568.    GLfloat slope;
  569.    GLuint i;
  570.  
  571.    if (y1==y2) {
  572.       /* skip horizontal edges */
  573.       return 0;
  574.    }
  575.  
  576.    slope = (x2-x1) / (y2-y1);
  577.    i = 0;
  578.  
  579.    if (y1<y2) {
  580.       ymin = (int) (y1 + 0.5F);
  581.       ymax = (int) (y2 + 0.5F) - 1;
  582.       for (iy=ymin; iy<=ymax; iy++) {
  583.          x[i] = x1 + ((iy+0.5F) - y1) * slope;
  584.          y[i] = iy;
  585.          i++;
  586.       }
  587.    }
  588.    else {
  589.       ymin = (int) (y2 + 0.5F);
  590.       ymax = (int) (y1 + 0.5F) - 1;
  591.       for (iy=ymax; iy>=ymin; iy--) {
  592.          x[i] = x1 + ((iy+0.5F) - y1) * slope;
  593.          y[i] = iy;
  594.          i++;
  595.       }
  596.    }
  597.    return i;
  598. }
  599.  
  600.  
  601.  
  602. /*
  603.  * Evaluate the current polygon's plane equation at (x,y) to get Z (integer).
  604.  */
  605. static GLint gl_compute_z( GLfloat x, GLfloat y )
  606. {
  607.    GLfloat fz;
  608.  
  609.    fz = (CC.PlaneD - CC.PlaneA*x - CC.PlaneB*y) / CC.PlaneC;
  610.  
  611.    if (fz<0.0F) {
  612.       return 0;
  613.    }
  614.    else if (fz>1.0F) {
  615.       return MAX_DEPTH;
  616.    }
  617.  
  618.    return (GLint) (fz * DEPTH_SCALE);
  619. }
  620.  
  621.  
  622.  
  623.  
  624. /*
  625.  * Render a texture mapped polygon.  This function is basically unchanged
  626.  * from Mesa 1.2.5 while all other polygon rasterizers have been rewritten.
  627.  * Textured polygons will improved eventually...
  628.  */
  629. static void textured_polygon( GLuint n, GLuint vlist[], GLuint pv )
  630. {
  631.    GLint i, j, y;
  632.    GLint ymin, ymax;
  633.    GLfloat lw[MAX_HEIGHT], rw[MAX_HEIGHT];
  634.  
  635.    /* find min and max of window coordinate Y values */
  636.    {
  637.       GLfloat min = 1.0e10;
  638.       GLfloat max = -1.0e10;
  639.       if (n==3) {
  640.          GLfloat winy;
  641.          winy = VB.Win[vlist[0]][1];
  642.          if (winy > max)  max = winy;
  643.          if (winy < min)  min = winy;
  644.          winy = VB.Win[vlist[1]][1];
  645.          if (winy > max)  max = winy;
  646.          if (winy < min)  min = winy;
  647.          winy = VB.Win[vlist[2]][1];
  648.          if (winy > max)  max = winy;
  649.          if (winy < min)  min = winy;
  650.       }
  651.       else {
  652.          for (i=0;i<n;i++) {
  653.             GLfloat winy = VB.Win[vlist[i]][1];
  654.             if (winy > max)  max = winy;
  655.             if (winy < min)  min = winy;
  656.          }
  657.       }
  658.       ymin = (GLint) min;
  659.       ymin = CLAMP( ymin, 0, MAX_HEIGHT-1 ) ;
  660.       ymax = (GLint) max;
  661.       ymax = CLAMP( ymax, 0, MAX_HEIGHT-1 ) ;
  662.    }
  663.  
  664.    /* init edge bounds */
  665.    for (y=ymin;y<=ymax;y++) {
  666.       flx[y] = (GLfloat) (MAX_WIDTH+1);
  667.       frx[y] = -1.0;
  668.    }
  669.  
  670.    /* process edges to compute bounds */
  671.    for (i=0;i<n;i++) {
  672.       GLuint j0, j1, len;
  673.       DEFARRAY( GLfloat, ex, EDGEMAX );  /* x in win coords */
  674.       DEFARRAY( GLint, ey, EDGEMAX );    /* y in win coords */
  675.       DEFARRAY( GLfloat, ew, EDGEMAX );  /* w in clip coords */
  676.       DEFARRAY( GLfloat, es, EDGEMAX );  /* texture s,t,r,q */
  677.       DEFARRAY( GLfloat, et, EDGEMAX );
  678.       DEFARRAY( GLfloat, eu, EDGEMAX );
  679.       DEFARRAY( GLfloat, ev, EDGEMAX );
  680.       GLfixed r0, g0, b0, a0, r1, g1, b1, a1, dr, dg, db, da;
  681.  
  682.  
  683.       j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  684.       j1 = vlist[i];
  685.  
  686.       /* compute edge pixels */
  687.       /* add 0.5 to undo the CC.RasterOffset */
  688.       len = gl_polygon_edge( VB.Win[j0][0]+0.5F, VB.Win[j0][1]+0.5F,
  689.                              VB.Win[j1][0]+0.5F, VB.Win[j1][1]+0.5F,
  690.                              ex, ey );
  691.  
  692.       /* setup for edge color interpolation */
  693.       if (CC.Light.ShadeModel==GL_FLAT) {
  694.          r0 = r1 = VB.Color[pv][0] << FIXED_SHIFT;
  695.          g0 = g1 = VB.Color[pv][1] << FIXED_SHIFT;
  696.          b0 = b1 = VB.Color[pv][2] << FIXED_SHIFT;
  697.          a0 = a1 = VB.Color[pv][3] << FIXED_SHIFT;
  698.       }
  699.       else {
  700.          r0 = VB.Color[j0][0];      r1 = VB.Color[j1][0];
  701.          g0 = VB.Color[j0][1];      g1 = VB.Color[j1][1];
  702.          b0 = VB.Color[j0][2];      b1 = VB.Color[j1][2];
  703.          a0 = VB.Color[j0][3];      a1 = VB.Color[j1][3];
  704.       }
  705.       if (len>1) {
  706.          GLint n = len-1;
  707.          dr = (r1-r0) / n;
  708.          dg = (g1-g0) / n;
  709.          db = (b1-b0) / n;
  710.          da = (a1-a0) / n;
  711.       }
  712.       else {
  713.          dr = dg = db = da = 0;
  714.       }
  715.  
  716.       gl_interp_texcoords( len, GL_TRUE, VB.Clip[j0][3], VB.Clip[j1][3],
  717.                VB.TexCoord[j0][0], VB.TexCoord[j1][0],
  718.                            VB.TexCoord[j0][1], VB.TexCoord[j1][1],
  719.                            VB.TexCoord[j0][2], VB.TexCoord[j1][2],
  720.                            VB.TexCoord[j0][3], VB.TexCoord[j1][3],
  721.                es, et, eu, ev, ew );
  722.  
  723.       /* update span bounds */
  724.       for (j=0;j<len;j++) {
  725.      register GLfloat x = ex[j];
  726.      register GLint y = ey[j];
  727.  
  728.      if (y>=0 && y<MAX_HEIGHT) {
  729.         /* update left and right span bounds */
  730.         if (x < flx[y]) {
  731.            flx[y] = x;
  732.            lr[y] = r0;
  733.            lg[y] = g0;
  734.            lb[y] = b0;
  735.            la[y] = a0;
  736.            ls[y] = es[j];
  737.            lt[y] = et[j];
  738.            lu[y] = eu[j] = 0.0;  /* just set to zero for now */
  739.            lv[y] = ev[j];
  740.            lw[y] = ew[j];
  741.         }
  742.         if (x > frx[y]) {
  743.            frx[y] = x;
  744.            rr[y] = r0;
  745.            rg[y] = g0;
  746.            rb[y] = b0;
  747.            ra[y] = a0;
  748.            rs[y] = es[j];
  749.            rt[y] = et[j];
  750.            ru[y] = eu[j] = 0.0;  /* just set to zero for now */
  751.            rv[y] = ev[j];
  752.            rw[y] = ew[j];
  753.         }
  754.      }
  755.          r0 += dr;   g0 += dg;   b0 += db;   a0 += da;
  756.       }
  757.       UNDEFARRAY( ex );
  758.       UNDEFARRAY( ey );
  759.       UNDEFARRAY( ew );
  760.       UNDEFARRAY( es );
  761.       UNDEFARRAY( et );
  762.       UNDEFARRAY( eu );
  763.       UNDEFARRAY( ev );
  764.    }
  765.  
  766.    /* process spans */
  767.    for (y=ymin;y<=ymax;y++) {
  768.       GLint xmin = (GLint) (flx[y] + 0.5);
  769.       GLint xmax = (GLint) (frx[y] - 0.5);
  770.       GLint len = xmax-xmin+1;
  771.       if (len>0) {
  772.      GLint z0, z1;
  773.      GLdepth zspan[MAX_WIDTH];
  774.          /* Allocate arrays dynamically on Mac */
  775.          DEFARRAY(GLubyte,red,MAX_WIDTH);
  776.          DEFARRAY(GLubyte,green,MAX_WIDTH);
  777.          DEFARRAY(GLubyte,blue,MAX_WIDTH);
  778.          DEFARRAY(GLubyte,alpha,MAX_WIDTH);
  779.          DEFARRAY(GLfloat,s,MAX_WIDTH);
  780.          DEFARRAY(GLfloat,t,MAX_WIDTH);
  781.          DEFARRAY(GLfloat,u,MAX_WIDTH);
  782.          DEFARRAY(GLfloat,v,MAX_WIDTH);
  783.  
  784.      /* interpolate z, colors and tex coords */
  785.      z0 = gl_compute_z( flx[y]+0.5F, (GLfloat) y + 0.5F );
  786.      z1 = gl_compute_z( frx[y]-0.5F, (GLfloat) y + 0.5F );
  787.      GL_INTERPOLATE_Z( len, z0, z1, zspan );
  788.      GL_INTERPOLATE_RGBA( len,
  789.                               lr[y], rr[y], red,
  790.                               lg[y], rg[y], green,
  791.                               lb[y], rb[y], blue,
  792.                               la[y], ra[y], alpha );
  793.  
  794.      gl_interp_texcoords( len, GL_FALSE,
  795.                   lw[y], rw[y],
  796.                   ls[y], rs[y], 
  797.                   lt[y], rt[y],
  798.                   lu[y], ru[y],
  799.                   lv[y], rv[y],
  800.                   s, t, u, v, NULL );
  801.  
  802.      gl_write_texture_span( len, xmin, y, zspan,  s, t,
  803.                 red, green, blue, alpha, GL_POLYGON );
  804.  
  805.          /* Free dynamic arrays on Mac */
  806.          UNDEFARRAY(red);
  807.          UNDEFARRAY(green);
  808.          UNDEFARRAY(blue);
  809.          UNDEFARRAY(alpha);
  810.          UNDEFARRAY(s);
  811.          UNDEFARRAY(t);
  812.          UNDEFARRAY(u);
  813.          UNDEFARRAY(v); 
  814.       }
  815.    }
  816. }
  817.  
  818.  
  819.  
  820.  
  821. /*
  822.  * Render a polygon whose front or back rendering modes are point or line.
  823.  */
  824. static void unfilled_polygon( GLuint n, GLuint vlist[], GLuint pv )
  825. {
  826.    GLuint i, j, j0, j1;
  827.    GLboolean edge;
  828.  
  829.    CC.StippleCounter = 0;  /* in case we're drawing polygon outline */
  830.  
  831.    if (CC.Mode==GL_TRIANGLES || CC.Mode==GL_QUADS || CC.Mode==GL_POLYGON) {
  832.       edge = GL_FALSE;
  833.    }
  834.    else {
  835.       edge = GL_TRUE;
  836.    }
  837.  
  838.    if (CC.Orientation==0) {
  839.       /* Front facing */
  840.       if (CC.Polygon.FrontMode==GL_POINT) {
  841.      for (i=0;i<n;i++) {
  842.         j = vlist[i];
  843.         if (edge || VB.Edgeflag[j]) {
  844.                VB.Win[j][0] += 1.0F;    /* adjust window coords because */
  845.                VB.Win[j][1] += 1.0F;    /* raster offsets are differnt */
  846.            (*CC.PointsFunc)( j, j );  /* for points and polygons */
  847.                VB.Win[j][0] -= 1.0F;
  848.                VB.Win[j][1] -= 1.0F;
  849.         }
  850.      }
  851.       }
  852.       else if (CC.Polygon.FrontMode==GL_LINE) {
  853.      for (i=0;i<n;i++) {
  854.         j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  855.         j1 = vlist[i];
  856.         if (edge || VB.Edgeflag[j0]) {
  857.                VB.Win[j0][0] += 1.0F;
  858.                VB.Win[j0][1] += 1.0F;
  859.                VB.Win[j1][0] += 1.0F;
  860.                VB.Win[j1][1] += 1.0F;
  861.            (*CC.LineFunc)( j0, j1, pv );
  862.                VB.Win[j0][0] -= 1.0F;
  863.                VB.Win[j0][1] -= 1.0F;
  864.                VB.Win[j1][0] -= 1.0F;
  865.                VB.Win[j1][1] -= 1.0F;
  866.         }
  867.      }
  868.       }
  869.       else {
  870.      (*CC.AuxPolygonFunc)( n, vlist, pv );
  871.       }
  872.    }
  873.    else {
  874.       /* Back facing */
  875.       if (CC.Polygon.BackMode==GL_POINT) {
  876.      for (i=0;i<n;i++) {
  877.         j = vlist[i];
  878.         if (edge || VB.Edgeflag[j]) {
  879.                VB.Win[j][0] += 1.0F;    /* adjust window coords because */
  880.                VB.Win[j][1] += 1.0F;    /* raster offsets are differnt */
  881.            (*CC.PointsFunc)( j, j );  /* for points and polygons */
  882.                VB.Win[j][0] -= 1.0F;
  883.                VB.Win[j][1] -= 1.0F;
  884.         }
  885.      }
  886.       }
  887.       else if (CC.Polygon.BackMode==GL_LINE) {
  888.      for (i=0;i<n;i++) {
  889.         j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  890.         j1 = vlist[i];
  891.         if (edge || VB.Edgeflag[j0]) {
  892.                VB.Win[j0][0] += 1.0F;
  893.                VB.Win[j0][1] += 1.0F;
  894.                VB.Win[j1][0] += 1.0F;
  895.                VB.Win[j1][1] += 1.0F;
  896.            (*CC.LineFunc)( j0, j1, pv );
  897.                VB.Win[j0][0] -= 1.0F;
  898.                VB.Win[j0][1] -= 1.0F;
  899.                VB.Win[j1][0] -= 1.0F;
  900.                VB.Win[j1][1] -= 1.0F;
  901.         }
  902.      }
  903.       }
  904.       else {
  905.      (*CC.AuxPolygonFunc)( n, vlist, pv );
  906.       }
  907.    }
  908. }
  909.  
  910.  
  911.  
  912. /*
  913.  * Determine which polygon rendering function to use given the current
  914.  * rendering context.
  915.  */
  916. void gl_set_polygon_function( void )
  917. {
  918.    static GLboolean first_time = GL_TRUE;
  919.  
  920.    if (first_time) {
  921.       /* one-time polygon initialization */
  922.       GLint i;
  923.       for (i=0;i<MAX_HEIGHT;i++) {
  924.          lx[i] = MAX_WIDTH;
  925.          rx[i] = -1;
  926.       }
  927.       first_time = GL_FALSE;
  928.    }
  929.  
  930.    if (CC.RenderMode==GL_RENDER) {
  931.       CC.PolygonFunc = (*DD.get_polygon_func)();
  932.       if (CC.PolygonFunc) {
  933.          /* Device Driver will draw the polygon */
  934.       }
  935.       else if (CC.Texture.Enabled) {
  936.      /* textured */
  937.      CC.PolygonFunc = textured_polygon;
  938.       }
  939.       else {
  940.      if (CC.Light.ShadeModel==GL_SMOOTH) {
  941.         /* smooth shaded, no texturing, stippled or some raster ops */
  942.         CC.PolygonFunc = CC.RGBAflag ? smooth_rgba_polygon : smooth_ci_polygon;
  943.      }
  944.      else {
  945.         /* flat shaded, no texturing, stippled or some raster ops */
  946.         CC.PolygonFunc = CC.RGBAflag ? flat_rgba_polygon : flat_ci_polygon;
  947.      }
  948.       }
  949.  
  950.       /* PolygonMode */
  951.       if (CC.Polygon.Unfilled) {
  952.      /* front or back are to be rendered as points or lines */
  953.      if (!CC.PointsFunc) {
  954.         gl_set_point_function();
  955.      }
  956.      if (!CC.LineFunc) {
  957.         gl_set_line_function();
  958.      }
  959.      CC.AuxPolygonFunc = CC.PolygonFunc;
  960.      CC.PolygonFunc = unfilled_polygon;
  961.       }
  962.    }
  963.    else if (CC.RenderMode==GL_FEEDBACK) {
  964.       CC.PolygonFunc = feedback_polygon;
  965.    }
  966.    else {
  967.       /* GL_SELECT mode */
  968.       CC.PolygonFunc = select_polygon;
  969.    }
  970. }
  971.  
  972.  
  973.