2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 * Regarding GL_NV_point_sprite:
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.
36 * Point rendering template code.
38 * Set FLAGS = bitwise-OR of the following tokens:
40 * RGBA = do rgba instead of color index
41 * SMOOTH = do antialiasing
42 * ATTRIBS = general attributes (texcoords, etc)
43 * LARGE = do points with diameter > 1 pixel
44 * ATTENUATE = compute point size attenuation
45 * SPRITE = GL_ARB_point_sprite / GL_NV_point_sprite
47 * Notes: LARGE and ATTENUATE are exclusive of each other.
48 * ATTRIBS requires RGBA
53 * NOTES on antialiased point rasterization:
55 * Let d = distance of fragment center from vertex.
57 * fragment has 100% coverage
58 * else if d > rmax2 then
59 * fragment has 0% coverage
61 * fragment has % coverage = (d - rmin2) / (rmax2 - rmin2)
66 NAME ( GLcontext
*ctx
, const SWvertex
*vert
)
68 #if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
72 #if (FLAGS & ATTENUATE) && (FLAGS & SMOOTH)
75 const GLchan red
= vert
->color
[0];
76 const GLchan green
= vert
->color
[1];
77 const GLchan blue
= vert
->color
[2];
78 const GLchan alpha
= vert
->color
[3];
81 const GLuint colorIndex
= (GLuint
) vert
->attrib
[FRAG_ATTRIB_CI
][0]; /* XXX round? */
84 GLfloat attrib
[FRAG_ATTRIB_MAX
][4]; /* texture & varying */
86 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
87 SWspan
*span
= &(swrast
->PointSpan
);
90 printf("%s %g %g %g %g\n", __FUNCTION__,
91 vert->attrib[FRAG_ATTRIB_COL1][0],
92 vert->attrib[FRAG_ATTRIB_COL1][1],
93 vert->attrib[FRAG_ATTRIB_COL1][2],
94 vert->attrib[FRAG_ATTRIB_COL1][3]);
95 if ( vert->attrib[FRAG_ATTRIB_COL1][0] == 0.0 &&
96 vert->attrib[FRAG_ATTRIB_COL1][1] == 1.0 &&
97 vert->attrib[FRAG_ATTRIB_COL1][2] == 0.0)
101 /* Cull primitives with malformed coordinates.
104 float tmp
= vert
->attrib
[FRAG_ATTRIB_WPOS
][0] + vert
->attrib
[FRAG_ATTRIB_WPOS
][1];
105 if (IS_INF_OR_NAN(tmp
))
112 span
->interpMask
= 0;
113 span
->arrayMask
= SPAN_XY
| SPAN_Z
;
115 span
->arrayMask
|= SPAN_RGBA
;
118 span
->arrayMask
|= SPAN_INDEX
;
121 span
->arrayMask
|= SPAN_LAMBDA
;
123 /* we're filling in the attrib arrays: */
124 span
->arrayAttribs
= swrast
->_ActiveAttribMask
;
127 COPY_4V(attrib
[attr
], vert
->attrib
[attr
]);
130 /* need these for fragment programs */
131 span
->attrStart
[FRAG_ATTRIB_WPOS
][3] = 1.0F
;
132 span
->attrStepX
[FRAG_ATTRIB_WPOS
][3] = 0.0F
;
133 span
->attrStepY
[FRAG_ATTRIB_WPOS
][3] = 0.0F
;
135 assert((swrast
->_ActiveAttribMask
& FRAG_BIT_COL1
) == 0);
139 span
->arrayMask
|= SPAN_COVERAGE
;
142 span
->arrayMask
|= SPAN_LAMBDA
;
145 /* Compute point size if not known to be one */
146 #if FLAGS & ATTENUATE
147 /* first, clamp attenuated size to the user-specifed range */
148 size
= CLAMP(vert
->pointSize
, ctx
->Point
.MinSize
, ctx
->Point
.MaxSize
);
149 #if (FLAGS & RGBA) && (FLAGS & SMOOTH)
150 /* only if multisampling, compute the fade factor */
151 if (ctx
->Multisample
.Enabled
) {
152 if (vert
->pointSize
>= ctx
->Point
.Threshold
) {
156 GLfloat dsize
= vert
->pointSize
/ ctx
->Point
.Threshold
;
157 alphaAtten
= dsize
* dsize
;
164 #elif FLAGS & (LARGE | SMOOTH | SPRITE)
165 /* constant, non-attenuated size */
166 size
= ctx
->Point
._Size
; /* this is already clamped */
170 #if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
172 *** Multi-pixel points
175 /* do final clamping now */
176 if (ctx
->Point
.SmoothFlag
) {
177 size
= CLAMP(size
, ctx
->Const
.MinPointSizeAA
, ctx
->Const
.MaxPointSizeAA
);
180 size
= CLAMP(size
, ctx
->Const
.MinPointSize
, ctx
->Const
.MaxPointSize
);
185 const GLfloat radius
= 0.5F
* size
;
186 const GLuint z
= (GLuint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][2] + 0.5F
);
189 const GLfloat rmin
= radius
- 0.7071F
; /* 0.7071 = sqrt(2)/2 */
190 const GLfloat rmax
= radius
+ 0.7071F
;
191 const GLfloat rmin2
= MAX2(0.0F
, rmin
* rmin
);
192 const GLfloat rmax2
= rmax
* rmax
;
193 const GLfloat cscale
= 1.0F
/ (rmax2
- rmin2
);
194 const GLint xmin
= (GLint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][0] - radius
);
195 const GLint xmax
= (GLint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][0] + radius
);
196 const GLint ymin
= (GLint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][1] - radius
);
197 const GLint ymax
= (GLint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][1] + radius
);
200 GLint xmin
, xmax
, ymin
, ymax
;
201 GLint iSize
= (GLint
) (size
+ 0.5F
);
203 iSize
= MAX2(1, iSize
);
207 xmin
= (GLint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][0] - iRadius
);
208 xmax
= (GLint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][0] + iRadius
);
209 ymin
= (GLint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][1] - iRadius
);
210 ymax
= (GLint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][1] + iRadius
);
214 xmin
= (GLint
) vert
->attrib
[FRAG_ATTRIB_WPOS
][0] - iRadius
+ 1;
215 xmax
= xmin
+ iSize
- 1;
216 ymin
= (GLint
) vert
->attrib
[FRAG_ATTRIB_WPOS
][1] - iRadius
+ 1;
217 ymax
= ymin
+ iSize
- 1;
221 /* check if we need to flush */
222 if (span
->end
+ (xmax
-xmin
+1) * (ymax
-ymin
+1) >= MAX_WIDTH
||
223 (swrast
->_RasterMask
& (BLEND_BIT
| LOGIC_OP_BIT
| MASKING_BIT
))) {
226 _swrast_write_rgba_span(ctx
, span
);
228 _swrast_write_index_span(ctx
, span
);
235 * OK, generate fragments
239 for (y
= ymin
; y
<= ymax
; y
++) {
240 /* check if we need to flush */
241 if (count
+ (xmax
-xmin
+1) >= MAX_WIDTH
) {
244 _swrast_write_rgba_span(ctx
, span
);
246 _swrast_write_index_span(ctx
, span
);
248 count
= span
->end
= 0;
250 for (x
= xmin
; x
<= xmax
; x
++) {
256 span
->array
->rgba
[count
][RCOMP
] = red
;
257 span
->array
->rgba
[count
][GCOMP
] = green
;
258 span
->array
->rgba
[count
][BCOMP
] = blue
;
259 span
->array
->rgba
[count
][ACOMP
] = alpha
;
262 span
->array
->index
[count
] = colorIndex
;
266 COPY_4V(span
->array
->attribs
[attr
][count
], attrib
[attr
]);
268 if (attr < FRAG_ATTRIB_VAR0) {
269 const GLuint u = attr - FRAG_ATTRIB_TEX0;
270 span->array->lambda[u][count] = 0.0;
277 /* compute coverage */
279 const GLfloat dx
= x
- vert
->attrib
[FRAG_ATTRIB_WPOS
][0] + 0.5F
;
280 const GLfloat dy
= y
- vert
->attrib
[FRAG_ATTRIB_WPOS
][1] + 0.5F
;
281 const GLfloat dist2
= dx
* dx
+ dy
* dy
;
283 if (dist2
>= rmin2
) {
284 /* compute partial coverage */
285 span
->array
->coverage
[count
] = 1.0F
- (dist2
- rmin2
) * cscale
;
287 /* coverage in [0,15] */
288 span
->array
->coverage
[count
] *= 15.0;
293 span
->array
->coverage
[count
] = 1.0F
;
296 span
->array
->x
[count
] = x
;
297 span
->array
->y
[count
] = y
;
298 span
->array
->z
[count
] = z
;
300 #if (FLAGS & ATTENUATE) && (FLAGS & RGBA)
301 span
->array
->rgba
[count
][ACOMP
] = (GLchan
) (alpha
* alphaAtten
);
303 span
->array
->rgba
[count
][ACOMP
] = alpha
;
311 /* not smooth (square points) */
312 span
->array
->x
[count
] = x
;
313 span
->array
->y
[count
] = y
;
314 span
->array
->z
[count
] = z
;
317 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
318 GLuint attr
= FRAG_ATTRIB_TEX0
+ u
;
319 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
320 if (ctx
->Point
.CoordReplace
[u
]) {
321 GLfloat s
= 0.5F
+ (x
+ 0.5F
- vert
->attrib
[FRAG_ATTRIB_WPOS
][0]) / size
;
323 if (ctx
->Point
.SpriteOrigin
== GL_LOWER_LEFT
)
324 t
= 0.5F
+ (y
+ 0.5F
- vert
->attrib
[FRAG_ATTRIB_WPOS
][1]) / size
;
325 else /* GL_UPPER_LEFT */
326 t
= 0.5F
- (y
+ 0.5F
- vert
->attrib
[FRAG_ATTRIB_WPOS
][1]) / size
;
327 if (ctx
->Point
.SpriteRMode
== GL_ZERO
)
329 else if (ctx
->Point
.SpriteRMode
== GL_S
)
330 r
= vert
->attrib
[attr
][0];
332 r
= vert
->attrib
[attr
][2];
333 span
->array
->attribs
[attr
][count
][0] = s
;
334 span
->array
->attribs
[attr
][count
][1] = t
;
335 span
->array
->attribs
[attr
][count
][2] = r
;
336 span
->array
->attribs
[attr
][count
][3] = 1.0F
;
337 span
->array
->lambda
[u
][count
] = 0.0; /* XXX fix? */
340 COPY_4V(span
->array
->attribs
[attr
][count
],
347 count
++; /* square point */
356 #else /* LARGE | ATTENUATE | SMOOTH | SPRITE */
359 *** Single-pixel points
364 /* check if we need to flush */
365 if (span
->end
>= MAX_WIDTH
||
366 (swrast
->_RasterMask
& (BLEND_BIT
| LOGIC_OP_BIT
| MASKING_BIT
))) {
368 _swrast_write_rgba_span(ctx
, span
);
370 _swrast_write_index_span(ctx
, span
);
378 span
->array
->rgba
[count
][RCOMP
] = red
;
379 span
->array
->rgba
[count
][GCOMP
] = green
;
380 span
->array
->rgba
[count
][BCOMP
] = blue
;
381 span
->array
->rgba
[count
][ACOMP
] = alpha
;
384 span
->array
->index
[count
] = colorIndex
;
388 COPY_4V(span
->array
->attribs
[attr
][count
], attribs
[attr
]);
392 span
->array
->x
[count
] = (GLint
) vert
->attrib
[FRAG_ATTRIB_WPOS
][0];
393 span
->array
->y
[count
] = (GLint
) vert
->attrib
[FRAG_ATTRIB_WPOS
][1];
394 span
->array
->z
[count
] = (GLint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][2] + 0.5F
);
396 span
->end
= count
+ 1;
399 #endif /* LARGE || ATTENUATE || SMOOTH */
401 ASSERT(span
->end
<= MAX_WIDTH
);