<commit_before>/*
 * Mesa 3-D graphics library
 * Version:  7.1
 *
 * Copyright (C) 1999-2007  <NAME>   All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * <NAME> BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */


#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "texstate.h"
#include "s_context.h"
#include "s_feedback.h"
#include "s_points.h"
#include "s_span.h"


/**
 * Used to cull points with invalid coords
 */
#define CULL_INVALID(V)                              \
   do {                                              \
      float tmp = (V)->attrib[FRAG_ATTRIB_WPOS][0]   \
                + (V)->attrib[FRAG_ATTRIB_WPOS][1];  \
      if (IS_INF_OR_NAN(tmp))                        \
	 return;                                     \
   } while(0)


/**
 * Draw a point sprite
 */
static void
sprite_point(GLcontext *ctx, const SWvertex *vert)
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   SWspan span;
   GLfloat size;
   GLuint tCoords[MAX_TEXTURE_COORD_UNITS];
   GLuint numTcoords = 0;
   GLfloat t0, dtdy;

   CULL_INVALID(vert);

   /* z coord */
   if (ctx->DrawBuffer->Visual.depthBits <= 16)
      span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
   else
      span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
   span.zStep = 0;

   /* compute size */
   if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
      /* use vertex's point size */
      /* first, clamp attenuated size to the user-specifed range */
      size = CLAMP(vert->pointSize, ctx->Point.MinSize, ctx->Point.MaxSize);
   }
   else {
      /* use constant point size */
      size = ctx->Point.Size;
   }
   /* clamp to non-AA implementation limits */
   size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);

   /* span init */
   INIT_SPAN(span, GL_POINT);
   span.interpMask = SPAN_Z | SPAN_RGBA;

   span.red   = ChanToFixed(vert->color[0]);
   span.green = ChanToFixed(vert->color[1]);
   span.blue  = ChanToFixed(vert->color[2]);
   span.alpha = ChanToFixed(vert->color[3]);
   span.redStep = 0;
   span.greenStep = 0;
   span.blueStep = 0;
   span.alphaStep = 0;

   /* need these for fragment programs */
   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;

   ATTRIB_LOOP_BEGIN
      if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0) {
         const GLuint u = attr - FRAG_ATTRIB_TEX0;
         /* a texcoord */
         if (ctx->Point.CoordReplace[u]) {
            GLfloat s, r, dsdx;

            s = 0.0;
            dsdx = 1.0 / size;

            if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) {
               t0 = 0.0;
               dtdy = 1.0 / size;
            }
            else {
               /* GL_UPPER_LEFT */
               t0 = 1.0;
               dtdy = -1.0 / size;
            }
            tCoords[numTcoords++] = attr;

            if (ctx->Point.SpriteRMode == GL_ZERO)
               r = 0.0F;
            else if (ctx->Point.SpriteRMode == GL_S)
               r = vert->attrib[attr][0];
            else /* GL_R */
               r = vert->attrib[attr][2];

            span.attrStart[attr][0] = s;
            span.attrStart[attr][1] = 0.0; /* overwritten below */
            span.attrStart[attr][2] = r;
            span.attrStart[attr][3] = 1.0;

            span.attrStepX[attr][0] = dsdx;
            span.attrStepX[attr][1] = 0.0;
            span.attrStepX[attr][2] = 0.0;
            span.attrStepX[attr][3] = 0.0;

            span.attrStepY[attr][0] = 0.0;
            span.attrStepY[attr][1] = dtdy;
            span.attrStepY[attr][2] = 0.0;
            span.attrStepY[attr][3] = 0.0;

            continue;
         }
      }
      /* use vertex's texcoord/attrib */
      COPY_4V(span.attrStart[attr], vert->attrib[attr]);
      ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
      ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
   ATTRIB_LOOP_END

   /* compute pos, bounds and render */
   {
      const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
      const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
      GLint iSize = (GLint) (size + 0.5F);
      GLint xmin, xmax, ymin, ymax, iy;
      GLint iRadius;
      GLfloat tcoord = t0;

      iSize = MAX2(1, iSize);
      iRadius = iSize / 2;

      if (iSize & 1) {
         /* odd size */
         xmin = (GLint) (x - iRadius);
         xmax = (GLint) (x + iRadius);
         ymin = (GLint) (y - iRadius);
         ymax = (GLint) (y + iRadius);
      }
      else {
         /* even size */
         xmin = (GLint) x - iRadius + 1;
         xmax = xmin + iSize - 1;
         ymin = (GLint) y - iRadius + 1;
         ymax = ymin + iSize - 1;
      }

      /* render spans */
      for (iy = ymin; iy <= ymax; iy++) {
         GLuint i;
         /* setup texcoord T for this row */
         for (i = 0; i < numTcoords; i++) {
            span.attrStart[tCoords[i]][1] = tcoord;
         }

         /* these might get changed by span clipping */
         span.x = xmin;
         span.y = iy;
         span.end = xmax - xmin + 1;

         _swrast_write_rgba_span(ctx, &span);

         tcoord += dtdy;
      }
   }
}


