swrast: implement GL_ARB_texture_storage
[mesa.git] / src / mesa / swrast / s_points.c
index ade1eab89178824d82a6bf44a6ea101c66ef7b69..11b7ef7b1f83423c948a7d632a86d5995a96e0c2 100644 (file)
  */
 
 
-#include "glheader.h"
-#include "colormac.h"
-#include "context.h"
-#include "macros.h"
-#include "texstate.h"
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/macros.h"
 #include "s_context.h"
 #include "s_feedback.h"
 #include "s_points.h"
    } while(0)
 
 
+
+/**
+ * Get/compute the point size.
+ * The size may come from a vertex shader, or computed with attentuation
+ * or just the glPointSize value.
+ * Must also clamp to user-defined range and implmentation limits.
+ */
+static inline GLfloat
+get_size(const struct gl_context *ctx, const SWvertex *vert, GLboolean smoothed)
+{
+   GLfloat size;
+
+   if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
+      /* use vertex's point size */
+      size = vert->pointSize;
+   }
+   else {
+      /* use constant point size */
+      size = ctx->Point.Size;
+   }
+   /* always clamp to user-specified limits */
+   size = CLAMP(size, ctx->Point.MinSize, ctx->Point.MaxSize);
+   /* clamp to implementation limits */
+   if (smoothed)
+      size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA);
+   else
+      size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
+
+   return size;
+}
+
+
 /**
  * Draw a point sprite
  */
 static void
-sprite_point(GLcontext *ctx, const SWvertex *vert)
+sprite_point(struct gl_context *ctx, const SWvertex *vert)
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    SWspan span;
    GLfloat size;
-   GLuint tCoords[MAX_TEXTURE_COORD_UNITS];
+   GLuint tCoords[MAX_TEXTURE_COORD_UNITS + 1];
    GLuint numTcoords = 0;
    GLfloat t0, dtdy;
 
@@ -68,23 +98,14 @@ sprite_point(GLcontext *ctx, const SWvertex *vert)
       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; /* already clamped to user range */
-   }
-   /* clamp to non-AA implementation limits */
-   size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
+   size = get_size(ctx, vert, GL_FALSE);
 
    /* span init */
-   INIT_SPAN(span, GL_POINT, 0, 0, 0);
+   INIT_SPAN(span, GL_POINT);
    span.interpMask = SPAN_Z | SPAN_RGBA;
 
+   span.facing = swrast->PointLineFacing;
+
    span.red   = ChanToFixed(vert->color[0]);
    span.green = ChanToFixed(vert->color[1]);
    span.blue  = ChanToFixed(vert->color[2]);
@@ -99,57 +120,72 @@ sprite_point(GLcontext *ctx, const SWvertex *vert)
    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;
+   {
+      GLfloat s, r, dsdx;
+
+      /* texcoord / pointcoord interpolants */
+      s = 0.0F;
+      dsdx = 1.0F / size;
+      if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) {
+         dtdy = 1.0F / size;
+         t0 = 0.5F * dtdy;
+      }
+      else {
+         /* GL_UPPER_LEFT */
+         dtdy = -1.0F / size;
+         t0 = 1.0F + 0.5F * dtdy;
+      }
 
