r300: Cleaned up the r300SetupVertexShader function.
[mesa.git] / src / mesa / swrast / s_pointtemp.h
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.3
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 * Regarding GL_NV_point_sprite:
27 *
28 * Portions of this software may use or implement intellectual
29 * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
30 * any and all warranties with respect to such intellectual property,
31 * including any use thereof or modifications thereto.
32 */
33
34
35 /*
36 * Point rendering template code.
37 *
38 * Set FLAGS = bitwise-OR of the following tokens:
39 *
40 * RGBA = do rgba instead of color index
41 * SMOOTH = do antialiasing
42 * ATTRIBS = general attributes (texcoords, etc)
43 * LARGE = do points with diameter > 1 pixel
44 * ATTENUATE = compute point size attenuation
45 * SPRITE = GL_ARB_point_sprite / GL_NV_point_sprite
46 *
47 * Notes: LARGE and ATTENUATE are exclusive of each other.
48 * ATTRIBS requires RGBA
49 */
50
51
52 /*
53 * NOTES on antialiased point rasterization:
54 *
55 * Let d = distance of fragment center from vertex.
56 * if d < rmin2 then
57 * fragment has 100% coverage
58 * else if d > rmax2 then
59 * fragment has 0% coverage
60 * else
61 * fragment has % coverage = (d - rmin2) / (rmax2 - rmin2)
62 */
63
64
65 static void
66 NAME ( GLcontext *ctx, const SWvertex *vert )
67 {
68 #if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
69 GLfloat size;
70 #endif
71 #if FLAGS & RGBA
72 #if (FLAGS & ATTENUATE) && (FLAGS & SMOOTH)
73 GLfloat alphaAtten;
74 #endif
75 const GLchan red = vert->color[0];
76 const GLchan green = vert->color[1];
77 const GLchan blue = vert->color[2];
78 const GLchan alpha = vert->color[3];
79 #endif
80 #if FLAGS & INDEX
81 const GLuint colorIndex = (GLuint) vert->attrib[FRAG_ATTRIB_CI][0]; /* XXX round? */
82 #endif
83 #if FLAGS & ATTRIBS
84 GLfloat attrib[FRAG_ATTRIB_MAX][4]; /* texture & varying */
85 #endif
86 SWcontext *swrast = SWRAST_CONTEXT(ctx);
87 SWspan *span = &(swrast->PointSpan);
88
89 /*
90 printf("%s %g %g %g %g\n", __FUNCTION__,
91 vert->attrib[FRAG_ATTRIB_COL1][0],
92 vert->attrib[FRAG_ATTRIB_COL1][1],
93 vert->attrib[FRAG_ATTRIB_COL1][2],
94 vert->attrib[FRAG_ATTRIB_COL1][3]);
95 if ( vert->attrib[FRAG_ATTRIB_COL1][0] == 0.0 &&
96 vert->attrib[FRAG_ATTRIB_COL1][1] == 1.0 &&
97 vert->attrib[FRAG_ATTRIB_COL1][2] == 0.0)
98 foo();
99 */
100
101 /* Cull primitives with malformed coordinates.
102 */
103 {
104 float tmp = vert->attrib[FRAG_ATTRIB_WPOS][0] + vert->attrib[FRAG_ATTRIB_WPOS][1];
105 if (IS_INF_OR_NAN(tmp))
106 return;
107 }
108
109 /*
110 * Span init
111 */
112 span->interpMask = 0;
113 span->arrayMask = SPAN_XY | SPAN_Z;
114 #if FLAGS & RGBA
115 span->arrayMask |= SPAN_RGBA;
116 #endif
117 #if FLAGS & INDEX
118 span->arrayMask |= SPAN_INDEX;
119 #endif
120 #if FLAGS & ATTRIBS
121 span->arrayMask |= SPAN_LAMBDA;
122
123 /* we're filling in the attrib arrays: */
124 span->arrayAttribs = swrast->_ActiveAttribMask;
125
126 ATTRIB_LOOP_BEGIN
127 COPY_4V(attrib[attr], vert->attrib[attr]);
128 ATTRIB_LOOP_END
129
130 /* need these for fragment programs */
131 span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
132 span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
133 span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
134 #else
135 assert((swrast->_ActiveAttribMask & FRAG_BIT_COL1) == 0);
136 #endif
137
138 #if FLAGS & SMOOTH
139 span->arrayMask |= SPAN_COVERAGE;
140 #endif
141 #if FLAGS & SPRITE
142 span->arrayMask |= SPAN_LAMBDA;
143 #endif
144
145 /* Compute point size if not known to be one */
146 #if FLAGS & ATTENUATE
147 /* first, clamp attenuated size to the user-specifed range */
148 size = CLAMP(vert->pointSize, ctx->Point.MinSize, ctx->Point.MaxSize);
149 #if (FLAGS & RGBA) && (FLAGS & SMOOTH)
150 /* only if multisampling, compute the fade factor */
151 if (ctx->Multisample.Enabled) {
152 if (vert->pointSize >= ctx->Point.Threshold) {
153 alphaAtten = 1.0F;
154 }
155 else {
156 GLfloat dsize = vert->pointSize / ctx->Point.Threshold;
157 alphaAtten = dsize * dsize;
158 }
159 }
160 else {
161 alphaAtten = 1.0;
162 }
163 #endif
164 #elif FLAGS & (LARGE | SMOOTH | SPRITE)
165 /* constant, non-attenuated size */
166 size = ctx->Point._Size; /* this is already clamped */
167 #endif
168
169
170 #if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
171 /***
172 *** Multi-pixel points
173 ***/
174
175 /* do final clamping now */
176 if (ctx->Point.SmoothFlag) {
177 size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA);
178 }
179 else {
180 size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
181 }
182
183 {{
184 GLint x, y;
185 const GLfloat radius = 0.5F * size;
186 const GLuint z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
187 GLuint count;
188 #if FLAGS & SMOOTH
189 const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
190 const GLfloat rmax = radius + 0.7071F;
191 const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
192 const GLfloat rmax2 = rmax * rmax;
193 const GLfloat cscale = 1.0F / (rmax2 - rmin2);
194 const GLint xmin = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][0] - radius);
195 const GLint xmax = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][0] + radius);
196 const GLint ymin = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][1] - radius);
197 const GLint ymax = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][1] + radius);
198 #else
199 /* non-smooth */
200 GLint xmin, xmax, ymin, ymax;
201 GLint iSize = (GLint) (size + 0.5F);
202 GLint iRadius;
203 iSize = MAX2(1, iSize);
204 iRadius = iSize / 2;
205 if (iSize & 1) {
206 /* odd size */
207 xmin = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][0] - iRadius);
208 xmax = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][0] + iRadius);
209 ymin = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][1] - iRadius);
210 ymax = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][1] + iRadius);
211 }
212 else {
213 /* even size */
214 xmin = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][0] - iRadius + 1;
215 xmax = xmin + iSize - 1;
216 ymin = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][1] - iRadius + 1;
217 ymax = ymin + iSize - 1;
218 }
219 #endif /*SMOOTH*/
220
221 /* check if we need to flush */
222 if (span->end + (xmax-xmin+1) * (ymax-ymin+1) >= MAX_WIDTH ||
223 (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT))) {
224 if (span->end > 0) {
225 #if FLAGS & RGBA
226 _swrast_write_rgba_span(ctx, span);
227 #else
228 _swrast_write_index_span(ctx, span);
229 #endif
230 span->end = 0;
231 }
232 }
233
234 /*
235 * OK, generate fragments
236 */
237 count = span->end;
238 (void) radius;
239 for (y = ymin; y <= ymax; y++) {
240 /* check if we need to flush */
241 if (count + (xmax-xmin+1) >= MAX_WIDTH) {
242 span->end = count;
243 #if FLAGS & RGBA
244 _swrast_write_rgba_span(ctx, span);
245 #else
246 _swrast_write_index_span(ctx, span);
247 #endif
248 count = span->end = 0;
249 }
250 for (x = xmin; x <= xmax; x++) {
251 #if FLAGS & SPRITE
252 GLuint u;
253 #endif
254
255 #if FLAGS & RGBA
256 span->array->rgba[count][RCOMP] = red;
257 span->array->rgba[count][GCOMP] = green;
258 span->array->rgba[count][BCOMP] = blue;
259 span->array->rgba[count][ACOMP] = alpha;
260 #endif
261 #if FLAGS & INDEX
262 span->array->index[count] = colorIndex;
263 #endif
264 #if FLAGS & ATTRIBS
265 ATTRIB_LOOP_BEGIN
266 COPY_4V(span->array->attribs[attr][count], attrib[attr]);
267 /**
268 if (attr < FRAG_ATTRIB_VAR0) {
269 const GLuint u = attr - FRAG_ATTRIB_TEX0;
270 span->array->lambda[u][count] = 0.0;
271 }
272 **/
273 ATTRIB_LOOP_END
274 #endif
275
276 #if FLAGS & SMOOTH
277 /* compute coverage */
278 {
279 const GLfloat dx = x - vert->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F;
280 const GLfloat dy = y - vert->attrib[FRAG_ATTRIB_WPOS][1] + 0.5F;
281 const GLfloat dist2 = dx * dx + dy * dy;
282 if (dist2 < rmax2) {
283 if (dist2 >= rmin2) {
284 /* compute partial coverage */
285 span->array->coverage[count] = 1.0F - (dist2 - rmin2) * cscale;
286 #if FLAGS & INDEX
287 /* coverage in [0,15] */
288 span->array->coverage[count] *= 15.0;
289 #endif
290 }
291 else {
292 /* full coverage */
293 span->array->coverage[count] = 1.0F;
294 }
295
296 span->array->x[count] = x;
297 span->array->y[count] = y;
298 span->array->z[count] = z;
299
300 #if (FLAGS & ATTENUATE) && (FLAGS & RGBA)
301 span->array->rgba[count][ACOMP] = (GLchan) (alpha * alphaAtten);
302 #elif FLAGS & RGBA
303 span->array->rgba[count][ACOMP] = alpha;
304 #endif /*ATTENUATE*/
305 count++;
306 } /*if*/
307 }
308
309 #else /*SMOOTH*/
310
311 /* not smooth (square points) */
312 span->array->x[count] = x;
313 span->array->y[count] = y;
314 span->array->z[count] = z;
315
316 #if FLAGS & SPRITE
317 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
318 GLuint attr = FRAG_ATTRIB_TEX0 + u;
319 if (ctx->Texture.Unit[u]._ReallyEnabled) {
320 if (ctx->Point.CoordReplace[u]) {
321 GLfloat s = 0.5F + (x + 0.5F - vert->attrib[FRAG_ATTRIB_WPOS][0]) / size;
322 GLfloat t, r;
323 if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT)
324 t = 0.5F + (y + 0.5F - vert->attrib[FRAG_ATTRIB_WPOS][1]) / size;
325 else /* GL_UPPER_LEFT */
326 t = 0.5F - (y + 0.5F - vert->attrib[FRAG_ATTRIB_WPOS][1]) / size;
327 if (ctx->Point.SpriteRMode == GL_ZERO)
328 r = 0.0F;
329 else if (ctx->Point.SpriteRMode == GL_S)
330 r = vert->attrib[attr][0];
331 else /* GL_R */
332 r = vert->attrib[attr][2];
333 span->array->attribs[attr][count][0] = s;
334 span->array->attribs[attr][count][1] = t;
335 span->array->attribs[attr][count][2] = r;
336 span->array->attribs[attr][count][3] = 1.0F;
337 span->array->lambda[u][count] = 0.0; /* XXX fix? */
338 }
339 else {
340 COPY_4V(span->array->attribs[attr][count],
341 vert->attrib[attr]);
342 }
343 }
344 }
345 #endif /*SPRITE*/
346
347 count++; /* square point */
348
349 #endif /*SMOOTH*/
350
351 } /*for x*/
352 } /*for y*/
353 span->end = count;
354 }}
355
356 #else /* LARGE | ATTENUATE | SMOOTH | SPRITE */
357
358 /***
359 *** Single-pixel points
360 ***/
361 {{
362 GLuint count;
363
364 /* check if we need to flush */
365 if (span->end >= MAX_WIDTH ||
366 (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT))) {
367 #if FLAGS & RGBA
368 _swrast_write_rgba_span(ctx, span);
369 #else
370 _swrast_write_index_span(ctx, span);
371 #endif
372 span->end = 0;
373 }
374
375 count = span->end;
376
377 #if FLAGS & RGBA
378 span->array->rgba[count][RCOMP] = red;
379 span->array->rgba[count][GCOMP] = green;
380 span->array->rgba[count][BCOMP] = blue;
381 span->array->rgba[count][ACOMP] = alpha;
382 #endif
383 #if FLAGS & INDEX
384 span->array->index[count] = colorIndex;
385 #endif
386 #if FLAGS & ATTRIBS
387 ATTRIB_LOOP_BEGIN
388 COPY_4V(span->array->attribs[attr][count], attribs[attr]);
389 ATTRIB_LOOP_END
390 #endif
391
392 span->array->x[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][0];
393 span->array->y[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][1];
394 span->array->z[count] = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
395
396 span->end = count + 1;
397 }}
398
399 #endif /* LARGE || ATTENUATE || SMOOTH */
400
401 ASSERT(span->end <= MAX_WIDTH);
402 }
403
404
405 #undef FLAGS
406 #undef NAME