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