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

  1. /* lines.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  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. $Id: lines.c,v 1.36 1996/02/12 19:08:45 brianp Exp $
  26.  
  27. $Log: lines.c,v $
  28.  * Revision 1.36  1996/02/12  19:08:45  brianp
  29.  * applied Bill's Feb 8 patches: change eye Z's to clip W's
  30.  *
  31.  * Revision 1.35  1996/02/01  00:55:40  brianp
  32.  * added some DEFARRAY(),UNDEFARRY() macros for Macintosh
  33.  *
  34.  * Revision 1.34  1996/01/22  15:29:16  brianp
  35.  * replaced gl_interpolate_4fixed() with gl_interpolate_rgba()
  36.  * changed a few variables from GLuint to GLint
  37.  *
  38.  * Revision 1.33  1995/12/30  17:17:22  brianp
  39.  * use new gl_interp_texcoords function, per Bill Triggs
  40.  *
  41.  * Revision 1.32  1995/12/30  00:55:22  brianp
  42.  * used fixed point vertex colors instead of floating point
  43.  *
  44.  * Revision 1.31  1995/12/20  15:26:14  brianp
  45.  * changed VB color indexes to GLuint
  46.  *
  47.  * Revision 1.30  1995/12/19  22:17:05  brianp
  48.  * removed 0.5 offset from window coordinates thanks to CC.RasterOffsetX/Y
  49.  *
  50.  * Revision 1.29  1995/12/18  17:26:15  brianp
  51.  * replaced MAX_DEPTH with DEPTH_SCALE
  52.  *
  53.  * Revision 1.28  1995/12/12  21:48:21  brianp
  54.  * call GL_INTERPOLATE_Z instead of GL_INTERPOLATE_I
  55.  *
  56.  * Revision 1.27  1995/10/23  21:28:30  brianp
  57.  * use new gl_interpolate_4ub function
  58.  *
  59.  * Revision 1.26  1995/10/17  21:40:58  brianp
  60.  * removed simple_ci/rgba_line() functions because of new device driver
  61.  *
  62.  * Revision 1.25  1995/09/21  14:07:29  brianp
  63.  * more new DD prototyping
  64.  *
  65.  * Revision 1.24  1995/09/20  18:20:39  brianp
  66.  * prototype device driver changes described
  67.  *
  68.  * Revision 1.23  1995/09/13  14:49:34  brianp
  69.  * use CC.NewState convention
  70.  * replaced VB.Vs and VB.Vt with VB.TexCoord
  71.  *
  72.  * Revision 1.22  1995/07/25  18:36:32  brianp
  73.  * convert window coords from floats to ints by rounding, not truncating
  74.  *
  75.  * Revision 1.21  1995/07/15  14:03:49  brianp
  76.  * added texture mapped lines
  77.  *
  78.  * Revision 1.20  1995/07/07  12:41:51  brianp
  79.  * use CLAMP macro in glLineStipple, upper limit being 256, not 255
  80.  *
  81.  * Revision 1.19  1995/06/20  16:21:34  brianp
  82.  * do float-to-int depth scaling here instead of in draw.c
  83.  *
  84.  * Revision 1.18  1995/06/12  15:39:09  brianp
  85.  * changed color arrays to GLubyte
  86.  * implement GL_LINE_RESET_TOKEN for feedback
  87.  * new interpolation functions
  88.  *
  89.  * Revision 1.17  1995/06/07  14:47:04  brianp
  90.  * faster width=2 lines
  91.  *
  92.  * Revision 1.16  1995/06/05  20:27:09  brianp
  93.  * removed PB.clipflag stuff
  94.  *
  95.  * Revision 1.15  1995/05/22  21:02:41  brianp
  96.  * Release 1.2
  97.  *
  98.  * Revision 1.14  1995/05/12  19:26:43  brianp
  99.  * replaced CC.Mode!=0 with INSIDE_BEGIN_END
  100.  *
  101.  * Revision 1.13  1995/05/12  16:26:50  brianp
  102.  * let PB do clipping of pixels for lines wider than 1
  103.  *
  104.  * Revision 1.12  1995/04/18  15:48:23  brianp
  105.  * fixed assignment of NULL to function pointers to prevent warnings on Suns
  106.  *
  107.  * Revision 1.11  1995/04/12  15:36:15  brianp
  108.  * updated to use DD.draw_* function pointers
  109.  *
  110.  * Revision 1.10  1995/03/27  20:31:53  brianp
  111.  * new Texture.Enabled scheme
  112.  *
  113.  * Revision 1.9  1995/03/24  15:33:25  brianp
  114.  * introduced VB
  115.  *
  116.  * Revision 1.8  1995/03/07  14:20:50  brianp
  117.  * updated for new XSetForeground/GC scheme
  118.  *
  119.  * Revision 1.7  1995/03/04  19:29:44  brianp
  120.  * 1.1 beta revision
  121.  *
  122.  * Revision 1.6  1995/03/04  19:16:57  brianp
  123.  * added width clamp
  124.  *
  125.  * Revision 1.5  1995/03/02  19:18:20  brianp
  126.  * new RasterMask logic
  127.  *
  128.  * Revision 1.4  1995/02/27  22:48:54  brianp
  129.  * modified for PB
  130.  *
  131.  * Revision 1.3  1995/02/27  15:08:08  brianp
  132.  * added Vcolor/Vindex scheme
  133.  *
  134.  * Revision 1.2  1995/02/24  15:15:53  brianp
  135.  * changed && to & in gl_set_line_func
  136.  *
  137.  * Revision 1.1  1995/02/24  14:23:09  brianp
  138.  * Initial revision
  139.  *
  140.  */
  141.  
  142.  
  143. #include "bresenhm.h"
  144. #include "context.h"
  145. #include "dd.h"
  146. #include "feedback.h"
  147. #include "interp.h"
  148. #include "list.h"
  149. #include "macros.h"
  150. #include "pb.h"
  151. #include "vb.h"
  152.  
  153.  
  154. #ifndef NULL
  155. #  define NULL 0
  156. #endif
  157.  
  158.  
  159. void glLineWidth( GLfloat width )
  160. {
  161.    if (CC.CompileFlag) {
  162.       gl_save_linewidth( width );
  163.    }
  164.    if (CC.ExecuteFlag) {
  165.       if (width<=0.0) {
  166.      gl_error( GL_INVALID_VALUE, "glLineWidth" );
  167.      return;
  168.       }
  169.       if (INSIDE_BEGIN_END) {
  170.      gl_error( GL_INVALID_OPERATION, "glLineWidth" );
  171.      return;
  172.       }
  173.  
  174.       CC.Line.Width = width;
  175.       CC.NewState = GL_TRUE;
  176.    }
  177. }
  178.  
  179.  
  180.  
  181. void glLineStipple( GLint factor, GLushort pattern )
  182. {
  183.    if (CC.CompileFlag) {
  184.       gl_save_linestipple( factor, pattern );
  185.    }
  186.    if (CC.ExecuteFlag) {
  187.       if (INSIDE_BEGIN_END) {
  188.      gl_error( GL_INVALID_OPERATION, "glLineStipple" );
  189.      return;
  190.       }
  191.  
  192.       CC.Line.StippleFactor = CLAMP( factor, 1, 256 );
  193.       CC.Line.StipplePattern = pattern;
  194.    }
  195. }
  196.  
  197.  
  198.  
  199. /**********************************************************************/
  200. /*****                    Rasterization                           *****/
  201. /**********************************************************************/
  202.  
  203.  
  204. /*
  205.  * There are 4 pairs (RGBA, CI) of line drawing functions:
  206.  *   1. simple:  width=1 and no special rasterization functions (fastest)
  207.  *   2. flat:  width=1, non-stippled, flat-shaded, any raster operations
  208.  *   3. smooth:  width=1, non-stippled, smooth-shaded, any raster operations
  209.  *   4. general:  any other kind of line (slowest)
  210.  */
  211.  
  212.  
  213. /*
  214.  * All line drawing functions have the same arguments:
  215.  * v1, v2 - indexes of first and second endpoints into vertex buffer arrays
  216.  * pv     - provoking vertex: which vertex color/index to use for flat shading.
  217.  */
  218.  
  219.  
  220.  
  221. static void feedback_line( GLuint v1, GLuint v2, GLuint pv )
  222. {
  223.    GLfloat x1, y1, z1, w1;
  224.    GLfloat x2, y2, z2, w2;
  225.    GLfloat tex1[4], tex2[4];  /* texture coord */
  226.  
  227.    x1 = VB.Win[v1][0] - CC.RasterOffsetX;
  228.    y1 = VB.Win[v1][1] - CC.RasterOffsetY;
  229.    z1 = VB.Win[v1][2];
  230.    w1 = VB.Clip[v1][3];
  231.  
  232.    x2 = VB.Win[v2][0] - CC.RasterOffsetX;
  233.    y2 = VB.Win[v2][1] - CC.RasterOffsetY;
  234.    z2 = VB.Win[v2][2];
  235.    w2 = VB.Clip[v2][3];
  236.  
  237.    if (CC.StippleCounter==0) {
  238.       APPEND_TOKEN( (GLfloat) GL_LINE_RESET_TOKEN );
  239.    }
  240.    else {
  241.       APPEND_TOKEN( (GLfloat) GL_LINE_TOKEN );
  242.    }
  243.    if (CC.Light.ShadeModel==GL_FLAT) {
  244.       GLfloat color[4];
  245.       /* convert color from integer back to a float in [0,1] */
  246.       color[0] = (GLfloat) VB.Color[pv][0] / CC.RedScale;
  247.       color[1] = (GLfloat) VB.Color[pv][1] / CC.GreenScale;
  248.       color[2] = (GLfloat) VB.Color[pv][2] / CC.BlueScale;
  249.       color[3] = (GLfloat) VB.Color[pv][3] / CC.AlphaScale;
  250.       gl_feedback_vertex( x1,y1,z1,w1, color, (GLfloat) VB.Index[pv], tex1 );
  251.       gl_feedback_vertex( x2,y2,z2,w2, color, (GLfloat) VB.Index[pv], tex2 );
  252.    }
  253.    else {
  254.       GLfloat color[4];
  255.       /* convert color from integer back to a float in [0,1] */
  256.       color[0] = (GLfloat) (VB.Color[v1][0] >> CC.ColorShift) / CC.RedScale;
  257.       color[1] = (GLfloat) (VB.Color[v1][1] >> CC.ColorShift) / CC.GreenScale;
  258.       color[2] = (GLfloat) (VB.Color[v1][2] >> CC.ColorShift) / CC.BlueScale;
  259.       color[3] = (GLfloat) (VB.Color[v1][3] >> CC.ColorShift) / CC.AlphaScale;
  260.       gl_feedback_vertex( x1,y1,z1,w1, color, (GLfloat) VB.Index[v1], tex1 );
  261.       /* convert color from integer back to a float in [0,1] */
  262.       color[0] = (GLfloat) (VB.Color[v2][0] >> CC.ColorShift) / CC.RedScale;
  263.       color[1] = (GLfloat) (VB.Color[v2][1] >> CC.ColorShift) / CC.GreenScale;
  264.       color[2] = (GLfloat) (VB.Color[v2][2] >> CC.ColorShift) / CC.BlueScale;
  265.       color[3] = (GLfloat) (VB.Color[v2][3] >> CC.ColorShift) / CC.AlphaScale;
  266.       gl_feedback_vertex( x2,y2,z2,w2, color, (GLfloat) VB.Index[v2], tex2 );
  267.    }
  268.    CC.StippleCounter++;
  269. }
  270.  
  271.  
  272.  
  273. static void select_line( GLuint v1, GLuint v2, GLuint pv )
  274. {
  275.    GLfloat z1 = VB.Win[v1][2];
  276.    GLfloat z2 = VB.Win[v2][2];
  277.  
  278.    CC.HitFlag = GL_TRUE;
  279.    if (z1 < CC.HitMinZ) {
  280.       CC.HitMinZ = z1;
  281.    }
  282.    if (z1 > CC.HitMaxZ) {
  283.       CC.HitMaxZ = z1;
  284.    }
  285.    if (z2 < CC.HitMinZ) {
  286.       CC.HitMinZ = z2;
  287.    }
  288.    if (z2 > CC.HitMaxZ) {
  289.       CC.HitMaxZ = z2;
  290.    }
  291. }
  292.  
  293.  
  294.  
  295. #if MAX_WIDTH > MAX_HEIGHT
  296. #  define MAXPOINTS MAX_WIDTH
  297. #else
  298. #  define MAXPOINTS MAX_HEIGHT
  299. #endif
  300.  
  301.  
  302. /*
  303.  * Flat shaded, width=1, non-stippled, color index line.
  304.  */
  305. static void flat_ci_line( GLuint v1, GLuint v2, GLuint pv )
  306. {
  307.    GLint x1 = (GLint) VB.Win[v1][0];
  308.    GLint y1 = (GLint) VB.Win[v1][1];
  309.    GLint x2 = (GLint) VB.Win[v2][0];
  310.    GLint y2 = (GLint) VB.Win[v2][1];
  311.    GLint n;
  312.  
  313.    PB_SET_INDEX( VB.Index[pv] );
  314.  
  315.    /* compute pixel locations */
  316.    n = gl_bresenham( x1, y1, x2, y2, PB.x+PB.count, PB.y+PB.count );
  317.  
  318.    /* interpolate z values */
  319.    if (CC.Depth.Test) {
  320.       GLdepth *zptr = PB.z + PB.count;
  321.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  322.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  323.       GL_INTERPOLATE_Z( n, z1, z2, zptr );
  324.    }
  325.  
  326.    PB.count += n;
  327.    PB_CHECK_FLUSH
  328. }
  329.  
  330.  
  331. /*
  332.  * Flat-shaded, width=1, non-stippled, rgba line.
  333.  */
  334. static void flat_rgba_line( GLuint v1, GLuint v2, GLuint pv )
  335. {
  336.    GLint x1 = (GLint) VB.Win[v1][0];
  337.    GLint y1 = (GLint) VB.Win[v1][1];
  338.    GLint x2 = (GLint) VB.Win[v2][0];
  339.    GLint y2 = (GLint) VB.Win[v2][1];
  340.    GLint n;
  341.  
  342.    /* Note that color components are ints, not fixed point here */
  343.    PB_SET_COLOR( VB.Color[pv][0], VB.Color[pv][1],
  344.                  VB.Color[pv][2], VB.Color[pv][3] );
  345.  
  346.    /* compute pixel locations */
  347.    n = gl_bresenham( x1, y1, x2, y2, PB.x+PB.count, PB.y+PB.count );
  348.  
  349.    /* interpolate z values */
  350.    if (CC.Depth.Test) {
  351.       GLdepth *zptr = PB.z + PB.count;
  352.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  353.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  354.       GL_INTERPOLATE_Z( n, z1, z2, zptr );
  355.    }
  356.  
  357.    PB.count += n;
  358.    PB_CHECK_FLUSH
  359. }
  360.  
  361.  
  362.  
  363. /*
  364.  * Smooth-shaded, width=1, non-stippled, color index line.
  365.  */
  366. static void smooth_ci_line( GLuint v1, GLuint v2, GLuint pv )
  367. {
  368.    GLint x1 = (GLint) VB.Win[v1][0];
  369.    GLint y1 = (GLint) VB.Win[v1][1];
  370.    GLint x2 = (GLint) VB.Win[v2][0];
  371.    GLint y2 = (GLint) VB.Win[v2][1];
  372.    GLint n;
  373.  
  374.    /* compute pixel locations */
  375.    n = gl_bresenham( x1, y1, x2, y2, PB.x+PB.count, PB.y+PB.count );
  376.  
  377.    /* interpolate z values */
  378.    if (CC.Depth.Test) {
  379.       GLdepth *zptr = PB.z + PB.count;
  380.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  381.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  382.       GL_INTERPOLATE_Z( n, z1, z2, zptr );
  383.    }
  384.  
  385.    /* interpolate index */
  386.    gl_interpolate_i( n, (GLint) VB.Index[v1], (GLint) VB.Index[v2],
  387.                      (GLint *) PB.i+PB.count );
  388.  
  389.    PB.count += n;
  390.    PB_CHECK_FLUSH
  391. }
  392.  
  393.  
  394. /*
  395.  * Smooth-shaded, width=1, non-stippled, RGBA line.
  396.  */
  397. static void smooth_rgba_line( GLuint v1, GLuint v2, GLuint pv )
  398. {
  399.    GLint x1 = (GLint) VB.Win[v1][0];
  400.    GLint y1 = (GLint) VB.Win[v1][1];
  401.    GLint x2 = (GLint) VB.Win[v2][0];
  402.    GLint y2 = (GLint) VB.Win[v2][1];
  403.    GLint i, n;
  404.  
  405.    /* compute pixel locations */
  406.    n = gl_bresenham( x1, y1, x2, y2, PB.x+PB.count, PB.y+PB.count );
  407.  
  408.    /* interpolate z values */
  409.    if (CC.Depth.Test) {
  410.       GLdepth *zptr = PB.z + PB.count;
  411.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  412.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  413.       GL_INTERPOLATE_Z( n, z1, z2, zptr );
  414.    }
  415.  
  416.    /* interpolate color, VB.Colors are in fixed point */
  417.    gl_interpolate_rgba( n,
  418.                         VB.Color[v1][0], VB.Color[v2][0], PB.r+PB.count,
  419.                         VB.Color[v1][1], VB.Color[v2][1], PB.g+PB.count,
  420.                         VB.Color[v1][2], VB.Color[v2][2], PB.b+PB.count,
  421.                         VB.Color[v1][3], VB.Color[v2][3], PB.a+PB.count );
  422.  
  423.    PB.count += n;
  424.    PB_CHECK_FLUSH
  425. }
  426.  
  427.  
  428.  
  429. /*
  430.  * General CI line:  any width, smooth or flat, stippled, any raster ops.
  431.  */
  432. static void general_ci_line( GLuint v1, GLuint v2, GLuint pv )
  433. {
  434.    GLint x1, y1, x2, y2;
  435.    GLint x[MAXPOINTS], y[MAXPOINTS];
  436.    GLdepth z[MAXPOINTS];
  437.    GLubyte mask[MAXPOINTS];
  438.    GLuint index[MAXPOINTS];
  439.    GLint i, n;
  440.    GLint dx, dy;
  441.  
  442.    x1 = (GLint) VB.Win[v1][0];
  443.    y1 = (GLint) VB.Win[v1][1];
  444.    x2 = (GLint) VB.Win[v2][0];
  445.    y2 = (GLint) VB.Win[v2][1];
  446.  
  447.    /* compute pixel locations */
  448.    if (CC.Line.StippleFlag) {
  449.       n = gl_stippled_bresenham( x1, y1, x2, y2, x, y, mask );
  450.    }
  451.    else {
  452.       n = gl_bresenham( x1, y1, x2, y2, x, y );
  453.       for (i=0;i<n;i++) {
  454.      mask[i] = 1;
  455.       }
  456.    }
  457.  
  458.    if (CC.Depth.Test) {
  459.       /* interpolate z */
  460.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  461.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  462.       GL_INTERPOLATE_Z( n, z1, z2, z );
  463.    }
  464.  
  465.    if (CC.Light.ShadeModel==GL_FLAT) {
  466.       GLuint indx = VB.Index[pv];
  467.       for (i=0;i<n;i++) {
  468.      index[i] = indx;
  469.       }
  470.    }
  471.    else {
  472.       /* interpolate index */
  473.       gl_interpolate_i( n, (GLint) VB.Index[v1], (GLint) VB.Index[v2],
  474.                 (GLint *) index );
  475.    }
  476.  
  477.    /* compute delta x and delta y */
  478.    if (x1>x2) {
  479.       dx = x1 - x2;
  480.    }
  481.    else {
  482.       dx = x2 - x1;
  483.    }
  484.    if (y1>y2) {
  485.       dy = y1 - y2;
  486.    }
  487.    else {
  488.       dy = y2 - y1;
  489.    }
  490.  
  491.  
  492.    /* render */
  493.    if (CC.Line.Width==2.0F) {
  494.       /* special case, easy to optimize */
  495.       if (dx>dy) {
  496.      /* X-major: duplicate pixels in Y direction */
  497.      for (i=0;i<n;i++) {
  498.         if (mask[i]) {
  499.            PB_WRITE_CI_PIXEL( x[i], y[i]-1, z[i], index[i] );
  500.            PB_WRITE_CI_PIXEL( x[i], y[i], z[i], index[i] );
  501.         }
  502.      }
  503.       }
  504.       else {
  505.      /* Y-major: duplicate pixels in X direction */
  506.      for (i=0;i<n;i++) {
  507.         if (mask[i]) {
  508.            PB_WRITE_CI_PIXEL( x[i]-1, y[i], z[i], index[i] );
  509.            PB_WRITE_CI_PIXEL( x[i], y[i], z[i], index[i] );
  510.         }
  511.      }
  512.       }
  513.       PB_CHECK_FLUSH
  514.    }
  515.    else {
  516.       GLint width, w0, w1;
  517.       width = (GLint) CLAMP( CC.Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
  518.       w0 = -width / 2;
  519.       w1 = w0 + width - 1;
  520.  
  521.       if (dx>dy) {
  522.      /* X-major: duplicate pixels in Y direction */
  523.      for (i=0;i<n;i++) {
  524.         if (mask[i]) {
  525.            GLint yy;
  526.            GLint y0 = y[i] + w0;
  527.            GLint y1 = y[i] + w1;
  528.            for (yy=y0;yy<=y1;yy++) {
  529.           PB_WRITE_CI_PIXEL( x[i], yy, z[i], index[i] );
  530.            }
  531.            PB_CHECK_FLUSH
  532.         }
  533.      }
  534.       }
  535.       else {
  536.      /* Y-major: duplicate pixels in X direction */
  537.      for (i=0;i<n;i++) {
  538.         if (mask[i]) {
  539.            GLint xx;
  540.            GLint x0 = x[i] + w0;
  541.            GLint x1 = x[i] + w1;
  542.            for (xx=x0;xx<=x1;xx++) {
  543.           PB_WRITE_CI_PIXEL( xx, y[i], z[i], index[i] );
  544.            }
  545.            PB_CHECK_FLUSH
  546.         }
  547.      }
  548.       }
  549.    }
  550. }
  551.  
  552.  
  553. /*
  554.  * General RGBA line:  any width, smooth or flat, stippled, any raster ops.
  555.  */
  556. static void general_rgba_line( GLuint v1, GLuint v2, GLuint pv )
  557. {
  558.    GLint x1, y1, x2, y2;
  559.    GLint x[MAXPOINTS], y[MAXPOINTS];
  560.    GLdepth z[MAXPOINTS];
  561.    GLubyte mask[MAXPOINTS];
  562.    GLubyte red[MAXPOINTS], green[MAXPOINTS], blue[MAXPOINTS], alpha[MAXPOINTS];
  563.    GLint i, n;
  564.    GLint dx, dy;
  565.  
  566.    x1 = (GLint) VB.Win[v1][0];
  567.    y1 = (GLint) VB.Win[v1][1];
  568.    x2 = (GLint) VB.Win[v2][0];
  569.    y2 = (GLint) VB.Win[v2][1];
  570.  
  571.    /* compute the line */
  572.    if (CC.Line.StippleFlag) {
  573.       n = gl_stippled_bresenham( x1, y1, x2, y2, x, y, mask );
  574.    }
  575.    else {
  576.       n = gl_bresenham( x1, y1, x2, y2, x, y );
  577.       for (i=0;i<n;i++) {
  578.      mask[i] = 1;
  579.       }
  580.    }
  581.  
  582.    if (CC.Depth.Test) {
  583.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  584.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  585.       GL_INTERPOLATE_Z( n, z1, z2, z );
  586.    }
  587.  
  588.    if (CC.Light.ShadeModel==GL_FLAT) {
  589.       GLint r, g, b, a;
  590.       r = VB.Color[pv][0];  /* colors are ints, not fixed point */
  591.       g = VB.Color[pv][1];
  592.       b = VB.Color[pv][2];
  593.       a = VB.Color[pv][3];
  594.       for (i=0;i<n;i++) {
  595.      red[i]   = r;
  596.      green[i] = g;
  597.      blue[i]  = b;
  598.      alpha[i] = a;
  599.       }
  600.    }
  601.    else {
  602.       /* interpolate color, VB.Colors are in fixed point */
  603.       gl_interpolate_rgba( n,
  604.                            VB.Color[v1][0], VB.Color[v2][0], red,
  605.                            VB.Color[v1][1], VB.Color[v2][1], green,
  606.                            VB.Color[v1][2], VB.Color[v2][2], blue,
  607.                            VB.Color[v1][3], VB.Color[v2][3], alpha );
  608.    }
  609.  
  610.    /* compute delta x and delta y */
  611.    if (x1>x2) {
  612.       dx = x1 - x2;
  613.    }
  614.    else {
  615.       dx = x2 - x1;
  616.    }
  617.    if (y1>y2) {
  618.       dy = y1 - y2;
  619.    }
  620.    else {
  621.       dy = y2 - y1;
  622.    }
  623.  
  624.    /* render */
  625.    if (CC.Line.Width==2.0F) {
  626.       /* special case, easy to optimize */
  627.       if (dx>dy) {
  628.      /* X-major: duplicate pixels in Y direction */
  629.      for (i=0;i<n;i++) {
  630.         if (mask[i]) {
  631.            PB_WRITE_RGBA_PIXEL( x[i], y[i]-1, z[i],
  632.                     red[i], green[i], blue[i], alpha[i] );
  633.            PB_WRITE_RGBA_PIXEL( x[i], y[i], z[i],
  634.                     red[i], green[i], blue[i], alpha[i] );
  635.         }
  636.      }
  637.       }
  638.       else {
  639.      /* Y-major: duplicate pixels in X direction */
  640.      for (i=0;i<n;i++) {
  641.         if (mask[i]) {
  642.            PB_WRITE_RGBA_PIXEL( x[i]-1, y[i], z[i],
  643.                     red[i], green[i], blue[i], alpha[i] );
  644.            PB_WRITE_RGBA_PIXEL( x[i], y[i], z[i],
  645.                     red[i], green[i], blue[i], alpha[i] );
  646.         }
  647.      }
  648.       }
  649.       PB_CHECK_FLUSH
  650.    }
  651.    else {
  652.       GLint width, w0, w1;
  653.       width = (GLint) CLAMP( CC.Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
  654.       w0 = -width / 2;
  655.       w1 = w0 + width - 1;
  656.  
  657.       if (dx>dy) {
  658.      /* X-major: duplicate pixels in Y direction */
  659.      for (i=0;i<n;i++) {
  660.         if (mask[i]) {
  661.            GLint yy;
  662.            GLint y0 = y[i] + w0;
  663.            GLint y1 = y[i] + w1;
  664.            for (yy=y0;yy<=y1;yy++) {
  665.           PB_WRITE_RGBA_PIXEL( x[i], yy, z[i],
  666.                        red[i], green[i], blue[i], alpha[i] );
  667.            }
  668.            PB_CHECK_FLUSH
  669.         }
  670.      }
  671.       }
  672.       else {
  673.      /* Y-major: duplicate pixels in X direction */
  674.      for (i=0;i<n;i++) {
  675.         if (mask[i]) {
  676.            GLint xx;
  677.            GLint x0 = x[i] + w0;
  678.            GLint x1 = x[i] + w1;
  679.            for (xx=x0;xx<=x1;xx++) {
  680.           PB_WRITE_RGBA_PIXEL( xx, y[i], z[i],
  681.                        red[i], green[i], blue[i], alpha[i] );
  682.            }
  683.            PB_CHECK_FLUSH
  684.         }
  685.      }
  686.       }
  687.    }
  688. }
  689.  
  690.  
  691.  
  692. /*
  693.  * Textured RGBA line:  any width, smooth or flat, stippled, any raster ops
  694.  * with texturing.
  695.  */
  696. static void textured_rgba_line( GLuint v1, GLuint v2, GLuint pv )
  697. {
  698.    GLint x1, y1, x2, y2;
  699.    GLint x[MAXPOINTS], y[MAXPOINTS];
  700.    GLdepth z[MAXPOINTS];
  701.    GLubyte mask[MAXPOINTS];
  702.    /* Allocate arrays dynamically on Mac */
  703.    DEFARRAY(GLubyte,red,MAXPOINTS);
  704.    DEFARRAY(GLubyte,green,MAXPOINTS);
  705.    DEFARRAY(GLubyte,blue,MAXPOINTS);
  706.    DEFARRAY(GLubyte,alpha,MAXPOINTS);
  707.    DEFARRAY(GLfloat,s,MAXPOINTS);
  708.    DEFARRAY(GLfloat,t,MAXPOINTS);
  709.    DEFARRAY(GLfloat,u,MAXPOINTS);
  710.    DEFARRAY(GLfloat,v,MAXPOINTS);
  711.    GLint i, n;
  712.    GLint dx, dy;
  713.  
  714.    x1 = (GLint) VB.Win[v1][0];
  715.    y1 = (GLint) VB.Win[v1][1];
  716.    x2 = (GLint) VB.Win[v2][0];
  717.    y2 = (GLint) VB.Win[v2][1];
  718.  
  719.    /* compute the line */
  720.    if (CC.Line.StippleFlag) {
  721.       n = gl_stippled_bresenham( x1, y1, x2, y2, x, y, mask );
  722.    }
  723.    else {
  724.       n = gl_bresenham( x1, y1, x2, y2, x, y );
  725.       for (i=0;i<n;i++) {
  726.      mask[i] = 1;
  727.       }
  728.    }
  729.  
  730.    if (CC.Depth.Test) {
  731.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  732.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  733.       GL_INTERPOLATE_Z( n, z1, z2, z );
  734.    }
  735.  
  736.    if (CC.Light.ShadeModel==GL_FLAT) {
  737.       GLint r, g, b, a;
  738.       r = VB.Color[pv][0];  /* colors are ints, not in fixed point */
  739.       g = VB.Color[pv][1];
  740.       b = VB.Color[pv][2];
  741.       a = VB.Color[pv][3];
  742.       for (i=0;i<n;i++) {
  743.      red[i]   = r;
  744.      green[i] = g;
  745.      blue[i]  = b;
  746.      alpha[i] = a;
  747.       }
  748.    }
  749.    else {
  750.       /* interpolate color, VB.Colors are in fixed point */
  751.       gl_interpolate_rgba( n,
  752.                            VB.Color[v1][0], VB.Color[v2][0], red,
  753.                            VB.Color[v1][1], VB.Color[v2][1], green,
  754.                            VB.Color[v1][2], VB.Color[v2][2], blue,
  755.                            VB.Color[v1][3], VB.Color[v2][3], alpha );
  756.    }
  757.  
  758.    /* interpolate texture coordinates */
  759.    gl_interp_texcoords( n, GL_FALSE, VB.Clip[v1][3],VB.Clip[v2][3],
  760.                 VB.TexCoord[v1][0], VB.TexCoord[v2][0],
  761.                         VB.TexCoord[v1][1], VB.TexCoord[v2][1],
  762.                         VB.TexCoord[v1][2], VB.TexCoord[v2][2],
  763.                         VB.TexCoord[v1][3], VB.TexCoord[v2][3],
  764.                 s, t, u, v, NULL );
  765.  
  766.    /* compute delta x and delta y */
  767.    if (x1>x2) {
  768.       dx = x1 - x2;
  769.    }
  770.    else {
  771.       dx = x2 - x1;
  772.    }
  773.    if (y1>y2) {
  774.       dy = y1 - y2;
  775.    }
  776.    else {
  777.       dy = y2 - y1;
  778.    }
  779.  
  780.    /* render */
  781.    if (CC.Line.Width==2.0F) {
  782.       /* special case, easy to optimize */
  783.       if (dx>dy) {
  784.      /* X-major: duplicate pixels in Y direction */
  785.      for (i=0;i<n;i++) {
  786.         if (mask[i]) {
  787.            PB_WRITE_TEX_PIXEL( x[i], y[i]-1, z[i],
  788.               red[i], green[i], blue[i], alpha[i], s[i], t[i] );
  789.            PB_WRITE_TEX_PIXEL( x[i], y[i], z[i],
  790.               red[i], green[i], blue[i], alpha[i], s[i], t[i] );
  791.         }
  792.      }
  793.       }
  794.       else {
  795.      /* Y-major: duplicate pixels in X direction */
  796.      for (i=0;i<n;i++) {
  797.         if (mask[i]) {
  798.            PB_WRITE_TEX_PIXEL( x[i]-1, y[i], z[i],
  799.               red[i], green[i], blue[i], alpha[i], s[i], t[i] );
  800.            PB_WRITE_TEX_PIXEL( x[i], y[i], z[i],
  801.               red[i], green[i], blue[i], alpha[i], s[i], t[i] );
  802.         }
  803.      }
  804.       }
  805.       PB_CHECK_FLUSH
  806.    }
  807.    else {
  808.       GLint width, w0, w1;
  809.       width = (GLint) CLAMP( CC.Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
  810.       w0 = -width / 2;
  811.       w1 = w0 + width - 1;
  812.  
  813.       if (dx>dy) {
  814.      /* X-major: duplicate pixels in Y direction */
  815.      for (i=0;i<n;i++) {
  816.         if (mask[i]) {
  817.            GLint yy;
  818.            GLint y0 = y[i] + w0;
  819.            GLint y1 = y[i] + w1;
  820.            for (yy=y0;yy<=y1;yy++) {
  821.           PB_WRITE_TEX_PIXEL( x[i], yy, z[i],
  822.                  red[i], green[i], blue[i], alpha[i], s[i], t[i] );
  823.            }
  824.            PB_CHECK_FLUSH
  825.         }
  826.      }
  827.       }
  828.       else {
  829.      /* Y-major: duplicate pixels in X direction */
  830.      for (i=0;i<n;i++) {
  831.         if (mask[i]) {
  832.            GLint xx;
  833.            GLint x0 = x[i] + w0;
  834.            GLint x1 = x[i] + w1;
  835.            for (xx=x0;xx<=x1;xx++) {
  836.           PB_WRITE_TEX_PIXEL( xx, y[i], z[i],
  837.                  red[i], green[i], blue[i], alpha[i], s[i], t[i] );
  838.            }
  839.            PB_CHECK_FLUSH
  840.         }
  841.      }
  842.       }
  843.    }
  844.  
  845.    /* Deallocate dynamic arrays on Mac */
  846.    UNDEFARRAY(red);
  847.    UNDEFARRAY(green);
  848.    UNDEFARRAY(blue);
  849.    UNDEFARRAY(alpha);
  850.    UNDEFARRAY(s);
  851.    UNDEFARRAY(t);
  852.    UNDEFARRAY(u);
  853.    UNDEFARRAY(v); 
  854. }
  855.  
  856.  
  857.  
  858.  
  859. /*
  860.  * Determine which line drawing function to use given the current
  861.  * rendering context.
  862.  */
  863. void gl_set_line_function( void )
  864. {
  865.    /* TODO: antialiased lines */
  866.  
  867.    if (CC.RenderMode==GL_RENDER) {
  868.       CC.LineFunc = (*DD.get_line_func)();
  869.       if (CC.LineFunc) {
  870.          /* Device driver will draw lines. */
  871.       }
  872.       else if (CC.Texture.Enabled) {
  873.      CC.LineFunc = textured_rgba_line;
  874.       }
  875.       else if (CC.Line.Width!=1.0 || CC.Line.StippleFlag || CC.Line.SmoothFlag
  876.            || CC.Texture.Enabled) {
  877.      CC.LineFunc = CC.RGBAflag ? general_rgba_line : general_ci_line;
  878.       }
  879.       else {
  880.      if (CC.Light.ShadeModel==GL_SMOOTH) {
  881.         /* Width==1, non-stippled, smooth-shaded, any raster ops */
  882.         CC.LineFunc = CC.RGBAflag ? smooth_rgba_line : smooth_ci_line;
  883.      }
  884.          else {
  885.         /* Width==1, non-stippled, flat-shaded, any raster ops */
  886.         CC.LineFunc = CC.RGBAflag ? flat_rgba_line : flat_ci_line;
  887.          }
  888.       }
  889.    }
  890.    else if (CC.RenderMode==GL_FEEDBACK) {
  891.       CC.LineFunc = feedback_line;
  892.    }
  893.    else {
  894.       /* GL_SELECT mode */
  895.       CC.LineFunc = select_line;
  896.    }
  897. }
  898.  
  899.  
  900.