Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  7.1
  4.  *
  5.  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25.  
  26. #include "main/glheader.h"
  27. #include "main/colormac.h"
  28. #include "main/macros.h"
  29. #include "s_context.h"
  30. #include "s_feedback.h"
  31. #include "s_points.h"
  32. #include "s_span.h"
  33.  
  34.  
  35. /**
  36.  * Used to cull points with invalid coords
  37.  */
  38. #define CULL_INVALID(V)                              \
  39.    do {                                              \
  40.       float tmp = (V)->attrib[FRAG_ATTRIB_WPOS][0]   \
  41.                 + (V)->attrib[FRAG_ATTRIB_WPOS][1];  \
  42.       if (IS_INF_OR_NAN(tmp))                        \
  43.          return;                                     \
  44.    } while(0)
  45.  
  46.  
  47.  
  48. /**
  49.  * Get/compute the point size.
  50.  * The size may come from a vertex shader, or computed with attentuation
  51.  * or just the glPointSize value.
  52.  * Must also clamp to user-defined range and implmentation limits.
  53.  */
  54. static INLINE GLfloat
  55. get_size(const struct gl_context *ctx, const SWvertex *vert, GLboolean smoothed)
  56. {
  57.    GLfloat size;
  58.  
  59.    if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
  60.       /* use vertex's point size */
  61.       size = vert->pointSize;
  62.    }
  63.    else {
  64.       /* use constant point size */
  65.       size = ctx->Point.Size;
  66.    }
  67.    /* always clamp to user-specified limits */
  68.    size = CLAMP(size, ctx->Point.MinSize, ctx->Point.MaxSize);
  69.    /* clamp to implementation limits */
  70.    if (smoothed)
  71.       size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA);
  72.    else
  73.       size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
  74.  
  75.    return size;
  76. }
  77.  
  78.  
  79. /**
  80.  * Draw a point sprite
  81.  */
  82. static void
  83. sprite_point(struct gl_context *ctx, const SWvertex *vert)
  84. {
  85.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  86.    SWspan span;
  87.    GLfloat size;
  88.    GLuint tCoords[MAX_TEXTURE_COORD_UNITS + 1];
  89.    GLuint numTcoords = 0;
  90.    GLfloat t0, dtdy;
  91.  
  92.    CULL_INVALID(vert);
  93.  
  94.    /* z coord */
  95.    if (ctx->DrawBuffer->Visual.depthBits <= 16)
  96.       span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
  97.    else
  98.       span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
  99.    span.zStep = 0;
  100.  
  101.    size = get_size(ctx, vert, GL_FALSE);
  102.  
  103.    /* span init */
  104.    INIT_SPAN(span, GL_POINT);
  105.    span.interpMask = SPAN_Z | SPAN_RGBA;
  106.  
  107.    span.facing = swrast->PointLineFacing;
  108.  
  109.    span.red   = ChanToFixed(vert->color[0]);
  110.    span.green = ChanToFixed(vert->color[1]);
  111.    span.blue  = ChanToFixed(vert->color[2]);
  112.    span.alpha = ChanToFixed(vert->color[3]);
  113.    span.redStep = 0;
  114.    span.greenStep = 0;
  115.    span.blueStep = 0;
  116.    span.alphaStep = 0;
  117.  
  118.    /* need these for fragment programs */
  119.    span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
  120.    span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
  121.    span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
  122.  
  123.    {
  124.       GLfloat s, r, dsdx;
  125.  
  126.       /* texcoord / pointcoord interpolants */
  127.       s = 0.0F;
  128.       dsdx = 1.0F / size;
  129.       if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) {
  130.          dtdy = 1.0F / size;
  131.          t0 = 0.5F * dtdy;
  132.       }
  133.       else {
  134.          /* GL_UPPER_LEFT */
  135.          dtdy = -1.0F / size;
  136.          t0 = 1.0F + 0.5F * dtdy;
  137.       }
  138.  
  139.       ATTRIB_LOOP_BEGIN
  140.          if (attr >= FRAG_ATTRIB_TEX0 && attr <= FRAG_ATTRIB_TEX7) {
  141.             /* a texcoord attribute */
  142.             const GLuint u = attr - FRAG_ATTRIB_TEX0;
  143.             ASSERT(u < Elements(ctx->Point.CoordReplace));
  144.             if (ctx->Point.CoordReplace[u]) {
  145.                tCoords[numTcoords++] = attr;
  146.  
  147.                if (ctx->Point.SpriteRMode == GL_ZERO)
  148.                   r = 0.0F;
  149.                else if (ctx->Point.SpriteRMode == GL_S)
  150.                   r = vert->attrib[attr][0];
  151.                else /* GL_R */
  152.                   r = vert->attrib[attr][2];
  153.  
  154.                span.attrStart[attr][0] = s;
  155.                span.attrStart[attr][1] = 0.0; /* overwritten below */
  156.                span.attrStart[attr][2] = r;
  157.                span.attrStart[attr][3] = 1.0;
  158.  
  159.                span.attrStepX[attr][0] = dsdx;
  160.                span.attrStepX[attr][1] = 0.0;
  161.                span.attrStepX[attr][2] = 0.0;
  162.                span.attrStepX[attr][3] = 0.0;
  163.  
  164.                span.attrStepY[attr][0] = 0.0;
  165.                span.attrStepY[attr][1] = dtdy;
  166.                span.attrStepY[attr][2] = 0.0;
  167.                span.attrStepY[attr][3] = 0.0;
  168.  
  169.                continue;
  170.             }
  171.          }
  172.          else if (attr == FRAG_ATTRIB_PNTC) {
  173.             /* GLSL gl_PointCoord.xy (.zw undefined) */
  174.             span.attrStart[FRAG_ATTRIB_PNTC][0] = 0.0;
  175.             span.attrStart[FRAG_ATTRIB_PNTC][1] = 0.0; /* t0 set below */
  176.             span.attrStepX[FRAG_ATTRIB_PNTC][0] = dsdx;
  177.             span.attrStepX[FRAG_ATTRIB_PNTC][1] = 0.0;
  178.             span.attrStepY[FRAG_ATTRIB_PNTC][0] = 0.0;
  179.             span.attrStepY[FRAG_ATTRIB_PNTC][1] = dtdy;
  180.             tCoords[numTcoords++] = FRAG_ATTRIB_PNTC;
  181.             continue;
  182.          }
  183.          /* use vertex's texcoord/attrib */
  184.          COPY_4V(span.attrStart[attr], vert->attrib[attr]);
  185.          ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
  186.          ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
  187.       ATTRIB_LOOP_END;
  188.    }
  189.  
  190.    /* compute pos, bounds and render */
  191.    {
  192.       const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
  193.       const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
  194.       GLint iSize = (GLint) (size + 0.5F);
  195.       GLint xmin, xmax, ymin, ymax, iy;
  196.       GLint iRadius;
  197.       GLfloat tcoord = t0;
  198.  
  199.       iSize = MAX2(1, iSize);
  200.       iRadius = iSize / 2;
  201.  
  202.       if (iSize & 1) {
  203.          /* odd size */
  204.          xmin = (GLint) (x - iRadius);
  205.          xmax = (GLint) (x + iRadius);
  206.          ymin = (GLint) (y - iRadius);
  207.          ymax = (GLint) (y + iRadius);
  208.       }
  209.       else {
  210.          /* even size */
  211.          /* 0.501 factor allows conformance to pass */
  212.          xmin = (GLint) (x + 0.501) - iRadius;
  213.          xmax = xmin + iSize - 1;
  214.          ymin = (GLint) (y + 0.501) - iRadius;
  215.          ymax = ymin + iSize - 1;
  216.       }
  217.  
  218.       /* render spans */
  219.       for (iy = ymin; iy <= ymax; iy++) {
  220.          GLuint i;
  221.          /* setup texcoord T for this row */
  222.          for (i = 0; i < numTcoords; i++) {
  223.             span.attrStart[tCoords[i]][1] = tcoord;
  224.          }
  225.  
  226.          /* these might get changed by span clipping */
  227.          span.x = xmin;
  228.          span.y = iy;
  229.          span.end = xmax - xmin + 1;
  230.  
  231.          _swrast_write_rgba_span(ctx, &span);
  232.  
  233.          tcoord += dtdy;
  234.       }
  235.    }
  236. }
  237.  
  238.  
  239. /**
  240.  * Draw smooth/antialiased point.  RGB or CI mode.
  241.  */
  242. static void
  243. smooth_point(struct gl_context *ctx, const SWvertex *vert)
  244. {
  245.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  246.    SWspan span;
  247.    GLfloat size, alphaAtten;
  248.  
  249.    CULL_INVALID(vert);
  250.  
  251.    /* z coord */
  252.    if (ctx->DrawBuffer->Visual.depthBits <= 16)
  253.       span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
  254.    else
  255.       span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
  256.    span.zStep = 0;
  257.  
  258.    size = get_size(ctx, vert, GL_TRUE);
  259.  
  260.    /* alpha attenuation / fade factor */
  261.    if (ctx->Multisample._Enabled) {
  262.       if (vert->pointSize >= ctx->Point.Threshold) {
  263.          alphaAtten = 1.0F;
  264.       }
  265.       else {
  266.          GLfloat dsize = vert->pointSize / ctx->Point.Threshold;
  267.          alphaAtten = dsize * dsize;
  268.       }
  269.    }
  270.    else {
  271.       alphaAtten = 1.0;
  272.    }
  273.    (void) alphaAtten; /* not used */
  274.  
  275.    /* span init */
  276.    INIT_SPAN(span, GL_POINT);
  277.    span.interpMask = SPAN_Z | SPAN_RGBA;
  278.    span.arrayMask = SPAN_COVERAGE | SPAN_MASK;
  279.  
  280.    span.facing = swrast->PointLineFacing;
  281.  
  282.    span.red   = ChanToFixed(vert->color[0]);
  283.    span.green = ChanToFixed(vert->color[1]);
  284.    span.blue  = ChanToFixed(vert->color[2]);
  285.    span.alpha = ChanToFixed(vert->color[3]);
  286.    span.redStep = 0;
  287.    span.greenStep = 0;
  288.    span.blueStep = 0;
  289.    span.alphaStep = 0;
  290.  
  291.    /* need these for fragment programs */
  292.    span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
  293.    span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
  294.    span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
  295.  
  296.    ATTRIB_LOOP_BEGIN
  297.       COPY_4V(span.attrStart[attr], vert->attrib[attr]);
  298.       ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
  299.       ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
  300.    ATTRIB_LOOP_END
  301.  
  302.    /* compute pos, bounds and render */
  303.    {
  304.       const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
  305.       const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
  306.       const GLfloat radius = 0.5F * size;
  307.       const GLfloat rmin = radius - 0.7071F;  /* 0.7071 = sqrt(2)/2 */
  308.       const GLfloat rmax = radius + 0.7071F;
  309.       const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
  310.       const GLfloat rmax2 = rmax * rmax;
  311.       const GLfloat cscale = 1.0F / (rmax2 - rmin2);
  312.       const GLint xmin = (GLint) (x - radius);
  313.       const GLint xmax = (GLint) (x + radius);
  314.       const GLint ymin = (GLint) (y - radius);
  315.       const GLint ymax = (GLint) (y + radius);
  316.       GLint ix, iy;
  317.  
  318.       for (iy = ymin; iy <= ymax; iy++) {
  319.  
  320.          /* these might get changed by span clipping */
  321.          span.x = xmin;
  322.          span.y = iy;
  323.          span.end = xmax - xmin + 1;
  324.  
  325.          /* compute coverage for each pixel in span */
  326.          for (ix = xmin; ix <= xmax; ix++) {
  327.             const GLfloat dx = ix - x + 0.5F;
  328.             const GLfloat dy = iy - y + 0.5F;
  329.             const GLfloat dist2 = dx * dx + dy * dy;
  330.             GLfloat coverage;
  331.  
  332.             if (dist2 < rmax2) {
  333.                if (dist2 >= rmin2) {
  334.                   /* compute partial coverage */
  335.                   coverage = 1.0F - (dist2 - rmin2) * cscale;
  336.                }
  337.                else {
  338.                   /* full coverage */
  339.                   coverage = 1.0F;
  340.                }
  341.                span.array->mask[ix - xmin] = 1;
  342.             }
  343.             else {
  344.                /* zero coverage - fragment outside the radius */
  345.                coverage = 0.0;
  346.                span.array->mask[ix - xmin] = 0;
  347.             }
  348.             span.array->coverage[ix - xmin] = coverage;
  349.          }
  350.  
  351.          /* render span */
  352.          _swrast_write_rgba_span(ctx, &span);
  353.  
  354.       }
  355.    }
  356. }
  357.  
  358.  
  359. /**
  360.  * Draw large (size >= 1) non-AA point.  RGB or CI mode.
  361.  */
  362. static void
  363. large_point(struct gl_context *ctx, const SWvertex *vert)
  364. {
  365.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  366.    SWspan span;
  367.    GLfloat size;
  368.  
  369.    CULL_INVALID(vert);
  370.  
  371.    /* z coord */
  372.    if (ctx->DrawBuffer->Visual.depthBits <= 16)
  373.       span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
  374.    else
  375.       span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
  376.    span.zStep = 0;
  377.  
  378.    size = get_size(ctx, vert, GL_FALSE);
  379.  
  380.    /* span init */
  381.    INIT_SPAN(span, GL_POINT);
  382.    span.arrayMask = SPAN_XY;
  383.    span.facing = swrast->PointLineFacing;
  384.  
  385.    span.interpMask = SPAN_Z | SPAN_RGBA;
  386.    span.red   = ChanToFixed(vert->color[0]);
  387.    span.green = ChanToFixed(vert->color[1]);
  388.    span.blue  = ChanToFixed(vert->color[2]);
  389.    span.alpha = ChanToFixed(vert->color[3]);
  390.    span.redStep = 0;
  391.    span.greenStep = 0;
  392.    span.blueStep = 0;
  393.    span.alphaStep = 0;
  394.  
  395.    /* need these for fragment programs */
  396.    span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
  397.    span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
  398.    span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
  399.  
  400.    ATTRIB_LOOP_BEGIN
  401.       COPY_4V(span.attrStart[attr], vert->attrib[attr]);
  402.       ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
  403.       ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
  404.    ATTRIB_LOOP_END
  405.  
  406.    /* compute pos, bounds and render */
  407.    {
  408.       const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
  409.       const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
  410.       GLint iSize = (GLint) (size + 0.5F);
  411.       GLint xmin, xmax, ymin, ymax, ix, iy;
  412.       GLint iRadius;
  413.  
  414.       iSize = MAX2(1, iSize);
  415.       iRadius = iSize / 2;
  416.  
  417.       if (iSize & 1) {
  418.          /* odd size */
  419.          xmin = (GLint) (x - iRadius);
  420.          xmax = (GLint) (x + iRadius);
  421.          ymin = (GLint) (y - iRadius);
  422.          ymax = (GLint) (y + iRadius);
  423.       }
  424.       else {
  425.          /* even size */
  426.          /* 0.501 factor allows conformance to pass */
  427.          xmin = (GLint) (x + 0.501) - iRadius;
  428.          xmax = xmin + iSize - 1;
  429.          ymin = (GLint) (y + 0.501) - iRadius;
  430.          ymax = ymin + iSize - 1;
  431.       }
  432.  
  433.       /* generate fragments */
  434.       span.end = 0;
  435.       for (iy = ymin; iy <= ymax; iy++) {
  436.          for (ix = xmin; ix <= xmax; ix++) {
  437.             span.array->x[span.end] = ix;
  438.             span.array->y[span.end] = iy;
  439.             span.end++;
  440.          }
  441.       }
  442.       assert(span.end <= MAX_WIDTH);
  443.       _swrast_write_rgba_span(ctx, &span);
  444.    }
  445. }
  446.  
  447.  
  448. /**
  449.  * Draw size=1, single-pixel point
  450.  */
  451. static void
  452. pixel_point(struct gl_context *ctx, const SWvertex *vert)
  453. {
  454.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  455.    /*
  456.     * Note that unlike the other functions, we put single-pixel points
  457.     * into a special span array in order to render as many points as
  458.     * possible with a single _swrast_write_rgba_span() call.
  459.     */
  460.    SWspan *span = &(swrast->PointSpan);
  461.    GLuint count;
  462.  
  463.    CULL_INVALID(vert);
  464.  
  465.    /* Span init */
  466.    span->interpMask = 0;
  467.    span->arrayMask = SPAN_XY | SPAN_Z;
  468.    span->arrayMask |= SPAN_RGBA;
  469.    /*span->arrayMask |= SPAN_LAMBDA;*/
  470.    span->arrayAttribs = swrast->_ActiveAttribMask; /* we'll produce these vals */
  471.  
  472.    /* need these for fragment programs */
  473.    span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
  474.    span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
  475.    span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
  476.  
  477.    /* check if we need to flush */
  478.    if (span->end >= MAX_WIDTH ||
  479.        (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT)) ||
  480.        span->facing != swrast->PointLineFacing) {
  481.       if (span->end > 0) {
  482.          _swrast_write_rgba_span(ctx, span);
  483.          span->end = 0;
  484.       }
  485.    }
  486.  
  487.    count = span->end;
  488.  
  489.    span->facing = swrast->PointLineFacing;
  490.  
  491.    /* fragment attributes */
  492.    span->array->rgba[count][RCOMP] = vert->color[0];
  493.    span->array->rgba[count][GCOMP] = vert->color[1];
  494.    span->array->rgba[count][BCOMP] = vert->color[2];
  495.    span->array->rgba[count][ACOMP] = vert->color[3];
  496.  
  497.    ATTRIB_LOOP_BEGIN
  498.       COPY_4V(span->array->attribs[attr][count], vert->attrib[attr]);
  499.    ATTRIB_LOOP_END
  500.  
  501.    /* fragment position */
  502.    span->array->x[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][0];
  503.    span->array->y[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][1];
  504.    span->array->z[count] = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
  505.  
  506.    span->end = count + 1;
  507.    ASSERT(span->end <= MAX_WIDTH);
  508. }
  509.  
  510.  
  511. /**
  512.  * Add specular color to primary color, draw point, restore original
  513.  * primary color.
  514.  */
  515. void
  516. _swrast_add_spec_terms_point(struct gl_context *ctx, const SWvertex *v0)
  517. {
  518.    SWvertex *ncv0 = (SWvertex *) v0; /* cast away const */
  519.    GLfloat rSum, gSum, bSum;
  520.    GLchan cSave[4];
  521.  
  522.    /* save */
  523.    COPY_CHAN4(cSave, ncv0->color);
  524.    /* sum */
  525.    rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[FRAG_ATTRIB_COL1][0];
  526.    gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[FRAG_ATTRIB_COL1][1];
  527.    bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[FRAG_ATTRIB_COL1][2];
  528.    UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
  529.    UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
  530.    UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
  531.    /* draw */
  532.    SWRAST_CONTEXT(ctx)->SpecPoint(ctx, ncv0);
  533.    /* restore */
  534.    COPY_CHAN4(ncv0->color, cSave);
  535. }
  536.  
  537.  
  538. /**
  539.  * Examine current state to determine which point drawing function to use.
  540.  */
  541. void
  542. _swrast_choose_point(struct gl_context *ctx)
  543. {
  544.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  545.    const GLfloat size = CLAMP(ctx->Point.Size,
  546.                               ctx->Point.MinSize,
  547.                               ctx->Point.MaxSize);
  548.  
  549.    if (ctx->RenderMode == GL_RENDER) {
  550.       if (ctx->Point.PointSprite) {
  551.          swrast->Point = sprite_point;
  552.       }
  553.       else if (ctx->Point.SmoothFlag) {
  554.          swrast->Point = smooth_point;
  555.       }
  556.       else if (size > 1.0 ||
  557.                ctx->Point._Attenuated ||
  558.                ctx->VertexProgram.PointSizeEnabled) {
  559.          swrast->Point = large_point;
  560.       }
  561.       else {
  562.          swrast->Point = pixel_point;
  563.       }
  564.    }
  565.    else if (ctx->RenderMode == GL_FEEDBACK) {
  566.       swrast->Point = _swrast_feedback_point;
  567.    }
  568.    else {
  569.       /* GL_SELECT mode */
  570.       swrast->Point = _swrast_select_point;
  571.    }
  572. }
  573.