/**
 * Draw smooth/antialiased point.  RGB or CI mode.
 */
static void
smooth_point(GLcontext *ctx, const SWvertex *vert)
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   const GLboolean ciMode = !ctx->Visual.rgbMode;
   SWspan span;
   GLfloat size, alphaAtten;

   CULL_INVALID(vert);

   /* z coord */
   if (ctx->DrawBuffer->Visual.depthBits <= 16)
      span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
   else
      span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
   span.zStep = 0;

   /* compute size */
   if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
      /* use vertex's point size */
      /* first, clamp attenuated size to the user-specifed range */
      size = CLAMP(vert->pointSize, ctx->Point.MinSize, ctx->Point.MaxSize);
   }
   else {
      /* use constant point size */
      size = ctx->Point.Size;
   }
   /* clamp to AA implementation limits */
   size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA);

   /* alpha attenuation / fade factor */
   if (ctx->Multisample.Enabled) {
      if (vert->pointSize >= ctx->Point.Threshold) {
         alphaAtten = 1.0F;
      }
      else {
         GLfloat dsize = vert->pointSize / ctx->Point.Threshold;
         alphaAtten = dsize * dsize;
      }
   }
   else {
      alphaAtten = 1.0;
   }
   (void) alphaAtten; /* not used */

   /* span init */
   INIT_SPAN(span, GL_POINT);
   span.interpMask = SPAN_Z | SPAN_RGBA;
   span.arrayMask = SPAN_COVERAGE | SPAN_MASK;

   span.red   = ChanToFixed(vert->color[0]);
   span.green = ChanToFixed(vert->color[1]);
   span.blue  = ChanToFixed(vert->color[2]);
   span.alpha = ChanToFixed(vert->color[3]);
   span.redStep = 0;
   span.greenStep = 0;
   span.blueStep = 0;
   span.alphaStep = 0;

   /* need these for fragment programs */
   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;

   ATTRIB_LOOP_BEGIN
      COPY_4V(span.attrStart[attr], vert->attrib[attr]);
      ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
      ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
   ATTRIB_LOOP_END

   /* compute pos, bounds and render */
   {
      const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
      const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
      const GLfloat radius = 0.5F * size;
      const GLfloat rmin = radius - 0.7071F;  /* 0.7071 = sqrt(2)/2 */
      const GLfloat rmax = radius + 0.7071F;
      const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
      const GLfloat rmax2 = rmax * rmax;
      const GLfloat cscale = 1.0F / (rmax2 - rmin2);
      const GLint xmin = (GLint) (x - radius);
      const GLint xmax = (GLint) (x + radius);
      const GLint ymin = (GLint) (y - radius);
      const GLint ymax = (GLint) (y + radius);
      GLint ix, iy;

      for (iy = ymin; iy <= ymax; iy++) {

         /* these might get changed by span clipping */
         span.x = xmin;
         span.y = iy;
         span.end = xmax - xmin + 1;

         /* compute coverage for each pixel in span */
         for (ix = xmin; ix <= xmax; ix++) {
            const GLfloat dx = ix - x + 0.5F;
            const GLfloat dy = iy - y + 0.5F;
            const GLfloat dist2 = dx * dx + dy * dy;
            GLfloat coverage;

            if (dist2 < rmax2) {
               if (dist2 >= rmin2) {
                  /* compute partial coverage */
                  coverage = 1.0F - (dist2 - rmin2) * cscale;
                  if (ciMode) {
                     /* coverage in [0,15] */
                     coverage *= 15.0;
                  }
               }
               else {
                  /* full coverage */
                  coverage = 1.0F;
               }
               span.array->mask[ix - xmin] = 1;
            }
            else {
               /* zero coverage - fragment outside the radius */
               coverage = 0.0;
               span.array->mask[ix - xmin] = 0;
            }
            span.array->coverage[ix - xmin] = coverage;
         }

         /* render span */
         _swrast_write_rgba_span(ctx, &span);

      }
   }
}


