don't divide texcoords by q if using a fragment program
[mesa.git] / src / mesa / swrast / s_pointtemp.h
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.3
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 */
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 texcoord[MAX_TEXTURE_COORD_UNITS][4];
92 GLuint u;
93 #endif
94 SWcontext *swrast = SWRAST_CONTEXT(ctx);
95 struct sw_span *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->fog = vert->fog;
111 span->fogStep = 0.0;
112 #if FLAGS & RGBA
113 span->arrayMask |= SPAN_RGBA;
114 #endif
115 #if FLAGS & SPECULAR
116 span->arrayMask |= SPAN_SPEC;
117 #endif
118 #if FLAGS & INDEX
119 span->arrayMask |= SPAN_INDEX;
120 #endif
121 #if FLAGS & TEXTURE
122 span->arrayMask |= SPAN_TEXTURE;
123 if (ctx->FragmentProgram._Enabled) {
124 /* Don't divide texture s,t,r by q (use TXP to do that) */
125 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
126 if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
127 COPY_4V(texcoord[u], vert->texcoord[u]);
128 }
129 }
130 }
131 else {
132 /* Divide texture s,t,r by q here */
133 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
134 if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
135 const GLfloat q = vert->texcoord[u][3];
136 const GLfloat invQ = (q == 0.0F || q == 1.0F) ? 1.0F : (1.0F / q);
137 texcoord[u][0] = vert->texcoord[u][0] * invQ;
138 texcoord[u][1] = vert->texcoord[u][1] * invQ;
139 texcoord[u][2] = vert->texcoord[u][2] * invQ;
140 texcoord[u][3] = q;
141 }
142 }
143 }
144 /* need these for fragment programs */
145 span->w = 1.0F;
146 span->dwdx = 0.0F;
147 span->dwdy = 0.0F;
148 #endif
149 #if FLAGS & SMOOTH
150 span->arrayMask |= SPAN_COVERAGE;
151 #endif
152 #if FLAGS & SPRITE
153 span->arrayMask |= SPAN_TEXTURE;
154 #endif
155
156 #if FLAGS & ATTENUATE
157 if (vert->pointSize >= ctx->Point.Threshold) {
158 size = MIN2(vert->pointSize, ctx->Point.MaxSize);
159 #if (FLAGS & RGBA) && (FLAGS & SMOOTH)
160 alphaAtten = 1.0F;
161 #endif
162 }
163 else {
164 #if (FLAGS & RGBA) && (FLAGS & SMOOTH)
165 GLfloat dsize = vert->pointSize / ctx->Point.Threshold;
166 alphaAtten = dsize * dsize;
167 #endif
168 size = MAX2(ctx->Point.Threshold, ctx->Point.MinSize);
169 }
170 #elif FLAGS & (LARGE | SMOOTH | SPRITE)
171 size = ctx->Point._Size;
172 #endif
173
174 #if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
175 /*
176 * Multi-pixel points
177 */
178 {{
179 GLint x, y;
180 const GLfloat radius = 0.5F * size;
181 const GLint z = (GLint) (vert->win[2] + 0.5F);
182 GLuint count;
183 #if FLAGS & SMOOTH
184 const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
185 const GLfloat rmax = radius + 0.7071F;
186 const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
187 const GLfloat rmax2 = rmax * rmax;
188 const GLfloat cscale = 1.0F / (rmax2 - rmin2);
189 const GLint xmin = (GLint) (vert->win[0] - radius);
190 const GLint xmax = (GLint) (vert->win[0] + radius);
191 const GLint ymin = (GLint) (vert->win[1] - radius);
192 const GLint ymax = (GLint) (vert->win[1] + radius);
193 #else
194 /* non-smooth */
195 GLint xmin, xmax, ymin, ymax;
196 GLint iSize = (GLint) (size + 0.5F);
197 GLint iRadius;
198 iSize = MAX2(1, iSize);
199 iRadius = iSize / 2;
200 if (iSize & 1) {
201 /* odd size */
202 xmin = (GLint) (vert->win[0] - iRadius);
203 xmax = (GLint) (vert->win[0] + iRadius);
204 ymin = (GLint) (vert->win[1] - iRadius);
205 ymax = (GLint) (vert->win[1] + iRadius);
206 }
207 else {
208 /* even size */
209 xmin = (GLint) vert->win[0] - iRadius + 1;
210 xmax = xmin + iSize - 1;
211 ymin = (GLint) vert->win[1] - iRadius + 1;
212 ymax = ymin + iSize - 1;
213 }
214 #endif /*SMOOTH*/
215
216 /* check if we need to flush */
217 if (span->end + (xmax-xmin+1) * (ymax-ymin+1) >= MAX_WIDTH ||
218 (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT))) {
219 #if FLAGS & (TEXTURE | SPRITE)
220 if (ctx->Texture._EnabledUnits)
221 _swrast_write_texture_span(ctx, span);
222 else
223 _swrast_write_rgba_span(ctx, span);
224 #elif FLAGS & RGBA
225 _swrast_write_rgba_span(ctx, span);
226 #else
227 _swrast_write_index_span(ctx, span);
228 #endif
229 span->end = 0;
230 }
231
232 /*
233 * OK, generate fragments
234 */
235 count = span->end;
236 (void) radius;
237 for (y = ymin; y <= ymax; y++) {
238 /* check if we need to flush */
239 if (count + (xmax-xmin+1) >= MAX_WIDTH) {
240 span->end = count;
241 #if FLAGS & (TEXTURE | SPRITE)
242 if (ctx->Texture._EnabledUnits)
243 _swrast_write_texture_span(ctx, span);
244 else
245 _swrast_write_rgba_span(ctx, span);
246 #elif FLAGS & RGBA
247 _swrast_write_rgba_span(ctx, span);
248 #else
249 _swrast_write_index_span(ctx, span);
250 #endif
251 count = span->end = 0;
252 }
253 for (x = xmin; x <= xmax; x++) {
254 #if FLAGS & (SPRITE | TEXTURE)
255 GLuint u;
256 #endif
257
258 #if FLAGS & RGBA
259 span->array->rgba[count][RCOMP] = red;
260 span->array->rgba[count][GCOMP] = green;
261 span->array->rgba[count][BCOMP] = blue;
262 span->array->rgba[count][ACOMP] = alpha;
263 #endif
264 #if FLAGS & SPECULAR
265 span->array->spec[count][RCOMP] = specRed;
266 span->array->spec[count][GCOMP] = specGreen;
267 span->array->spec[count][BCOMP] = specBlue;
268 #endif
269 #if FLAGS & INDEX
270 span->array->index[count] = colorIndex;
271 #endif
272 #if FLAGS & TEXTURE
273 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
274 if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
275 COPY_4V(span->array->texcoords[u][count], texcoord[u]);
276 }
277 }
278 #endif
279
280 #if FLAGS & SMOOTH
281 /* compute coverage */
282 {
283 const GLfloat dx = x - vert->win[0] + 0.5F;
284 const GLfloat dy = y - vert->win[1] + 0.5F;
285 const GLfloat dist2 = dx * dx + dy * dy;
286 if (dist2 < rmax2) {
287 if (dist2 >= rmin2) {
288 /* compute partial coverage */
289 span->array->coverage[count] = 1.0F - (dist2 - rmin2) * cscale;
290 #if FLAGS & INDEX
291 /* coverage in [0,15] */
292 span->array->coverage[count] *= 15.0;
293 #endif
294 }
295 else {
296 /* full coverage */
297 span->array->coverage[count] = 1.0F;
298 }
299
300 span->array->x[count] = x;
301 span->array->y[count] = y;
302 span->array->z[count] = z;
303
304 #if (FLAGS & ATTENUATE) && (FLAGS & RGBA)
305 span->array->rgba[count][ACOMP] = (GLchan) (alpha * alphaAtten);
306 #elif FLAGS & RGBA
307 span->array->rgba[count][ACOMP] = alpha;
308 #endif /*ATTENUATE*/
309 count++;
310 } /*if*/
311 }
312
313 #else /*SMOOTH*/
314
315 /* not smooth (square points) */
316 span->array->x[count] = x;
317 span->array->y[count] = y;
318 span->array->z[count] = z;
319
320 #if FLAGS & SPRITE
321 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
322 if (ctx->Texture.Unit[u]._ReallyEnabled) {
323 if (ctx->Point.CoordReplace[u]) {
324 GLfloat s = 0.5F + (x + 0.5F - vert->win[0]) / size;
325 GLfloat t;
326 if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT)
327 t = 0.5F + (y + 0.5F - vert->win[1]) / size;
328 else /* GL_UPPER_LEFT */
329 t = 0.5F - (y + 0.5F - vert->win[1]) / size;
330 span->array->texcoords[u][count][0] = s;
331 span->array->texcoords[u][count][1] = t;
332 span->array->texcoords[u][count][3] = 1.0F;
333 if (ctx->Point.SpriteRMode == GL_ZERO)
334 span->array->texcoords[u][count][2] = 0.0F;
335 else if (ctx->Point.SpriteRMode == GL_S)
336 span->array->texcoords[u][count][2] = vert->texcoord[u][0];
337 else /* GL_R */
338 span->array->texcoords[u][count][2] = vert->texcoord[u][2];
339 }
340 else {
341 COPY_4V(span->array->texcoords[u][count], vert->texcoord[u]);
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 & (TEXTURE | SPRITE)
368 if (ctx->Texture._EnabledUnits)
369 _swrast_write_texture_span(ctx, span);
370 else
371 _swrast_write_rgba_span(ctx, span);
372 #elif FLAGS & RGBA
373 _swrast_write_rgba_span(ctx, span);
374 #else
375 _swrast_write_index_span(ctx, span);
376 #endif
377 span->end = 0;
378 }
379
380 count = span->end;
381
382 #if FLAGS & RGBA
383 span->array->rgba[count][RCOMP] = red;
384 span->array->rgba[count][GCOMP] = green;
385 span->array->rgba[count][BCOMP] = blue;
386 span->array->rgba[count][ACOMP] = alpha;
387 #endif
388 #if FLAGS & SPECULAR
389 span->array->spec[count][RCOMP] = specRed;
390 span->array->spec[count][GCOMP] = specGreen;
391 span->array->spec[count][BCOMP] = specBlue;
392 #endif
393 #if FLAGS & INDEX
394 span->array->index[count] = colorIndex;
395 #endif
396 #if FLAGS & TEXTURE
397 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
398 if (ctx->Texture.Unit[u]._ReallyEnabled) {
399 COPY_4V(span->array->texcoords[u][count], texcoord[u]);
400 }
401 }
402 #endif
403
404 span->array->x[count] = (GLint) vert->win[0];
405 span->array->y[count] = (GLint) vert->win[1];
406 span->array->z[count] = (GLint) (vert->win[2] + 0.5F);
407 span->end = count + 1;
408 }}
409
410 #endif /* LARGE || ATTENUATE || SMOOTH */
411
412 ASSERT(span->end <= MAX_WIDTH);
413 }
414
415
416 #undef FLAGS
417 #undef NAME