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
;
156 ASSERT((span
->interpMask
& SPAN_RGBA
) &&
157 !(span
->arrayMask
& SPAN_RGBA
));
159 if (span
->interpMask
& SPAN_FLAT
) {
162 color
[RCOMP
] = FixedToChan(span
->red
);
163 color
[GCOMP
] = FixedToChan(span
->green
);
164 color
[BCOMP
] = FixedToChan(span
->blue
);
165 color
[ACOMP
] = FixedToChan(span
->alpha
);
166 for (i
= 0; i
< n
; i
++) {
167 COPY_CHAN4(span
->array
->rgba
[i
], color
);
172 #if CHAN_TYPE == GL_FLOAT
173 GLfloat r
= span
->red
;
174 GLfloat g
= span
->green
;
175 GLfloat b
= span
->blue
;
176 GLfloat a
= span
->alpha
;
177 const GLfloat dr
= span
->redStep
;
178 const GLfloat dg
= span
->greenStep
;
179 const GLfloat db
= span
->blueStep
;
180 const GLfloat da
= span
->alphaStep
;
182 GLfixed r
= span
->red
;
183 GLfixed g
= span
->green
;
184 GLfixed b
= span
->blue
;
185 GLfixed a
= span
->alpha
;
186 const GLint dr
= span
->redStep
;
187 const GLint dg
= span
->greenStep
;
188 const GLint db
= span
->blueStep
;
189 const GLint da
= span
->alphaStep
;
191 for (i
= 0; i
< n
; i
++) {
192 rgba
[i
][RCOMP
] = FixedToChan(r
);
193 rgba
[i
][GCOMP
] = FixedToChan(g
);
194 rgba
[i
][BCOMP
] = FixedToChan(b
);
195 rgba
[i
][ACOMP
] = FixedToChan(a
);
202 span
->arrayMask
|= SPAN_RGBA
;
206 /* Fill in the span.color.index array from the interpolation values */
208 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
210 GLfixed index
= span
->index
;
211 const GLint indexStep
= span
->indexStep
;
212 const GLuint n
= span
->end
;
213 GLuint
*indexes
= span
->array
->index
;
216 ASSERT((span
->interpMask
& SPAN_INDEX
) &&
217 !(span
->arrayMask
& SPAN_INDEX
));
219 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
221 index
= FixedToInt(index
);
222 for (i
= 0; i
< n
; i
++) {
228 for (i
= 0; i
< n
; i
++) {
229 indexes
[i
] = FixedToInt(index
);
233 span
->arrayMask
|= SPAN_INDEX
;
237 /* Fill in the span.->array->spec array from the interpolation values */
239 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
242 if (span
->interpMask
& SPAN_FLAT
) {
244 const GLchan r
= FixedToChan(span
->specRed
);
245 const GLchan g
= FixedToChan(span
->specGreen
);
246 const GLchan b
= FixedToChan(span
->specBlue
);
248 for (i
= 0; i
< span
->end
; i
++) {
249 span
->array
->spec
[i
][RCOMP
] = r
;
250 span
->array
->spec
[i
][GCOMP
] = g
;
251 span
->array
->spec
[i
][BCOMP
] = b
;
256 #if CHAN_TYPE == GL_FLOAT
257 GLfloat r
= span
->specRed
;
258 GLfloat g
= span
->specGreen
;
259 GLfloat b
= span
->specBlue
;
261 GLfixed r
= span
->specRed
;
262 GLfixed g
= span
->specGreen
;
263 GLfixed b
= span
->specBlue
;
266 for (i
= 0; i
< span
->end
; i
++) {
267 span
->array
->spec
[i
][RCOMP
] = FixedToChan(r
);
268 span
->array
->spec
[i
][GCOMP
] = FixedToChan(g
);
269 span
->array
->spec
[i
][BCOMP
] = FixedToChan(b
);
270 r
+= span
->specRedStep
;
271 g
+= span
->specGreenStep
;
272 b
+= span
->specBlueStep
;
275 span
->arrayMask
|= SPAN_SPEC
;
279 /* Fill in the span.zArray array from the interpolation values */
281 _swrast_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
283 const GLuint n
= span
->end
;
286 ASSERT((span
->interpMask
& SPAN_Z
) &&
287 !(span
->arrayMask
& SPAN_Z
));
289 if (ctx
->Visual
.depthBits
<= 16) {
290 GLfixed zval
= span
->z
;
291 GLdepth
*z
= span
->array
->z
;
292 for (i
= 0; i
< n
; i
++) {
293 z
[i
] = FixedToInt(zval
);
298 /* Deep Z buffer, no fixed->int shift */
299 GLfixed zval
= span
->z
;
300 GLdepth
*z
= span
->array
->z
;
301 for (i
= 0; i
< n
; i
++) {
306 span
->arrayMask
|= SPAN_Z
;
311 * This the ideal solution, as given in the OpenGL spec.
315 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
316 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
317 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
319 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
320 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
321 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
322 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
323 GLfloat x
= SQRTF(dudx
* dudx
+ dvdx
* dvdx
);
324 GLfloat y
= SQRTF(dudy
* dudy
+ dvdy
* dvdy
);
325 GLfloat rho
= MAX2(x
, y
);
326 GLfloat lambda
= LOG2(rho
);
333 * This is a faster approximation
336 _swrast_compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
337 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
338 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
340 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
341 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
342 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
343 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
344 GLfloat maxU
, maxV
, rho
, lambda
;
345 dsdx2
= FABSF(dsdx2
);
346 dsdy2
= FABSF(dsdy2
);
347 dtdx2
= FABSF(dtdx2
);
348 dtdy2
= FABSF(dtdy2
);
349 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
350 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
351 rho
= MAX2(maxU
, maxV
);
358 * Fill in the span.texcoords array from the interpolation values.
359 * Note: in the places where we divide by Q (or mult by invQ) we're
360 * really doing two things: perspective correction and texcoord
361 * projection. Remember, for texcoord (s,t,r,q) we need to index
362 * texels with (s/q, t/q, r/q).
363 * If we're using a fragment program, we never do the division
364 * for texcoord projection. That's done by the TXP instruction
365 * or user-written code.
368 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
370 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
371 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
373 if (ctx
->Texture
._EnabledCoordUnits
> 1) {
376 span
->arrayMask
|= SPAN_TEXTURE
;
377 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
378 if (ctx
->Texture
._EnabledCoordUnits
& (1 << u
)) {
379 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
381 GLboolean needLambda
;
383 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
384 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
385 || ctx
->FragmentProgram
._Enabled
;
386 texW
= img
->WidthScale
;
387 texH
= img
->HeightScale
;
390 /* using a fragment program */
393 needLambda
= GL_FALSE
;
396 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
397 GLfloat
*lambda
= span
->array
->lambda
[u
];
398 const GLfloat dsdx
= span
->texStepX
[u
][0];
399 const GLfloat dsdy
= span
->texStepY
[u
][0];
400 const GLfloat dtdx
= span
->texStepX
[u
][1];
401 const GLfloat dtdy
= span
->texStepY
[u
][1];
402 const GLfloat drdx
= span
->texStepX
[u
][2];
403 const GLfloat dqdx
= span
->texStepX
[u
][3];
404 const GLfloat dqdy
= span
->texStepY
[u
][3];
405 GLfloat s
= span
->tex
[u
][0];
406 GLfloat t
= span
->tex
[u
][1];
407 GLfloat r
= span
->tex
[u
][2];
408 GLfloat q
= span
->tex
[u
][3];
410 if (ctx
->FragmentProgram
._Enabled
) {
411 /* do perspective correction but don't divide s, t, r by q */
412 const GLfloat dwdx
= span
->dwdx
;
414 for (i
= 0; i
< span
->end
; i
++) {
415 const GLfloat invW
= 1.0F
/ w
;
416 texcoord
[i
][0] = s
* invW
;
417 texcoord
[i
][1] = t
* invW
;
418 texcoord
[i
][2] = r
* invW
;
419 texcoord
[i
][3] = q
* invW
;
420 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
421 dqdx
, dqdy
, texW
, texH
,
432 for (i
= 0; i
< span
->end
; i
++) {
433 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
434 texcoord
[i
][0] = s
* invQ
;
435 texcoord
[i
][1] = t
* invQ
;
436 texcoord
[i
][2] = r
* invQ
;
438 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
439 dqdx
, dqdy
, texW
, texH
,
447 span
->arrayMask
|= SPAN_LAMBDA
;
450 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
451 GLfloat
*lambda
= span
->array
->lambda
[u
];
452 const GLfloat dsdx
= span
->texStepX
[u
][0];
453 const GLfloat dtdx
= span
->texStepX
[u
][1];
454 const GLfloat drdx
= span
->texStepX
[u
][2];
455 const GLfloat dqdx
= span
->texStepX
[u
][3];
456 GLfloat s
= span
->tex
[u
][0];
457 GLfloat t
= span
->tex
[u
][1];
458 GLfloat r
= span
->tex
[u
][2];
459 GLfloat q
= span
->tex
[u
][3];
461 if (ctx
->FragmentProgram
._Enabled
) {
462 /* do perspective correction but don't divide s, t, r by q */
463 const GLfloat dwdx
= span
->dwdx
;
465 for (i
= 0; i
< span
->end
; i
++) {
466 const GLfloat invW
= 1.0F
/ w
;
467 texcoord
[i
][0] = s
* invW
;
468 texcoord
[i
][1] = t
* invW
;
469 texcoord
[i
][2] = r
* invW
;
470 texcoord
[i
][3] = q
* invW
;
479 else if (dqdx
== 0.0F
) {
480 /* Ortho projection or polygon's parallel to window X axis */
481 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
482 for (i
= 0; i
< span
->end
; i
++) {
483 texcoord
[i
][0] = s
* invQ
;
484 texcoord
[i
][1] = t
* invQ
;
485 texcoord
[i
][2] = r
* invQ
;
494 for (i
= 0; i
< span
->end
; i
++) {
495 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
496 texcoord
[i
][0] = s
* invQ
;
497 texcoord
[i
][1] = t
* invQ
;
498 texcoord
[i
][2] = r
* invQ
;
513 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
515 GLboolean needLambda
;
517 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
518 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
519 || ctx
->FragmentProgram
._Enabled
;
520 texW
= (GLfloat
) img
->WidthScale
;
521 texH
= (GLfloat
) img
->HeightScale
;
524 needLambda
= GL_FALSE
;
527 span
->arrayMask
|= SPAN_TEXTURE
;
529 /* just texture unit 0, with lambda */
530 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
531 GLfloat
*lambda
= span
->array
->lambda
[0];
532 const GLfloat dsdx
= span
->texStepX
[0][0];
533 const GLfloat dsdy
= span
->texStepY
[0][0];
534 const GLfloat dtdx
= span
->texStepX
[0][1];
535 const GLfloat dtdy
= span
->texStepY
[0][1];
536 const GLfloat drdx
= span
->texStepX
[0][2];
537 const GLfloat dqdx
= span
->texStepX
[0][3];
538 const GLfloat dqdy
= span
->texStepY
[0][3];
539 GLfloat s
= span
->tex
[0][0];
540 GLfloat t
= span
->tex
[0][1];
541 GLfloat r
= span
->tex
[0][2];
542 GLfloat q
= span
->tex
[0][3];
544 if (ctx
->FragmentProgram
._Enabled
) {
545 /* do perspective correction but don't divide s, t, r by q */
546 const GLfloat dwdx
= span
->dwdx
;
548 for (i
= 0; i
< span
->end
; i
++) {
549 const GLfloat invW
= 1.0F
/ w
;
550 texcoord
[i
][0] = s
* invW
;
551 texcoord
[i
][1] = t
* invW
;
552 texcoord
[i
][2] = r
* invW
;
553 texcoord
[i
][3] = q
* invW
;
554 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
555 dqdx
, dqdy
, texW
, texH
,
566 for (i
= 0; i
< span
->end
; i
++) {
567 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
568 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
569 dqdx
, dqdy
, texW
, texH
,
571 texcoord
[i
][0] = s
* invQ
;
572 texcoord
[i
][1] = t
* invQ
;
573 texcoord
[i
][2] = r
* invQ
;
581 span
->arrayMask
|= SPAN_LAMBDA
;
584 /* just texture 0, without lambda */
585 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
586 const GLfloat dsdx
= span
->texStepX
[0][0];
587 const GLfloat dtdx
= span
->texStepX
[0][1];
588 const GLfloat drdx
= span
->texStepX
[0][2];
589 const GLfloat dqdx
= span
->texStepX
[0][3];
590 GLfloat s
= span
->tex
[0][0];
591 GLfloat t
= span
->tex
[0][1];
592 GLfloat r
= span
->tex
[0][2];
593 GLfloat q
= span
->tex
[0][3];
595 if (ctx
->FragmentProgram
._Enabled
) {
596 /* do perspective correction but don't divide s, t, r by q */
597 const GLfloat dwdx
= span
->dwdx
;
599 for (i
= 0; i
< span
->end
; i
++) {
600 const GLfloat invW
= 1.0F
/ w
;
601 texcoord
[i
][0] = s
* invW
;
602 texcoord
[i
][1] = t
* invW
;
603 texcoord
[i
][2] = r
* invW
;
604 texcoord
[i
][3] = q
* invW
;
612 else if (dqdx
== 0.0F
) {
613 /* Ortho projection or polygon's parallel to window X axis */
614 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
615 for (i
= 0; i
< span
->end
; i
++) {
616 texcoord
[i
][0] = s
* invQ
;
617 texcoord
[i
][1] = t
* invQ
;
618 texcoord
[i
][2] = r
* invQ
;
626 for (i
= 0; i
< span
->end
; i
++) {
627 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
628 texcoord
[i
][0] = s
* invQ
;
629 texcoord
[i
][1] = t
* invQ
;
630 texcoord
[i
][2] = r
* invQ
;
644 * Apply the current polygon stipple pattern to a span of pixels.
647 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
649 const GLuint highbit
= 0x80000000;
650 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
651 GLubyte
*mask
= span
->array
->mask
;
654 ASSERT(ctx
->Polygon
.StippleFlag
);
655 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
657 m
= highbit
>> (GLuint
) (span
->x
% 32);
659 for (i
= 0; i
< span
->end
; i
++) {
660 if ((m
& stipple
) == 0) {
668 span
->writeAll
= GL_FALSE
;
673 * Clip a pixel span to the current buffer/window boundaries:
674 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
675 * window clipping and scissoring.
676 * Return: GL_TRUE some pixels still visible
677 * GL_FALSE nothing visible
680 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
682 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
683 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
684 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
685 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
687 if (span
->arrayMask
& SPAN_XY
) {
688 /* arrays of x/y pixel coords */
689 const GLint
*x
= span
->array
->x
;
690 const GLint
*y
= span
->array
->y
;
691 const GLint n
= span
->end
;
692 GLubyte
*mask
= span
->array
->mask
;
694 if (span
->arrayMask
& SPAN_MASK
) {
695 /* note: using & intead of && to reduce branches */
696 for (i
= 0; i
< n
; i
++) {
697 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
698 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
702 /* note: using & intead of && to reduce branches */
703 for (i
= 0; i
< n
; i
++) {
704 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
705 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
708 return GL_TRUE
; /* some pixels visible */
711 /* horizontal span of pixels */
712 const GLint x
= span
->x
;
713 const GLint y
= span
->y
;
714 const GLint n
= span
->end
;
716 /* Trivial rejection tests */
717 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
719 return GL_FALSE
; /* all pixels clipped */
722 /* Clip to the left */
724 ASSERT(x
+ n
> xmin
);
725 span
->writeAll
= GL_FALSE
;
726 _mesa_bzero(span
->array
->mask
, (xmin
- x
) * sizeof(GLubyte
));
732 span
->end
= xmax
- x
;
735 return GL_TRUE
; /* some pixels visible */
742 * Draw to more than one color buffer (or none).
745 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
747 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
750 /* loop over four possible dest color buffers */
751 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
752 if (bufferBit
& ctx
->Color
._DrawDestMask
[0]) {
753 GLuint indexTmp
[MAX_WIDTH
];
754 ASSERT(span
->end
< MAX_WIDTH
);
756 /* Set the current read/draw buffer */
757 swrast
->CurrentBufferBit
= bufferBit
;
758 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
760 /* make copy of incoming indexes */
761 MEMCPY( indexTmp
, span
->array
->index
, span
->end
* sizeof(GLuint
) );
763 if (ctx
->Color
.IndexLogicOpEnabled
) {
764 _swrast_logicop_ci_span(ctx
, span
, indexTmp
);
767 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
768 _swrast_mask_index_span(ctx
, span
, indexTmp
);
771 if (span
->arrayMask
& SPAN_XY
) {
772 /* array of pixel coords */
773 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
774 span
->array
->x
, span
->array
->y
,
775 indexTmp
, span
->array
->mask
);
778 /* horizontal run of pixels */
779 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
780 indexTmp
, span
->array
->mask
);
785 /* restore default dest buffer */
786 _swrast_use_draw_buffer(ctx
);
791 * Draw to more than one RGBA color buffer (or none).
792 * All fragment operations, up to (but not) blending/logicop should
793 * have been done first.
796 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
798 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
800 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
802 ASSERT(colorMask
!= 0x0);
804 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
807 /* loop over four possible dest color buffers */
808 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
809 if (bufferBit
& ctx
->Color
._DrawDestMask
[0]) {
810 GLchan rgbaTmp
[MAX_WIDTH
][4];
811 ASSERT(span
->end
< MAX_WIDTH
);
813 /* Set the current read/draw buffer */
814 swrast
->CurrentBufferBit
= bufferBit
;
815 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
817 /* make copy of incoming colors */
818 MEMCPY( rgbaTmp
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
) );
820 if (ctx
->Color
._LogicOpEnabled
) {
821 _swrast_logicop_rgba_span(ctx
, span
, rgbaTmp
);
823 else if (ctx
->Color
.BlendEnabled
) {
824 _swrast_blend_span(ctx
, span
, rgbaTmp
);
827 if (colorMask
!= 0xffffffff) {
828 _swrast_mask_rgba_span(ctx
, span
, rgbaTmp
);
831 if (span
->arrayMask
& SPAN_XY
) {
832 /* array of pixel coords */
833 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
834 span
->array
->x
, span
->array
->y
,
835 (const GLchan (*)[4]) rgbaTmp
,
837 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
838 _swrast_write_alpha_pixels(ctx
, span
->end
,
839 span
->array
->x
, span
->array
->y
,
840 (const GLchan (*)[4]) rgbaTmp
,
845 /* horizontal run of pixels */
846 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
847 (const GLchan (*)[4]) rgbaTmp
,
849 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
850 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
851 (const GLchan (*)[4]) rgbaTmp
,
858 /* restore default dest buffer */
859 _swrast_use_draw_buffer(ctx
);
865 * This function may modify any of the array values in the span.
866 * span->interpMask and span->arrayMask may be changed but will be restored
867 * to their original values before returning.
870 _swrast_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
872 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
873 const GLuint origInterpMask
= span
->interpMask
;
874 const GLuint origArrayMask
= span
->arrayMask
;
876 ASSERT(span
->end
<= MAX_WIDTH
);
877 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
878 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
879 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
880 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
882 if (span
->arrayMask
& SPAN_MASK
) {
883 /* mask was initialized by caller, probably glBitmap */
884 span
->writeAll
= GL_FALSE
;
887 MEMSET(span
->array
->mask
, 1, span
->end
);
888 span
->writeAll
= GL_TRUE
;
892 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
893 if (!clip_span(ctx
, span
)) {
898 /* Depth bounds test */
899 if (ctx
->Depth
.BoundsTest
&& ctx
->Visual
.depthBits
> 0) {
900 if (!_swrast_depth_bounds_test(ctx
, span
)) {
906 if (span
->arrayMask
& SPAN_XY
) {
908 for (i
= 0; i
< span
->end
; i
++) {
909 if (span
->array
->mask
[i
]) {
910 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
911 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
912 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
913 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
919 /* Polygon Stippling */
920 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
921 stipple_polygon_span(ctx
, span
);
924 /* Depth test and stencil */
925 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
926 if (span
->interpMask
& SPAN_Z
)
927 _swrast_span_interpolate_z(ctx
, span
);
929 if (ctx
->Stencil
.Enabled
) {
930 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
931 span
->arrayMask
= origArrayMask
;
936 ASSERT(ctx
->Depth
.Test
);
937 if (!_swrast_depth_test_span(ctx
, span
)) {
938 span
->arrayMask
= origArrayMask
;
944 /* if we get here, something passed the depth test */
945 if (ctx
->Depth
.OcclusionTest
) {
946 ctx
->OcclusionResult
= GL_TRUE
;
949 #if FEATURE_ARB_occlusion_query
950 if (ctx
->Occlusion
.Active
) {
951 /* update count of 'passed' fragments */
953 for (i
= 0; i
< span
->end
; i
++)
954 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
958 /* we have to wait until after occlusion to do this test */
959 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
960 /* write no pixels */
961 span
->arrayMask
= origArrayMask
;
965 /* Interpolate the color indexes if needed */
966 if (span
->interpMask
& SPAN_INDEX
) {
967 interpolate_indexes(ctx
, span
);
968 /* clear the bit - this allows the WriteMonoCISpan optimization below */
969 span
->interpMask
&= ~SPAN_INDEX
;
973 if (ctx
->Fog
.Enabled
) {
974 _swrast_fog_ci_span(ctx
, span
);
977 /* Antialias coverage application */
978 if (span
->arrayMask
& SPAN_COVERAGE
) {
980 GLuint
*index
= span
->array
->index
;
981 GLfloat
*coverage
= span
->array
->coverage
;
982 for (i
= 0; i
< span
->end
; i
++) {
983 ASSERT(coverage
[i
] < 16);
984 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) coverage
[i
]);
988 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
989 /* draw to zero or two or more buffers */
990 multi_write_index_span(ctx
, span
);
993 /* normal situation: draw to exactly one buffer */
994 if (ctx
->Color
.IndexLogicOpEnabled
) {
995 _swrast_logicop_ci_span(ctx
, span
, span
->array
->index
);
998 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
999 _swrast_mask_index_span(ctx
, span
, span
->array
->index
);
1003 if (span
->arrayMask
& SPAN_XY
) {
1004 /* array of pixel coords */
1005 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
1006 /* all pixels have same color index */
1007 (*swrast
->Driver
.WriteMonoCIPixels
)(ctx
, span
->end
,
1008 span
->array
->x
, span
->array
->y
,
1009 FixedToInt(span
->index
),
1013 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->array
->x
,
1014 span
->array
->y
, span
->array
->index
,
1015 span
->array
->mask
);
1019 /* horizontal run of pixels */
1020 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
1021 /* all pixels have same color index */
1022 (*swrast
->Driver
.WriteMonoCISpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1023 FixedToInt(span
->index
),
1027 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
1034 span
->interpMask
= origInterpMask
;
1035 span
->arrayMask
= origArrayMask
;
1040 * This function may modify any of the array values in the span.
1041 * span->interpMask and span->arrayMask may be changed but will be restored
1042 * to their original values before returning.
1045 _swrast_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
1047 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1048 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1049 const GLuint origInterpMask
= span
->interpMask
;
1050 const GLuint origArrayMask
= span
->arrayMask
;
1051 GLboolean monoColor
;
1053 ASSERT(span
->end
<= MAX_WIDTH
);
1054 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1055 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1056 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1057 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_RGBA
);
1059 if (ctx
->Fog
.Enabled
)
1060 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
1061 if (ctx
->Depth
.Test
)
1062 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_Z
);
1065 if (span
->arrayMask
& SPAN_MASK
) {
1066 /* mask was initialized by caller, probably glBitmap */
1067 span
->writeAll
= GL_FALSE
;
1070 MEMSET(span
->array
->mask
, 1, span
->end
);
1071 span
->writeAll
= GL_TRUE
;
1074 /* Determine if we have mono-chromatic colors */
1075 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
1076 span
->redStep
== 0 && span
->greenStep
== 0 &&
1077 span
->blueStep
== 0 && span
->alphaStep
== 0;
1080 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1081 if (!clip_span(ctx
, span
)) {
1086 /* Depth bounds test */
1087 if (ctx
->Depth
.BoundsTest
&& ctx
->Visual
.depthBits
> 0) {
1088 if (!_swrast_depth_bounds_test(ctx
, span
)) {
1094 if (span
->arrayMask
& SPAN_XY
) {
1096 for (i
= 0; i
< span
->end
; i
++) {
1097 if (span
->array
->mask
[i
]) {
1098 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1099 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1100 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1101 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1107 /* Polygon Stippling */
1108 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1109 stipple_polygon_span(ctx
, span
);
1112 /* Fragment program */
1113 if (ctx
->FragmentProgram
._Enabled
) {
1114 /* Now we may need to interpolate the colors and texcoords */
1115 if ((span
->interpMask
& SPAN_RGBA
) &&
1116 (span
->arrayMask
& SPAN_RGBA
) == 0) {
1117 interpolate_colors(ctx
, span
);
1118 span
->interpMask
&= ~SPAN_RGBA
;
1120 if (span
->interpMask
& SPAN_SPEC
) {
1121 interpolate_specular(ctx
, span
);
1123 if ((span
->interpMask
& SPAN_TEXTURE
)
1124 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1125 interpolate_texcoords(ctx
, span
);
1126 _swrast_exec_fragment_program(ctx
, span
);
1127 monoColor
= GL_FALSE
;
1130 /* Do the alpha test */
1131 if (ctx
->Color
.AlphaEnabled
) {
1132 if (!_swrast_alpha_test(ctx
, span
)) {
1133 span
->interpMask
= origInterpMask
;
1134 span
->arrayMask
= origArrayMask
;
1139 /* Stencil and Z testing */
1140 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1141 if (span
->interpMask
& SPAN_Z
)
1142 _swrast_span_interpolate_z(ctx
, span
);
1144 if (ctx
->Stencil
.Enabled
) {
1145 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1146 span
->interpMask
= origInterpMask
;
1147 span
->arrayMask
= origArrayMask
;
1152 ASSERT(ctx
->Depth
.Test
);
1153 ASSERT(span
->arrayMask
& SPAN_Z
);
1154 /* regular depth testing */
1155 if (!_swrast_depth_test_span(ctx
, span
)) {
1156 span
->interpMask
= origInterpMask
;
1157 span
->arrayMask
= origArrayMask
;
1163 /* if we get here, something passed the depth test */
1164 if (ctx
->Depth
.OcclusionTest
) {
1165 ctx
->OcclusionResult
= GL_TRUE
;
1168 #if FEATURE_ARB_occlusion_query
1169 if (ctx
->Occlusion
.Active
) {
1170 /* update count of 'passed' fragments */
1172 for (i
= 0; i
< span
->end
; i
++)
1173 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
1177 /* can't abort span-writing until after occlusion testing */
1178 if (colorMask
== 0x0) {
1179 span
->interpMask
= origInterpMask
;
1180 span
->arrayMask
= origArrayMask
;
1184 /* Now we may need to interpolate the colors */
1185 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
1186 interpolate_colors(ctx
, span
);
1187 /* clear the bit - this allows the WriteMonoCISpan optimization below */
1188 span
->interpMask
&= ~SPAN_RGBA
;
1192 if (swrast
->_FogEnabled
) {
1193 _swrast_fog_rgba_span(ctx
, span
);
1194 monoColor
= GL_FALSE
;
1197 /* Antialias coverage application */
1198 if (span
->arrayMask
& SPAN_COVERAGE
) {
1199 GLchan (*rgba
)[4] = span
->array
->rgba
;
1200 GLfloat
*coverage
= span
->array
->coverage
;
1202 for (i
= 0; i
< span
->end
; i
++) {
1203 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1205 monoColor
= GL_FALSE
;
1208 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1209 multi_write_rgba_span(ctx
, span
);
1212 /* normal: write to exactly one buffer */
1213 if (ctx
->Color
._LogicOpEnabled
) {
1214 _swrast_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1215 monoColor
= GL_FALSE
;
1217 else if (ctx
->Color
.BlendEnabled
) {
1218 _swrast_blend_span(ctx
, span
, span
->array
->rgba
);
1219 monoColor
= GL_FALSE
;
1222 /* Color component masking */
1223 if (colorMask
!= 0xffffffff) {
1224 _swrast_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1225 monoColor
= GL_FALSE
;
1229 if (span
->arrayMask
& SPAN_XY
) {
1230 /* array of pixel coords */
1232 /* all pixels have same color */
1234 color
[RCOMP
] = FixedToChan(span
->red
);
1235 color
[GCOMP
] = FixedToChan(span
->green
);
1236 color
[BCOMP
] = FixedToChan(span
->blue
);
1237 color
[ACOMP
] = FixedToChan(span
->alpha
);
1238 (*swrast
->Driver
.WriteMonoRGBAPixels
)(ctx
, span
->end
,
1239 span
->array
->x
, span
->array
->y
, color
, span
->array
->mask
);
1240 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1241 _swrast_write_mono_alpha_pixels(ctx
, span
->end
,
1242 span
->array
->x
, span
->array
->y
,
1243 color
[ACOMP
], span
->array
->mask
);
1247 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
1248 span
->array
->x
, span
->array
->y
,
1249 (const GLchan (*)[4]) span
->array
->rgba
,
1251 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1252 _swrast_write_alpha_pixels(ctx
, span
->end
,
1253 span
->array
->x
, span
->array
->y
,
1254 (const GLchan (*)[4]) span
->array
->rgba
,
1260 /* horizontal run of pixels */
1262 /* all pixels have same color */
1264 color
[RCOMP
] = FixedToChan(span
->red
);
1265 color
[GCOMP
] = FixedToChan(span
->green
);
1266 color
[BCOMP
] = FixedToChan(span
->blue
);
1267 color
[ACOMP
] = FixedToChan(span
->alpha
);
1268 (*swrast
->Driver
.WriteMonoRGBASpan
)(ctx
, span
->end
, span
->x
,
1269 span
->y
, color
, span
->array
->mask
);
1270 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1271 _swrast_write_mono_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1273 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1277 /* each pixel is a different color */
1278 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1279 (const GLchan (*)[4]) span
->array
->rgba
,
1280 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1281 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1282 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1283 (const GLchan (*)[4]) span
->array
->rgba
,
1284 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1290 span
->interpMask
= origInterpMask
;
1291 span
->arrayMask
= origArrayMask
;
1296 * Add specular color to base color. This is used only when
1297 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1300 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1303 for (i
= 0; i
< n
; i
++) {
1304 #if CHAN_TYPE == GL_FLOAT
1306 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1307 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1308 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1310 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1311 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1312 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1313 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1314 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1315 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1322 * This function may modify any of the array values in the span.
1323 * span->interpMask and span->arrayMask may be changed but will be restored
1324 * to their original values before returning.
1327 _swrast_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
1329 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1330 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1331 const GLuint origInterpMask
= span
->interpMask
;
1332 const GLuint origArrayMask
= span
->arrayMask
;
1334 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1335 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1336 ASSERT(span
->end
<= MAX_WIDTH
);
1337 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1338 ASSERT(ctx
->Texture
._EnabledCoordUnits
|| ctx
->FragmentProgram
._Enabled
);
1341 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1344 if (span
->arrayMask
& SPAN_MASK
) {
1345 /* mask was initialized by caller, probably glBitmap */
1346 span
->writeAll
= GL_FALSE
;
1349 MEMSET(span
->array
->mask
, 1, span
->end
);
1350 span
->writeAll
= GL_TRUE
;
1354 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1355 if (!clip_span(ctx
, span
)) {
1361 if (span
->arrayMask
& SPAN_XY
) {
1363 for (i
= 0; i
< span
->end
; i
++) {
1364 if (span
->array
->mask
[i
]) {
1365 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1366 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1367 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1368 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1374 /* Polygon Stippling */
1375 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1376 stipple_polygon_span(ctx
, span
);
1379 /* Need texture coordinates now */
1380 if ((span
->interpMask
& SPAN_TEXTURE
)
1381 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1382 interpolate_texcoords(ctx
, span
);
1384 /* Texture with alpha test */
1385 if (ctx
->Color
.AlphaEnabled
) {
1387 /* Now we need the rgba array, fill it in if needed */
1388 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1389 interpolate_colors(ctx
, span
);
1391 if (span
->interpMask
& SPAN_SPEC
) {
1392 interpolate_specular(ctx
, span
);
1395 /* Texturing without alpha is done after depth-testing which
1396 * gives a potential speed-up.
1398 if (ctx
->FragmentProgram
._Enabled
)
1399 _swrast_exec_fragment_program( ctx
, span
);
1401 _swrast_texture_span( ctx
, span
);
1403 /* Do the alpha test */
1404 if (!_swrast_alpha_test(ctx
, span
)) {
1405 span
->arrayMask
= origArrayMask
;
1410 /* Stencil and Z testing */
1411 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1412 if (span
->interpMask
& SPAN_Z
)
1413 _swrast_span_interpolate_z(ctx
, span
);
1415 if (ctx
->Stencil
.Enabled
) {
1416 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1417 span
->interpMask
= origInterpMask
;
1418 span
->arrayMask
= origArrayMask
;
1423 ASSERT(ctx
->Depth
.Test
);
1424 ASSERT(span
->arrayMask
& SPAN_Z
);
1425 /* regular depth testing */
1426 if (!_swrast_depth_test_span(ctx
, span
)) {
1427 span
->interpMask
= origInterpMask
;
1428 span
->arrayMask
= origArrayMask
;
1434 /* if we get here, some fragments passed the depth test */
1435 if (ctx
->Depth
.OcclusionTest
) {
1436 ctx
->OcclusionResult
= GL_TRUE
;
1439 #if FEATURE_ARB_occlusion_query
1440 if (ctx
->Occlusion
.Active
) {
1441 /* update count of 'passed' fragments */
1443 for (i
= 0; i
< span
->end
; i
++)
1444 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
1448 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1449 * the occlusion test.
1451 if (colorMask
== 0x0) {
1452 span
->interpMask
= origInterpMask
;
1453 span
->arrayMask
= origArrayMask
;
1457 /* Texture without alpha test */
1458 if (!ctx
->Color
.AlphaEnabled
) {
1460 /* Now we need the rgba array, fill it in if needed */
1461 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1462 interpolate_colors(ctx
, span
);
1464 if (span
->interpMask
& SPAN_SPEC
) {
1465 interpolate_specular(ctx
, span
);
1468 if (ctx
->FragmentProgram
._Enabled
)
1469 _swrast_exec_fragment_program( ctx
, span
);
1471 _swrast_texture_span( ctx
, span
);
1474 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1476 /* Add base and specular colors */
1477 if (ctx
->Fog
.ColorSumEnabled
||
1478 (ctx
->Light
.Enabled
&&
1479 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1480 if (span
->interpMask
& SPAN_SPEC
) {
1481 interpolate_specular(ctx
, span
);
1483 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1484 add_colors( span
->end
, span
->array
->rgba
, span
->array
->spec
);
1488 if (swrast
->_FogEnabled
) {
1489 _swrast_fog_rgba_span(ctx
, span
);
1492 /* Antialias coverage application */
1493 if (span
->arrayMask
& SPAN_COVERAGE
) {
1494 GLchan (*rgba
)[4] = span
->array
->rgba
;
1495 GLfloat
*coverage
= span
->array
->coverage
;
1497 for (i
= 0; i
< span
->end
; i
++) {
1498 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1502 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1503 multi_write_rgba_span(ctx
, span
);
1506 /* normal: write to exactly one buffer */
1507 if (ctx
->Color
._LogicOpEnabled
) {
1508 _swrast_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1510 else if (ctx
->Color
.BlendEnabled
) {
1511 _swrast_blend_span(ctx
, span
, span
->array
->rgba
);
1514 /* Color component masking */
1515 if (colorMask
!= 0xffffffff) {
1516 _swrast_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1520 if (span
->arrayMask
& SPAN_XY
) {
1521 /* array of pixel coords */
1522 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1523 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1524 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1525 _swrast_write_alpha_pixels(ctx
, span
->end
,
1526 span
->array
->x
, span
->array
->y
,
1527 (const GLchan (*)[4]) span
->array
->rgba
,
1532 /* horizontal run of pixels */
1533 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1534 (const GLchan (*)[4]) span
->array
->rgba
,
1535 span
->writeAll
? NULL
: span
->array
->mask
);
1536 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1537 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1538 (const GLchan (*)[4]) span
->array
->rgba
,
1539 span
->writeAll
? NULL
: span
->array
->mask
);
1544 span
->interpMask
= origInterpMask
;
1545 span
->arrayMask
= origArrayMask
;
1551 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1552 * reading ouside the buffer's boundaries.
1555 _swrast_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1556 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1558 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1559 const GLint bufWidth
= (GLint
) buffer
->Width
;
1560 const GLint bufHeight
= (GLint
) buffer
->Height
;
1562 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1563 /* completely above, below, or right */
1564 /* XXX maybe leave undefined? */
1565 _mesa_bzero(rgba
, 4 * n
* sizeof(GLchan
));
1570 /* left edge clippping */
1572 length
= (GLint
) n
- skip
;
1574 /* completely left of window */
1577 if (length
> bufWidth
) {
1581 else if ((GLint
) (x
+ n
) > bufWidth
) {
1582 /* right edge clipping */
1584 length
= bufWidth
- x
;
1586 /* completely to right of window */
1596 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1597 if (buffer
->UseSoftwareAlphaBuffers
) {
1598 _swrast_read_alpha_span(ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1605 * Read CI pixels from frame buffer. Clipping will be done to prevent
1606 * reading ouside the buffer's boundaries.
1609 _swrast_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1610 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1612 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1613 const GLint bufWidth
= (GLint
) buffer
->Width
;
1614 const GLint bufHeight
= (GLint
) buffer
->Height
;
1616 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1617 /* completely above, below, or right */
1618 _mesa_bzero(indx
, n
* sizeof(GLuint
));
1623 /* left edge clippping */
1625 length
= (GLint
) n
- skip
;
1627 /* completely left of window */
1630 if (length
> bufWidth
) {
1634 else if ((GLint
) (x
+ n
) > bufWidth
) {
1635 /* right edge clipping */
1637 length
= bufWidth
- x
;
1639 /* completely to right of window */
1649 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);