/**
 * Draw large (size >= 1) non-AA point.  RGB or CI mode.
 */
static void
large_point(GLcontext *ctx, const SWvertex *vert)
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   const GLboolean ciMode = !ctx->Visual.rgbMode;
   SWspan span;
   GLfloat size;

   CULL_INVALID(vert);

   /* z coord */
   if (ctx->DrawBuffer->Visual.depthBits <= 16)
      span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
   else
      span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
   span.zStep = 0;

   /* compute size */
   if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
      /* use vertex's point size */
      /* first, clamp attenuated size to the user-specifed range */
      size = CLAMP(vert->pointSize, ctx->Point.MinSize, ctx->Point.MaxSize);
   }
   else {
      /* use constant point size */
      size = ctx->Point.Size;
   }
   /* clamp to non-AA implementation limits */
   size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);

   /* span init */
   INIT_SPAN(span, GL_POINT);
   span.arrayMask = SPAN_XY;

   if (ciMode) {
      span.interpMask = SPAN_Z | SPAN_INDEX;
      span.index = FloatToFixed(vert->attrib[FRAG_ATTRIB_CI][0]);
      span.indexStep = 0;
   }
   else {
      span.interpMask = SPAN_Z | SPAN_RGBA;
      span.red   = ChanToFixed(vert->color[0]);
      span.green = ChanToFixed(vert->color[1]);
      span.blue  = ChanToFixed(vert->color[2]);
      span.alpha = ChanToFixed(vert->color[3]);
      span.redStep = 0;
      span.greenStep = 0;
      span.blueStep = 0;
      span.alphaStep = 0;
   }

   /* need these for fragment programs */
   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;

   ATTRIB_LOOP_BEGIN
      COPY_4V(span.attrStart[attr], vert->attrib[attr]);
      ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
      ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
   ATTRIB_LOOP_END

   /* compute pos, bounds and render */
   {
      const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
      const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
      GLint iSize = (GLint) (size + 0.5F);
      GLint xmin, xmax, ymin, ymax, ix, iy;
      GLint iRadius;

      iSize = MAX2(1, iSize);
      iRadius = iSize / 2;

      if (iSize & 1) {
         /* odd size */
         xmin = (GLint) (x - iRadius);
         xmax = (GLint) (x + iRadius);
         ymin = (GLint) (y - iRadius);
         ymax = (GLint) (y + iRadius);
      }
      else {
         /* even size */
         xmin = (GLint) x - iRadius + 1;
         xmax = xmin + iSize - 1;
         ymin = (GLint) y - iRadius + 1;
         ymax = ymin + iSize - 1;
      }

      /* generate fragments */
      span.end = 0;
      for (iy = ymin; iy <= ymax; iy++) {
         for (ix = xmin; ix <= xmax; ix++) {
            span.array->x[span.end] = ix;
            span.array->y[span.end] = iy;
            span.end++;
         }
      }
      assert(span.end <= MAX_WIDTH);
      _swrast_write_rgba_span(ctx, &span);
   }
}


/**
 * Draw size=1, single-pixel point
 */
static void<commit_msg>fix even-sized point positioning (bug 11874)<commit_after>/*
 * Mesa 3-D graphics library
 * Version:  7.1
 *
 * Copyright (C) 1999-2007  <NAME>   All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */


