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.
31 #include "s_context.h"
32 #include "s_feedback.h"
38 * Used to cull points with invalid coords
40 #define CULL_INVALID(V) \
42 float tmp = (V)->attrib[FRAG_ATTRIB_WPOS][0] \
43 + (V)->attrib[FRAG_ATTRIB_WPOS][1]; \
44 if (IS_INF_OR_NAN(tmp)) \
53 sprite_point(GLcontext
*ctx
, const SWvertex
*vert
)
55 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
58 GLuint tCoords
[MAX_TEXTURE_COORD_UNITS
];
59 GLuint numTcoords
= 0;
65 if (ctx
->DrawBuffer
->Visual
.depthBits
<= 16)
66 span
.z
= FloatToFixed(vert
->attrib
[FRAG_ATTRIB_WPOS
][2] + 0.5F
);
68 span
.z
= (GLuint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][2] + 0.5F
);
72 if (ctx
->Point
._Attenuated
|| ctx
->VertexProgram
.PointSizeEnabled
) {
73 /* use vertex's point size */
74 /* first, clamp attenuated size to the user-specifed range */
75 size
= CLAMP(vert
->pointSize
, ctx
->Point
.MinSize
, ctx
->Point
.MaxSize
);
78 /* use constant point size */
79 size
= ctx
->Point
._Size
; /* already clamped to user range */
81 /* clamp to non-AA implementation limits */
82 size
= CLAMP(size
, ctx
->Const
.MinPointSize
, ctx
->Const
.MaxPointSize
);
85 INIT_SPAN(span
, GL_POINT
);
86 span
.interpMask
= SPAN_Z
| SPAN_RGBA
;
88 span
.red
= ChanToFixed(vert
->color
[0]);
89 span
.green
= ChanToFixed(vert
->color
[1]);
90 span
.blue
= ChanToFixed(vert
->color
[2]);
91 span
.alpha
= ChanToFixed(vert
->color
[3]);
97 /* need these for fragment programs */
98 span
.attrStart
[FRAG_ATTRIB_WPOS
][3] = 1.0F
;
99 span
.attrStepX
[FRAG_ATTRIB_WPOS
][3] = 0.0F
;
100 span
.attrStepY
[FRAG_ATTRIB_WPOS
][3] = 0.0F
;
103 if (attr
>= FRAG_ATTRIB_TEX0
&& attr
< FRAG_ATTRIB_VAR0
) {
104 const GLuint u
= attr
- FRAG_ATTRIB_TEX0
;
106 if (ctx
->Point
.CoordReplace
[u
]) {
112 if (ctx
->Point
.SpriteOrigin
== GL_LOWER_LEFT
) {
121 tCoords
[numTcoords
++] = attr
;
123 if (ctx
->Point
.SpriteRMode
== GL_ZERO
)
125 else if (ctx
->Point
.SpriteRMode
== GL_S
)
126 r
= vert
->attrib
[attr
][0];
128 r
= vert
->attrib
[attr
][2];
130 span
.attrStart
[attr
][0] = s
;
131 span
.attrStart
[attr
][1] = 0.0; /* overwritten below */
132 span
.attrStart
[attr
][2] = r
;
133 span
.attrStart
[attr
][3] = 1.0;
135 span
.attrStepX
[attr
][0] = dsdx
;
136 span
.attrStepX
[attr
][1] = 0.0;
137 span
.attrStepX
[attr
][2] = 0.0;
138 span
.attrStepX
[attr
][3] = 0.0;
140 span
.attrStepY
[attr
][0] = 0.0;
141 span
.attrStepY
[attr
][1] = dtdy
;
142 span
.attrStepY
[attr
][2] = 0.0;
143 span
.attrStepY
[attr
][3] = 0.0;
148 /* use vertex's texcoord/attrib */
149 COPY_4V(span
.attrStart
[attr
], vert
->attrib
[attr
]);
150 ASSIGN_4V(span
.attrStepX
[attr
], 0, 0, 0, 0);
151 ASSIGN_4V(span
.attrStepY
[attr
], 0, 0, 0, 0);
154 /* compute pos, bounds and render */
156 const GLfloat x
= vert
->attrib
[FRAG_ATTRIB_WPOS
][0];
157 const GLfloat y
= vert
->attrib
[FRAG_ATTRIB_WPOS
][1];
158 GLint iSize
= (GLint
) (size
+ 0.5F
);
159 GLint xmin
, xmax
, ymin
, ymax
, iy
;
163 iSize
= MAX2(1, iSize
);
168 xmin
= (GLint
) (x
- iRadius
);
169 xmax
= (GLint
) (x
+ iRadius
);
170 ymin
= (GLint
) (y
- iRadius
);
171 ymax
= (GLint
) (y
+ iRadius
);
175 xmin
= (GLint
) x
- iRadius
+ 1;
176 xmax
= xmin
+ iSize
- 1;
177 ymin
= (GLint
) y
- iRadius
+ 1;
178 ymax
= ymin
+ iSize
- 1;
182 for (iy
= ymin
; iy
<= ymax
; iy
++) {
184 /* setup texcoord T for this row */
185 for (i
= 0; i
< numTcoords
; i
++) {
186 span
.attrStart
[tCoords
[i
]][1] = tcoord
;
189 /* these might get changed by span clipping */
192 span
.end
= xmax
- xmin
+ 1;
194 _swrast_write_rgba_span(ctx
, &span
);
203 * Draw smooth/antialiased point. RGB or CI mode.
206 smooth_point(GLcontext
*ctx
, const SWvertex
*vert
)
208 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
209 const GLboolean ciMode
= !ctx
->Visual
.rgbMode
;
211 GLfloat size
, alphaAtten
;
216 if (ctx
->DrawBuffer
->Visual
.depthBits
<= 16)
217 span
.z
= FloatToFixed(vert
->attrib
[FRAG_ATTRIB_WPOS
][2] + 0.5F
);
219 span
.z
= (GLuint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][2] + 0.5F
);
223 if (ctx
->Point
._Attenuated
|| ctx
->VertexProgram
.PointSizeEnabled
) {
224 /* use vertex's point size */
225 /* first, clamp attenuated size to the user-specifed range */
226 size
= CLAMP(vert
->pointSize
, ctx
->Point
.MinSize
, ctx
->Point
.MaxSize
);
229 /* use constant point size */
230 size
= ctx
->Point
._Size
; /* this is already clamped */
232 /* clamp to AA implementation limits */
233 size
= CLAMP(size
, ctx
->Const
.MinPointSizeAA
, ctx
->Const
.MaxPointSizeAA
);
235 /* alpha attenuation / fade factor */
236 if (ctx
->Multisample
.Enabled
) {
237 if (vert
->pointSize
>= ctx
->Point
.Threshold
) {
241 GLfloat dsize
= vert
->pointSize
/ ctx
->Point
.Threshold
;
242 alphaAtten
= dsize
* dsize
;
248 (void) alphaAtten
; /* not used */
251 INIT_SPAN(span
, GL_POINT
);
252 span
.interpMask
= SPAN_Z
| SPAN_RGBA
;
253 span
.arrayMask
= SPAN_COVERAGE
| SPAN_MASK
;
255 span
.red
= ChanToFixed(vert
->color
[0]);
256 span
.green
= ChanToFixed(vert
->color
[1]);
257 span
.blue
= ChanToFixed(vert
->color
[2]);
258 span
.alpha
= ChanToFixed(vert
->color
[3]);
264 /* need these for fragment programs */
265 span
.attrStart
[FRAG_ATTRIB_WPOS
][3] = 1.0F
;
266 span
.attrStepX
[FRAG_ATTRIB_WPOS
][3] = 0.0F
;
267 span
.attrStepY
[FRAG_ATTRIB_WPOS
][3] = 0.0F
;
270 COPY_4V(span
.attrStart
[attr
], vert
->attrib
[attr
]);
271 ASSIGN_4V(span
.attrStepX
[attr
], 0, 0, 0, 0);
272 ASSIGN_4V(span
.attrStepY
[attr
], 0, 0, 0, 0);
275 /* compute pos, bounds and render */
277 const GLfloat x
= vert
->attrib
[FRAG_ATTRIB_WPOS
][0];
278 const GLfloat y
= vert
->attrib
[FRAG_ATTRIB_WPOS
][1];
279 const GLfloat radius
= 0.5F
* size
;
280 const GLfloat rmin
= radius
- 0.7071F
; /* 0.7071 = sqrt(2)/2 */
281 const GLfloat rmax
= radius
+ 0.7071F
;
282 const GLfloat rmin2
= MAX2(0.0F
, rmin
* rmin
);
283 const GLfloat rmax2
= rmax
* rmax
;
284 const GLfloat cscale
= 1.0F
/ (rmax2
- rmin2
);
285 const GLint xmin
= (GLint
) (x
- radius
);
286 const GLint xmax
= (GLint
) (x
+ radius
);
287 const GLint ymin
= (GLint
) (y
- radius
);
288 const GLint ymax
= (GLint
) (y
+ radius
);
291 for (iy
= ymin
; iy
<= ymax
; iy
++) {
293 /* these might get changed by span clipping */
296 span
.end
= xmax
- xmin
+ 1;
298 /* compute coverage for each pixel in span */
299 for (ix
= xmin
; ix
<= xmax
; ix
++) {
300 const GLfloat dx
= ix
- x
+ 0.5F
;
301 const GLfloat dy
= iy
- y
+ 0.5F
;
302 const GLfloat dist2
= dx
* dx
+ dy
* dy
;
306 if (dist2
>= rmin2
) {
307 /* compute partial coverage */
308 coverage
= 1.0F
- (dist2
- rmin2
) * cscale
;
310 /* coverage in [0,15] */
318 span
.array
->mask
[ix
- xmin
] = 1;
321 /* zero coverage - fragment outside the radius */
323 span
.array
->mask
[ix
- xmin
] = 0;
325 span
.array
->coverage
[ix
- xmin
] = coverage
;
329 _swrast_write_rgba_span(ctx
, &span
);
337 * Draw large (size >= 1) non-AA point. RGB or CI mode.
340 large_point(GLcontext
*ctx
, const SWvertex
*vert
)
342 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
343 const GLboolean ciMode
= !ctx
->Visual
.rgbMode
;
350 if (ctx
->DrawBuffer
->Visual
.depthBits
<= 16)
351 span
.z
= FloatToFixed(vert
->attrib
[FRAG_ATTRIB_WPOS
][2] + 0.5F
);
353 span
.z
= (GLuint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][2] + 0.5F
);
357 if (ctx
->Point
._Attenuated
|| ctx
->VertexProgram
.PointSizeEnabled
) {
358 /* use vertex's point size */
359 /* first, clamp attenuated size to the user-specifed range */
360 size
= CLAMP(vert
->pointSize
, ctx
->Point
.MinSize
, ctx
->Point
.MaxSize
);
363 /* use constant point size */
364 size
= ctx
->Point
._Size
; /* already clamped to user range */
366 /* clamp to non-AA implementation limits */
367 size
= CLAMP(size
, ctx
->Const
.MinPointSize
, ctx
->Const
.MaxPointSize
);
370 INIT_SPAN(span
, GL_POINT
);
371 span
.arrayMask
= SPAN_XY
;
374 span
.interpMask
= SPAN_Z
| SPAN_INDEX
;
375 span
.index
= FloatToFixed(vert
->attrib
[FRAG_ATTRIB_CI
][0]);
379 span
.interpMask
= SPAN_Z
| SPAN_RGBA
;
380 span
.red
= ChanToFixed(vert
->color
[0]);
381 span
.green
= ChanToFixed(vert
->color
[1]);
382 span
.blue
= ChanToFixed(vert
->color
[2]);
383 span
.alpha
= ChanToFixed(vert
->color
[3]);
390 /* need these for fragment programs */
391 span
.attrStart
[FRAG_ATTRIB_WPOS
][3] = 1.0F
;
392 span
.attrStepX
[FRAG_ATTRIB_WPOS
][3] = 0.0F
;
393 span
.attrStepY
[FRAG_ATTRIB_WPOS
][3] = 0.0F
;
396 COPY_4V(span
.attrStart
[attr
], vert
->attrib
[attr
]);
397 ASSIGN_4V(span
.attrStepX
[attr
], 0, 0, 0, 0);
398 ASSIGN_4V(span
.attrStepY
[attr
], 0, 0, 0, 0);
401 /* compute pos, bounds and render */
403 const GLfloat x
= vert
->attrib
[FRAG_ATTRIB_WPOS
][0];
404 const GLfloat y
= vert
->attrib
[FRAG_ATTRIB_WPOS
][1];
405 GLint iSize
= (GLint
) (size
+ 0.5F
);
406 GLint xmin
, xmax
, ymin
, ymax
, ix
, iy
;
409 iSize
= MAX2(1, iSize
);
414 xmin
= (GLint
) (x
- iRadius
);
415 xmax
= (GLint
) (x
+ iRadius
);
416 ymin
= (GLint
) (y
- iRadius
);
417 ymax
= (GLint
) (y
+ iRadius
);
421 xmin
= (GLint
) x
- iRadius
+ 1;
422 xmax
= xmin
+ iSize
- 1;
423 ymin
= (GLint
) y
- iRadius
+ 1;
424 ymax
= ymin
+ iSize
- 1;
427 /* generate fragments */
429 for (iy
= ymin
; iy
<= ymax
; iy
++) {
430 for (ix
= xmin
; ix
<= xmax
; ix
++) {
431 span
.array
->x
[span
.end
] = ix
;
432 span
.array
->y
[span
.end
] = iy
;
436 assert(span
.end
<= MAX_WIDTH
);
437 _swrast_write_rgba_span(ctx
, &span
);
443 * Draw size=1, single-pixel point
446 pixel_point(GLcontext
*ctx
, const SWvertex
*vert
)
448 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
449 const GLboolean ciMode
= !ctx
->Visual
.rgbMode
;
451 * Note that unlike the other functions, we put single-pixel points
452 * into a special span array in order to render as many points as
453 * possible with a single _swrast_write_rgba_span() call.
455 SWspan
*span
= &(swrast
->PointSpan
);
461 span
->interpMask
= 0;
462 span
->arrayMask
= SPAN_XY
| SPAN_Z
;
464 span
->arrayMask
|= SPAN_INDEX
;
466 span
->arrayMask
|= SPAN_RGBA
;
467 /*span->arrayMask |= SPAN_LAMBDA;*/
468 span
->arrayAttribs
= swrast
->_ActiveAttribMask
; /* we'll produce these vals */
470 /* need these for fragment programs */
471 span
->attrStart
[FRAG_ATTRIB_WPOS
][3] = 1.0F
;
472 span
->attrStepX
[FRAG_ATTRIB_WPOS
][3] = 0.0F
;
473 span
->attrStepY
[FRAG_ATTRIB_WPOS
][3] = 0.0F
;
475 /* check if we need to flush */
476 if (span
->end
>= MAX_WIDTH
||
477 (swrast
->_RasterMask
& (BLEND_BIT
| LOGIC_OP_BIT
| MASKING_BIT
))) {
479 _swrast_write_index_span(ctx
, span
);
481 _swrast_write_rgba_span(ctx
, span
);
487 /* fragment attributes */
489 span
->array
->index
[count
] = (GLuint
) vert
->attrib
[FRAG_ATTRIB_CI
][0];
492 span
->array
->rgba
[count
][RCOMP
] = vert
->color
[0];
493 span
->array
->rgba
[count
][GCOMP
] = vert
->color
[1];
494 span
->array
->rgba
[count
][BCOMP
] = vert
->color
[2];
495 span
->array
->rgba
[count
][ACOMP
] = vert
->color
[3];
498 COPY_4V(span
->array
->attribs
[attr
][count
], vert
->attrib
[attr
]);
501 /* fragment position */
502 span
->array
->x
[count
] = (GLint
) vert
->attrib
[FRAG_ATTRIB_WPOS
][0];
503 span
->array
->y
[count
] = (GLint
) vert
->attrib
[FRAG_ATTRIB_WPOS
][1];
504 span
->array
->z
[count
] = (GLint
) (vert
->attrib
[FRAG_ATTRIB_WPOS
][2] + 0.5F
);
506 span
->end
= count
+ 1;
507 ASSERT(span
->end
<= MAX_WIDTH
);
512 * Add specular color to primary color, draw point, restore original
516 _swrast_add_spec_terms_point(GLcontext
*ctx
, const SWvertex
*v0
)
518 SWvertex
*ncv0
= (SWvertex
*) v0
; /* cast away const */
519 GLfloat rSum
, gSum
, bSum
;
523 COPY_CHAN4(cSave
, ncv0
->color
);
525 rSum
= CHAN_TO_FLOAT(ncv0
->color
[0]) + ncv0
->attrib
[FRAG_ATTRIB_COL1
][0];
526 gSum
= CHAN_TO_FLOAT(ncv0
->color
[1]) + ncv0
->attrib
[FRAG_ATTRIB_COL1
][1];
527 bSum
= CHAN_TO_FLOAT(ncv0
->color
[2]) + ncv0
->attrib
[FRAG_ATTRIB_COL1
][2];
528 UNCLAMPED_FLOAT_TO_CHAN(ncv0
->color
[0], rSum
);
529 UNCLAMPED_FLOAT_TO_CHAN(ncv0
->color
[1], gSum
);
530 UNCLAMPED_FLOAT_TO_CHAN(ncv0
->color
[2], bSum
);
532 SWRAST_CONTEXT(ctx
)->SpecPoint(ctx
, ncv0
);
534 COPY_CHAN4(ncv0
->color
, cSave
);
539 * Examine current state to determine which point drawing function to use.
542 _swrast_choose_point(GLcontext
*ctx
)
544 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
546 if (ctx
->RenderMode
== GL_RENDER
) {
547 if (ctx
->Point
.PointSprite
) {
548 swrast
->Point
= sprite_point
;
550 else if (ctx
->Point
.SmoothFlag
) {
551 swrast
->Point
= smooth_point
;
553 else if (ctx
->Point
._Size
> 1.0 ||
554 ctx
->Point
._Attenuated
||
555 ctx
->VertexProgram
.PointSizeEnabled
) {
556 swrast
->Point
= large_point
;
559 swrast
->Point
= pixel_point
;
562 else if (ctx
->RenderMode
== GL_FEEDBACK
) {
563 swrast
->Point
= _swrast_feedback_point
;
567 swrast
->Point
= _swrast_select_point
;