fix ugly bug triggered by macro expansion
[mesa.git] / src / mesa / swrast / s_pointtemp.h
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.0
4 *
5 * Copyright (C) 1999-2004 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 * TEXTURE = do texture coords
43 * SPECULAR = do separate specular color
44 * LARGE = do points with diameter > 1 pixel
45 * ATTENUATE = compute point size attenuation
46 * SPRITE = GL_ARB_point_sprite / GL_NV_point_sprite
47 *
48 * Notes: LARGE and ATTENUATE are exclusive of each other.
49 * TEXTURE requires RGBA
50 * SPECULAR requires TEXTURE
51 */
52
53
54 /*
55 * NOTES on antialiased point rasterization:
56 *
57 * Let d = distance of fragment center from vertex.
58 * if d < rmin2 then
59 * fragment has 100% coverage
60 * else if d > rmax2 then
61 * fragment has 0% coverage
62 * else
63 * fragment has % coverage = (d - rmin2) / (rmax2 - rmin2)
64 */
65
66
67
68 static void
69 NAME ( GLcontext *ctx, const SWvertex *vert )
70 {
71 #if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
72 GLfloat size;
73 #endif
74 #if FLAGS & RGBA
75 #if (FLAGS & ATTENUATE) && (FLAGS & SMOOTH)
76 GLfloat alphaAtten;
77 #endif
78 const GLchan red = vert->color[0];
79 const GLchan green = vert->color[1];
80 const GLchan blue = vert->color[2];
81 const GLchan alpha = vert->color[3];
82 #endif
83 #if FLAGS & SPECULAR
84 const GLchan specRed = vert->specular[0];
85 const GLchan specGreen = vert->specular[1];
86 const GLchan specBlue = vert->specular[2];
87 #endif
88 #if FLAGS & INDEX
89 const GLuint colorIndex = vert->index;
90 #endif
91 #if FLAGS & TEXTURE
92 GLfloat texcoord[MAX_TEXTURE_COORD_UNITS][4];
93 GLuint u;
94 #endif
95 SWcontext *swrast = SWRAST_CONTEXT(ctx);
96 struct sw_span *span = &(swrast->PointSpan);
97
98 /* Cull primitives with malformed coordinates.
99 */
100 {
101 float tmp = vert->win[0] + vert->win[1];
102 if (IS_INF_OR_NAN(tmp))
103 return;
104 }
105
106 /*
107 * Span init
108 */
109 span->interpMask = SPAN_FOG;
110 span->arrayMask = SPAN_XY | SPAN_Z;
111 span->fog = vert->fog;
112 span->fogStep = 0.0;
113 #if FLAGS & RGBA
114 span->arrayMask |= SPAN_RGBA;
115 #endif
116 #if FLAGS & SPECULAR
117 span->arrayMask |= SPAN_SPEC;
118 #endif
119 #if FLAGS & INDEX
120 span->arrayMask |= SPAN_INDEX;
121 #endif
122 #if FLAGS & TEXTURE
123 span->arrayMask |= SPAN_TEXTURE;
124 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
125 if (ctx->Texture.Unit[u]._ReallyEnabled) {
126 const GLfloat q = vert->texcoord[u][3];
127 const GLfloat invQ = (q == 0.0F || q == 1.0F) ? 1.0F : (1.0F / q);
128 texcoord[u][0] = vert->texcoord[u][0] * invQ;
129 texcoord[u][1] = vert->texcoord[u][1] * invQ;
130 texcoord[u][2] = vert->texcoord[u][2] * invQ;
131 texcoord[u][3] = q;
132 }
133 }
134 #endif
135 #if FLAGS & SMOOTH
136 span->arrayMask |= SPAN_COVERAGE;
137 #endif
138 #if FLAGS & SPRITE
139 span->arrayMask |= SPAN_TEXTURE;
140 #endif
141
142 #if FLAGS & ATTENUATE
143 if (vert->pointSize >= ctx->Point.Threshold) {
144 size = MIN2(vert->pointSize, ctx->Point.MaxSize);
145 #if (FLAGS & RGBA) && (FLAGS & SMOOTH)
146 alphaAtten = 1.0F;
147 #endif
148 }
149 else {
150 #if (FLAGS & RGBA) && (FLAGS & SMOOTH)
151 GLfloat dsize = vert->pointSize / ctx->Point.Threshold;
152 alphaAtten = dsize * dsize;
153 #endif
154 size = MAX2(ctx->Point.Threshold, ctx->Point.MinSize);
155 }
156 #elif FLAGS & (LARGE | SMOOTH | SPRITE)
157 size = ctx->Point._Size;
158 #endif
159
160 #if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
161 /*
162 * Multi-pixel points
163 */
164 {{
165 GLint x, y;
166 const GLfloat radius = 0.5F * size;
167 const GLint z = (GLint) (vert->win[2] + 0.5F);
168 GLuint count;
169 #if FLAGS & SMOOTH
170 const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
171 const GLfloat rmax = radius + 0.7071F;
172 const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
173 const GLfloat rmax2 = rmax * rmax;
174 const GLfloat cscale = 1.0F / (rmax2 - rmin2);
175 const GLint xmin = (GLint) (vert->win[0] - radius);
176 const GLint xmax = (GLint) (vert->win[0] + radius);
177 const GLint ymin = (GLint) (vert->win[1] - radius);
178 const GLint ymax = (GLint) (vert->win[1] + radius);
179 #else
180 /* non-smooth */
181 GLint xmin, xmax, ymin, ymax;
182 GLint iSize = (GLint) (size + 0.5F);
183 GLint iRadius;
184 iSize = MAX2(1, iSize);
185 iRadius = iSize / 2;
186 if (iSize & 1) {
187 /* odd size */
188 xmin = (GLint) (vert->win[0] - iRadius);
189 xmax = (GLint) (vert->win[0] + iRadius);
190 ymin = (GLint) (vert->win[1] - iRadius);
191 ymax = (GLint) (vert->win[1] + iRadius);
192 }
193 else {
194 /* even size */
195 xmin = (GLint) vert->win[0] - iRadius + 1;
196 xmax = xmin + iSize - 1;
197 ymin = (GLint) vert->win[1] - iRadius + 1;
198 ymax = ymin + iSize - 1;
199 }
200 #endif /*SMOOTH*/
201
202 /* check if we need to flush */
203 if (span->end + (xmax-xmin+1) * (ymax-ymin+1) >= MAX_WIDTH ||
204 (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT))) {
205 #if FLAGS & (TEXTURE | SPRITE)
206 if (ctx->Texture._EnabledUnits)
207 _swrast_write_texture_span(ctx, span);
208 else
209 _swrast_write_rgba_span(ctx, span);
210 #elif FLAGS & RGBA
211 _swrast_write_rgba_span(ctx, span);
212 #else
213 _swrast_write_index_span(ctx, span);
214 #endif
215 span->end = 0;
216 }
217
218 /*
219 * OK, generate fragments
220 */
221 count = span->end;
222 (void) radius;
223 for (y = ymin; y <= ymax; y++) {
224 for (x = xmin; x <= xmax; x++) {
225 #if FLAGS & (SPRITE | TEXTURE)
226 GLuint u;
227 #endif
228
229 #if FLAGS & RGBA
230 span->array->rgba[count][RCOMP] = red;
231 span->array->rgba[count][GCOMP] = green;
232 span->array->rgba[count][BCOMP] = blue;
233 span->array->rgba[count][ACOMP] = alpha;
234 #endif
235 #if FLAGS & SPECULAR
236 span->array->spec[count][RCOMP] = specRed;
237 span->array->spec[count][GCOMP] = specGreen;
238 span->array->spec[count][BCOMP] = specBlue;
239 #endif
240 #if FLAGS & INDEX
241 span->array->index[count] = colorIndex;
242 #endif
243 #if FLAGS & TEXTURE
244 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
245 if (ctx->Texture.Unit[u]._ReallyEnabled) {
246 COPY_4V(span->array->texcoords[u][count], texcoord[u]);
247 }
248 }
249 #endif
250
251 #if FLAGS & SMOOTH
252 /* compute coverage */
253 {
254 const GLfloat dx = x - vert->win[0] + 0.5F;
255 const GLfloat dy = y - vert->win[1] + 0.5F;
256 const GLfloat dist2 = dx * dx + dy * dy;
257 if (dist2 < rmax2) {
258 if (dist2 >= rmin2) {
259 /* compute partial coverage */
260 span->array->coverage[count] = 1.0F - (dist2 - rmin2) * cscale;
261 #if FLAGS & INDEX
262 /* coverage in [0,15] */
263 span->array->coverage[count] *= 15.0;
264 #endif
265 }
266 else {
267 /* full coverage */
268 span->array->coverage[count] = 1.0F;
269 }
270
271 span->array->x[count] = x;
272 span->array->y[count] = y;
273 span->array->z[count] = z;
274
275 #if (FLAGS & ATTENUATE) && (FLAGS & RGBA)
276 span->array->rgba[count][ACOMP] = (GLchan) (alpha * alphaAtten);
277 #elif FLAGS & RGBA
278 span->array->rgba[count][ACOMP] = alpha;
279 #endif /*ATTENUATE*/
280 count++;
281 } /*if*/
282 }
283
284 #else /*SMOOTH*/
285
286 /* not smooth (square points) */
287 span->array->x[count] = x;
288 span->array->y[count] = y;
289 span->array->z[count] = z;
290
291 #if FLAGS & SPRITE
292 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
293 if (ctx->Texture.Unit[u]._ReallyEnabled) {
294 if (ctx->Point.CoordReplace[u]) {
295 GLfloat s = 0.5F + (x + 0.5F - vert->win[0]) / size;
296 GLfloat t = 0.5F - (y + 0.5F - vert->win[1]) / size;
297 span->array->texcoords[u][count][0] = s;
298 span->array->texcoords[u][count][1] = t;
299 span->array->texcoords[u][count][3] = 1.0F;
300 if (ctx->Point.SpriteRMode == GL_ZERO)
301 span->array->texcoords[u][count][2] = 0.0F;
302 else if (ctx->Point.SpriteRMode == GL_S)
303 span->array->texcoords[u][count][2] = vert->texcoord[u][0];
304 else /* GL_R */
305 span->array->texcoords[u][count][2] = vert->texcoord[u][2];
306 }
307 else {
308 COPY_4V(span->array->texcoords[u][count], vert->texcoord[u]);
309 }
310 }
311 }
312 #endif /*SPRITE*/
313
314 count++; /* square point */
315
316 #endif /*SMOOTH*/
317
318 } /*for x*/
319 } /*for y*/
320 span->end = count;
321 }}
322
323 #else /* LARGE | ATTENUATE | SMOOTH | SPRITE */
324
325 /*
326 * Single-pixel points
327 */
328 {{
329 GLuint count;
330
331 /* check if we need to flush */
332 if (span->end >= MAX_WIDTH ||
333 (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT))) {
334 #if FLAGS & (TEXTURE | SPRITE)
335 if (ctx->Texture._EnabledUnits)
336 _swrast_write_texture_span(ctx, span);
337 else
338 _swrast_write_rgba_span(ctx, span);
339 #elif FLAGS & RGBA
340 _swrast_write_rgba_span(ctx, span);
341 #else
342 _swrast_write_index_span(ctx, span);
343 #endif
344 span->end = 0;
345 }
346
347 count = span->end;
348
349 #if FLAGS & RGBA
350 span->array->rgba[count][RCOMP] = red;
351 span->array->rgba[count][GCOMP] = green;
352 span->array->rgba[count][BCOMP] = blue;
353 span->array->rgba[count][ACOMP] = alpha;
354 #endif
355 #if FLAGS & SPECULAR
356 span->array->spec[count][RCOMP] = specRed;
357 span->array->spec[count][GCOMP] = specGreen;
358 span->array->spec[count][BCOMP] = specBlue;
359 #endif
360 #if FLAGS & INDEX
361 span->array->index[count] = colorIndex;
362 #endif
363 #if FLAGS & TEXTURE
364 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
365 if (ctx->Texture.Unit[u]._ReallyEnabled) {
366 COPY_4V(span->array->texcoords[u][count], texcoord[u]);
367 }
368 }
369 #endif
370
371 span->array->x[count] = (GLint) vert->win[0];
372 span->array->y[count] = (GLint) vert->win[1];
373 span->array->z[count] = (GLint) (vert->win[2] + 0.5F);
374 span->end = count + 1;
375 }}
376
377 #endif /* LARGE || ATTENUATE || SMOOTH */
378
379 ASSERT(span->end <= MAX_WIDTH);
380 }
381
382
383 #undef FLAGS
384 #undef NAME