#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "texstate.h"
#include "s_context.h"
#include "s_feedback.h"
#include "s_points.h"
#include "s_span.h"


/**
 * Used to cull points with invalid coords
 */
#define CULL_INVALID(V)                              \
   do {                                              \
      float tmp = (V)->attrib[FRAG_ATTRIB_WPOS][0]   \
                + (V)->attrib[FRAG_ATTRIB_WPOS][1];  \
      if (IS_INF_OR_NAN(tmp))                        \
	 return;                                     \
   } while(0)


/**
 * Draw a point sprite
 */
static void
sprite_point(GLcontext *ctx, const SWvertex *vert)
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   SWspan span;
   GLfloat size;
   GLuint tCoords[MAX_TEXTURE_COORD_UNITS];
   GLuint numTcoords = 0;
   GLfloat t0, dtdy;

   CULL_INVALID(vert);

   /* z coord */
   if (ctx->DrawBuffer->Visual.depthBits <= 16)
      span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
   else
      span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
   span.zStep = 0;

   /* compute size */
   if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
      /* use vertex's point size */
      /* first, clamp attenuated size to the user-specifed range */
      size = CLAMP(vert->pointSize, ctx->Point.MinSize, ctx->Point.MaxSize);
   }
   else {
      /* use constant point size */
      size = ctx->Point.Size;
   }
   /* clamp to non-AA implementation limits */
   size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);

   /* span init */
   INIT_SPAN(span, GL_POINT);
   span.interpMask = SPAN_Z | SPAN_RGBA;

   span.red   = ChanToFixed(vert->color[0]);
   span.green = ChanToFixed(vert->color[1]);
   span.blue  = ChanToFixed(vert->color[2]);
   span.alpha = ChanToFixed(vert->color[3]);
   span.redStep = 0;
   span.greenStep = 0;
   span.blueStep = 0;
   span.alphaStep = 0;

   /* need these for fragment programs */
   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;

   ATTRIB_LOOP_BEGIN
      if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0) {
         const GLuint u = attr - FRAG_ATTRIB_TEX0;
         /* a texcoord */
         if (ctx->Point.CoordReplace[u]) {
            GLfloat s, r, dsdx;

            s = 0.0;
            dsdx = 1.0 / size;

            if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) {
               t0 = 0.0;
               dtdy = 1.0 / size;
            }
            else {
               /* GL_UPPER_LEFT */
               t0 = 1.0;
               dtdy = -1.0 / size;
            }
            tCoords[numTcoords++] = attr;

            if (ctx->Point.SpriteRMode == GL_ZERO)
               r = 0.0F;
            else if (ctx->Point.SpriteRMode == GL_S)
               r = vert->attrib[attr][0];
            else /* GL_R */
               r = vert->attrib[attr][2];

            span.attrStart[attr][0] = s;
            span.attrStart[attr][1] = 0.0; /* overwritten below */
            span.attrStart[attr][2] = r;
            span.attrStart[attr][3] = 1.0;

            span.attrStepX[attr][0] = dsdx;
            span.attrStepX[attr][1] = 0.0;
            span.attrStepX[attr][2] = 0.0;
            span.attrStepX[attr][3] = 0.0;

            span.attrStepY[attr][0] = 0.0;
            span.attrStepY[attr][1] = dtdy;
            span.attrStepY[attr][2] = 0.0;
            span.attrStepY[attr][3] = 0.0;

            continue;
         }
      }
      /* use vertex's texcoord/attrib */
      COPY_4V(span.attrStart[attr], vert->attrib[attr]);
      ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
      ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
   ATTRIB_LOOP_END

   /* compute pos, bounds and render */
   {
      const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
      const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
      GLint iSize = (GLint) (size + 0.5F);
      GLint xmin, xmax, ymin, ymax, iy;
      GLint iRadius;
      GLfloat tcoord = t0;

      iSize = MAX2(1, iSize);
      iRadius = iSize / 2;

      if (iSize & 1) {
         /* odd size */
         xmin = (GLint) (x - iRadius);
         xmax = (GLint) (x + iRadius);
         ymin = (GLint) (y - iRadius);
         ymax = (GLint) (y + iRadius);
      }
      else {
         /* even size */
         xmin = (GLint) x - iRadius;
         xmax = xmin + iSize - 1;
         ymin = (GLint) y - iRadius;
         ymax = ymin + iSize - 1;
      }

      /* render spans */
      for (iy = ymin; iy <= ymax; iy++) {
         GLuint i;
         /* setup texcoord T for this row */
         for (i = 0; i < numTcoords; i++) {
            span.attrStart[tCoords[i]][1] = tcoord;
         }

         /* these might get changed by span clipping */
         span.x = xmin;
         span.y = iy;
         span.end = xmax - xmin + 1;

         _swrast_write_rgba_span(ctx, &span);

         tcoord += dtdy;
      }
   }
}


