3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Point rendering template code.
30 * Set FLAGS = bitwise-OR of the following tokens:
32 * RGBA = do rgba instead of color index
33 * SMOOTH = do antialiasing
34 * TEXTURE = do texture coords
35 * SPECULAR = do separate specular color
36 * LARGE = do points with diameter > 1 pixel
37 * ATTENUATE = compute point size attenuation
38 * SPRITE = GL_NV_point_sprite
40 * Notes: LARGE and ATTENUATE are exclusive of each other.
41 * TEXTURE requires RGBA
42 * SPECULAR requires TEXTURE
47 * NOTES on antialiased point rasterization:
49 * Let d = distance of fragment center from vertex.
51 * fragment has 100% coverage
52 * else if d > rmax2 then
53 * fragment has 0% coverage
55 * fragment has % coverage = (d - rmin2) / (rmax2 - rmin2)
61 NAME ( GLcontext
*ctx
, const SWvertex
*vert
)
63 #if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
70 const GLchan red
= vert
->color
[0];
71 const GLchan green
= vert
->color
[1];
72 const GLchan blue
= vert
->color
[2];
73 const GLchan alpha
= vert
->color
[3];
76 const GLchan specRed
= vert
->specular
[0];
77 const GLchan specGreen
= vert
->specular
[1];
78 const GLchan specBlue
= vert
->specular
[2];
81 const GLuint colorIndex
= vert
->index
;
84 GLfloat texcoord
[MAX_TEXTURE_COORD_UNITS
][4];
87 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
88 struct sw_span
*span
= &(swrast
->PointSpan
);
90 /* Cull primitives with malformed coordinates.
93 float tmp
= vert
->win
[0] + vert
->win
[1];
94 if (IS_INF_OR_NAN(tmp
))
101 span
->interpMask
= SPAN_FOG
;
102 span
->arrayMask
= SPAN_XY
| SPAN_Z
;
103 span
->fog
= vert
->fog
;
106 span
->arrayMask
|= SPAN_RGBA
;
109 span
->arrayMask
|= SPAN_SPEC
;
112 span
->arrayMask
|= SPAN_INDEX
;
115 span
->arrayMask
|= SPAN_TEXTURE
;
116 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
117 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
118 const GLfloat q
= vert
->texcoord
[u
][3];
119 const GLfloat invQ
= (q
== 0.0F
|| q
== 1.0F
) ? 1.0F
: (1.0F
/ q
);
120 texcoord
[u
][0] = vert
->texcoord
[u
][0] * invQ
;
121 texcoord
[u
][1] = vert
->texcoord
[u
][1] * invQ
;
122 texcoord
[u
][2] = vert
->texcoord
[u
][2] * invQ
;
128 span
->arrayMask
|= SPAN_COVERAGE
;
131 span
->arrayMask
|= SPAN_TEXTURE
;
134 #if FLAGS & ATTENUATE
135 if (vert
->pointSize
>= ctx
->Point
.Threshold
) {
136 size
= MIN2(vert
->pointSize
, ctx
->Point
.MaxSize
);
140 GLfloat dsize
= vert
->pointSize
/ ctx
->Point
.Threshold
;
141 size
= MAX2(ctx
->Point
.Threshold
, ctx
->Point
.MinSize
);
142 alphaAtten
= dsize
* dsize
;
144 #elif FLAGS & (LARGE | SMOOTH | SPRITE)
145 size
= ctx
->Point
._Size
;
148 #if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
154 const GLfloat radius
= 0.5F
* size
;
155 const GLint z
= (GLint
) (vert
->win
[2] + 0.5F
);
158 const GLfloat rmin
= radius
- 0.7071F
; /* 0.7071 = sqrt(2)/2 */
159 const GLfloat rmax
= radius
+ 0.7071F
;
160 const GLfloat rmin2
= MAX2(0.0F
, rmin
* rmin
);
161 const GLfloat rmax2
= rmax
* rmax
;
162 const GLfloat cscale
= 1.0F
/ (rmax2
- rmin2
);
163 const GLint xmin
= (GLint
) (vert
->win
[0] - radius
);
164 const GLint xmax
= (GLint
) (vert
->win
[0] + radius
);
165 const GLint ymin
= (GLint
) (vert
->win
[1] - radius
);
166 const GLint ymax
= (GLint
) (vert
->win
[1] + radius
);
169 GLint xmin
, xmax
, ymin
, ymax
;
170 GLint iSize
= (GLint
) (size
+ 0.5F
);
172 iSize
= MAX2(1, iSize
);
176 xmin
= (GLint
) (vert
->win
[0] - iRadius
);
177 xmax
= (GLint
) (vert
->win
[0] + iRadius
);
178 ymin
= (GLint
) (vert
->win
[1] - iRadius
);
179 ymax
= (GLint
) (vert
->win
[1] + iRadius
);
183 xmin
= (GLint
) vert
->win
[0] - iRadius
+ 1;
184 xmax
= xmin
+ iSize
- 1;
185 ymin
= (GLint
) vert
->win
[1] - iRadius
+ 1;
186 ymax
= ymin
+ iSize
- 1;
190 /* check if we need to flush */
191 if (span
->end
+ (xmax
-xmin
+1) * (ymax
-ymin
+1) >= MAX_WIDTH
||
192 (swrast
->_RasterMask
& (BLEND_BIT
| LOGIC_OP_BIT
| MASKING_BIT
))) {
193 #if FLAGS & (TEXTURE | SPRITE)
194 if (ctx
->Texture
._EnabledUnits
)
195 _swrast_write_texture_span(ctx
, span
);
197 _swrast_write_rgba_span(ctx
, span
);
199 _swrast_write_rgba_span(ctx
, span
);
201 _swrast_write_index_span(ctx
, span
);
207 * OK, generate fragments
211 for (y
= ymin
; y
<= ymax
; y
++) {
212 for (x
= xmin
; x
<= xmax
; x
++) {
213 #if FLAGS & (SPRITE | TEXTURE)
218 span
->array
->rgba
[count
][RCOMP
] = red
;
219 span
->array
->rgba
[count
][GCOMP
] = green
;
220 span
->array
->rgba
[count
][BCOMP
] = blue
;
221 span
->array
->rgba
[count
][ACOMP
] = alpha
;
224 span
->array
->spec
[count
][RCOMP
] = specRed
;
225 span
->array
->spec
[count
][GCOMP
] = specGreen
;
226 span
->array
->spec
[count
][BCOMP
] = specBlue
;
229 span
->array
->index
[count
] = colorIndex
;
232 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
233 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
234 COPY_4V(span
->array
->texcoords
[u
][count
], texcoord
[u
]);
240 /* compute coverage */
242 const GLfloat dx
= x
- vert
->win
[0] + 0.5F
;
243 const GLfloat dy
= y
- vert
->win
[1] + 0.5F
;
244 const GLfloat dist2
= dx
* dx
+ dy
* dy
;
246 if (dist2
>= rmin2
) {
247 /* compute partial coverage */
248 span
->array
->coverage
[count
] = 1.0F
- (dist2
- rmin2
) * cscale
;
250 /* coverage in [0,15] */
251 span
->array
->coverage
[count
] *= 15.0;
256 span
->array
->coverage
[count
] = 1.0F
;
259 span
->array
->x
[count
] = x
;
260 span
->array
->y
[count
] = y
;
261 span
->array
->z
[count
] = z
;
263 #if (FLAGS & ATTENUATE) && (FLAGS & RGBA)
264 span
->array
->rgba
[count
][ACOMP
] = (GLchan
) (alpha
* alphaAtten
);
266 span
->array
->rgba
[count
][ACOMP
] = alpha
;
274 /* not smooth (square points) */
275 span
->array
->x
[count
] = x
;
276 span
->array
->y
[count
] = y
;
277 span
->array
->z
[count
] = z
;
280 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
281 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
282 if (ctx
->Point
.CoordReplace
[u
]) {
283 GLfloat s
= 0.5F
+ (x
+ 0.5F
- vert
->win
[0]) / size
;
284 GLfloat t
= 0.5F
- (y
+ 0.5F
- vert
->win
[1]) / size
;
285 span
->array
->texcoords
[u
][count
][0] = s
;
286 span
->array
->texcoords
[u
][count
][1] = t
;
287 span
->array
->texcoords
[u
][count
][3] = 1.0F
;
288 if (ctx
->Point
.SpriteRMode
== GL_ZERO
)
289 span
->array
->texcoords
[u
][count
][2] = 0.0F
;
290 else if (ctx
->Point
.SpriteRMode
== GL_S
)
291 span
->array
->texcoords
[u
][count
][2] = vert
->texcoord
[u
][0];
293 span
->array
->texcoords
[u
][count
][2] = vert
->texcoord
[u
][2];
296 COPY_4V(span
->array
->texcoords
[u
][count
], vert
->texcoord
[u
]);
302 count
++; /* square point */
311 #else /* LARGE | ATTENUATE | SMOOTH | SPRITE */
314 * Single-pixel points
319 /* check if we need to flush */
320 if (span
->end
>= MAX_WIDTH
||
321 (swrast
->_RasterMask
& (BLEND_BIT
| LOGIC_OP_BIT
| MASKING_BIT
))) {
322 #if FLAGS & (TEXTURE | SPRITE)
323 if (ctx
->Texture
._EnabledUnits
)
324 _swrast_write_texture_span(ctx
, span
);
326 _swrast_write_rgba_span(ctx
, span
);
328 _swrast_write_rgba_span(ctx
, span
);
330 _swrast_write_index_span(ctx
, span
);
338 span
->array
->rgba
[count
][RCOMP
] = red
;
339 span
->array
->rgba
[count
][GCOMP
] = green
;
340 span
->array
->rgba
[count
][BCOMP
] = blue
;
341 span
->array
->rgba
[count
][ACOMP
] = alpha
;
344 span
->array
->spec
[count
][RCOMP
] = specRed
;
345 span
->array
->spec
[count
][GCOMP
] = specGreen
;
346 span
->array
->spec
[count
][BCOMP
] = specBlue
;
349 span
->array
->index
[count
] = colorIndex
;
352 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
353 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
354 COPY_4V(span
->array
->texcoords
[u
][count
], texcoord
[u
]);
359 span
->array
->x
[count
] = (GLint
) vert
->win
[0];
360 span
->array
->y
[count
] = (GLint
) vert
->win
[1];
361 span
->array
->z
[count
] = (GLint
) (vert
->win
[2] + 0.5F
);
362 span
->end
= count
+ 1;
365 #endif /* LARGE || ATTENUATE || SMOOTH */
367 ASSERT(span
->end
<= MAX_WIDTH
);