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