1e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/*
2e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Mesa 3-D graphics library
31d52b6aaf41b32aaf8d1cdf5a3cd5ff4ecba28f4Brian * Version:  7.1
422144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
51d52b6aaf41b32aaf8d1cdf5a3cd5ff4ecba28f4Brian * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
7e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a
8e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * copy of this software and associated documentation files (the "Software"),
9e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * to deal in the Software without restriction, including without limitation
10e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * and/or sell copies of the Software, and to permit persons to whom the
12e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Software is furnished to do so, subject to the following conditions:
1322144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
14e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * The above copyright notice and this permission notice shall be included
15e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * in all copies or substantial portions of the Software.
1622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
17e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
24e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
25e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
26bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/glheader.h"
27bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/colormac.h"
28bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/macros.h"
29cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "s_context.h"
30cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "s_feedback.h"
31cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "s_points.h"
32e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_span.h"
33e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
34e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
35fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian/**
36fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian * Used to cull points with invalid coords
37e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
38fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian#define CULL_INVALID(V)                              \
39fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   do {                                              \
40fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      float tmp = (V)->attrib[FRAG_ATTRIB_WPOS][0]   \
41fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian                + (V)->attrib[FRAG_ATTRIB_WPOS][1];  \
42fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      if (IS_INF_OR_NAN(tmp))                        \
43fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian	 return;                                     \
44fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   } while(0)
45e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
46e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
470fd679a1903d997b53fe20b86821a58c1a66262fBrian
480fd679a1903d997b53fe20b86821a58c1a66262fBrian/**
490fd679a1903d997b53fe20b86821a58c1a66262fBrian * Get/compute the point size.
500fd679a1903d997b53fe20b86821a58c1a66262fBrian * The size may come from a vertex shader, or computed with attentuation
510fd679a1903d997b53fe20b86821a58c1a66262fBrian * or just the glPointSize value.
520fd679a1903d997b53fe20b86821a58c1a66262fBrian * Must also clamp to user-defined range and implmentation limits.
530fd679a1903d997b53fe20b86821a58c1a66262fBrian */
549520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLfloat
55f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergget_size(const struct gl_context *ctx, const SWvertex *vert, GLboolean smoothed)
560fd679a1903d997b53fe20b86821a58c1a66262fBrian{
570fd679a1903d997b53fe20b86821a58c1a66262fBrian   GLfloat size;
580fd679a1903d997b53fe20b86821a58c1a66262fBrian
590fd679a1903d997b53fe20b86821a58c1a66262fBrian   if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
600fd679a1903d997b53fe20b86821a58c1a66262fBrian      /* use vertex's point size */
610fd679a1903d997b53fe20b86821a58c1a66262fBrian      size = vert->pointSize;
620fd679a1903d997b53fe20b86821a58c1a66262fBrian   }
630fd679a1903d997b53fe20b86821a58c1a66262fBrian   else {
640fd679a1903d997b53fe20b86821a58c1a66262fBrian      /* use constant point size */
650fd679a1903d997b53fe20b86821a58c1a66262fBrian      size = ctx->Point.Size;
660fd679a1903d997b53fe20b86821a58c1a66262fBrian   }
670fd679a1903d997b53fe20b86821a58c1a66262fBrian   /* always clamp to user-specified limits */
680fd679a1903d997b53fe20b86821a58c1a66262fBrian   size = CLAMP(size, ctx->Point.MinSize, ctx->Point.MaxSize);
690fd679a1903d997b53fe20b86821a58c1a66262fBrian   /* clamp to implementation limits */
700fd679a1903d997b53fe20b86821a58c1a66262fBrian   if (smoothed)
710fd679a1903d997b53fe20b86821a58c1a66262fBrian      size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA);
720fd679a1903d997b53fe20b86821a58c1a66262fBrian   else
730fd679a1903d997b53fe20b86821a58c1a66262fBrian      size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
740fd679a1903d997b53fe20b86821a58c1a66262fBrian
750fd679a1903d997b53fe20b86821a58c1a66262fBrian   return size;
760fd679a1903d997b53fe20b86821a58c1a66262fBrian}
770fd679a1903d997b53fe20b86821a58c1a66262fBrian
780fd679a1903d997b53fe20b86821a58c1a66262fBrian
79fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian/**
80fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian * Draw a point sprite
81e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
82fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brianstatic void
83f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsprite_point(struct gl_context *ctx, const SWvertex *vert)
84fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian{
85fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   SWcontext *swrast = SWRAST_CONTEXT(ctx);
86fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   SWspan span;
87fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   GLfloat size;
88e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian   GLuint tCoords[MAX_TEXTURE_COORD_UNITS + 1];
89fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   GLuint numTcoords = 0;
90fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   GLfloat t0, dtdy;
91fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
92fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   CULL_INVALID(vert);
93fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
94fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* z coord */
95fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   if (ctx->DrawBuffer->Visual.depthBits <= 16)
96fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
97fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   else
98fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
99fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.zStep = 0;
100fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
1010fd679a1903d997b53fe20b86821a58c1a66262fBrian   size = get_size(ctx, vert, GL_FALSE);
102fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
103fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* span init */
104f4b103dc993491355ec3e3640d9cb060138175c2Brian   INIT_SPAN(span, GL_POINT);
105fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.interpMask = SPAN_Z | SPAN_RGBA;
106fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
107fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian   span.facing = swrast->PointLineFacing;
108fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian
109fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.red   = ChanToFixed(vert->color[0]);
110fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.green = ChanToFixed(vert->color[1]);
111fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.blue  = ChanToFixed(vert->color[2]);
112fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.alpha = ChanToFixed(vert->color[3]);
113fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.redStep = 0;
114fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.greenStep = 0;
115fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.blueStep = 0;
116fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.alphaStep = 0;
117fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
118fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* need these for fragment programs */
119fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
120fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
121fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
122fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
123e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian   {
124e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian      GLfloat s, r, dsdx;
125e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian
126e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian      /* texcoord / pointcoord interpolants */
127880411c72aee7c0ec81366bdf6ab8cf25bebb9d5Brian Paul      s = 0.0F;
128880411c72aee7c0ec81366bdf6ab8cf25bebb9d5Brian Paul      dsdx = 1.0F / size;
129e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian      if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) {
130880411c72aee7c0ec81366bdf6ab8cf25bebb9d5Brian Paul         dtdy = 1.0F / size;
131880411c72aee7c0ec81366bdf6ab8cf25bebb9d5Brian Paul         t0 = 0.5F * dtdy;
132e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian      }
133e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian      else {
134e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian         /* GL_UPPER_LEFT */
135880411c72aee7c0ec81366bdf6ab8cf25bebb9d5Brian Paul         dtdy = -1.0F / size;
136880411c72aee7c0ec81366bdf6ab8cf25bebb9d5Brian Paul         t0 = 1.0F + 0.5F * dtdy;
137e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian      }
138fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
139e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian      ATTRIB_LOOP_BEGIN
140f7618f4f37d42461b1a6feaa392935d1ae703873Brian Paul         if (attr >= FRAG_ATTRIB_TEX0 && attr <= FRAG_ATTRIB_TEX7) {
141f7618f4f37d42461b1a6feaa392935d1ae703873Brian Paul            /* a texcoord attribute */
142e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian            const GLuint u = attr - FRAG_ATTRIB_TEX0;
143f7618f4f37d42461b1a6feaa392935d1ae703873Brian Paul            ASSERT(u < Elements(ctx->Point.CoordReplace));
144e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian            if (ctx->Point.CoordReplace[u]) {
145e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               tCoords[numTcoords++] = attr;
146e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian
147e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               if (ctx->Point.SpriteRMode == GL_ZERO)
148e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian                  r = 0.0F;
149e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               else if (ctx->Point.SpriteRMode == GL_S)
150e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian                  r = vert->attrib[attr][0];
151e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               else /* GL_R */
152e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian                  r = vert->attrib[attr][2];
153e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian
154e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               span.attrStart[attr][0] = s;
155e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               span.attrStart[attr][1] = 0.0; /* overwritten below */
156e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               span.attrStart[attr][2] = r;
157e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               span.attrStart[attr][3] = 1.0;
158e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian
159e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               span.attrStepX[attr][0] = dsdx;
160e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               span.attrStepX[attr][1] = 0.0;
161e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               span.attrStepX[attr][2] = 0.0;
162e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               span.attrStepX[attr][3] = 0.0;
163e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian
164e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               span.attrStepY[attr][0] = 0.0;
165e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               span.attrStepY[attr][1] = dtdy;
166e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               span.attrStepY[attr][2] = 0.0;
167e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               span.attrStepY[attr][3] = 0.0;
168e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian
169e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian               continue;
170fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            }
171e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian         }
1729d0b8d72d8d704ff4d8e10448b60cbb42f07eecbBrian Paul         else if (attr == FRAG_ATTRIB_PNTC) {
1739d0b8d72d8d704ff4d8e10448b60cbb42f07eecbBrian Paul            /* GLSL gl_PointCoord.xy (.zw undefined) */
1749d0b8d72d8d704ff4d8e10448b60cbb42f07eecbBrian Paul            span.attrStart[FRAG_ATTRIB_PNTC][0] = 0.0;
1759d0b8d72d8d704ff4d8e10448b60cbb42f07eecbBrian Paul            span.attrStart[FRAG_ATTRIB_PNTC][1] = 0.0; /* t0 set below */
1769d0b8d72d8d704ff4d8e10448b60cbb42f07eecbBrian Paul            span.attrStepX[FRAG_ATTRIB_PNTC][0] = dsdx;
1779d0b8d72d8d704ff4d8e10448b60cbb42f07eecbBrian Paul            span.attrStepX[FRAG_ATTRIB_PNTC][1] = 0.0;
1789d0b8d72d8d704ff4d8e10448b60cbb42f07eecbBrian Paul            span.attrStepY[FRAG_ATTRIB_PNTC][0] = 0.0;
1799d0b8d72d8d704ff4d8e10448b60cbb42f07eecbBrian Paul            span.attrStepY[FRAG_ATTRIB_PNTC][1] = dtdy;
1809d0b8d72d8d704ff4d8e10448b60cbb42f07eecbBrian Paul            tCoords[numTcoords++] = FRAG_ATTRIB_PNTC;
181fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            continue;
182fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         }
183e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian         /* use vertex's texcoord/attrib */
184e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian         COPY_4V(span.attrStart[attr], vert->attrib[attr]);
185e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian         ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
186e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian         ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
187e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian      ATTRIB_LOOP_END;
188e48f0b09abe42aa3393a492af07e53b76ad0ff3cBrian   }
189fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
190fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* compute pos, bounds and render */
191fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   {
192fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
193fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
194fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      GLint iSize = (GLint) (size + 0.5F);
195fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      GLint xmin, xmax, ymin, ymax, iy;
196fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      GLint iRadius;
197fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      GLfloat tcoord = t0;
198fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
199fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      iSize = MAX2(1, iSize);
200fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      iRadius = iSize / 2;
201fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
202fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      if (iSize & 1) {
203fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         /* odd size */
204fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         xmin = (GLint) (x - iRadius);
205fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         xmax = (GLint) (x + iRadius);
206fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         ymin = (GLint) (y - iRadius);
207fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         ymax = (GLint) (y + iRadius);
208fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      }
209fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      else {
210fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         /* even size */
2114f9d29cd4e876cd202a7d3e81f6d91fc7f9625a2Brian         /* 0.501 factor allows conformance to pass */
2124f9d29cd4e876cd202a7d3e81f6d91fc7f9625a2Brian         xmin = (GLint) (x + 0.501) - iRadius;
213fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         xmax = xmin + iSize - 1;
2144f9d29cd4e876cd202a7d3e81f6d91fc7f9625a2Brian         ymin = (GLint) (y + 0.501) - iRadius;
215fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         ymax = ymin + iSize - 1;
216fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      }
217e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
218fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      /* render spans */
219fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      for (iy = ymin; iy <= ymax; iy++) {
220fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         GLuint i;
221fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         /* setup texcoord T for this row */
222fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         for (i = 0; i < numTcoords; i++) {
2239d0b8d72d8d704ff4d8e10448b60cbb42f07eecbBrian Paul            span.attrStart[tCoords[i]][1] = tcoord;
224fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         }
225e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
226fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         /* these might get changed by span clipping */
227fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         span.x = xmin;
228fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         span.y = iy;
229fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         span.end = xmax - xmin + 1;
230e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
231fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         _swrast_write_rgba_span(ctx, &span);
232e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
233fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         tcoord += dtdy;
234fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      }
235fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   }
236fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian}
237e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
238cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell
239fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian/**
240fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian * Draw smooth/antialiased point.  RGB or CI mode.
241e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
242fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brianstatic void
243f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsmooth_point(struct gl_context *ctx, const SWvertex *vert)
244fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian{
245fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   SWcontext *swrast = SWRAST_CONTEXT(ctx);
246fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   SWspan span;
247fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   GLfloat size, alphaAtten;
248fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
249fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   CULL_INVALID(vert);
250fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
251fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* z coord */
252fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   if (ctx->DrawBuffer->Visual.depthBits <= 16)
253fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
254fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   else
255fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
256fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.zStep = 0;
257fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
2580fd679a1903d997b53fe20b86821a58c1a66262fBrian   size = get_size(ctx, vert, GL_TRUE);
259e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
260fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* alpha attenuation / fade factor */
2615ef4e4ffb8053db87f52df3c9b2ddb71d9c7d6e5Roland Scheidegger   if (ctx->Multisample._Enabled) {
262fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      if (vert->pointSize >= ctx->Point.Threshold) {
263fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         alphaAtten = 1.0F;
264fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      }
265fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      else {
266fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         GLfloat dsize = vert->pointSize / ctx->Point.Threshold;
267fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         alphaAtten = dsize * dsize;
268fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      }
269fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   }
270fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   else {
271fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      alphaAtten = 1.0;
272fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   }
273fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   (void) alphaAtten; /* not used */
274fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
275fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* span init */
276f4b103dc993491355ec3e3640d9cb060138175c2Brian   INIT_SPAN(span, GL_POINT);
277fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.interpMask = SPAN_Z | SPAN_RGBA;
278fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.arrayMask = SPAN_COVERAGE | SPAN_MASK;
279fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
280fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian   span.facing = swrast->PointLineFacing;
281fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian
282fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.red   = ChanToFixed(vert->color[0]);
283fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.green = ChanToFixed(vert->color[1]);
284fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.blue  = ChanToFixed(vert->color[2]);
285fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.alpha = ChanToFixed(vert->color[3]);
286fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.redStep = 0;
287fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.greenStep = 0;
288fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.blueStep = 0;
289fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.alphaStep = 0;
290fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
291fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* need these for fragment programs */
292fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
293fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
294fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
295fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
296fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   ATTRIB_LOOP_BEGIN
297fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      COPY_4V(span.attrStart[attr], vert->attrib[attr]);
298fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
299fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
300fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   ATTRIB_LOOP_END
301fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
302fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* compute pos, bounds and render */
303fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   {
304fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
305fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
306fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLfloat radius = 0.5F * size;
307fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLfloat rmin = radius - 0.7071F;  /* 0.7071 = sqrt(2)/2 */
308fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLfloat rmax = radius + 0.7071F;
309fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
310fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLfloat rmax2 = rmax * rmax;
311fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLfloat cscale = 1.0F / (rmax2 - rmin2);
312fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLint xmin = (GLint) (x - radius);
313fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLint xmax = (GLint) (x + radius);
314fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLint ymin = (GLint) (y - radius);
315fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLint ymax = (GLint) (y + radius);
316fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      GLint ix, iy;
317fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
318fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      for (iy = ymin; iy <= ymax; iy++) {
319fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
320fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         /* these might get changed by span clipping */
321fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         span.x = xmin;
322fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         span.y = iy;
323fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         span.end = xmax - xmin + 1;
324fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
325fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         /* compute coverage for each pixel in span */
326fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         for (ix = xmin; ix <= xmax; ix++) {
327fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            const GLfloat dx = ix - x + 0.5F;
328fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            const GLfloat dy = iy - y + 0.5F;
329fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            const GLfloat dist2 = dx * dx + dy * dy;
330fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            GLfloat coverage;
331fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
332fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            if (dist2 < rmax2) {
333fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian               if (dist2 >= rmin2) {
334fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian                  /* compute partial coverage */
335fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian                  coverage = 1.0F - (dist2 - rmin2) * cscale;
336fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian               }
337fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian               else {
338fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian                  /* full coverage */
339fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian                  coverage = 1.0F;
340fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian               }
341fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian               span.array->mask[ix - xmin] = 1;
342fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            }
343fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            else {
344fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian               /* zero coverage - fragment outside the radius */
345fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian               coverage = 0.0;
346fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian               span.array->mask[ix - xmin] = 0;
347fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            }
348fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            span.array->coverage[ix - xmin] = coverage;
349fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         }
350e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
351fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         /* render span */
352fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         _swrast_write_rgba_span(ctx, &span);
353e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
354fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      }
355fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   }
356fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian}
3572fd9c8690fa86b17c42afcc73307d2232b8f79f6Brian Paul
3582fd9c8690fa86b17c42afcc73307d2232b8f79f6Brian Paul
359fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian/**
360fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian * Draw large (size >= 1) non-AA point.  RGB or CI mode.
3612fd9c8690fa86b17c42afcc73307d2232b8f79f6Brian Paul */
362fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brianstatic void
363f9995b30756140724f41daf963fa06167912be7fKristian Høgsberglarge_point(struct gl_context *ctx, const SWvertex *vert)
364fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian{
365fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   SWcontext *swrast = SWRAST_CONTEXT(ctx);
366fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   SWspan span;
367fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   GLfloat size;
368fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
369fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   CULL_INVALID(vert);
370fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
371fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* z coord */
372fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   if (ctx->DrawBuffer->Visual.depthBits <= 16)
373fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
374fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   else
375fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
376fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.zStep = 0;
377fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
3780fd679a1903d997b53fe20b86821a58c1a66262fBrian   size = get_size(ctx, vert, GL_FALSE);
379e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
380fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* span init */
381f4b103dc993491355ec3e3640d9cb060138175c2Brian   INIT_SPAN(span, GL_POINT);
382fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.arrayMask = SPAN_XY;
383fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian   span.facing = swrast->PointLineFacing;
384e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
385dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span.interpMask = SPAN_Z | SPAN_RGBA;
386dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span.red   = ChanToFixed(vert->color[0]);
387dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span.green = ChanToFixed(vert->color[1]);
388dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span.blue  = ChanToFixed(vert->color[2]);
389dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span.alpha = ChanToFixed(vert->color[3]);
390dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span.redStep = 0;
391dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span.greenStep = 0;
392dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span.blueStep = 0;
393dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span.alphaStep = 0;
394e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
395fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* need these for fragment programs */
396fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
397fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
398fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
399fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
400fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   ATTRIB_LOOP_BEGIN
401fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      COPY_4V(span.attrStart[attr], vert->attrib[attr]);
402fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
403fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
404fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   ATTRIB_LOOP_END
405fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
406fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* compute pos, bounds and render */
407fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   {
408fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
409fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
410fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      GLint iSize = (GLint) (size + 0.5F);
411fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      GLint xmin, xmax, ymin, ymax, ix, iy;
412fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      GLint iRadius;
413fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
414fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      iSize = MAX2(1, iSize);
415fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      iRadius = iSize / 2;
416fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
417fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      if (iSize & 1) {
418fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         /* odd size */
419fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         xmin = (GLint) (x - iRadius);
420fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         xmax = (GLint) (x + iRadius);
421fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         ymin = (GLint) (y - iRadius);
422fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         ymax = (GLint) (y + iRadius);
423fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      }
424fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      else {
425fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         /* even size */
4264f9d29cd4e876cd202a7d3e81f6d91fc7f9625a2Brian         /* 0.501 factor allows conformance to pass */
4274f9d29cd4e876cd202a7d3e81f6d91fc7f9625a2Brian         xmin = (GLint) (x + 0.501) - iRadius;
428fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         xmax = xmin + iSize - 1;
4294f9d29cd4e876cd202a7d3e81f6d91fc7f9625a2Brian         ymin = (GLint) (y + 0.501) - iRadius;
430fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         ymax = ymin + iSize - 1;
431fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      }
432e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
433fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      /* generate fragments */
434fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      span.end = 0;
435fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      for (iy = ymin; iy <= ymax; iy++) {
436fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         for (ix = xmin; ix <= xmax; ix++) {
437fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            span.array->x[span.end] = ix;
438fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            span.array->y[span.end] = iy;
439fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian            span.end++;
440fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         }
441fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      }
44247d88ef204b42a9220c6be3e98c92df9c9aa0860Brian Paul      assert(span.end <= SWRAST_MAX_WIDTH);
443fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      _swrast_write_rgba_span(ctx, &span);
444fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   }
445fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian}
446e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
447e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
448fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian/**
449fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian * Draw size=1, single-pixel point
450e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
451fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brianstatic void
452f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergpixel_point(struct gl_context *ctx, const SWvertex *vert)
453fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian{
454fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   SWcontext *swrast = SWRAST_CONTEXT(ctx);
455fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /*
456fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian    * Note that unlike the other functions, we put single-pixel points
457fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian    * into a special span array in order to render as many points as
458fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian    * possible with a single _swrast_write_rgba_span() call.
459fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian    */
460fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   SWspan *span = &(swrast->PointSpan);
461fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   GLuint count;
462fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
463fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   CULL_INVALID(vert);
464fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
465fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* Span init */
466fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span->interpMask = 0;
467fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span->arrayMask = SPAN_XY | SPAN_Z;
468dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span->arrayMask |= SPAN_RGBA;
469fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /*span->arrayMask |= SPAN_LAMBDA;*/
470fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span->arrayAttribs = swrast->_ActiveAttribMask; /* we'll produce these vals */
471fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
472fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* need these for fragment programs */
473fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
474fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
475fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
476fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian
477fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* check if we need to flush */
47847d88ef204b42a9220c6be3e98c92df9c9aa0860Brian Paul   if (span->end >= SWRAST_MAX_WIDTH ||
479fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian       (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT)) ||
480fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian       span->facing != swrast->PointLineFacing) {
48148aa35a8b28e2cd5dab994c2cc0d728275b9aad2Brian      if (span->end > 0) {
482dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick	 _swrast_write_rgba_span(ctx, span);
48348aa35a8b28e2cd5dab994c2cc0d728275b9aad2Brian         span->end = 0;
48448aa35a8b28e2cd5dab994c2cc0d728275b9aad2Brian      }
485fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   }
486e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
487fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   count = span->end;
488e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
489fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian   span->facing = swrast->PointLineFacing;
490fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian
491fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* fragment attributes */
492dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span->array->rgba[count][RCOMP] = vert->color[0];
493dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span->array->rgba[count][GCOMP] = vert->color[1];
494dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span->array->rgba[count][BCOMP] = vert->color[2];
495dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick   span->array->rgba[count][ACOMP] = vert->color[3];
496dbe901ceb01e48ba7d79fd9245b9d339ef17c692Ian Romanick
497fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   ATTRIB_LOOP_BEGIN
498fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      COPY_4V(span->array->attribs[attr][count], vert->attrib[attr]);
499fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   ATTRIB_LOOP_END
50006d05afdd687fcd1d59d46c6a86c2e5707e1859bBrian Paul
501fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   /* fragment position */
502fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span->array->x[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][0];
503fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span->array->y[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][1];
504fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span->array->z[count] = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
50506d05afdd687fcd1d59d46c6a86c2e5707e1859bBrian Paul
506fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   span->end = count + 1;
50747d88ef204b42a9220c6be3e98c92df9c9aa0860Brian Paul   ASSERT(span->end <= SWRAST_MAX_WIDTH);
508fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian}
50906d05afdd687fcd1d59d46c6a86c2e5707e1859bBrian Paul
51006d05afdd687fcd1d59d46c6a86c2e5707e1859bBrian Paul
511fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian/**
512fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian * Add specular color to primary color, draw point, restore original
513fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian * primary color.
514fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian */
5159e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrianvoid
516f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_add_spec_terms_point(struct gl_context *ctx, const SWvertex *v0)
51746b0988c673b28e072fd0cbf477632a9ab6f9f18Keith Whitwell{
518fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   SWvertex *ncv0 = (SWvertex *) v0; /* cast away const */
5199e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   GLfloat rSum, gSum, bSum;
5209e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   GLchan cSave[4];
5219e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
5229e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* save */
523fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   COPY_CHAN4(cSave, ncv0->color);
5249e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* sum */
5259e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[FRAG_ATTRIB_COL1][0];
5269e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[FRAG_ATTRIB_COL1][1];
5279e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[FRAG_ATTRIB_COL1][2];
5289e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
5299e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
5309e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
5319e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* draw */
5329e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   SWRAST_CONTEXT(ctx)->SpecPoint(ctx, ncv0);
5339e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* restore */
5349e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   COPY_CHAN4(ncv0->color, cSave);
53546b0988c673b28e072fd0cbf477632a9ab6f9f18Keith Whitwell}
53646b0988c673b28e072fd0cbf477632a9ab6f9f18Keith Whitwell
53746b0988c673b28e072fd0cbf477632a9ab6f9f18Keith Whitwell
538fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian/**
539fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian * Examine current state to determine which point drawing function to use.
540e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
54122144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughesvoid
542f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_choose_point(struct gl_context *ctx)
543e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
544cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
545228f20e324249ef25beed725a6a821e0bd0cc232Brian Paul   const GLfloat size = CLAMP(ctx->Point.Size,
546228f20e324249ef25beed725a6a821e0bd0cc232Brian Paul                              ctx->Point.MinSize,
547228f20e324249ef25beed725a6a821e0bd0cc232Brian Paul                              ctx->Point.MaxSize);
5481d52b6aaf41b32aaf8d1cdf5a3cd5ff4ecba28f4Brian
549fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   if (ctx->RenderMode == GL_RENDER) {
5506c408b46678637959dba04663fbc34eb9c4bc397Brian Paul      if (ctx->Point.PointSprite) {
551fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         swrast->Point = sprite_point;
5522fd9c8690fa86b17c42afcc73307d2232b8f79f6Brian Paul      }
553fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      else if (ctx->Point.SmoothFlag) {
554fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         swrast->Point = smooth_point;
5552fd9c8690fa86b17c42afcc73307d2232b8f79f6Brian Paul      }
556228f20e324249ef25beed725a6a821e0bd0cc232Brian Paul      else if (size > 1.0 ||
557fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian               ctx->Point._Attenuated ||
558fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian               ctx->VertexProgram.PointSizeEnabled) {
559fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         swrast->Point = large_point;
560e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
561e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
562fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian         swrast->Point = pixel_point;
5632fd9c8690fa86b17c42afcc73307d2232b8f79f6Brian Paul      }
564e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
565fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian   else if (ctx->RenderMode == GL_FEEDBACK) {
566fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      swrast->Point = _swrast_feedback_point;
567e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
568e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
569e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* GL_SELECT mode */
570fc5bf536440efeb9766cc1fd6e69642bc27afbd8Brian      swrast->Point = _swrast_select_point;
571e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
572e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
573