2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 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.
27 * \file swrast/s_span.c
28 * \brief Span processing functions used by all rasterization functions.
29 * This is where all the per-fragment tests are performed
40 #include "s_alphabuf.h"
42 #include "s_context.h"
46 #include "s_masking.h"
47 #include "s_nvfragprog.h"
49 #include "s_stencil.h"
50 #include "s_texture.h"
54 * Init span's Z interpolation values to the RasterPos Z.
55 * Used during setup for glDraw/CopyPixels.
58 _swrast_span_default_z( GLcontext
*ctx
, struct sw_span
*span
)
60 if (ctx
->Visual
.depthBits
<= 16)
61 span
->z
= FloatToFixed(ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
+ 0.5F
);
63 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
+ 0.5F
);
65 span
->interpMask
|= SPAN_Z
;
70 * Init span's fog interpolation values to the RasterPos fog.
71 * Used during setup for glDraw/CopyPixels.
74 _swrast_span_default_fog( GLcontext
*ctx
, struct sw_span
*span
)
76 span
->fog
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
77 span
->fogStep
= span
->dfogdx
= span
->dfogdy
= 0.0F
;
78 span
->interpMask
|= SPAN_FOG
;
83 * Init span's color or index interpolation values to the RasterPos color.
84 * Used during setup for glDraw/CopyPixels.
87 _swrast_span_default_color( GLcontext
*ctx
, struct sw_span
*span
)
89 if (ctx
->Visual
.rgbMode
) {
91 UNCLAMPED_FLOAT_TO_CHAN(r
, ctx
->Current
.RasterColor
[0]);
92 UNCLAMPED_FLOAT_TO_CHAN(g
, ctx
->Current
.RasterColor
[1]);
93 UNCLAMPED_FLOAT_TO_CHAN(b
, ctx
->Current
.RasterColor
[2]);
94 UNCLAMPED_FLOAT_TO_CHAN(a
, ctx
->Current
.RasterColor
[3]);
95 #if CHAN_TYPE == GL_FLOAT
101 span
->red
= IntToFixed(r
);
102 span
->green
= IntToFixed(g
);
103 span
->blue
= IntToFixed(b
);
104 span
->alpha
= IntToFixed(a
);
110 span
->interpMask
|= SPAN_RGBA
;
113 span
->index
= FloatToFixed(ctx
->Current
.RasterIndex
);
115 span
->interpMask
|= SPAN_INDEX
;
121 * Init span's texcoord interpolation values to the RasterPos texcoords.
122 * Used during setup for glDraw/CopyPixels.
125 _swrast_span_default_texcoords( GLcontext
*ctx
, struct sw_span
*span
)
128 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
129 const GLfloat
*tc
= ctx
->Current
.RasterTexCoords
[i
];
131 /* use (s/q, t/q, r/q, 1) */
132 span
->tex
[i
][0] = tc
[0] / tc
[3];
133 span
->tex
[i
][1] = tc
[1] / tc
[3];
134 span
->tex
[i
][2] = tc
[2] / tc
[3];
135 span
->tex
[i
][3] = 1.0;
138 ASSIGN_4V(span
->tex
[i
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
140 ASSIGN_4V(span
->texStepX
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
141 ASSIGN_4V(span
->texStepY
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
143 span
->interpMask
|= SPAN_TEXTURE
;
147 /* Fill in the span.color.rgba array from the interpolation values */
149 interpolate_colors(GLcontext
*ctx
, struct sw_span
*span
)
151 const GLuint n
= span
->end
;
152 GLchan (*rgba
)[4] = span
->array
->rgba
;
155 ASSERT((span
->interpMask
& SPAN_RGBA
) &&
156 !(span
->arrayMask
& SPAN_RGBA
));
158 if (span
->interpMask
& SPAN_FLAT
) {
161 color
[RCOMP
] = FixedToChan(span
->red
);
162 color
[GCOMP
] = FixedToChan(span
->green
);
163 color
[BCOMP
] = FixedToChan(span
->blue
);
164 color
[ACOMP
] = FixedToChan(span
->alpha
);
165 for (i
= 0; i
< n
; i
++) {
166 COPY_CHAN4(span
->array
->rgba
[i
], color
);
171 #if CHAN_TYPE == GL_FLOAT
172 GLfloat r
= span
->red
;
173 GLfloat g
= span
->green
;
174 GLfloat b
= span
->blue
;
175 GLfloat a
= span
->alpha
;
176 const GLfloat dr
= span
->redStep
;
177 const GLfloat dg
= span
->greenStep
;
178 const GLfloat db
= span
->blueStep
;
179 const GLfloat da
= span
->alphaStep
;
181 GLfixed r
= span
->red
;
182 GLfixed g
= span
->green
;
183 GLfixed b
= span
->blue
;
184 GLfixed a
= span
->alpha
;
185 const GLint dr
= span
->redStep
;
186 const GLint dg
= span
->greenStep
;
187 const GLint db
= span
->blueStep
;
188 const GLint da
= span
->alphaStep
;
190 for (i
= 0; i
< n
; i
++) {
191 rgba
[i
][RCOMP
] = FixedToChan(r
);
192 rgba
[i
][GCOMP
] = FixedToChan(g
);
193 rgba
[i
][BCOMP
] = FixedToChan(b
);
194 rgba
[i
][ACOMP
] = FixedToChan(a
);
201 span
->arrayMask
|= SPAN_RGBA
;
205 /* Fill in the span.color.index array from the interpolation values */
207 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
209 GLfixed index
= span
->index
;
210 const GLint indexStep
= span
->indexStep
;
211 const GLuint n
= span
->end
;
212 GLuint
*indexes
= span
->array
->index
;
214 ASSERT((span
->interpMask
& SPAN_INDEX
) &&
215 !(span
->arrayMask
& SPAN_INDEX
));
217 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
219 index
= FixedToInt(index
);
220 for (i
= 0; i
< n
; i
++) {
226 for (i
= 0; i
< n
; i
++) {
227 indexes
[i
] = FixedToInt(index
);
231 span
->arrayMask
|= SPAN_INDEX
;
235 /* Fill in the span.->array->spec array from the interpolation values */
237 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
239 if (span
->interpMask
& SPAN_FLAT
) {
241 const GLchan r
= FixedToChan(span
->specRed
);
242 const GLchan g
= FixedToChan(span
->specGreen
);
243 const GLchan b
= FixedToChan(span
->specBlue
);
245 for (i
= 0; i
< span
->end
; i
++) {
246 span
->array
->spec
[i
][RCOMP
] = r
;
247 span
->array
->spec
[i
][GCOMP
] = g
;
248 span
->array
->spec
[i
][BCOMP
] = b
;
253 #if CHAN_TYPE == GL_FLOAT
254 GLfloat r
= span
->specRed
;
255 GLfloat g
= span
->specGreen
;
256 GLfloat b
= span
->specBlue
;
258 GLfixed r
= span
->specRed
;
259 GLfixed g
= span
->specGreen
;
260 GLfixed b
= span
->specBlue
;
263 for (i
= 0; i
< span
->end
; i
++) {
264 span
->array
->spec
[i
][RCOMP
] = FixedToChan(r
);
265 span
->array
->spec
[i
][GCOMP
] = FixedToChan(g
);
266 span
->array
->spec
[i
][BCOMP
] = FixedToChan(b
);
267 r
+= span
->specRedStep
;
268 g
+= span
->specGreenStep
;
269 b
+= span
->specBlueStep
;
272 span
->arrayMask
|= SPAN_SPEC
;
276 /* Fill in the span.zArray array from the interpolation values */
278 _swrast_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
280 const GLuint n
= span
->end
;
283 ASSERT((span
->interpMask
& SPAN_Z
) &&
284 !(span
->arrayMask
& SPAN_Z
));
286 if (ctx
->Visual
.depthBits
<= 16) {
287 GLfixed zval
= span
->z
;
288 GLdepth
*z
= span
->array
->z
;
289 for (i
= 0; i
< n
; i
++) {
290 z
[i
] = FixedToInt(zval
);
295 /* Deep Z buffer, no fixed->int shift */
296 GLfixed zval
= span
->z
;
297 GLdepth
*z
= span
->array
->z
;
298 for (i
= 0; i
< n
; i
++) {
303 span
->arrayMask
|= SPAN_Z
;
308 * This the ideal solution, as given in the OpenGL spec.
312 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
313 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
314 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
316 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
317 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
318 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
319 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
320 GLfloat x
= SQRTF(dudx
* dudx
+ dvdx
* dvdx
);
321 GLfloat y
= SQRTF(dudy
* dudy
+ dvdy
* dvdy
);
322 GLfloat rho
= MAX2(x
, y
);
323 GLfloat lambda
= LOG2(rho
);
330 * This is a faster approximation
333 _swrast_compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
334 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
335 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
337 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
338 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
339 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
340 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
341 GLfloat maxU
, maxV
, rho
, lambda
;
342 dsdx2
= FABSF(dsdx2
);
343 dsdy2
= FABSF(dsdy2
);
344 dtdx2
= FABSF(dtdx2
);
345 dtdy2
= FABSF(dtdy2
);
346 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
347 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
348 rho
= MAX2(maxU
, maxV
);
355 * Fill in the span.texcoords array from the interpolation values.
356 * Note: in the places where we divide by Q (or mult by invQ) we're
357 * really doing two things: perspective correction and texcoord
358 * projection. Remember, for texcoord (s,t,r,q) we need to index
359 * texels with (s/q, t/q, r/q).
360 * If we're using a fragment program, we never do the division
361 * for texcoord projection. That's done by the TXP instruction
362 * or user-written code.
365 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
367 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
368 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
370 if (ctx
->Texture
._EnabledCoordUnits
> 1) {
373 span
->arrayMask
|= SPAN_TEXTURE
;
374 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
375 if (ctx
->Texture
._EnabledCoordUnits
& (1 << u
)) {
376 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
378 GLboolean needLambda
;
380 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
381 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
382 || ctx
->FragmentProgram
._Enabled
;
383 texW
= img
->WidthScale
;
384 texH
= img
->HeightScale
;
387 /* using a fragment program */
390 needLambda
= GL_FALSE
;
393 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
394 GLfloat
*lambda
= span
->array
->lambda
[u
];
395 const GLfloat dsdx
= span
->texStepX
[u
][0];
396 const GLfloat dsdy
= span
->texStepY
[u
][0];
397 const GLfloat dtdx
= span
->texStepX
[u
][1];
398 const GLfloat dtdy
= span
->texStepY
[u
][1];
399 const GLfloat drdx
= span
->texStepX
[u
][2];
400 const GLfloat dqdx
= span
->texStepX
[u
][3];
401 const GLfloat dqdy
= span
->texStepY
[u
][3];
402 GLfloat s
= span
->tex
[u
][0];
403 GLfloat t
= span
->tex
[u
][1];
404 GLfloat r
= span
->tex
[u
][2];
405 GLfloat q
= span
->tex
[u
][3];
407 if (ctx
->FragmentProgram
._Enabled
) {
408 /* do perspective correction but don't divide s, t, r by q */
409 const GLfloat dwdx
= span
->dwdx
;
411 for (i
= 0; i
< span
->end
; i
++) {
412 const GLfloat invW
= 1.0F
/ w
;
413 texcoord
[i
][0] = s
* invW
;
414 texcoord
[i
][1] = t
* invW
;
415 texcoord
[i
][2] = r
* invW
;
416 texcoord
[i
][3] = q
* invW
;
417 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
418 dqdx
, dqdy
, texW
, texH
,
429 for (i
= 0; i
< span
->end
; i
++) {
430 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
431 texcoord
[i
][0] = s
* invQ
;
432 texcoord
[i
][1] = t
* invQ
;
433 texcoord
[i
][2] = r
* invQ
;
435 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
436 dqdx
, dqdy
, texW
, texH
,
444 span
->arrayMask
|= SPAN_LAMBDA
;
447 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
448 GLfloat
*lambda
= span
->array
->lambda
[u
];
449 const GLfloat dsdx
= span
->texStepX
[u
][0];
450 const GLfloat dtdx
= span
->texStepX
[u
][1];
451 const GLfloat drdx
= span
->texStepX
[u
][2];
452 const GLfloat dqdx
= span
->texStepX
[u
][3];
453 GLfloat s
= span
->tex
[u
][0];
454 GLfloat t
= span
->tex
[u
][1];
455 GLfloat r
= span
->tex
[u
][2];
456 GLfloat q
= span
->tex
[u
][3];
458 if (ctx
->FragmentProgram
._Enabled
) {
459 /* do perspective correction but don't divide s, t, r by q */
460 const GLfloat dwdx
= span
->dwdx
;
462 for (i
= 0; i
< span
->end
; i
++) {
463 const GLfloat invW
= 1.0F
/ w
;
464 texcoord
[i
][0] = s
* invW
;
465 texcoord
[i
][1] = t
* invW
;
466 texcoord
[i
][2] = r
* invW
;
467 texcoord
[i
][3] = q
* invW
;
476 else if (dqdx
== 0.0F
) {
477 /* Ortho projection or polygon's parallel to window X axis */
478 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
479 for (i
= 0; i
< span
->end
; i
++) {
480 texcoord
[i
][0] = s
* invQ
;
481 texcoord
[i
][1] = t
* invQ
;
482 texcoord
[i
][2] = r
* invQ
;
491 for (i
= 0; i
< span
->end
; i
++) {
492 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
493 texcoord
[i
][0] = s
* invQ
;
494 texcoord
[i
][1] = t
* invQ
;
495 texcoord
[i
][2] = r
* invQ
;
510 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
512 GLboolean needLambda
;
514 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
515 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
516 || ctx
->FragmentProgram
._Enabled
;
517 texW
= (GLfloat
) img
->WidthScale
;
518 texH
= (GLfloat
) img
->HeightScale
;
521 needLambda
= GL_FALSE
;
524 span
->arrayMask
|= SPAN_TEXTURE
;
526 /* just texture unit 0, with lambda */
527 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
528 GLfloat
*lambda
= span
->array
->lambda
[0];
529 const GLfloat dsdx
= span
->texStepX
[0][0];
530 const GLfloat dsdy
= span
->texStepY
[0][0];
531 const GLfloat dtdx
= span
->texStepX
[0][1];
532 const GLfloat dtdy
= span
->texStepY
[0][1];
533 const GLfloat drdx
= span
->texStepX
[0][2];
534 const GLfloat dqdx
= span
->texStepX
[0][3];
535 const GLfloat dqdy
= span
->texStepY
[0][3];
536 GLfloat s
= span
->tex
[0][0];
537 GLfloat t
= span
->tex
[0][1];
538 GLfloat r
= span
->tex
[0][2];
539 GLfloat q
= span
->tex
[0][3];
541 if (ctx
->FragmentProgram
._Enabled
) {
542 /* do perspective correction but don't divide s, t, r by q */
543 const GLfloat dwdx
= span
->dwdx
;
545 for (i
= 0; i
< span
->end
; i
++) {
546 const GLfloat invW
= 1.0F
/ w
;
547 texcoord
[i
][0] = s
* invW
;
548 texcoord
[i
][1] = t
* invW
;
549 texcoord
[i
][2] = r
* invW
;
550 texcoord
[i
][3] = q
* invW
;
551 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
552 dqdx
, dqdy
, texW
, texH
,
563 for (i
= 0; i
< span
->end
; i
++) {
564 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
565 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
566 dqdx
, dqdy
, texW
, texH
,
568 texcoord
[i
][0] = s
* invQ
;
569 texcoord
[i
][1] = t
* invQ
;
570 texcoord
[i
][2] = r
* invQ
;
578 span
->arrayMask
|= SPAN_LAMBDA
;
581 /* just texture 0, without lambda */
582 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
583 const GLfloat dsdx
= span
->texStepX
[0][0];
584 const GLfloat dtdx
= span
->texStepX
[0][1];
585 const GLfloat drdx
= span
->texStepX
[0][2];
586 const GLfloat dqdx
= span
->texStepX
[0][3];
587 GLfloat s
= span
->tex
[0][0];
588 GLfloat t
= span
->tex
[0][1];
589 GLfloat r
= span
->tex
[0][2];
590 GLfloat q
= span
->tex
[0][3];
592 if (ctx
->FragmentProgram
._Enabled
) {
593 /* do perspective correction but don't divide s, t, r by q */
594 const GLfloat dwdx
= span
->dwdx
;
596 for (i
= 0; i
< span
->end
; i
++) {
597 const GLfloat invW
= 1.0F
/ w
;
598 texcoord
[i
][0] = s
* invW
;
599 texcoord
[i
][1] = t
* invW
;
600 texcoord
[i
][2] = r
* invW
;
601 texcoord
[i
][3] = q
* invW
;
609 else if (dqdx
== 0.0F
) {
610 /* Ortho projection or polygon's parallel to window X axis */
611 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
612 for (i
= 0; i
< span
->end
; i
++) {
613 texcoord
[i
][0] = s
* invQ
;
614 texcoord
[i
][1] = t
* invQ
;
615 texcoord
[i
][2] = r
* invQ
;
623 for (i
= 0; i
< span
->end
; i
++) {
624 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
625 texcoord
[i
][0] = s
* invQ
;
626 texcoord
[i
][1] = t
* invQ
;
627 texcoord
[i
][2] = r
* invQ
;
641 * Apply the current polygon stipple pattern to a span of pixels.
644 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
646 const GLuint highbit
= 0x80000000;
647 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
648 GLubyte
*mask
= span
->array
->mask
;
651 ASSERT(ctx
->Polygon
.StippleFlag
);
652 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
654 m
= highbit
>> (GLuint
) (span
->x
% 32);
656 for (i
= 0; i
< span
->end
; i
++) {
657 if ((m
& stipple
) == 0) {
665 span
->writeAll
= GL_FALSE
;
670 * Clip a pixel span to the current buffer/window boundaries:
671 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
672 * window clipping and scissoring.
673 * Return: GL_TRUE some pixels still visible
674 * GL_FALSE nothing visible
677 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
679 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
680 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
681 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
682 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
684 if (span
->arrayMask
& SPAN_XY
) {
685 /* arrays of x/y pixel coords */
686 const GLint
*x
= span
->array
->x
;
687 const GLint
*y
= span
->array
->y
;
688 const GLint n
= span
->end
;
689 GLubyte
*mask
= span
->array
->mask
;
691 if (span
->arrayMask
& SPAN_MASK
) {
692 /* note: using & intead of && to reduce branches */
693 for (i
= 0; i
< n
; i
++) {
694 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
695 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
699 /* note: using & intead of && to reduce branches */
700 for (i
= 0; i
< n
; i
++) {
701 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
702 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
705 return GL_TRUE
; /* some pixels visible */
708 /* horizontal span of pixels */
709 const GLint x
= span
->x
;
710 const GLint y
= span
->y
;
711 const GLint n
= span
->end
;
713 /* Trivial rejection tests */
714 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
716 return GL_FALSE
; /* all pixels clipped */
719 /* Clip to the left */
721 ASSERT(x
+ n
> xmin
);
722 span
->writeAll
= GL_FALSE
;
723 _mesa_bzero(span
->array
->mask
, (xmin
- x
) * sizeof(GLubyte
));
729 span
->end
= xmax
- x
;
732 return GL_TRUE
; /* some pixels visible */
739 * Draw to more than one color buffer (or none).
742 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
744 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
747 /* loop over four possible dest color buffers */
748 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
749 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
750 GLuint indexTmp
[MAX_WIDTH
];
751 ASSERT(span
->end
< MAX_WIDTH
);
753 /* Set the current read/draw buffer */
754 swrast
->CurrentBufferBit
= bufferBit
;
755 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
757 /* make copy of incoming indexes */
758 MEMCPY( indexTmp
, span
->array
->index
, span
->end
* sizeof(GLuint
) );
760 if (ctx
->Color
.IndexLogicOpEnabled
) {
761 _swrast_logicop_ci_span(ctx
, span
, indexTmp
);
764 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
765 _swrast_mask_index_span(ctx
, span
, indexTmp
);
768 if (span
->arrayMask
& SPAN_XY
) {
769 /* array of pixel coords */
770 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
771 span
->array
->x
, span
->array
->y
,
772 indexTmp
, span
->array
->mask
);
775 /* horizontal run of pixels */
776 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
777 indexTmp
, span
->array
->mask
);
782 /* restore default dest buffer */
783 _swrast_use_draw_buffer(ctx
);
788 * Draw to more than one RGBA color buffer (or none).
789 * All fragment operations, up to (but not) blending/logicop should
790 * have been done first.
793 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
795 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
797 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
799 ASSERT(colorMask
!= 0x0);
801 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
804 /* loop over four possible dest color buffers */
805 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
806 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
807 GLchan rgbaTmp
[MAX_WIDTH
][4];
808 ASSERT(span
->end
< MAX_WIDTH
);
810 /* Set the current read/draw buffer */
811 swrast
->CurrentBufferBit
= bufferBit
;
812 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
814 /* make copy of incoming colors */
815 MEMCPY( rgbaTmp
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
) );
817 if (ctx
->Color
._LogicOpEnabled
) {
818 _swrast_logicop_rgba_span(ctx
, span
, rgbaTmp
);
820 else if (ctx
->Color
.BlendEnabled
) {
821 _swrast_blend_span(ctx
, span
, rgbaTmp
);
824 if (colorMask
!= 0xffffffff) {
825 _swrast_mask_rgba_span(ctx
, span
, rgbaTmp
);
828 if (span
->arrayMask
& SPAN_XY
) {
829 /* array of pixel coords */
830 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
831 span
->array
->x
, span
->array
->y
,
832 (const GLchan (*)[4]) rgbaTmp
,
834 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
835 _swrast_write_alpha_pixels(ctx
, span
->end
,
836 span
->array
->x
, span
->array
->y
,
837 (const GLchan (*)[4]) rgbaTmp
,
842 /* horizontal run of pixels */
843 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
844 (const GLchan (*)[4]) rgbaTmp
,
846 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
847 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
848 (const GLchan (*)[4]) rgbaTmp
,
855 /* restore default dest buffer */
856 _swrast_use_draw_buffer(ctx
);
862 * This function may modify any of the array values in the span.
863 * span->interpMask and span->arrayMask may be changed but will be restored
864 * to their original values before returning.
867 _swrast_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
869 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
870 const GLuint origInterpMask
= span
->interpMask
;
871 const GLuint origArrayMask
= span
->arrayMask
;
873 ASSERT(span
->end
<= MAX_WIDTH
);
874 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
875 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
876 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
877 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
879 if (span
->arrayMask
& SPAN_MASK
) {
880 /* mask was initialized by caller, probably glBitmap */
881 span
->writeAll
= GL_FALSE
;
884 MEMSET(span
->array
->mask
, 1, span
->end
);
885 span
->writeAll
= GL_TRUE
;
889 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
890 if (!clip_span(ctx
, span
)) {
895 /* Depth bounds test */
896 if (ctx
->Depth
.BoundsTest
&& ctx
->Visual
.depthBits
> 0) {
897 if (!_swrast_depth_bounds_test(ctx
, span
)) {
903 if (span
->arrayMask
& SPAN_XY
) {
905 for (i
= 0; i
< span
->end
; i
++) {
906 if (span
->array
->mask
[i
]) {
907 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
908 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
909 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
910 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
916 /* Polygon Stippling */
917 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
918 stipple_polygon_span(ctx
, span
);
921 /* Depth test and stencil */
922 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
923 if (span
->interpMask
& SPAN_Z
)
924 _swrast_span_interpolate_z(ctx
, span
);
926 if (ctx
->Stencil
.Enabled
) {
927 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
928 span
->arrayMask
= origArrayMask
;
933 ASSERT(ctx
->Depth
.Test
);
934 if (!_swrast_depth_test_span(ctx
, span
)) {
935 span
->arrayMask
= origArrayMask
;
941 /* if we get here, something passed the depth test */
942 ctx
->OcclusionResult
= GL_TRUE
;
944 #if FEATURE_ARB_occlusion_query
945 if (ctx
->Occlusion
.Active
) {
947 for (i
= 0; i
< span
->end
; i
++)
948 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
952 /* we have to wait until after occlusion to do this test */
953 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
954 /* write no pixels */
955 span
->arrayMask
= origArrayMask
;
959 /* Interpolate the color indexes if needed */
960 if (span
->interpMask
& SPAN_INDEX
) {
961 interpolate_indexes(ctx
, span
);
962 /* clear the bit - this allows the WriteMonoCISpan optimization below */
963 span
->interpMask
&= ~SPAN_INDEX
;
967 if (ctx
->Fog
.Enabled
) {
968 _swrast_fog_ci_span(ctx
, span
);
971 /* Antialias coverage application */
972 if (span
->arrayMask
& SPAN_COVERAGE
) {
974 GLuint
*index
= span
->array
->index
;
975 GLfloat
*coverage
= span
->array
->coverage
;
976 for (i
= 0; i
< span
->end
; i
++) {
977 ASSERT(coverage
[i
] < 16);
978 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) coverage
[i
]);
982 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
983 /* draw to zero or two or more buffers */
984 multi_write_index_span(ctx
, span
);
987 /* normal situation: draw to exactly one buffer */
988 if (ctx
->Color
.IndexLogicOpEnabled
) {
989 _swrast_logicop_ci_span(ctx
, span
, span
->array
->index
);
992 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
993 _swrast_mask_index_span(ctx
, span
, span
->array
->index
);
997 if (span
->arrayMask
& SPAN_XY
) {
998 /* array of pixel coords */
999 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
1000 /* all pixels have same color index */
1001 (*swrast
->Driver
.WriteMonoCIPixels
)(ctx
, span
->end
,
1002 span
->array
->x
, span
->array
->y
,
1003 FixedToInt(span
->index
),
1007 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->array
->x
,
1008 span
->array
->y
, span
->array
->index
,
1009 span
->array
->mask
);
1013 /* horizontal run of pixels */
1014 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
1015 /* all pixels have same color index */
1016 (*swrast
->Driver
.WriteMonoCISpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1017 FixedToInt(span
->index
),
1021 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
1028 span
->interpMask
= origInterpMask
;
1029 span
->arrayMask
= origArrayMask
;
1034 * This function may modify any of the array values in the span.
1035 * span->interpMask and span->arrayMask may be changed but will be restored
1036 * to their original values before returning.
1039 _swrast_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
1041 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1042 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1043 const GLuint origInterpMask
= span
->interpMask
;
1044 const GLuint origArrayMask
= span
->arrayMask
;
1045 GLboolean monoColor
;
1047 ASSERT(span
->end
<= MAX_WIDTH
);
1048 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1049 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1050 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1051 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_RGBA
);
1053 if (ctx
->Fog
.Enabled
)
1054 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
1055 if (ctx
->Depth
.Test
)
1056 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_Z
);
1059 if (span
->arrayMask
& SPAN_MASK
) {
1060 /* mask was initialized by caller, probably glBitmap */
1061 span
->writeAll
= GL_FALSE
;
1064 MEMSET(span
->array
->mask
, 1, span
->end
);
1065 span
->writeAll
= GL_TRUE
;
1068 /* Determine if we have mono-chromatic colors */
1069 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
1070 span
->redStep
== 0 && span
->greenStep
== 0 &&
1071 span
->blueStep
== 0 && span
->alphaStep
== 0;
1074 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1075 if (!clip_span(ctx
, span
)) {
1080 /* Depth bounds test */
1081 if (ctx
->Depth
.BoundsTest
&& ctx
->Visual
.depthBits
> 0) {
1082 if (!_swrast_depth_bounds_test(ctx
, span
)) {
1088 if (span
->arrayMask
& SPAN_XY
) {
1090 for (i
= 0; i
< span
->end
; i
++) {
1091 if (span
->array
->mask
[i
]) {
1092 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1093 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1094 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1095 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1101 /* Polygon Stippling */
1102 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1103 stipple_polygon_span(ctx
, span
);
1106 /* Fragment program */
1107 if (ctx
->FragmentProgram
._Enabled
) {
1108 /* Now we may need to interpolate the colors and texcoords */
1109 if ((span
->interpMask
& SPAN_RGBA
) &&
1110 (span
->arrayMask
& SPAN_RGBA
) == 0) {
1111 interpolate_colors(ctx
, span
);
1112 span
->interpMask
&= ~SPAN_RGBA
;
1114 if (span
->interpMask
& SPAN_SPEC
) {
1115 interpolate_specular(ctx
, span
);
1117 if ((span
->interpMask
& SPAN_TEXTURE
)
1118 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1119 interpolate_texcoords(ctx
, span
);
1120 _swrast_exec_fragment_program(ctx
, span
);
1121 monoColor
= GL_FALSE
;
1124 /* Do the alpha test */
1125 if (ctx
->Color
.AlphaEnabled
) {
1126 if (!_swrast_alpha_test(ctx
, span
)) {
1127 span
->interpMask
= origInterpMask
;
1128 span
->arrayMask
= origArrayMask
;
1133 /* Stencil and Z testing */
1134 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1135 if (span
->interpMask
& SPAN_Z
)
1136 _swrast_span_interpolate_z(ctx
, span
);
1138 if (ctx
->Stencil
.Enabled
) {
1139 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1140 span
->interpMask
= origInterpMask
;
1141 span
->arrayMask
= origArrayMask
;
1146 ASSERT(ctx
->Depth
.Test
);
1147 ASSERT(span
->arrayMask
& SPAN_Z
);
1148 /* regular depth testing */
1149 if (!_swrast_depth_test_span(ctx
, span
)) {
1150 span
->interpMask
= origInterpMask
;
1151 span
->arrayMask
= origArrayMask
;
1157 /* if we get here, something passed the depth test */
1158 ctx
->OcclusionResult
= GL_TRUE
;
1160 #if FEATURE_ARB_occlusion_query
1161 if (ctx
->Occlusion
.Active
) {
1163 for (i
= 0; i
< span
->end
; i
++)
1164 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
1168 /* can't abort span-writing until after occlusion testing */
1169 if (colorMask
== 0x0) {
1170 span
->interpMask
= origInterpMask
;
1171 span
->arrayMask
= origArrayMask
;
1175 /* Now we may need to interpolate the colors */
1176 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
1177 interpolate_colors(ctx
, span
);
1178 /* clear the bit - this allows the WriteMonoCISpan optimization below */
1179 span
->interpMask
&= ~SPAN_RGBA
;
1183 if (swrast
->_FogEnabled
) {
1184 _swrast_fog_rgba_span(ctx
, span
);
1185 monoColor
= GL_FALSE
;
1188 /* Antialias coverage application */
1189 if (span
->arrayMask
& SPAN_COVERAGE
) {
1190 GLchan (*rgba
)[4] = span
->array
->rgba
;
1191 GLfloat
*coverage
= span
->array
->coverage
;
1193 for (i
= 0; i
< span
->end
; i
++) {
1194 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1196 monoColor
= GL_FALSE
;
1199 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1200 multi_write_rgba_span(ctx
, span
);
1203 /* normal: write to exactly one buffer */
1204 if (ctx
->Color
._LogicOpEnabled
) {
1205 _swrast_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1206 monoColor
= GL_FALSE
;
1208 else if (ctx
->Color
.BlendEnabled
) {
1209 _swrast_blend_span(ctx
, span
, span
->array
->rgba
);
1210 monoColor
= GL_FALSE
;
1213 /* Color component masking */
1214 if (colorMask
!= 0xffffffff) {
1215 _swrast_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1216 monoColor
= GL_FALSE
;
1220 if (span
->arrayMask
& SPAN_XY
) {
1221 /* array of pixel coords */
1223 /* all pixels have same color */
1225 color
[RCOMP
] = FixedToChan(span
->red
);
1226 color
[GCOMP
] = FixedToChan(span
->green
);
1227 color
[BCOMP
] = FixedToChan(span
->blue
);
1228 color
[ACOMP
] = FixedToChan(span
->alpha
);
1229 (*swrast
->Driver
.WriteMonoRGBAPixels
)(ctx
, span
->end
,
1230 span
->array
->x
, span
->array
->y
, color
, span
->array
->mask
);
1231 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1232 _swrast_write_mono_alpha_pixels(ctx
, span
->end
,
1233 span
->array
->x
, span
->array
->y
,
1234 color
[ACOMP
], span
->array
->mask
);
1238 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
1239 span
->array
->x
, span
->array
->y
,
1240 (const GLchan (*)[4]) span
->array
->rgba
,
1242 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1243 _swrast_write_alpha_pixels(ctx
, span
->end
,
1244 span
->array
->x
, span
->array
->y
,
1245 (const GLchan (*)[4]) span
->array
->rgba
,
1251 /* horizontal run of pixels */
1253 /* all pixels have same color */
1255 color
[RCOMP
] = FixedToChan(span
->red
);
1256 color
[GCOMP
] = FixedToChan(span
->green
);
1257 color
[BCOMP
] = FixedToChan(span
->blue
);
1258 color
[ACOMP
] = FixedToChan(span
->alpha
);
1259 (*swrast
->Driver
.WriteMonoRGBASpan
)(ctx
, span
->end
, span
->x
,
1260 span
->y
, color
, span
->array
->mask
);
1261 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1262 _swrast_write_mono_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1264 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1268 /* each pixel is a different color */
1269 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1270 (const GLchan (*)[4]) span
->array
->rgba
,
1271 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1272 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1273 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1274 (const GLchan (*)[4]) span
->array
->rgba
,
1275 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1281 span
->interpMask
= origInterpMask
;
1282 span
->arrayMask
= origArrayMask
;
1287 * Add specular color to base color. This is used only when
1288 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1291 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1294 for (i
= 0; i
< n
; i
++) {
1295 #if CHAN_TYPE == GL_FLOAT
1297 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1298 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1299 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1301 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1302 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1303 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1304 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1305 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1306 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1313 * This function may modify any of the array values in the span.
1314 * span->interpMask and span->arrayMask may be changed but will be restored
1315 * to their original values before returning.
1318 _swrast_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
1320 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1321 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1322 const GLuint origInterpMask
= span
->interpMask
;
1323 const GLuint origArrayMask
= span
->arrayMask
;
1325 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1326 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1327 ASSERT(span
->end
<= MAX_WIDTH
);
1328 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1329 ASSERT(ctx
->Texture
._EnabledCoordUnits
|| ctx
->FragmentProgram
._Enabled
);
1332 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1335 if (span
->arrayMask
& SPAN_MASK
) {
1336 /* mask was initialized by caller, probably glBitmap */
1337 span
->writeAll
= GL_FALSE
;
1340 MEMSET(span
->array
->mask
, 1, span
->end
);
1341 span
->writeAll
= GL_TRUE
;
1345 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1346 if (!clip_span(ctx
, span
)) {
1352 if (span
->arrayMask
& SPAN_XY
) {
1354 for (i
= 0; i
< span
->end
; i
++) {
1355 if (span
->array
->mask
[i
]) {
1356 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1357 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1358 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1359 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1365 /* Polygon Stippling */
1366 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1367 stipple_polygon_span(ctx
, span
);
1370 /* Need texture coordinates now */
1371 if ((span
->interpMask
& SPAN_TEXTURE
)
1372 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1373 interpolate_texcoords(ctx
, span
);
1375 /* Texture with alpha test */
1376 if (ctx
->Color
.AlphaEnabled
) {
1378 /* Now we need the rgba array, fill it in if needed */
1379 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1380 interpolate_colors(ctx
, span
);
1382 if (span
->interpMask
& SPAN_SPEC
) {
1383 interpolate_specular(ctx
, span
);
1386 /* Texturing without alpha is done after depth-testing which
1387 * gives a potential speed-up.
1389 if (ctx
->FragmentProgram
._Enabled
)
1390 _swrast_exec_fragment_program( ctx
, span
);
1392 _swrast_texture_span( ctx
, span
);
1394 /* Do the alpha test */
1395 if (!_swrast_alpha_test(ctx
, span
)) {
1396 span
->arrayMask
= origArrayMask
;
1401 /* Stencil and Z testing */
1402 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1403 if (span
->interpMask
& SPAN_Z
)
1404 _swrast_span_interpolate_z(ctx
, span
);
1406 if (ctx
->Stencil
.Enabled
) {
1407 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1408 span
->interpMask
= origInterpMask
;
1409 span
->arrayMask
= origArrayMask
;
1414 ASSERT(ctx
->Depth
.Test
);
1415 ASSERT(span
->arrayMask
& SPAN_Z
);
1416 /* regular depth testing */
1417 if (!_swrast_depth_test_span(ctx
, span
)) {
1418 span
->interpMask
= origInterpMask
;
1419 span
->arrayMask
= origArrayMask
;
1425 /* if we get here, some fragments passed the depth test */
1426 ctx
->OcclusionResult
= GL_TRUE
;
1428 #if FEATURE_ARB_occlusion_query
1429 if (ctx
->Occlusion
.Active
) {
1431 for (i
= 0; i
< span
->end
; i
++)
1432 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
1436 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1437 * the occlusion test.
1439 if (colorMask
== 0x0) {
1440 span
->interpMask
= origInterpMask
;
1441 span
->arrayMask
= origArrayMask
;
1445 /* Texture without alpha test */
1446 if (!ctx
->Color
.AlphaEnabled
) {
1448 /* Now we need the rgba array, fill it in if needed */
1449 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1450 interpolate_colors(ctx
, span
);
1452 if (span
->interpMask
& SPAN_SPEC
) {
1453 interpolate_specular(ctx
, span
);
1456 if (ctx
->FragmentProgram
._Enabled
)
1457 _swrast_exec_fragment_program( ctx
, span
);
1459 _swrast_texture_span( ctx
, span
);
1462 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1464 /* Add base and specular colors */
1465 if (ctx
->Fog
.ColorSumEnabled
||
1466 (ctx
->Light
.Enabled
&&
1467 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1468 if (span
->interpMask
& SPAN_SPEC
) {
1469 interpolate_specular(ctx
, span
);
1471 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1472 add_colors( span
->end
, span
->array
->rgba
, span
->array
->spec
);
1476 if (swrast
->_FogEnabled
) {
1477 _swrast_fog_rgba_span(ctx
, span
);
1480 /* Antialias coverage application */
1481 if (span
->arrayMask
& SPAN_COVERAGE
) {
1482 GLchan (*rgba
)[4] = span
->array
->rgba
;
1483 GLfloat
*coverage
= span
->array
->coverage
;
1485 for (i
= 0; i
< span
->end
; i
++) {
1486 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1490 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1491 multi_write_rgba_span(ctx
, span
);
1494 /* normal: write to exactly one buffer */
1495 if (ctx
->Color
._LogicOpEnabled
) {
1496 _swrast_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1498 else if (ctx
->Color
.BlendEnabled
) {
1499 _swrast_blend_span(ctx
, span
, span
->array
->rgba
);
1502 /* Color component masking */
1503 if (colorMask
!= 0xffffffff) {
1504 _swrast_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1508 if (span
->arrayMask
& SPAN_XY
) {
1509 /* array of pixel coords */
1510 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1511 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1512 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1513 _swrast_write_alpha_pixels(ctx
, span
->end
,
1514 span
->array
->x
, span
->array
->y
,
1515 (const GLchan (*)[4]) span
->array
->rgba
,
1520 /* horizontal run of pixels */
1521 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1522 (const GLchan (*)[4]) span
->array
->rgba
,
1523 span
->writeAll
? NULL
: span
->array
->mask
);
1524 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1525 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1526 (const GLchan (*)[4]) span
->array
->rgba
,
1527 span
->writeAll
? NULL
: span
->array
->mask
);
1532 span
->interpMask
= origInterpMask
;
1533 span
->arrayMask
= origArrayMask
;
1539 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1540 * reading ouside the buffer's boundaries.
1543 _swrast_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1544 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1546 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1547 const GLint bufWidth
= (GLint
) buffer
->Width
;
1548 const GLint bufHeight
= (GLint
) buffer
->Height
;
1550 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1551 /* completely above, below, or right */
1552 /* XXX maybe leave undefined? */
1553 _mesa_bzero(rgba
, 4 * n
* sizeof(GLchan
));
1558 /* left edge clippping */
1560 length
= (GLint
) n
- skip
;
1562 /* completely left of window */
1565 if (length
> bufWidth
) {
1569 else if ((GLint
) (x
+ n
) > bufWidth
) {
1570 /* right edge clipping */
1572 length
= bufWidth
- x
;
1574 /* completely to right of window */
1584 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1585 if (buffer
->UseSoftwareAlphaBuffers
) {
1586 _swrast_read_alpha_span(ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1593 * Read CI pixels from frame buffer. Clipping will be done to prevent
1594 * reading ouside the buffer's boundaries.
1597 _swrast_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1598 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1600 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1601 const GLint bufWidth
= (GLint
) buffer
->Width
;
1602 const GLint bufHeight
= (GLint
) buffer
->Height
;
1604 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1605 /* completely above, below, or right */
1606 _mesa_bzero(indx
, n
* sizeof(GLuint
));
1611 /* left edge clippping */
1613 length
= (GLint
) n
- skip
;
1615 /* completely left of window */
1618 if (length
> bufWidth
) {
1622 else if ((GLint
) (x
+ n
) > bufWidth
) {
1623 /* right edge clipping */
1625 length
= bufWidth
- x
;
1627 /* completely to right of window */
1637 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);