home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / swrast / s_lines.cpp < prev    next >
C/C++ Source or Header  |  2002-11-14  |  10KB  |  345 lines

  1. /* $Id: s_lines.c,v 1.33 2002/11/14 03:48:03 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  5.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. #include "glheader.h"
  29. #include "colormac.h"
  30. #include "macros.h"
  31. #include "mmath.h"
  32. #include "s_aaline.h"
  33. #include "s_context.h"
  34. #include "s_depth.h"
  35. #include "s_feedback.h"
  36. #include "s_lines.h"
  37. #include "s_span.h"
  38.  
  39.  
  40. /*
  41.  * Init the mask[] array to implement a line stipple.
  42.  */
  43. static void
  44. compute_stipple_mask( GLcontext *ctx, GLuint len, GLubyte mask[] )
  45. {
  46.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  47.    GLuint i;
  48.  
  49.    for (i = 0; i < len; i++) {
  50.       GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
  51.       if ((1 << bit) & ctx->Line.StipplePattern) {
  52.          mask[i] = GL_TRUE;
  53.       }
  54.       else {
  55.          mask[i] = GL_FALSE;
  56.       }
  57.       swrast->StippleCounter++;
  58.    }
  59. }
  60.  
  61.  
  62. /*
  63.  * To draw a wide line we can simply redraw the span N times, side by side.
  64.  */
  65. static void
  66. draw_wide_line( GLcontext *ctx, struct sw_span *span, GLboolean xMajor )
  67. {
  68.    GLint width, start;
  69.  
  70.    ASSERT(span->end < MAX_WIDTH);
  71.  
  72.    width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
  73.  
  74.    if (width & 1)
  75.       start = width / 2;
  76.    else
  77.       start = width / 2 - 1;
  78.  
  79.    if (xMajor) {
  80.       GLint *y = span->array->y;
  81.       GLuint i;
  82.       GLint w;
  83.       for (w = 0; w < width; w++) {
  84.          if (w == 0) {
  85.             for (i = 0; i < span->end; i++)
  86.                y[i] -= start;
  87.          }
  88.          else {
  89.             for (i = 0; i < span->end; i++)
  90.                y[i]++;
  91.          }
  92.          if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE)
  93.             _mesa_write_texture_span(ctx, span);
  94.          else if ((span->interpMask | span->arrayMask) & SPAN_RGBA)
  95.             _mesa_write_rgba_span(ctx, span);
  96.          else
  97.             _mesa_write_index_span(ctx, span);
  98.       }
  99.    }
  100.    else {
  101.       GLint *x = span->array->x;
  102.       GLuint i;
  103.       GLint w;
  104.       for (w = 0; w < width; w++) {
  105.          if (w == 0) {
  106.             for (i = 0; i < span->end; i++)
  107.                x[i] -= start;
  108.          }
  109.          else {
  110.             for (i = 0; i < span->end; i++)
  111.                x[i]++;
  112.          }
  113.          if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE)
  114.             _mesa_write_texture_span(ctx, span);
  115.          else if ((span->interpMask | span->arrayMask) & SPAN_RGBA)
  116.             _mesa_write_rgba_span(ctx, span);
  117.          else
  118.             _mesa_write_index_span(ctx, span);
  119.       }
  120.    }
  121. }
  122.  
  123.  
  124.  
  125. /**********************************************************************/
  126. /*****                    Rasterization                           *****/
  127. /**********************************************************************/
  128.  
  129.  
  130. /* Simple color index line (no stipple, width=1, no Z, no fog, no tex)*/
  131. #define NAME simple_ci_line
  132. #define INTERP_INDEX
  133. #define RENDER_SPAN(span) _mesa_write_index_span(ctx, &span)
  134. #include "s_linetemp.h"
  135.  
  136.  
  137. /* Simple RGBA index line (no stipple, width=1, no Z, no fog, no tex)*/
  138. #define NAME simple_rgba_line
  139. #define INTERP_RGBA
  140. #define RENDER_SPAN(span) _mesa_write_rgba_span(ctx, &span);
  141. #include "s_linetemp.h"
  142.  
  143.  
  144. /* Z, fog, wide, stipple color index line */
  145. #define NAME general_ci_line
  146. #define INTERP_INDEX
  147. #define INTERP_Z
  148. #define INTERP_FOG
  149. #define RENDER_SPAN(span)                    \
  150.    if (ctx->Line.StippleFlag) {                    \
  151.       span.arrayMask |= SPAN_MASK;                \
  152.       compute_stipple_mask(ctx, span.end, span.array->mask);    \
  153.    }                                \
  154.    if (ctx->Line.Width > 1.0) {                    \
  155.       draw_wide_line(ctx, &span, dx > dy);            \
  156.    }                                \
  157.    else {                            \
  158.       _mesa_write_index_span(ctx, &span);            \
  159.    }
  160. #include "s_linetemp.h"
  161.  
  162.  
  163. /* Z, fog, wide, stipple RGBA line */
  164. #define NAME general_rgba_line
  165. #define INTERP_RGBA
  166. #define INTERP_Z
  167. #define INTERP_FOG
  168. #define RENDER_SPAN(span)                    \
  169.    if (ctx->Line.StippleFlag) {                    \
  170.       span.arrayMask |= SPAN_MASK;                \
  171.       compute_stipple_mask(ctx, span.end, span.array->mask);    \
  172.    }                                \
  173.    if (ctx->Line.Width > 1.0) {                    \
  174.       draw_wide_line(ctx, &span, dx > dy);            \
  175.    }                                \
  176.    else {                            \
  177.       _mesa_write_rgba_span(ctx, &span);            \
  178.    }
  179. #include "s_linetemp.h"
  180.  
  181.  
  182. /* Single-texture line, w/ fog, Z, specular, etc. */
  183. #define NAME textured_line
  184. #define INTERP_RGBA
  185. #define INTERP_Z
  186. #define INTERP_FOG
  187. #define INTERP_TEX
  188. #define RENDER_SPAN(span)                    \
  189.    if (ctx->Line.StippleFlag) {                    \
  190.       span.arrayMask |= SPAN_MASK;                \
  191.       compute_stipple_mask(ctx, span.end, span.array->mask);    \
  192.    }                                \
  193.    if (ctx->Line.Width > 1.0) {                    \
  194.       draw_wide_line(ctx, &span, dx > dy);            \
  195.    }                                \
  196.    else {                            \
  197.       _mesa_write_texture_span(ctx, &span);            \
  198.    }
  199. #include "s_linetemp.h"
  200.  
  201.  
  202. /* Multi-texture or separate specular line, w/ fog, Z, specular, etc. */
  203. #define NAME multitextured_line
  204. #define INTERP_RGBA
  205. #define INTERP_SPEC
  206. #define INTERP_Z
  207. #define INTERP_FOG
  208. #define INTERP_MULTITEX
  209. #define RENDER_SPAN(span)                    \
  210.    if (ctx->Line.StippleFlag) {                    \
  211.       span.arrayMask |= SPAN_MASK;                \
  212.       compute_stipple_mask(ctx, span.end, span.array->mask);    \
  213.    }                                \
  214.    if (ctx->Line.Width > 1.0) {                    \
  215.       draw_wide_line(ctx, &span, dx > dy);            \
  216.    }                                \
  217.    else {                            \
  218.       _mesa_write_texture_span(ctx, &span);            \
  219.    }
  220. #include "s_linetemp.h"
  221.  
  222.  
  223.  
  224. void
  225. _swrast_add_spec_terms_line( GLcontext *ctx,
  226.                              const SWvertex *v0,
  227.                              const SWvertex *v1 )
  228. {
  229.    SWvertex *ncv0 = (SWvertex *)v0;
  230.    SWvertex *ncv1 = (SWvertex *)v1;
  231.    GLchan c[2][4];
  232.    COPY_CHAN4( c[0], ncv0->color );
  233.    COPY_CHAN4( c[1], ncv1->color );
  234.    ACC_3V( ncv0->color, ncv0->specular );
  235.    ACC_3V( ncv1->color, ncv1->specular );
  236.    SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 );
  237.    COPY_CHAN4( ncv0->color, c[0] );
  238.    COPY_CHAN4( ncv1->color, c[1] );
  239. }
  240.  
  241.  
  242. #ifdef DEBUG
  243. extern void
  244. _mesa_print_line_function(GLcontext *ctx);  /* silence compiler warning */
  245. void
  246. _mesa_print_line_function(GLcontext *ctx)
  247. {
  248.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  249.  
  250.    _mesa_printf("Line Func == ");
  251.    if (swrast->Line == simple_ci_line)
  252.       _mesa_printf("simple_ci_line\n");
  253.    else if (swrast->Line == simple_rgba_line)
  254.       _mesa_printf("simple_rgba_line\n");
  255.    else if (swrast->Line == general_ci_line)
  256.       _mesa_printf("general_ci_line\n");
  257.    else if (swrast->Line == general_rgba_line)
  258.       _mesa_printf("general_rgba_line\n");
  259.    else if (swrast->Line == textured_line)
  260.       _mesa_printf("textured_line\n");
  261.    else if (swrast->Line == multitextured_line)
  262.       _mesa_printf("multitextured_line\n");
  263.    else
  264.       _mesa_printf("Driver func %p\n", (void *) swrast->Line);
  265. }
  266. #endif
  267.  
  268.  
  269.  
  270. #ifdef DEBUG
  271.  
  272. /* record the current line function name */
  273. static const char *lineFuncName = NULL;
  274.  
  275. #define USE(lineFunc)                   \
  276. do {                                    \
  277.     lineFuncName = #lineFunc;           \
  278.     /*_mesa_printf("%s\n", lineFuncName);*/   \
  279.     swrast->Line = lineFunc;            \
  280. } while (0)
  281.  
  282. #else
  283.  
  284. #define USE(lineFunc)  swrast->Line = lineFunc
  285.  
  286. #endif
  287.  
  288.  
  289.  
  290. /*
  291.  * Determine which line drawing function to use given the current
  292.  * rendering context.
  293.  *
  294.  * Please update the summary flag _SWRAST_NEW_LINE if you add or remove
  295.  * tests to this code.
  296.  */
  297. void
  298. _swrast_choose_line( GLcontext *ctx )
  299. {
  300.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  301.    const GLboolean rgbmode = ctx->Visual.rgbMode;
  302.  
  303.    if (ctx->RenderMode == GL_RENDER) {
  304.       if (ctx->Line.SmoothFlag) {
  305.          /* antialiased lines */
  306.          _swrast_choose_aa_line_function(ctx);
  307.          ASSERT(swrast->Triangle);
  308.       }
  309.       else if (ctx->Texture._EnabledUnits) {
  310.          /* textured lines */
  311.          if (ctx->Texture._EnabledUnits > 0x1 || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)) {
  312.             /* multi-texture and/or separate specular color */
  313.             USE(multitextured_line);
  314.          }
  315.          else {
  316.             USE(textured_line);
  317.          }
  318.       }
  319.       else if (ctx->Depth.Test || ctx->Fog.Enabled || ctx->Line.Width != 1.0
  320.                || ctx->Line.StippleFlag) {
  321.          /* no texture, but Z, fog, width>1, stipple, etc. */
  322.          if (rgbmode)
  323.             USE(general_rgba_line);
  324.          else
  325.             USE(general_ci_line);
  326.       }
  327.       else {
  328.          /* simplest lines */
  329.          if (rgbmode)
  330.             USE(simple_rgba_line);
  331.          else
  332.             USE(simple_ci_line);
  333.       }
  334.    }
  335.    else if (ctx->RenderMode == GL_FEEDBACK) {
  336.       USE(_mesa_feedback_line);
  337.    }
  338.    else {
  339.       ASSERT(ctx->RenderMode == GL_SELECT);
  340.       USE(_mesa_select_line);
  341.    }
  342.  
  343.    /*_mesa_print_line_function(ctx);*/
  344. }
  345.