+      ATTRIB_LOOP_BEGIN
+         if (attr >= FRAG_ATTRIB_TEX0 && attr <= FRAG_ATTRIB_TEX7) {
+            /* a texcoord attribute */
+            const GLuint u = attr - FRAG_ATTRIB_TEX0;
+            ASSERT(u < Elements(ctx->Point.CoordReplace));
+            if (ctx->Point.CoordReplace[u]) {
+               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;
+            }
+         }
+         else if (attr == FRAG_ATTRIB_PNTC) {
+            /* GLSL gl_PointCoord.xy (.zw undefined) */
+            span.attrStart[FRAG_ATTRIB_PNTC][0] = 0.0;
+            span.attrStart[FRAG_ATTRIB_PNTC][1] = 0.0; /* t0 set below */
+            span.attrStepX[FRAG_ATTRIB_PNTC][0] = dsdx;
+            span.attrStepX[FRAG_ATTRIB_PNTC][1] = 0.0;
+            span.attrStepY[FRAG_ATTRIB_PNTC][0] = 0.0;
+            span.attrStepY[FRAG_ATTRIB_PNTC][1] = dtdy;
+            tCoords[numTcoords++] = FRAG_ATTRIB_PNTC;
             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
+         /* 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 */
    {
@@ -172,9 +208,10 @@ sprite_point(GLcontext *ctx, const SWvertex *vert)
       }
       else {
          /* even size */
-         xmin = (GLint) x - iRadius + 1;
+         /* 0.501 factor allows conformance to pass */
+         xmin = (GLint) (x + 0.501) - iRadius;
          xmax = xmin + iSize - 1;
-         ymin = (GLint) y - iRadius + 1;
+         ymin = (GLint) (y + 0.501) - iRadius;
          ymax = ymin + iSize - 1;
       }
 
@@ -203,10 +240,9 @@ sprite_point(GLcontext *ctx, const SWvertex *vert)
  * Draw smooth/antialiased point.  RGB or CI mode.
  */
 static void
-smooth_point(GLcontext *ctx, const SWvertex *vert)
+smooth_point(struct gl_context *ctx, const SWvertex *vert)
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
-   const GLboolean ciMode = !ctx->Visual.rgbMode;
    SWspan span;
    GLfloat size, alphaAtten;
 
@@ -219,21 +255,10 @@ smooth_point(GLcontext *ctx, const SWvertex *vert)
       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; /* this is already clamped */
-   }
-   /* clamp to AA implementation limits */
-   size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA);
+   size = get_size(ctx, vert, GL_TRUE);
 
    /* alpha attenuation / fade factor */
-   if (ctx->Multisample.Enabled) {
+   if (ctx->Multisample._Enabled) {
       if (vert->pointSize >= ctx->Point.Threshold) {
          alphaAtten = 1.0F;
       }
@@ -248,10 +273,12 @@ smooth_point(GLcontext *ctx, const SWvertex *vert)
    (void) alphaAtten; /* not used */
 
    /* span init */
-   INIT_SPAN(span, GL_POINT, 0, 0, 0);
+   INIT_SPAN(span, GL_POINT);
    span.interpMask = SPAN_Z | SPAN_RGBA;
    span.arrayMask = SPAN_COVERAGE | SPAN_MASK;
 
+   span.facing = swrast->PointLineFacing;
+
    span.red   = ChanToFixed(vert->color[0]);
    span.green = ChanToFixed(vert->color[1]);
    span.blue  = ChanToFixed(vert->color[2]);
@@ -306,10 +333,6 @@ smooth_point(GLcontext *ctx, const SWvertex *vert)
                if (dist2 >= rmin2) {
                   /* compute partial coverage */
                   coverage = 1.0F - (dist2 - rmin2) * cscale;
-                  if (ciMode) {
-                     /* coverage in [0,15] */
-                     coverage *= 15.0;
-                  }
                }
                else {
                   /* full coverage */
@@ -337,10 +360,9 @@ smooth_point(GLcontext *ctx, const SWvertex *vert)
  * Draw large (size >= 1) non-AA point.  RGB or CI mode.
  */
 static void
-large_point(GLcontext *ctx, const SWvertex *vert)
+large_point(struct gl_context *ctx, const SWvertex *vert)
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
-   const GLboolean ciMode = !ctx->Visual.rgbMode;
    SWspan span;
    GLfloat size;
 
@@ -353,39 +375,22 @@ large_point(GLcontext *ctx, const SWvertex *vert)
       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; /* already clamped to user range */
-   }
-   /* clamp to non-AA implementation limits */
-   size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
+   size = get_size(ctx, vert, GL_FALSE);
 
    /* span init */
-   INIT_SPAN(span, GL_POINT, 0, 0, 0);
+   INIT_SPAN(span, GL_POINT);
    span.arrayMask = SPAN_XY;
+   span.facing = swrast->PointLineFacing;
 
-   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;
-   }
+   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;
@@ -418,9 +423,10 @@ large_point(GLcontext *ctx, const SWvertex *vert)
       }
       else {
          /* even size */
-         xmin = (GLint) x - iRadius + 1;
+         /* 0.501 factor allows conformance to pass */
+         xmin = (GLint) (x + 0.501) - iRadius;
          xmax = xmin + iSize - 1;
-         ymin = (GLint) y - iRadius + 1;
+         ymin = (GLint) (y + 0.501) - iRadius;
          ymax = ymin + iSize - 1;
       }
 
