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

  1. /* $Id: lines.c,v 1.18 1997/07/24 01:24:11 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.4
  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: lines.c,v $
  26.  * Revision 1.18  1997/07/24 01:24:11  brianp
  27.  * changed precompiled header symbol from PCH to PC_HEADER
  28.  *
  29.  * Revision 1.17  1997/07/05 16:03:51  brianp
  30.  * fixed PB overflow problem
  31.  *
  32.  * Revision 1.16  1997/06/20 02:01:49  brianp
  33.  * changed color components from GLfixed to GLubyte
  34.  *
  35.  * Revision 1.15  1997/06/03 01:38:22  brianp
  36.  * fixed divide by zero problem in feedback function (William Mitchell)
  37.  *
  38.  * Revision 1.14  1997/05/28 03:25:26  brianp
  39.  * added precompiled header (PCH) support
  40.  *
  41.  * Revision 1.13  1997/05/03 00:51:02  brianp
  42.  * removed calls to gl_texturing_enabled()
  43.  *
  44.  * Revision 1.12  1997/04/14 02:00:39  brianp
  45.  * #include "texstate.h" instead of "texture.h"
  46.  *
  47.  * Revision 1.11  1997/04/12 12:25:01  brianp
  48.  * replaced ctx->LineFunc with ctx->Driver.LineFunc, fixed PB->count bug
  49.  *
  50.  * Revision 1.10  1997/03/16 02:07:31  brianp
  51.  * now use linetemp.h in line drawing functions
  52.  *
  53.  * Revision 1.9  1997/03/08 02:04:27  brianp
  54.  * better implementation of feedback function
  55.  *
  56.  * Revision 1.8  1997/02/09 18:44:20  brianp
  57.  * added GL_EXT_texture3D support
  58.  *
  59.  * Revision 1.7  1997/01/09 19:48:00  brianp
  60.  * now call gl_texturing_enabled()
  61.  *
  62.  * Revision 1.6  1996/11/08 02:21:21  brianp
  63.  * added null drawing function for GL_NO_RASTER
  64.  *
  65.  * Revision 1.5  1996/09/27 01:28:56  brianp
  66.  * removed unused variables
  67.  *
  68.  * Revision 1.4  1996/09/25 02:01:54  brianp
  69.  * new texture coord interpolation
  70.  *
  71.  * Revision 1.3  1996/09/15 14:18:10  brianp
  72.  * now use GLframebuffer and GLvisual
  73.  *
  74.  * Revision 1.2  1996/09/15 01:48:58  brianp
  75.  * removed #define NULL 0
  76.  *
  77.  * Revision 1.1  1996/09/13 01:38:16  brianp
  78.  * Initial revision
  79.  *
  80.  */
  81.  
  82.  
  83. #ifdef PC_HEADER
  84. #include "all.h"
  85. #else
  86. #include "context.h"
  87. #include "depth.h"
  88. #include "feedback.h"
  89. #include "lines.h"
  90. #include "dlist.h"
  91. #include "macros.h"
  92. #include "pb.h"
  93. #include "texstate.h"
  94. #include "types.h"
  95. #include "vb.h"
  96. #endif
  97.  
  98. #define BOOL_TO_FLOAT(X)        ( (GLfloat)(GLint) (X) )
  99. #define BOOL_TO_DOUBLE(X)        ( (GLdouble)(GLint) (X) )
  100.  
  101.  
  102. void gl_LineWidth( GLcontext *ctx, GLfloat width )
  103. {
  104.    if (width<=0.0) {
  105.       gl_error( ctx, GL_INVALID_VALUE, "glLineWidth" );
  106.       return;
  107.    }
  108.    if (INSIDE_BEGIN_END(ctx)) {
  109.       gl_error( ctx, GL_INVALID_OPERATION, "glLineWidth" );
  110.       return;
  111.    }
  112.    ctx->NewState |= NEW_RASTER_OPS;
  113.    ctx->Line.Width = width;
  114. }
  115.  
  116.  
  117.  
  118. void gl_LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
  119. {
  120.    if (INSIDE_BEGIN_END(ctx)) {
  121.       gl_error( ctx, GL_INVALID_OPERATION, "glLineStipple" );
  122.       return;
  123.    }
  124.    ctx->NewState |= NEW_RASTER_OPS;
  125.    ctx->Line.StippleFactor = CLAMP( factor, 1, 256 );
  126.    ctx->Line.StipplePattern = pattern;
  127. }
  128.  
  129.  
  130.  
  131. /**********************************************************************/
  132. /*****                    Rasterization                           *****/
  133. /**********************************************************************/
  134.  
  135.  
  136. /*
  137.  * There are 4 pairs (RGBA, CI) of line drawing functions:
  138.  *   1. simple:  width=1 and no special rasterization functions (fastest)
  139.  *   2. flat:  width=1, non-stippled, flat-shaded, any raster operations
  140.  *   3. smooth:  width=1, non-stippled, smooth-shaded, any raster operations
  141.  *   4. general:  any other kind of line (slowest)
  142.  */
  143.  
  144.  
  145. /*
  146.  * All line drawing functions have the same arguments:
  147.  * v1, v2 - indexes of first and second endpoints into vertex buffer arrays
  148.  * pv     - provoking vertex: which vertex color/index to use for flat shading.
  149.  */
  150.  
  151.  
  152.  
  153. static void feedback_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  154. {
  155.    struct vertex_buffer *VB = ctx->VB;
  156.    GLfloat x1, y1, z1, w1;
  157.    GLfloat x2, y2, z2, w2;
  158.    GLfloat tex1[4], tex2[4], invq;
  159.    GLfloat invRedScale   = ctx->Visual->InvRedScale;
  160.    GLfloat invGreenScale = ctx->Visual->InvGreenScale;
  161.    GLfloat invBlueScale  = ctx->Visual->InvBlueScale;
  162.    GLfloat invAlphaScale = ctx->Visual->InvAlphaScale;
  163.  
  164.    x1 = VB->Win[v1][0];
  165.    y1 = VB->Win[v1][1];
  166.    z1 = VB->Win[v1][2] / DEPTH_SCALE;
  167.    w1 = VB->Clip[v1][3];
  168.  
  169.    x2 = VB->Win[v2][0];
  170.    y2 = VB->Win[v2][1];
  171.    z2 = VB->Win[v2][2] / DEPTH_SCALE;
  172.    w2 = VB->Clip[v2][3];
  173.  
  174.    invq = (VB->TexCoord[v1][3]==0.0) ? 1.0 : (1.0F / VB->TexCoord[v1][3]);
  175.    tex1[0] = VB->TexCoord[v1][0] * invq;
  176.    tex1[1] = VB->TexCoord[v1][1] * invq;
  177.    tex1[2] = VB->TexCoord[v1][2] * invq;
  178.    tex1[3] = VB->TexCoord[v1][3];
  179.    invq = (VB->TexCoord[v2][3]==0.0) ? 1.0 : (1.0F / VB->TexCoord[v2][3]);
  180.    tex2[0] = VB->TexCoord[v2][0] * invq;
  181.    tex2[1] = VB->TexCoord[v2][1] * invq;
  182.    tex2[2] = VB->TexCoord[v2][2] * invq;
  183.    tex2[3] = VB->TexCoord[v2][3];
  184.  
  185.    if (ctx->StippleCounter==0) {
  186.       FEEDBACK_TOKEN( ctx, BOOL_TO_FLOAT(GL_LINE_RESET_TOKEN) );
  187.    }
  188.    else {
  189.       FEEDBACK_TOKEN( ctx, BOOL_TO_FLOAT(GL_LINE_TOKEN) );
  190.    }
  191.  
  192.    {
  193.       GLfloat color[4];
  194.       /* convert color from integer to a float in [0,1] */
  195.       color[0] = (GLfloat) VB->Color[pv][0] * invRedScale;
  196.       color[1] = (GLfloat) VB->Color[pv][1] * invGreenScale;
  197.       color[2] = (GLfloat) VB->Color[pv][2] * invBlueScale;
  198.       color[3] = (GLfloat) VB->Color[pv][3] * invAlphaScale;
  199.       gl_feedback_vertex( ctx, x1,y1,z1,w1, color,
  200.               (GLfloat) VB->Index[pv], tex1 );
  201.       gl_feedback_vertex( ctx, x2,y2,z2,w2, color,
  202.               (GLfloat) VB->Index[pv], tex2 );
  203.    }
  204.  
  205.    ctx->StippleCounter++;
  206. }
  207.  
  208.  
  209.  
  210. static void select_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  211. {
  212.    gl_update_hitflag( ctx, ctx->VB->Win[v1][2] / DEPTH_SCALE );
  213.    gl_update_hitflag( ctx, ctx->VB->Win[v2][2] / DEPTH_SCALE );
  214. }
  215.  
  216.  
  217.  
  218. #if MAX_WIDTH > MAX_HEIGHT
  219. #  define MAXPOINTS MAX_WIDTH
  220. #else
  221. #  define MAXPOINTS MAX_HEIGHT
  222. #endif
  223.  
  224.  
  225. /* Flat, color index line */
  226. static void flat_ci_line( GLcontext *ctx,
  227.               GLuint vert0, GLuint vert1, GLuint pvert )
  228. {
  229.    GLint count;
  230.    GLint *pbx = ctx->PB->x;
  231.    GLint *pby = ctx->PB->y;
  232.    PB_SET_INDEX( ctx, ctx->PB, ctx->VB->Index[pvert] );
  233.    count = ctx->PB->count;
  234.  
  235. #define INTERP_XY 1
  236.  
  237. #define PLOT(X,Y)               \
  238.     pbx[count] = X;         \
  239.     pby[count] = Y;         \
  240.     count++;
  241.  
  242. #include "linetemp.h"
  243.  
  244.    ctx->PB->count = count;
  245.    PB_CHECK_FLUSH( ctx, ctx->PB );
  246. }
  247.  
  248.  
  249.  
  250. /* Flat, color index line with Z interpolation/testing */
  251. static void flat_ci_z_line( GLcontext *ctx,
  252.                 GLuint vert0, GLuint vert1, GLuint pvert )
  253. {
  254.    GLint count;
  255.    GLint *pbx = ctx->PB->x;
  256.    GLint *pby = ctx->PB->y;
  257.    GLdepth *pbz = ctx->PB->z;
  258.    PB_SET_INDEX( ctx, ctx->PB, ctx->VB->Index[pvert] );
  259.    count = ctx->PB->count;
  260.  
  261. #define INTERP_XY 1
  262. #define INTERP_Z 1
  263.  
  264. #define PLOT(X,Y)               \
  265.     pbx[count] = X;         \
  266.     pby[count] = Y;         \
  267.     pbz[count] = Z;         \
  268.     count++;
  269.  
  270. #include "linetemp.h"
  271.  
  272.    ctx->PB->count = count;
  273.    PB_CHECK_FLUSH( ctx, ctx->PB );
  274. }
  275.  
  276.  
  277.  
  278. /* Flat-shaded, RGBA line */
  279. static void flat_rgba_line( GLcontext *ctx,
  280.                 GLuint vert0, GLuint vert1, GLuint pvert )
  281. {
  282.    GLint count;
  283.    GLint *pbx = ctx->PB->x;
  284.    GLint *pby = ctx->PB->y;
  285.    GLubyte *color = ctx->VB->Color[pvert];
  286.    PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] );
  287.    count = ctx->PB->count;
  288.  
  289. #define INTERP_XY 1
  290.  
  291. #define PLOT(X,Y)               \
  292.     pbx[count] = X;         \
  293.     pby[count] = Y;         \
  294.     count++;
  295.  
  296. #include "linetemp.h"
  297.  
  298.    ctx->PB->count = count;
  299.    PB_CHECK_FLUSH( ctx, ctx->PB );
  300. }
  301.  
  302.  
  303.  
  304. /* Flat-shaded, RGBA line with Z interpolation/testing */
  305. static void flat_rgba_z_line( GLcontext *ctx,
  306.                   GLuint vert0, GLuint vert1, GLuint pvert )
  307. {
  308.    GLint count;
  309.    GLint *pbx = ctx->PB->x;
  310.    GLint *pby = ctx->PB->y;
  311.    GLdepth *pbz = ctx->PB->z;
  312.    GLubyte *color = ctx->VB->Color[pvert];
  313.    PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] );
  314.    count = ctx->PB->count;
  315.  
  316. #define INTERP_XY 1
  317. #define INTERP_Z 1
  318.  
  319. #define PLOT(X,Y)       \
  320.     pbx[count] = X; \
  321.     pby[count] = Y; \
  322.     pbz[count] = Z; \
  323.     count++;
  324.  
  325. #include "linetemp.h"
  326.  
  327.    ctx->PB->count = count;
  328.    PB_CHECK_FLUSH( ctx, ctx->PB );
  329. }
  330.  
  331.  
  332.  
  333. /* Smooth shaded, color index line */
  334. static void smooth_ci_line( GLcontext *ctx,
  335.                 GLuint vert0, GLuint vert1, GLuint pvert )
  336. {
  337.    GLint count = ctx->PB->count;
  338.    GLint *pbx = ctx->PB->x;
  339.    GLint *pby = ctx->PB->y;
  340.    GLuint *pbi = ctx->PB->i;
  341.  
  342. #define INTERP_XY 1
  343. #define INTERP_INDEX 1
  344.  
  345. #define PLOT(X,Y)               \
  346.     pbx[count] = X;         \
  347.     pby[count] = Y;         \
  348.     pbi[count] = I;         \
  349.     count++;
  350.  
  351. #include "linetemp.h"
  352.  
  353.    ctx->PB->count = count;
  354.    PB_CHECK_FLUSH( ctx, ctx->PB );
  355. }
  356.  
  357.  
  358.  
  359. /* Smooth shaded, color index line with Z interpolation/testing */
  360. static void smooth_ci_z_line( GLcontext *ctx,
  361.                   GLuint vert0, GLuint vert1, GLuint pvert )
  362. {
  363.    GLint count = ctx->PB->count;
  364.    GLint *pbx = ctx->PB->x;
  365.    GLint *pby = ctx->PB->y;
  366.    GLdepth *pbz = ctx->PB->z;
  367.    GLuint *pbi = ctx->PB->i;
  368.  
  369. #define INTERP_XY 1
  370. #define INTERP_Z 1
  371. #define INTERP_INDEX 1
  372.  
  373. #define PLOT(X,Y)               \
  374.     pbx[count] = X;         \
  375.     pby[count] = Y;         \
  376.     pbz[count] = Z;         \
  377.     pbi[count] = I;         \
  378.     count++;
  379.  
  380. #include "linetemp.h"
  381.  
  382.    ctx->PB->count = count;
  383.    PB_CHECK_FLUSH( ctx, ctx->PB );
  384. }
  385.  
  386.  
  387.  
  388. /* Smooth-shaded, RGBA line */
  389. static void smooth_rgba_line( GLcontext *ctx,
  390.                   GLuint vert0, GLuint vert1, GLuint pvert )
  391. {
  392.    GLint count = ctx->PB->count;
  393.    GLint *pbx = ctx->PB->x;
  394.    GLint *pby = ctx->PB->y;
  395.    GLubyte *pbr = ctx->PB->r;
  396.    GLubyte *pbg = ctx->PB->g;
  397.    GLubyte *pbb = ctx->PB->b;
  398.    GLubyte *pba = ctx->PB->a;
  399.  
  400. #define INTERP_XY 1
  401. #define INTERP_RGB 1
  402. #define INTERP_ALPHA 1
  403.  
  404. #define PLOT(X,Y)                       \
  405.     pbx[count] = X;                 \
  406.     pby[count] = Y;                 \
  407.     pbr[count] = FixedToInt(r0);    \
  408.     pbg[count] = FixedToInt(g0);    \
  409.     pbb[count] = FixedToInt(b0);    \
  410.     pba[count] = FixedToInt(a0);    \
  411.     count++;
  412.  
  413. #include "linetemp.h"
  414.  
  415.    ctx->PB->count = count;
  416.    PB_CHECK_FLUSH( ctx, ctx->PB );
  417. }
  418.  
  419.  
  420.  
  421. /* Smooth-shaded, RGBA line with Z interpolation/testing */
  422. static void smooth_rgba_z_line( GLcontext *ctx,
  423.                 GLuint vert0, GLuint vert1, GLuint pvert )
  424. {
  425.    GLint count = ctx->PB->count;
  426.    GLint *pbx = ctx->PB->x;
  427.    GLint *pby = ctx->PB->y;
  428.    GLdepth *pbz = ctx->PB->z;
  429.    GLubyte *pbr = ctx->PB->r;
  430.    GLubyte *pbg = ctx->PB->g;
  431.    GLubyte *pbb = ctx->PB->b;
  432.    GLubyte *pba = ctx->PB->a;
  433.  
  434. #define INTERP_XY 1
  435. #define INTERP_Z 1
  436. #define INTERP_RGB 1
  437. #define INTERP_ALPHA 1
  438.  
  439. #define PLOT(X,Y)                       \
  440.     pbx[count] = X;                 \
  441.     pby[count] = Y;                 \
  442.     pbz[count] = Z;                 \
  443.     pbr[count] = FixedToInt(r0);    \
  444.     pbg[count] = FixedToInt(g0);    \
  445.     pbb[count] = FixedToInt(b0);    \
  446.     pba[count] = FixedToInt(a0);    \
  447.     count++;
  448.  
  449. #include "linetemp.h"
  450.  
  451.    ctx->PB->count = count;
  452.    PB_CHECK_FLUSH( ctx, ctx->PB );
  453. }
  454.  
  455.  
  456. #define CHECK_FULL(count)                       \
  457.     if (count >= PB_SIZE-MAX_WIDTH) {       \
  458.        ctx->PB->count = count;              \
  459.        gl_flush_pb(ctx);                    \
  460.        count = ctx->PB->count;              \
  461.     }
  462.  
  463.  
  464.  
  465. /* Smooth shaded, color index, any width, maybe stippled */
  466. static void general_smooth_ci_line( GLcontext *ctx,
  467.                     GLuint vert0, GLuint vert1, GLuint pvert )
  468. {
  469.    GLint count = ctx->PB->count;
  470.    GLint *pbx = ctx->PB->x;
  471.    GLint *pby = ctx->PB->y;
  472.    GLdepth *pbz = ctx->PB->z;
  473.    GLuint *pbi = ctx->PB->i;
  474.  
  475.    if (ctx->Line.StippleFlag) {
  476.       /* stippled */
  477. #define INTERP_XY 1
  478. #define INTERP_Z 1
  479. #define INTERP_INDEX 1
  480. #define WIDE 1
  481. #define STIPPLE 1
  482. #define PLOT(X,Y)               \
  483.     pbx[count] = X;         \
  484.     pby[count] = Y;         \
  485.     pbz[count] = Z;         \
  486.     pbi[count] = I;         \
  487.     count++;                \
  488.     CHECK_FULL(count);
  489. #include "linetemp.h"
  490.    }
  491.    else {
  492.       /* unstippled */
  493.       if (ctx->Line.Width==2.0F) {
  494.      /* special case: unstippled and width=2 */
  495. #define INTERP_XY 1
  496. #define INTERP_Z 1
  497. #define INTERP_INDEX 1
  498. #define XMAJOR_PLOT(X,Y)                        \
  499.     pbx[count] = X;  pbx[count+1] = X;      \
  500.     pby[count] = Y;  pby[count+1] = Y+1;    \
  501.     pbz[count] = Z;  pbz[count+1] = Z;      \
  502.     pbi[count] = I;  pbi[count+1] = I;      \
  503.     count += 2;
  504. #define YMAJOR_PLOT(X,Y)                        \
  505.     pbx[count] = X;  pbx[count+1] = X+1;    \
  506.     pby[count] = Y;  pby[count+1] = Y;      \
  507.     pbz[count] = Z;  pbz[count+1] = Z;      \
  508.     pbi[count] = I;  pbi[count+1] = I;      \
  509.     count += 2;
  510. #include "linetemp.h"
  511.       }
  512.       else {
  513.      /* unstippled, any width */
  514. #define INTERP_XY 1
  515. #define INTERP_Z 1
  516. #define INTERP_INDEX 1
  517. #define WIDE 1
  518. #define PLOT(X,Y)               \
  519.     pbx[count] = X;         \
  520.     pby[count] = Y;         \
  521.     pbz[count] = Z;         \
  522.     pbi[count] = I;         \
  523.     count++;                \
  524.     CHECK_FULL(count);
  525. #include "linetemp.h"
  526.       }
  527.    }
  528.  
  529.    ctx->PB->count = count;
  530.    PB_CHECK_FLUSH( ctx, ctx->PB );
  531. }
  532.  
  533.  
  534. /* Flat shaded, color index, any width, maybe stippled */
  535. static void general_flat_ci_line( GLcontext *ctx,
  536.                   GLuint vert0, GLuint vert1, GLuint pvert )
  537. {
  538.    GLint count;
  539.    GLint *pbx = ctx->PB->x;
  540.    GLint *pby = ctx->PB->y;
  541.    GLdepth *pbz = ctx->PB->z;
  542.    PB_SET_INDEX( ctx, ctx->PB, ctx->VB->Index[pvert] );
  543.    count = ctx->PB->count;
  544.  
  545.    if (ctx->Line.StippleFlag) {
  546.       /* stippled, any width */
  547. #define INTERP_XY 1
  548. #define INTERP_Z 1
  549. #define WIDE 1
  550. #define STIPPLE 1
  551. #define PLOT(X,Y)               \
  552.     pbx[count] = X;         \
  553.     pby[count] = Y;         \
  554.     pbz[count] = Z;         \
  555.     count++;                \
  556.     CHECK_FULL(count);
  557. #include "linetemp.h"
  558.    }
  559.    else {
  560.       /* unstippled */
  561.       if (ctx->Line.Width==2.0F) {
  562.      /* special case: unstippled and width=2 */
  563. #define INTERP_XY 1
  564. #define INTERP_Z 1
  565. #define XMAJOR_PLOT(X,Y)                        \
  566.     pbx[count] = X;  pbx[count+1] = X;      \
  567.     pby[count] = Y;  pby[count+1] = Y+1;    \
  568.     pbz[count] = Z;  pbz[count+1] = Z;      \
  569.     count += 2;
  570. #define YMAJOR_PLOT(X,Y)                        \
  571.     pbx[count] = X;  pbx[count+1] = X+1;    \
  572.     pby[count] = Y;  pby[count+1] = Y;      \
  573.     pbz[count] = Z;  pbz[count+1] = Z;      \
  574.     count += 2;
  575. #include "linetemp.h"
  576.       }
  577.       else {
  578.      /* unstippled, any width */
  579. #define INTERP_XY 1
  580. #define INTERP_Z 1
  581. #define WIDE 1
  582. #define PLOT(X,Y)               \
  583.     pbx[count] = X;         \
  584.     pby[count] = Y;         \
  585.     pbz[count] = Z;         \
  586.     count++;                \
  587.     CHECK_FULL(count);
  588. #include "linetemp.h"
  589.       }
  590.    }
  591.  
  592.    ctx->PB->count = count;
  593.    PB_CHECK_FLUSH( ctx, ctx->PB );
  594. }
  595.  
  596.  
  597.  
  598. static void general_smooth_rgba_line( GLcontext *ctx,
  599.                       GLuint vert0, GLuint vert1, GLuint pvert)
  600. {
  601.    GLint count = ctx->PB->count;
  602.    GLint *pbx = ctx->PB->x;
  603.    GLint *pby = ctx->PB->y;
  604.    GLdepth *pbz = ctx->PB->z;
  605.    GLubyte *pbr = ctx->PB->r;
  606.    GLubyte *pbg = ctx->PB->g;
  607.    GLubyte *pbb = ctx->PB->b;
  608.    GLubyte *pba = ctx->PB->a;
  609.  
  610.    if (ctx->Line.StippleFlag) {
  611.       /* stippled */
  612. #define INTERP_XY 1
  613. #define INTERP_Z 1
  614. #define INTERP_RGB 1
  615. #define INTERP_ALPHA 1
  616. #define WIDE 1
  617. #define STIPPLE 1
  618. #define PLOT(X,Y)                       \
  619.     pbx[count] = X;                 \
  620.     pby[count] = Y;                 \
  621.     pbz[count] = Z;                 \
  622.     pbr[count] = FixedToInt(r0);    \
  623.     pbg[count] = FixedToInt(g0);    \
  624.     pbb[count] = FixedToInt(b0);    \
  625.     pba[count] = FixedToInt(a0);    \
  626.     count++;                        \
  627.     CHECK_FULL(count);
  628. #include "linetemp.h"
  629.    }
  630.    else {
  631.       /* unstippled */
  632.       if (ctx->Line.Width==2.0F) {
  633.      /* special case: unstippled and width=2 */
  634. #define INTERP_XY 1
  635. #define INTERP_Z 1
  636. #define INTERP_RGB 1
  637. #define INTERP_ALPHA 1
  638. #define XMAJOR_PLOT(X,Y)                                                \
  639.     pbx[count] = X;  pbx[count+1] = X;                              \
  640.     pby[count] = Y;  pby[count+1] = Y+1;                            \
  641.     pbz[count] = Z;  pbz[count+1] = Z;                              \
  642.     pbr[count] = FixedToInt(r0);  pbr[count+1] = FixedToInt(r0);    \
  643.     pbg[count] = FixedToInt(g0);  pbg[count+1] = FixedToInt(g0);    \
  644.     pbb[count] = FixedToInt(b0);  pbb[count+1] = FixedToInt(b0);    \
  645.     pba[count] = FixedToInt(a0);  pba[count+1] = FixedToInt(a0);    \
  646.     count += 2;
  647. #define YMAJOR_PLOT(X,Y)                                                \
  648.     pbx[count] = X;  pbx[count+1] = X+1;                            \
  649.     pby[count] = Y;  pby[count+1] = Y;                              \
  650.     pbz[count] = Z;  pbz[count+1] = Z;                              \
  651.     pbr[count] = FixedToInt(r0);  pbr[count+1] = FixedToInt(r0);    \
  652.     pbg[count] = FixedToInt(g0);  pbg[count+1] = FixedToInt(g0);    \
  653.     pbb[count] = FixedToInt(b0);  pbb[count+1] = FixedToInt(b0);    \
  654.     pba[count] = FixedToInt(a0);  pba[count+1] = FixedToInt(a0);    \
  655.     count += 2;
  656. #include "linetemp.h"
  657.       }
  658.       else {
  659.      /* unstippled, any width */
  660. #define INTERP_XY 1
  661. #define INTERP_Z 1
  662. #define INTERP_RGB 1
  663. #define INTERP_ALPHA 1
  664. #define WIDE 1
  665. #define PLOT(X,Y)                       \
  666.     pbx[count] = X;                 \
  667.     pby[count] = Y;                 \
  668.     pbz[count] = Z;                 \
  669.     pbr[count] = FixedToInt(r0);    \
  670.     pbg[count] = FixedToInt(g0);    \
  671.     pbb[count] = FixedToInt(b0);    \
  672.     pba[count] = FixedToInt(a0);    \
  673.     count++;                        \
  674.     CHECK_FULL(count);
  675. #include "linetemp.h"
  676.       }
  677.    }
  678.  
  679.    ctx->PB->count = count;
  680.    PB_CHECK_FLUSH( ctx, ctx->PB );
  681. }
  682.  
  683.  
  684. static void general_flat_rgba_line( GLcontext *ctx,
  685.                     GLuint vert0, GLuint vert1, GLuint pvert )
  686. {
  687.    GLint count;
  688.    GLint *pbx = ctx->PB->x;
  689.    GLint *pby = ctx->PB->y;
  690.    GLdepth *pbz = ctx->PB->z;
  691.    GLubyte *color = ctx->VB->Color[pvert];
  692.    PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] );
  693.    count = ctx->PB->count;
  694.  
  695.    if (ctx->Line.StippleFlag) {
  696.       /* stippled */
  697. #define INTERP_XY 1
  698. #define INTERP_Z 1
  699. #define WIDE 1
  700. #define STIPPLE 1
  701. #define PLOT(X,Y)                       \
  702.     pbx[count] = X;                 \
  703.     pby[count] = Y;                 \
  704.     pbz[count] = Z;                 \
  705.     count++;                        \
  706.     CHECK_FULL(count);
  707. #include "linetemp.h"
  708.    }
  709.    else {
  710.       /* unstippled */
  711.       if (ctx->Line.Width==2.0F) {
  712.      /* special case: unstippled and width=2 */
  713. #define INTERP_XY 1
  714. #define INTERP_Z 1
  715. #define XMAJOR_PLOT(X,Y)                        \
  716.     pbx[count] = X;  pbx[count+1] = X;      \
  717.     pby[count] = Y;  pby[count+1] = Y+1;    \
  718.     pbz[count] = Z;  pbz[count+1] = Z;      \
  719.     count += 2;
  720. #define YMAJOR_PLOT(X,Y)                        \
  721.     pbx[count] = X;  pbx[count+1] = X+1;    \
  722.     pby[count] = Y;  pby[count+1] = Y;      \
  723.     pbz[count] = Z;  pbz[count+1] = Z;      \
  724.     count += 2;
  725. #include "linetemp.h"
  726.       }
  727.       else {
  728.      /* unstippled, any width */
  729. #define INTERP_XY 1
  730. #define INTERP_Z 1
  731. #define WIDE 1
  732. #define PLOT(X,Y)                       \
  733.     pbx[count] = X;                 \
  734.     pby[count] = Y;                 \
  735.     pbz[count] = Z;                 \
  736.     count++;                        \
  737.     CHECK_FULL(count);
  738. #include "linetemp.h"
  739.       }
  740.    }
  741.  
  742.    ctx->PB->count = count;
  743.    PB_CHECK_FLUSH( ctx, ctx->PB );
  744. }
  745.  
  746.  
  747.  
  748. /* Flat-shaded, textured, any width, maybe stippled */
  749. static void flat_textured_line( GLcontext *ctx,
  750.                 GLuint vert0, GLuint vert1, GLuint pv )
  751. {
  752.    GLint count;
  753.    GLint *pbx = ctx->PB->x;
  754.    GLint *pby = ctx->PB->y;
  755.    GLdepth *pbz = ctx->PB->z;
  756.    GLfloat *pbs = ctx->PB->s;
  757.    GLfloat *pbt = ctx->PB->t;
  758.    GLfloat *pbu = ctx->PB->u;
  759.    GLubyte *color = ctx->VB->Color[pv];
  760.    PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] );
  761.    count = ctx->PB->count;
  762.  
  763.    if (ctx->Line.StippleFlag) {
  764.       /* stippled */
  765. #define INTERP_XY 1
  766. #define INTERP_Z 1
  767. #define INTERP_STW 1
  768. #define INTERP_UV 1
  769. #define WIDE 1
  770. #define STIPPLE 1
  771. #define PLOT(X,Y)                       \
  772.     pbx[count] = X;                 \
  773.     pby[count] = Y;                 \
  774.     pbz[count] = Z;                 \
  775.     pbs[count] = s0 / w0;           \
  776.     pbt[count] = t0 / w0;           \
  777.     pbu[count] = u0 / w0;           \
  778.     count++;                        \
  779.     CHECK_FULL(count);
  780. #include "linetemp.h"
  781.    }
  782.    else {
  783.       /* unstippled */
  784. #define INTERP_XY 1
  785. #define INTERP_Z 1
  786. #define INTERP_STW 1
  787. #define INTERP_UV 1
  788. #define WIDE 1
  789. #define PLOT(X,Y)                       \
  790.     pbx[count] = X;                 \
  791.     pby[count] = Y;                 \
  792.     pbz[count] = Z;                 \
  793.     pbs[count] = s0 / w0;           \
  794.     pbt[count] = t0 / w0;           \
  795.     pbu[count] = u0 / w0;           \
  796.     count++;                        \
  797.     CHECK_FULL(count);
  798. #include "linetemp.h"
  799.    }
  800.  
  801.    ctx->PB->count = count;
  802.    PB_CHECK_FLUSH( ctx, ctx->PB );
  803. }
  804.  
  805.  
  806.  
  807. /* Smooth-shaded, textured, any width, maybe stippled */
  808. static void smooth_textured_line( GLcontext *ctx,
  809.                   GLuint vert0, GLuint vert1, GLuint pv )
  810. {
  811.    GLint count = ctx->PB->count;
  812.    GLint *pbx = ctx->PB->x;
  813.    GLint *pby = ctx->PB->y;
  814.    GLdepth *pbz = ctx->PB->z;
  815.    GLfloat *pbs = ctx->PB->s;
  816.    GLfloat *pbt = ctx->PB->t;
  817.    GLfloat *pbu = ctx->PB->u;
  818.    GLubyte *pbr = ctx->PB->r;
  819.    GLubyte *pbg = ctx->PB->g;
  820.    GLubyte *pbb = ctx->PB->b;
  821.    GLubyte *pba = ctx->PB->a;
  822.  
  823.    if (ctx->Line.StippleFlag) {
  824.       /* stippled */
  825. #define INTERP_XY 1
  826. #define INTERP_Z 1
  827. #define INTERP_RGB 1
  828. #define INTERP_ALPHA 1
  829. #define INTERP_STW 1
  830. #define INTERP_UV 1
  831. #define WIDE 1
  832. #define STIPPLE 1
  833. #define PLOT(X,Y)                       \
  834.     pbx[count] = X;                 \
  835.     pby[count] = Y;                 \
  836.     pbz[count] = Z;                 \
  837.     pbs[count] = s0 / w0;           \
  838.     pbt[count] = t0 / w0;           \
  839.     pbu[count] = u0 / w0;           \
  840.     pbr[count] = FixedToInt(r0);    \
  841.     pbg[count] = FixedToInt(g0);    \
  842.     pbb[count] = FixedToInt(b0);    \
  843.     pba[count] = FixedToInt(a0);    \
  844.     count++;                        \
  845.     CHECK_FULL(count);
  846. #include "linetemp.h"
  847.    }
  848.    else {
  849.       /* unstippled */
  850. #define INTERP_XY 1
  851. #define INTERP_Z 1
  852. #define INTERP_RGB 1
  853. #define INTERP_ALPHA 1
  854. #define INTERP_STW 1
  855. #define INTERP_UV 1
  856. #define WIDE 1
  857. #define PLOT(X,Y)                       \
  858.     pbx[count] = X;                 \
  859.     pby[count] = Y;                 \
  860.     pbz[count] = Z;                 \
  861.     pbs[count] = s0 / w0;           \
  862.     pbt[count] = t0 / w0;           \
  863.     pbu[count] = u0 / w0;           \
  864.     pbr[count] = FixedToInt(r0);    \
  865.     pbg[count] = FixedToInt(g0);    \
  866.     pbb[count] = FixedToInt(b0);    \
  867.     pba[count] = FixedToInt(a0);    \
  868.     count++;                        \
  869.     CHECK_FULL(count);
  870. #include "linetemp.h"
  871.    }
  872.  
  873.    ctx->PB->count = count;
  874.    PB_CHECK_FLUSH( ctx, ctx->PB );
  875. }
  876.  
  877.  
  878.  
  879. /*
  880.  * Null rasterizer for measuring transformation speed.
  881.  */
  882. static void null_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  883. {
  884. }
  885.  
  886.  
  887.  
  888. /*
  889.  * Determine which line drawing function to use given the current
  890.  * rendering context.
  891.  */
  892. void gl_set_line_function( GLcontext *ctx )
  893. {
  894.    GLboolean rgbmode = ctx->Visual->RGBAflag;
  895.    /* TODO: antialiased lines */
  896.  
  897.    if (ctx->RenderMode==GL_RENDER) {
  898.       if (ctx->NoRaster) {
  899.      ctx->Driver.LineFunc = null_line;
  900.      return;
  901.       }
  902.       if (ctx->Driver.LineFunc) {
  903.      /* Device driver will draw lines. */
  904.      ctx->Driver.LineFunc = ctx->Driver.LineFunc;
  905.       }
  906.       else if (ctx->Texture.Enabled) {
  907.      if (ctx->Light.ShadeModel==GL_SMOOTH) {
  908.         ctx->Driver.LineFunc = smooth_textured_line;
  909.      }
  910.      else {
  911.         ctx->Driver.LineFunc = flat_textured_line;
  912.      }
  913.       }
  914.       else if (ctx->Line.Width!=1.0 || ctx->Line.StippleFlag
  915.            || ctx->Line.SmoothFlag || ctx->Texture.Enabled) {
  916.      if (ctx->Light.ShadeModel==GL_SMOOTH) {
  917.         ctx->Driver.LineFunc = rgbmode ? (line_func)general_smooth_rgba_line
  918.                        : (line_func)general_smooth_ci_line;
  919.      }
  920.      else {
  921.         ctx->Driver.LineFunc = rgbmode ? (line_func)general_flat_rgba_line
  922.                        : (line_func)general_flat_ci_line;
  923.      }
  924.       }
  925.       else {
  926.      if (ctx->Light.ShadeModel==GL_SMOOTH) {
  927.         /* Width==1, non-stippled, smooth-shaded */
  928.         if (ctx->Depth.Test
  929.         || (ctx->Fog.Enabled && ctx->Hint.Fog==GL_NICEST)) {
  930.            ctx->Driver.LineFunc = rgbmode ? (line_func)smooth_rgba_z_line
  931.                           : (line_func)smooth_ci_z_line;
  932.         }
  933.         else {
  934.            ctx->Driver.LineFunc = rgbmode ? (line_func)smooth_rgba_line
  935.                           : (line_func)smooth_ci_line;
  936.         }
  937.      }
  938.      else {
  939.         /* Width==1, non-stippled, flat-shaded */
  940.         if (ctx->Depth.Test
  941.         || (ctx->Fog.Enabled && ctx->Hint.Fog==GL_NICEST)) {
  942.            ctx->Driver.LineFunc = rgbmode ? (line_func)flat_rgba_z_line
  943.                           : (line_func)flat_ci_z_line;
  944.         }
  945.         else {
  946.            ctx->Driver.LineFunc = rgbmode ? (line_func)flat_rgba_line
  947.                           : (line_func)flat_ci_line;
  948.         }
  949.      }
  950.       }
  951.    }
  952.    else if (ctx->RenderMode==GL_FEEDBACK) {
  953.       ctx->Driver.LineFunc = feedback_line;
  954.    }
  955.    else {
  956.       /* GL_SELECT mode */
  957.       ctx->Driver.LineFunc = select_line;
  958.    }
  959. }
  960.  
  961.