/**
 * Draw smooth/antialiased point.  RGB or CI mode.
 */
static void
smooth_point(GLcontext *ctx, const SWvertex *vert)
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   const GLboolean ciMode = !ctx->Visual.rgbMode;
   SWspan span;
   GLfloat size, alphaAtten;

   CULL_INVALID(vert);

   /* z coord */
   if (ctx->DrawBuffer->Visual.depthBits <= 16)
      span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
   else
      span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
   span.zStep = 0;

   /* compute size */
   if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
      /* use vertex's point size */
      /* first, clamp attenuated size to the user-specifed range */
      size = CLAMP(vert->pointSize, ctx->Point.MinSize, ctx->Point.MaxSize);
   }
   else {
      /* use constant point size */
      size = ctx->Point.Size;
   }
   /* clamp to AA implementation limits */
   size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA);

   /* alpha attenuation / fade factor */
   if (ctx->Multisample.Enabled) {
      if (vert->pointSize >= ctx->Point.Threshold) {
         alphaAtten = 1.0F;
      }
      else {
         GLfloat dsize = vert->pointSize / ctx->Point.Threshold;
         alphaAtten = dsize * dsize;
      }
   }
   else {
      alphaAtten = 1.0;
   }
   (void) alphaAtten; /* not used */

   /* span init */
   INIT_SPAN(span, GL_POINT);
   span.interpMask = SPAN_Z | SPAN_RGBA;
   span.arrayMask = SPAN_COVERAGE | SPAN_MASK;

   span.red   = ChanToFixed(vert->color[0]);
   span.green = ChanToFixed(vert->color[1]);
   span.blue  = ChanToFixed(vert->color[2]);
   span.alpha = ChanToFixed(vert->color[3]);
   span.redStep = 0;
   span.greenStep = 0;
   span.blueStep = 0;
   span.alphaStep = 0;

   /* need these for fragment programs */
   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;

   ATTRIB_LOOP_BEGIN
      COPY_4V(span.attrStart[attr], vert->attrib[attr]);
      ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
      ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
   ATTRIB_LOOP_END

   /* compute pos, bounds and render */
   {
      const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
      const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
      const GLfloat radius = 0.5F * size;
      const GLfloat rmin = radius - 0.7071F;  /* 0.7071 = sqrt(2)/2 */
      const GLfloat rmax = radius + 0.7071F;
      const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
      const GLfloat rmax2 = rmax * rmax;
      const GLfloat cscale = 1.0F / (rmax2 - rmin2);
      const GLint xmin = (GLint) (x - radius);
      const GLint xmax = (GLint) (x + radius);
      const GLint ymin = (GLint) (y - radius);
      const GLint ymax = (GLint) (y + radius);
      GLint ix, iy;

      for (iy = ymin; iy <= ymax; iy++) {

         /* these might get changed by span clipping */
         span.x = xmin;
         span.y = iy;
         span.end = xmax - xmin + 1;

         /* compute coverage for each pixel in span */
         for (ix = xmin; ix <= xmax; ix++) {
            const GLfloat dx = ix - x + 0.5F;
            const GLfloat dy = iy - y + 0.5F;
            const GLfloat dist2 = dx * dx + dy * dy;
            GLfloat coverage;

            if (dist2 < rmax2) {
               if (dist2 >= rmin2) {
                  /* compute partial coverage */
                  coverage = 1.0F - (dist2 - rmin2) * cscale;
                  if (ciMode) {
                     /* coverage in [0,15] */
                     coverage *= 15.0;
                  }
               }
               else {
                  /* full coverage */
                  coverage = 1.0F;
               }
               span.array->mask[ix - xmin] = 1;
            }
            else {
               /* zero coverage - fragment outside the radius */
               coverage = 0.0;
               span.array->mask[ix - xmin] = 0;
            }
            span.array->coverage[ix - xmin] = coverage;
         }

         /* render span */
         _swrast_write_rgba_span(ctx, &span);

      }
   }
}