@@ -443,10 +449,9 @@ large_point(GLcontext *ctx, const SWvertex *vert)
  * Draw size=1, single-pixel point
  */
 static void
-pixel_point(GLcontext *ctx, const SWvertex *vert)
+pixel_point(struct gl_context *ctx, const SWvertex *vert)
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
-   const GLboolean ciMode = !ctx->Visual.rgbMode;
    /*
     * Note that unlike the other functions, we put single-pixel points
     * into a special span array in order to render as many points as
@@ -460,10 +465,7 @@ pixel_point(GLcontext *ctx, const SWvertex *vert)
    /* Span init */
    span->interpMask = 0;
    span->arrayMask = SPAN_XY | SPAN_Z;
-   if (ciMode)
-      span->arrayMask |= SPAN_INDEX;
-   else
-      span->arrayMask |= SPAN_RGBA;
+   span->arrayMask |= SPAN_RGBA;
    /*span->arrayMask |= SPAN_LAMBDA;*/
    span->arrayAttribs = swrast->_ActiveAttribMask; /* we'll produce these vals */
 
@@ -474,26 +476,24 @@ pixel_point(GLcontext *ctx, const SWvertex *vert)
 
    /* check if we need to flush */
    if (span->end >= MAX_WIDTH ||
-       (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT))) {
-      if (ciMode)
-         _swrast_write_index_span(ctx, span);
-      else
-         _swrast_write_rgba_span(ctx, span);
-      span->end = 0;
+       (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT)) ||
+       span->facing != swrast->PointLineFacing) {
+      if (span->end > 0) {
+        _swrast_write_rgba_span(ctx, span);
+         span->end = 0;
+      }
    }
 
    count = span->end;
 
+   span->facing = swrast->PointLineFacing;
+
    /* fragment attributes */
-   if (ciMode) {
-      span->array->index[count] = (GLuint) vert->attrib[FRAG_ATTRIB_CI][0];
-   }
-   else {
-      span->array->rgba[count][RCOMP] = vert->color[0];
-      span->array->rgba[count][GCOMP] = vert->color[1];
-      span->array->rgba[count][BCOMP] = vert->color[2];
-      span->array->rgba[count][ACOMP] = vert->color[3];
-   }
+   span->array->rgba[count][RCOMP] = vert->color[0];
+   span->array->rgba[count][GCOMP] = vert->color[1];
+   span->array->rgba[count][BCOMP] = vert->color[2];
+   span->array->rgba[count][ACOMP] = vert->color[3];
+
    ATTRIB_LOOP_BEGIN
       COPY_4V(span->array->attribs[attr][count], vert->attrib[attr]);
    ATTRIB_LOOP_END
@@ -513,7 +513,7 @@ pixel_point(GLcontext *ctx, const SWvertex *vert)
  * primary color.
  */
 void
-_swrast_add_spec_terms_point(GLcontext *ctx, const SWvertex *v0)
+_swrast_add_spec_terms_point(struct gl_context *ctx, const SWvertex *v0)
 {
    SWvertex *ncv0 = (SWvertex *) v0; /* cast away const */
    GLfloat rSum, gSum, bSum;
@@ -539,9 +539,12 @@ _swrast_add_spec_terms_point(GLcontext *ctx, const SWvertex *v0)
  * Examine current state to determine which point drawing function to use.
  */
 void
-_swrast_choose_point(GLcontext *ctx)
+_swrast_choose_point(struct gl_context *ctx)
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
+   const GLfloat size = CLAMP(ctx->Point.Size,
+                              ctx->Point.MinSize,
+                              ctx->Point.MaxSize);
 
    if (ctx->RenderMode == GL_RENDER) {
       if (ctx->Point.PointSprite) {
@@ -550,7 +553,7 @@ _swrast_choose_point(GLcontext *ctx)
       else if (ctx->Point.SmoothFlag) {
          swrast->Point = smooth_point;
       }
-      else if (ctx->Point._Size > 1.0 ||
+      else if (size > 1.0 ||
                ctx->Point._Attenuated ||
                ctx->VertexProgram.PointSizeEnabled) {
          swrast->Point = large_point;