/**
 * Draw large (size >= 1) non-AA point.  RGB or CI mode.
 */
static void
large_point(GLcontext *ctx, const SWvertex *vert)
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   const GLboolean ciMode = !ctx->Visual.rgbMode;
   SWspan span;
   GLfloat size;

   CULL_INVALID(vert);

   /* z coord */
   if (ctx->DrawBuffer->Visual.depthBits <= 16)
      span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
   else
      span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
   span.zStep = 0;

   /* compute size */
   if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
      /* use vertex's point size */
      /* first, clamp attenuated size to the user-specifed range */
      size = CLAMP(vert->pointSize, ctx->Point.MinSize, ctx->Point.MaxSize);
   }
   else {
      /* use constant point size */
      size = ctx->Point.Size;
   }
   /* clamp to non-AA implementation limits */
   size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);

   /* span init */
   INIT_SPAN(span, GL_POINT);
   span.arrayMask = SPAN_XY;

   if (ciMode) {
      span.interpMask = SPAN_Z | SPAN_INDEX;
      span.index = FloatToFixed(vert->attrib[FRAG_ATTRIB_CI][0]);
      span.indexStep = 0;
   }
   else {
      span.interpMask = SPAN_Z | SPAN_RGBA;
      span.red   = ChanToFixed(vert->color[0]);
      span.green = ChanToFixed(vert->color[1]);
      span.blue  = ChanToFixed(vert->color[2]);
      span.alpha = ChanToFixed(vert->color[3]);
      span.redStep = 0;
      span.greenStep = 0;
      span.blueStep = 0;
      span.alphaStep = 0;
   }

   /* need these for fragment programs */
   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;

   ATTRIB_LOOP_BEGIN
      COPY_4V(span.attrStart[attr], vert->attrib[attr]);
      ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
      ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
   ATTRIB_LOOP_END

   /* compute pos, bounds and render */
   {
      const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
      const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
      GLint iSize = (GLint) (size + 0.5F);
      GLint xmin, xmax, ymin, ymax, ix, iy;
      GLint iRadius;

      iSize = MAX2(1, iSize);
      iRadius = iSize / 2;

      if (iSize & 1) {
         /* odd size */
         xmin = (GLint) (x - iRadius);
         xmax = (GLint) (x + iRadius);
         ymin = (GLint) (y - iRadius);
         ymax = (GLint) (y + iRadius);
      }
      else {
         /* even size */
         xmin = (GLint) x - iRadius;
         xmax = xmin + iSize - 1;
         ymin = (GLint) y - iRadius;
         ymax = ymin + iSize - 1;
      }

      /* generate fragments */
      span.end = 0;
      for (iy = ymin; iy <= ymax; iy++) {
         for (ix = xmin; ix <= xmax; ix++) {
            span.array->x[span.end] = ix;
            span.array->y[span.end] = iy;
            span.end++;
         }
      }
      assert(span.end <= MAX_WIDTH);
      _swrast_write_rgba_span(ctx, &span);
   }
}


/**
 * Draw size=1, single-pixel point
 */
static void
{'fraction_non_alphanumeric': 0.13549441164457318, 'fraction_numerical': 0.020014110133303627, 'mean_word_length': 1.9951067615658362, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 170, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1974806', 'n_tokens_mistral': 9826, 'n_tokens_neox': 9339, 'n_words': 2241}