1 /* $Id: s_span.c,v 1.30 2002/02/02 21:40:33 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * pixel span rasterization:
30 * These functions implement the rasterization pipeline.
41 #include "s_alphabuf.h"
43 #include "s_context.h"
47 #include "s_masking.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 _mesa_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
);
63 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
);
65 span
->interpMask
|= SPAN_Z
;
70 * Init span's fog interpolation values to the RasterPos fog.
71 * Used during setup for glDraw/CopyPixels.
74 _mesa_span_default_fog( GLcontext
*ctx
, struct sw_span
*span
)
76 if (ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORDINATE_EXT
)
77 span
->fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterFogCoord
);
79 span
->fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
81 span
->interpMask
|= SPAN_FOG
;
86 * Init span's color or index interpolation values to the RasterPos color.
87 * Used during setup for glDraw/CopyPixels.
90 _mesa_span_default_color( GLcontext
*ctx
, struct sw_span
*span
)
92 if (ctx
->Visual
.rgbMode
) {
94 UNCLAMPED_FLOAT_TO_CHAN(r
, ctx
->Current
.RasterColor
[0]);
95 UNCLAMPED_FLOAT_TO_CHAN(g
, ctx
->Current
.RasterColor
[1]);
96 UNCLAMPED_FLOAT_TO_CHAN(b
, ctx
->Current
.RasterColor
[2]);
97 UNCLAMPED_FLOAT_TO_CHAN(a
, ctx
->Current
.RasterColor
[3]);
98 #if CHAN_TYPE == GL_FLOAT
104 span
->red
= IntToFixed(r
);
105 span
->green
= IntToFixed(g
);
106 span
->blue
= IntToFixed(b
);
107 span
->alpha
= IntToFixed(a
);
113 span
->interpMask
|= SPAN_RGBA
;
116 span
->index
= IntToFixed(ctx
->Current
.RasterIndex
);
118 span
->interpMask
|= SPAN_INDEX
;
123 /* Fill in the span.color.rgba array from the interpolation values */
125 interpolate_colors(GLcontext
*ctx
, struct sw_span
*span
)
127 GLfixed r
= span
->red
;
128 GLfixed g
= span
->green
;
129 GLfixed b
= span
->blue
;
130 GLfixed a
= span
->alpha
;
131 const GLint dr
= span
->redStep
;
132 const GLint dg
= span
->greenStep
;
133 const GLint db
= span
->blueStep
;
134 const GLint da
= span
->alphaStep
;
135 const GLuint n
= span
->end
;
136 GLchan (*rgba
)[4] = span
->color
.rgba
;
139 ASSERT(span
->interpMask
& SPAN_RGBA
);
141 if (span
->interpMask
& SPAN_FLAT
) {
144 color
[RCOMP
] = FixedToChan(r
);
145 color
[GCOMP
] = FixedToChan(g
);
146 color
[BCOMP
] = FixedToChan(b
);
147 color
[ACOMP
] = FixedToChan(a
);
148 for (i
= 0; i
< n
; i
++) {
149 COPY_CHAN4(span
->color
.rgba
[i
], color
);
154 for (i
= 0; i
< n
; i
++) {
155 rgba
[i
][RCOMP
] = FixedToChan(r
);
156 rgba
[i
][GCOMP
] = FixedToChan(g
);
157 rgba
[i
][BCOMP
] = FixedToChan(b
);
158 rgba
[i
][ACOMP
] = FixedToChan(a
);
165 span
->arrayMask
|= SPAN_RGBA
;
169 /* Fill in the span.color.index array from the interpolation values */
171 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
173 GLfixed index
= span
->index
;
174 const GLint indexStep
= span
->indexStep
;
175 const GLuint n
= span
->end
;
176 GLuint
*indexes
= span
->color
.index
;
178 ASSERT(span
->interpMask
& SPAN_INDEX
);
180 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
182 index
= FixedToInt(index
);
183 for (i
= 0; i
< n
; i
++) {
189 for (i
= 0; i
< n
; i
++) {
190 indexes
[i
] = FixedToInt(index
);
194 span
->arrayMask
|= SPAN_INDEX
;
198 /* Fill in the span.specArray array from the interpolation values */
200 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
202 if (span
->interpMask
& SPAN_FLAT
) {
204 const GLchan r
= FixedToChan(span
->specRed
);
205 const GLchan g
= FixedToChan(span
->specGreen
);
206 const GLchan b
= FixedToChan(span
->specBlue
);
208 for (i
= 0; i
< span
->end
; i
++) {
209 span
->specArray
[i
][RCOMP
] = r
;
210 span
->specArray
[i
][GCOMP
] = g
;
211 span
->specArray
[i
][BCOMP
] = b
;
216 #if CHAN_TYPE == GL_FLOAT
217 GLfloat r
= span
->specRed
;
218 GLfloat g
= span
->specGreen
;
219 GLfloat b
= span
->specBlue
;
221 GLfixed r
= span
->specRed
;
222 GLfixed g
= span
->specGreen
;
223 GLfixed b
= span
->specBlue
;
226 for (i
= 0; i
< span
->end
; i
++) {
227 span
->specArray
[i
][RCOMP
] = FixedToChan(r
);
228 span
->specArray
[i
][GCOMP
] = FixedToChan(g
);
229 span
->specArray
[i
][BCOMP
] = FixedToChan(b
);
230 r
+= span
->specRedStep
;
231 g
+= span
->specGreenStep
;
232 b
+= span
->specBlueStep
;
235 span
->arrayMask
|= SPAN_SPEC
;
239 /* Fill in the span.zArray array from the interpolation values */
241 interpolate_z(GLcontext
*ctx
, struct sw_span
*span
)
243 const GLuint n
= span
->end
;
246 ASSERT(span
->interpMask
& SPAN_Z
);
248 if (ctx
->Visual
.depthBits
<= 16) {
249 GLfixed zval
= span
->z
;
250 for (i
= 0; i
< n
; i
++) {
251 span
->zArray
[i
] = FixedToInt(zval
);
256 /* Deep Z buffer, no fixed->int shift */
257 GLfixed zval
= span
->z
;
258 for (i
= 0; i
< n
; i
++) {
259 span
->zArray
[i
] = zval
;
263 span
->arrayMask
|= SPAN_Z
;
268 /* Fill in the span.texcoords array from the interpolation values */
270 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
272 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
274 if (ctx
->Texture
._ReallyEnabled
& ~TEXTURE0_ANY
) {
275 if (span
->interpMask
& SPAN_LAMBDA
) {
276 /* multitexture, lambda */
278 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
279 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
280 const GLfloat ds
= span
->texStep
[u
][0];
281 const GLfloat dt
= span
->texStep
[u
][1];
282 const GLfloat dr
= span
->texStep
[u
][2];
283 const GLfloat dq
= span
->texStep
[u
][3];
284 GLfloat s
= span
->tex
[u
][0];
285 GLfloat t
= span
->tex
[u
][1];
286 GLfloat r
= span
->tex
[u
][2];
287 GLfloat q
= span
->tex
[u
][3];
289 for (i
= 0; i
< span
->end
; i
++) {
290 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
291 span
->texcoords
[u
][i
][0] = s
* invQ
;
292 span
->texcoords
[u
][i
][1] = t
* invQ
;
293 span
->texcoords
[u
][i
][2] = r
* invQ
;
294 span
->lambda
[u
][i
] = (GLfloat
)
295 (log(span
->rho
[u
] * invQ
* invQ
) * 1.442695F
* 0.5F
);
303 span
->arrayMask
|= SPAN_LAMBDA
;
306 /* multitexture, no lambda */
308 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
309 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
310 const GLfloat ds
= span
->texStep
[u
][0];
311 const GLfloat dt
= span
->texStep
[u
][1];
312 const GLfloat dr
= span
->texStep
[u
][2];
313 const GLfloat dq
= span
->texStep
[u
][3];
314 GLfloat s
= span
->tex
[u
][0];
315 GLfloat t
= span
->tex
[u
][1];
316 GLfloat r
= span
->tex
[u
][2];
317 GLfloat q
= span
->tex
[u
][3];
319 for (i
= 0; i
< span
->end
; i
++) {
320 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
321 span
->texcoords
[u
][i
][0] = s
* invQ
;
322 span
->texcoords
[u
][i
][1] = t
* invQ
;
323 span
->texcoords
[u
][i
][2] = r
* invQ
;
334 if (span
->interpMask
& SPAN_LAMBDA
) {
335 /* just texture unit 0, with lambda */
336 const GLfloat ds
= span
->texStep
[0][0];
337 const GLfloat dt
= span
->texStep
[0][1];
338 const GLfloat dr
= span
->texStep
[0][2];
339 const GLfloat dq
= span
->texStep
[0][3];
340 GLfloat s
= span
->tex
[0][0];
341 GLfloat t
= span
->tex
[0][1];
342 GLfloat r
= span
->tex
[0][2];
343 GLfloat q
= span
->tex
[0][3];
345 for (i
= 0; i
< span
->end
; i
++) {
346 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
347 span
->texcoords
[0][i
][0] = s
* invQ
;
348 span
->texcoords
[0][i
][1] = t
* invQ
;
349 span
->texcoords
[0][i
][2] = r
* invQ
;
350 span
->lambda
[0][i
] = (GLfloat
)
351 (log(span
->rho
[0] * invQ
* invQ
) * 1.442695F
* 0.5F
);
357 span
->arrayMask
|= SPAN_LAMBDA
;
360 /* just texture 0, without lambda */
361 const GLfloat ds
= span
->texStep
[0][0];
362 const GLfloat dt
= span
->texStep
[0][1];
363 const GLfloat dr
= span
->texStep
[0][2];
364 const GLfloat dq
= span
->texStep
[0][3];
365 GLfloat s
= span
->tex
[0][0];
366 GLfloat t
= span
->tex
[0][1];
367 GLfloat r
= span
->tex
[0][2];
368 GLfloat q
= span
->tex
[0][3];
370 for (i
= 0; i
< span
->end
; i
++) {
371 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
372 span
->texcoords
[0][i
][0] = s
* invQ
;
373 span
->texcoords
[0][i
][1] = t
* invQ
;
374 span
->texcoords
[0][i
][2] = r
* invQ
;
386 * Apply the current polygon stipple pattern to a span of pixels.
389 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
391 const GLuint highbit
= 0x80000000;
392 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
395 ASSERT(ctx
->Polygon
.StippleFlag
);
396 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
398 m
= highbit
>> (GLuint
) (span
->x
% 32);
400 for (i
= 0; i
< span
->end
; i
++) {
401 if ((m
& stipple
) == 0) {
409 span
->writeAll
= GL_FALSE
;
414 * Clip a pixel span to the current buffer/window boundaries:
415 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
416 * window clipping and scissoring.
417 * Return: GL_TRUE some pixels still visible
418 * GL_FALSE nothing visible
421 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
423 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
424 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
425 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
426 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
428 if (span
->arrayMask
& SPAN_XY
) {
429 /* arrays of x/y pixel coords */
430 const GLint
*x
= span
->xArray
;
431 const GLint
*y
= span
->yArray
;
432 const GLint n
= span
->end
;
433 GLubyte
*mask
= span
->mask
;
435 if (span
->arrayMask
& SPAN_MASK
) {
436 /* note: using & intead of && to reduce branches */
437 for (i
= 0; i
< n
; i
++) {
438 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
439 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
443 /* note: using & intead of && to reduce branches */
444 for (i
= 0; i
< n
; i
++) {
445 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
446 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
449 return GL_TRUE
; /* some pixels visible */
452 /* horizontal span of pixels */
453 const GLint x
= span
->x
;
454 const GLint y
= span
->y
;
455 const GLint n
= span
->end
;
457 /* Trivial rejection tests */
458 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
460 return GL_FALSE
; /* all pixels clipped */
463 /* Clip to the left */
465 ASSERT(x
+ n
> xmin
);
466 span
->writeAll
= GL_FALSE
;
467 BZERO(span
->mask
, (xmin
- x
) * sizeof(GLubyte
));
473 span
->end
= xmax
- x
;
476 return GL_TRUE
; /* some pixels visible */
483 * Draw to more than one color buffer (or none).
486 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
488 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
491 /* loop over four possible dest color buffers */
492 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
493 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
494 GLuint indexTmp
[MAX_WIDTH
];
495 ASSERT(span
->end
< MAX_WIDTH
);
497 if (bufferBit
== FRONT_LEFT_BIT
)
498 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
499 else if (bufferBit
== FRONT_RIGHT_BIT
)
500 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
501 else if (bufferBit
== BACK_LEFT_BIT
)
502 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
504 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
506 /* make copy of incoming indexes */
507 MEMCPY( indexTmp
, span
->color
.index
, span
->end
* sizeof(GLuint
) );
509 if (ctx
->Color
.IndexLogicOpEnabled
) {
510 _mesa_logicop_ci_span(ctx
, span
, indexTmp
);
513 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
514 _mesa_mask_index_span(ctx
, span
, indexTmp
);
517 if (span
->arrayMask
& SPAN_XY
) {
518 /* array of pixel coords */
519 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
520 span
->xArray
, span
->yArray
,
521 indexTmp
, span
->mask
);
524 /* horizontal run of pixels */
525 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
526 indexTmp
, span
->mask
);
531 /* restore default dest buffer */
532 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
537 * Draw to more than one RGBA color buffer (or none).
538 * All fragment operations, up to (but not) blending/logicop should
539 * have been done first.
542 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
544 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
546 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
548 ASSERT(colorMask
!= 0x0);
550 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
553 /* loop over four possible dest color buffers */
554 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
555 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
556 GLchan rgbaTmp
[MAX_WIDTH
][4];
557 ASSERT(span
->end
< MAX_WIDTH
);
559 if (bufferBit
== FRONT_LEFT_BIT
) {
560 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
561 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontLeftAlpha
;
563 else if (bufferBit
== FRONT_RIGHT_BIT
) {
564 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
565 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontRightAlpha
;
567 else if (bufferBit
== BACK_LEFT_BIT
) {
568 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
569 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackLeftAlpha
;
572 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
573 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackRightAlpha
;
576 /* make copy of incoming colors */
577 MEMCPY( rgbaTmp
, span
->color
.rgba
, 4 * span
->end
* sizeof(GLchan
) );
579 if (ctx
->Color
.ColorLogicOpEnabled
) {
580 _mesa_logicop_rgba_span(ctx
, span
, rgbaTmp
);
582 else if (ctx
->Color
.BlendEnabled
) {
583 _mesa_blend_span(ctx
, span
, rgbaTmp
);
586 if (colorMask
!= 0xffffffff) {
587 _mesa_mask_rgba_span(ctx
, span
, rgbaTmp
);
590 if (span
->arrayMask
& SPAN_XY
) {
591 /* array of pixel coords */
592 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
593 span
->xArray
, span
->yArray
,
594 (const GLchan (*)[4]) rgbaTmp
,
596 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
597 _mesa_write_alpha_pixels(ctx
, span
->end
,
598 span
->xArray
, span
->yArray
,
599 (const GLchan (*)[4]) rgbaTmp
,
604 /* horizontal run of pixels */
605 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
606 (const GLchan (*)[4]) rgbaTmp
,
608 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
609 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
610 (const GLchan (*)[4]) rgbaTmp
,
617 /* restore default dest buffer */
618 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
624 * This function may modify any of the array values in the span.
625 * span->interpMask and span->arrayMask may be changed but will be restored
626 * to their original values before returning.
629 _mesa_write_index_span( GLcontext
*ctx
, struct sw_span
*span
,
632 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
633 const GLuint origInterpMask
= span
->interpMask
;
634 const GLuint origArrayMask
= span
->arrayMask
;
636 ASSERT(span
->end
<= MAX_WIDTH
);
637 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
638 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
640 if (span
->arrayMask
& SPAN_MASK
) {
641 /* mask was initialized by caller, probably glBitmap */
642 span
->writeAll
= GL_FALSE
;
645 MEMSET(span
->mask
, 1, span
->end
);
646 span
->writeAll
= GL_TRUE
;
650 if ((swrast
->_RasterMask
& CLIP_BIT
) || (primitive
== GL_BITMAP
)
651 || (primitive
== GL_POINT
) || (primitive
== GL_LINE
)) {
652 if (!clip_span(ctx
, span
)) {
658 if (span
->arrayMask
& SPAN_XY
) {
660 for (i
= 0; i
< span
->end
; i
++) {
662 assert(span
->xArray
[i
] >= ctx
->DrawBuffer
->_Xmin
);
663 assert(span
->xArray
[i
] < ctx
->DrawBuffer
->_Xmax
);
664 assert(span
->yArray
[i
] >= ctx
->DrawBuffer
->_Ymin
);
665 assert(span
->yArray
[i
] < ctx
->DrawBuffer
->_Ymax
);
671 /* Polygon Stippling */
672 if (ctx
->Polygon
.StippleFlag
&& primitive
== GL_POLYGON
) {
673 stipple_polygon_span(ctx
, span
);
676 /* Depth test and stencil */
677 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
678 if (span
->interpMask
& SPAN_Z
)
679 interpolate_z(ctx
, span
);
681 if (ctx
->Stencil
.Enabled
) {
682 if (_mesa_stencil_and_ztest_span(ctx
, span
) == GL_FALSE
) {
683 span
->arrayMask
= origArrayMask
;
688 ASSERT(ctx
->Depth
.Test
);
689 if (_mesa_depth_test_span(ctx
, span
) == 0) {
690 span
->arrayMask
= origArrayMask
;
696 /* if we get here, something passed the depth test */
697 ctx
->OcclusionResult
= GL_TRUE
;
699 /* we have to wait until after occlusion to do this test */
700 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
701 /* write no pixels */
702 span
->arrayMask
= origArrayMask
;
706 /* Interpolate the color indexes if needed */
707 if (span
->interpMask
& SPAN_INDEX
) {
708 interpolate_indexes(ctx
, span
);
709 /* clear the bit - this allows the WriteMonoCISpan optimization below */
710 span
->interpMask
&= ~SPAN_INDEX
;
714 /* XXX try to simplify the fog code! */
715 if (ctx
->Fog
.Enabled
) {
716 if ((span
->arrayMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
717 _mesa_fog_ci_pixels_with_array( ctx
, span
, span
->fogArray
,
719 else if ((span
->interpMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
720 _mesa_fog_ci_pixels( ctx
, span
, span
->color
.index
);
722 _mesa_depth_fog_ci_pixels( ctx
, span
, span
->color
.index
);
725 /* Antialias coverage application */
726 if (span
->arrayMask
& SPAN_COVERAGE
) {
728 GLuint
*index
= span
->color
.index
;
729 for (i
= 0; i
< span
->end
; i
++) {
730 ASSERT(span
->coverage
[i
] < 16);
731 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) (span
->coverage
[i
]));
735 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
736 /* draw to zero or two or more buffers */
737 multi_write_index_span(ctx
, span
);
740 /* normal situation: draw to exactly one buffer */
741 if (ctx
->Color
.IndexLogicOpEnabled
) {
742 _mesa_logicop_ci_span(ctx
, span
, span
->color
.index
);
745 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
746 _mesa_mask_index_span(ctx
, span
, span
->color
.index
);
750 if (span
->arrayMask
& SPAN_XY
) {
751 /* array of pixel coords */
752 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
753 /* all pixels have same color index */
754 (*swrast
->Driver
.WriteMonoCIPixels
)(ctx
, span
->end
,
755 span
->xArray
, span
->yArray
,
756 FixedToInt(span
->index
),
760 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->xArray
,
761 span
->yArray
, span
->color
.index
,
766 /* horizontal run of pixels */
767 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
768 /* all pixels have same color index */
769 (*swrast
->Driver
.WriteMonoCISpan
)(ctx
, span
->end
, span
->x
, span
->y
,
770 FixedToInt(span
->index
),
774 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
775 span
->color
.index
, span
->mask
);
780 span
->interpMask
= origInterpMask
;
781 span
->arrayMask
= origArrayMask
;
786 * This function may modify any of the array values in the span.
787 * span->interpMask and span->arrayMask may be changed but will be restored
788 * to their original values before returning.
791 _mesa_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
,
794 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
795 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
796 const GLuint origInterpMask
= span
->interpMask
;
797 const GLuint origArrayMask
= span
->arrayMask
;
800 ASSERT(span
->end
<= MAX_WIDTH
);
801 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
802 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_RGBA
);
803 if (ctx
->Fog
.Enabled
)
804 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
807 printf("%s() interp 0x%x array 0x%x p=0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask, primitive);
810 if (span
->arrayMask
& SPAN_MASK
) {
811 /* mask was initialized by caller, probably glBitmap */
812 span
->writeAll
= GL_FALSE
;
815 MEMSET(span
->mask
, 1, span
->end
);
816 span
->writeAll
= GL_TRUE
;
819 /* Determine if we have mono-chromatic colors */
820 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
821 span
->redStep
== 0 && span
->greenStep
== 0 &&
822 span
->blueStep
== 0 && span
->alphaStep
== 0;
825 if ((swrast
->_RasterMask
& CLIP_BIT
) || (primitive
== GL_BITMAP
)
826 || (primitive
== GL_POINT
) || (primitive
== GL_LINE
)) {
827 if (!clip_span(ctx
, span
)) {
833 if (span
->arrayMask
& SPAN_XY
) {
835 for (i
= 0; i
< span
->end
; i
++) {
837 assert(span
->xArray
[i
] >= ctx
->DrawBuffer
->_Xmin
);
838 assert(span
->xArray
[i
] < ctx
->DrawBuffer
->_Xmax
);
839 assert(span
->yArray
[i
] >= ctx
->DrawBuffer
->_Ymin
);
840 assert(span
->yArray
[i
] < ctx
->DrawBuffer
->_Ymax
);
846 /* Polygon Stippling */
847 if (ctx
->Polygon
.StippleFlag
&& primitive
== GL_POLYGON
) {
848 stipple_polygon_span(ctx
, span
);
851 /* Do the alpha test */
852 if (ctx
->Color
.AlphaEnabled
) {
853 if (!_mesa_alpha_test(ctx
, span
)) {
854 span
->interpMask
= origInterpMask
;
855 span
->arrayMask
= origArrayMask
;
860 /* Stencil and Z testing */
861 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
862 if (span
->interpMask
& SPAN_Z
)
863 interpolate_z(ctx
, span
);
865 if (ctx
->Stencil
.Enabled
) {
866 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
867 span
->interpMask
= origInterpMask
;
868 span
->arrayMask
= origArrayMask
;
873 ASSERT(ctx
->Depth
.Test
);
874 ASSERT(span
->arrayMask
& SPAN_Z
);
875 /* regular depth testing */
876 if (!_mesa_depth_test_span(ctx
, span
)) {
877 span
->interpMask
= origInterpMask
;
878 span
->arrayMask
= origArrayMask
;
884 /* if we get here, something passed the depth test */
885 ctx
->OcclusionResult
= GL_TRUE
;
887 /* can't abort span-writing until after occlusion testing */
888 if (colorMask
== 0x0) {
889 span
->interpMask
= origInterpMask
;
890 span
->arrayMask
= origArrayMask
;
894 /* Now we may need to interpolate the colors */
895 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
896 interpolate_colors(ctx
, span
);
897 /* clear the bit - this allows the WriteMonoCISpan optimization below */
898 span
->interpMask
&= ~SPAN_RGBA
;
902 /* XXX try to simplify the fog code! */
903 if (ctx
->Fog
.Enabled
) {
904 if ((span
->arrayMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
) {
905 _mesa_fog_rgba_pixels_with_array(ctx
, span
, span
->fogArray
,
908 else if ((span
->interpMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
) {
909 _mesa_fog_rgba_pixels(ctx
, span
, span
->color
.rgba
);
912 if ((span
->interpMask
& SPAN_Z
) && (span
->arrayMask
& SPAN_Z
) == 0)
913 interpolate_z(ctx
, span
);
914 _mesa_depth_fog_rgba_pixels(ctx
, span
, span
->color
.rgba
);
916 monoColor
= GL_FALSE
;
919 /* Antialias coverage application */
920 if (span
->arrayMask
& SPAN_COVERAGE
) {
921 GLchan (*rgba
)[4] = span
->color
.rgba
;
923 for (i
= 0; i
< span
->end
; i
++) {
924 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * span
->coverage
[i
]);
926 monoColor
= GL_FALSE
;
929 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
930 multi_write_rgba_span(ctx
, span
);
933 /* normal: write to exactly one buffer */
935 if (ctx
->Color
.ColorLogicOpEnabled
) {
936 _mesa_logicop_rgba_span(ctx
, span
, span
->color
.rgba
);
937 monoColor
= GL_FALSE
;
939 else if (ctx
->Color
.BlendEnabled
) {
940 _mesa_blend_span(ctx
, span
, span
->color
.rgba
);
941 monoColor
= GL_FALSE
;
944 /* Color component masking */
945 if (colorMask
!= 0xffffffff) {
946 _mesa_mask_rgba_span(ctx
, span
, span
->color
.rgba
);
947 monoColor
= GL_FALSE
;
951 if (span
->arrayMask
& SPAN_XY
) {
952 /* array of pixel coords */
953 /* XXX test for mono color */
954 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->xArray
,
955 span
->yArray
, (const GLchan (*)[4]) span
->color
.rgba
, span
->mask
);
956 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
957 _mesa_write_alpha_pixels(ctx
, span
->end
,
958 span
->xArray
, span
->yArray
,
959 (const GLchan (*)[4]) span
->color
.rgba
,
964 /* horizontal run of pixels */
966 /* all pixels have same color */
968 color
[RCOMP
] = FixedToChan(span
->red
);
969 color
[GCOMP
] = FixedToChan(span
->green
);
970 color
[BCOMP
] = FixedToChan(span
->blue
);
971 color
[ACOMP
] = FixedToChan(span
->alpha
);
972 (*swrast
->Driver
.WriteMonoRGBASpan
)(ctx
, span
->end
, span
->x
,
973 span
->y
, color
, span
->mask
);
974 /* XXX software alpha buffer writes! */
977 /* each pixel is a different color */
978 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
979 (const GLchan (*)[4]) span
->color
.rgba
,
980 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->mask
);
981 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
982 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
983 (const GLchan (*)[4]) span
->color
.rgba
,
984 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->mask
);
990 span
->interpMask
= origInterpMask
;
991 span
->arrayMask
= origArrayMask
;
996 * Add specular color to base color. This is used only when
997 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1000 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1003 for (i
= 0; i
< n
; i
++) {
1004 #if CHAN_TYPE == GL_FLOAT
1006 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1007 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1008 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1010 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1011 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1012 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1013 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1014 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1015 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1022 * This function may modify any of the array values in the span.
1023 * span->interpMask and span->arrayMask may be changed but will be restored
1024 * to their original values before returning.
1027 _mesa_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
,
1030 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1031 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1032 const GLuint origArrayMask
= span
->arrayMask
;
1034 ASSERT(span
->end
<= MAX_WIDTH
);
1035 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1036 ASSERT(ctx
->Texture
._ReallyEnabled
);
1039 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1042 if (span
->arrayMask
& SPAN_MASK
) {
1043 /* mask was initialized by caller, probably glBitmap */
1044 span
->writeAll
= GL_FALSE
;
1047 MEMSET(span
->mask
, 1, span
->end
);
1048 span
->writeAll
= GL_TRUE
;
1052 if ((swrast
->_RasterMask
& CLIP_BIT
) || (primitive
== GL_BITMAP
)
1053 || (primitive
== GL_POINT
) || (primitive
== GL_LINE
)) {
1054 if (!clip_span(ctx
, span
)) {
1060 if (span
->arrayMask
& SPAN_XY
) {
1062 for (i
= 0; i
< span
->end
; i
++) {
1063 if (span
->mask
[i
]) {
1064 assert(span
->xArray
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1065 assert(span
->xArray
[i
] < ctx
->DrawBuffer
->_Xmax
);
1066 assert(span
->yArray
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1067 assert(span
->yArray
[i
] < ctx
->DrawBuffer
->_Ymax
);
1073 /* Polygon Stippling */
1074 if (ctx
->Polygon
.StippleFlag
&& primitive
== GL_POLYGON
) {
1075 stipple_polygon_span(ctx
, span
);
1078 /* Need texture coordinates now */
1079 if ((span
->interpMask
& SPAN_TEXTURE
)
1080 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1081 interpolate_texcoords(ctx
, span
);
1083 /* Texture with alpha test */
1084 if (ctx
->Color
.AlphaEnabled
) {
1086 /* Now we need the rgba array, fill it in if needed */
1087 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1088 interpolate_colors(ctx
, span
);
1090 /* Texturing without alpha is done after depth-testing which
1091 * gives a potential speed-up.
1093 _swrast_multitexture_fragments( ctx
, span
);
1095 /* Do the alpha test */
1096 if (!_mesa_alpha_test(ctx
, span
)) {
1097 span
->arrayMask
= origArrayMask
;
1102 /* Stencil and Z testing */
1103 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1104 if (span
->interpMask
& SPAN_Z
)
1105 interpolate_z(ctx
, span
);
1107 if (ctx
->Stencil
.Enabled
) {
1108 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
1109 span
->arrayMask
= origArrayMask
;
1114 ASSERT(ctx
->Depth
.Test
);
1115 ASSERT(span
->arrayMask
& SPAN_Z
);
1116 /* regular depth testing */
1117 if (!_mesa_depth_test_span(ctx
, span
)) {
1118 span
->arrayMask
= origArrayMask
;
1124 /* if we get here, some fragments passed the depth test */
1125 ctx
->OcclusionResult
= GL_TRUE
;
1127 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1128 * the occlusion test.
1130 if (colorMask
== 0x0) {
1131 span
->arrayMask
= origArrayMask
;
1135 /* Texture without alpha test */
1136 if (!ctx
->Color
.AlphaEnabled
) {
1138 /* Now we need the rgba array, fill it in if needed */
1139 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1140 interpolate_colors(ctx
, span
);
1142 _swrast_multitexture_fragments( ctx
, span
);
1145 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1147 /* Add base and specular colors */
1148 if (ctx
->Fog
.ColorSumEnabled
||
1149 (ctx
->Light
.Enabled
&&
1150 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1151 if (span
->interpMask
& SPAN_SPEC
) {
1152 interpolate_specular(ctx
, span
);
1154 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1155 add_colors( span
->end
, span
->color
.rgba
, span
->specArray
);
1159 /* XXX try to simplify the fog code! */
1160 if (ctx
->Fog
.Enabled
) {
1161 if ((span
->arrayMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
1162 _mesa_fog_rgba_pixels_with_array( ctx
, span
, span
->fogArray
,
1164 else if ((span
->interpMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
1165 _mesa_fog_rgba_pixels( ctx
, span
, span
->color
.rgba
);
1167 if ((span
->interpMask
& SPAN_Z
) && (span
->arrayMask
& SPAN_Z
) == 0)
1168 interpolate_z(ctx
, span
);
1169 _mesa_depth_fog_rgba_pixels(ctx
, span
, span
->color
.rgba
);
1173 /* Antialias coverage application */
1174 if (span
->arrayMask
& SPAN_COVERAGE
) {
1175 GLchan (*rgba
)[4] = span
->color
.rgba
;
1177 for (i
= 0; i
< span
->end
; i
++) {
1178 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * span
->coverage
[i
]);
1182 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1183 multi_write_rgba_span(ctx
, span
);
1186 /* normal: write to exactly one buffer */
1187 if (ctx
->Color
.ColorLogicOpEnabled
) {
1188 _mesa_logicop_rgba_span(ctx
, span
, span
->color
.rgba
);
1190 else if (ctx
->Color
.BlendEnabled
) {
1191 _mesa_blend_span(ctx
, span
, span
->color
.rgba
);
1194 if (colorMask
!= 0xffffffff) {
1195 _mesa_mask_rgba_span(ctx
, span
, span
->color
.rgba
);
1199 if (span
->arrayMask
& SPAN_XY
) {
1200 /* array of pixel coords */
1201 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->xArray
,
1202 span
->yArray
, (const GLchan (*)[4]) span
->color
.rgba
, span
->mask
);
1203 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1204 _mesa_write_alpha_pixels(ctx
, span
->end
,
1205 span
->xArray
, span
->yArray
,
1206 (const GLchan (*)[4]) span
->color
.rgba
,
1211 /* horizontal run of pixels */
1212 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1213 (const GLchan (*)[4]) span
->color
.rgba
,
1214 span
->writeAll
? NULL
: span
->mask
);
1215 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1216 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1217 (const GLchan (*)[4]) span
->color
.rgba
,
1218 span
->writeAll
? NULL
: span
->mask
);
1223 span
->arrayMask
= origArrayMask
;
1229 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1230 * reading ouside the buffer's boundaries.
1233 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1234 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1236 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1237 if (y
< 0 || y
>= buffer
->Height
1238 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1239 /* completely above, below, or right */
1240 /* XXX maybe leave undefined? */
1241 BZERO(rgba
, 4 * n
* sizeof(GLchan
));
1246 /* left edge clippping */
1248 length
= (GLint
) n
- skip
;
1250 /* completely left of window */
1253 if (length
> buffer
->Width
) {
1254 length
= buffer
->Width
;
1257 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1258 /* right edge clipping */
1260 length
= buffer
->Width
- x
;
1262 /* completely to right of window */
1272 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1273 if (buffer
->UseSoftwareAlphaBuffers
) {
1274 _mesa_read_alpha_span(ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1283 * Read CI pixels from frame buffer. Clipping will be done to prevent
1284 * reading ouside the buffer's boundaries.
1287 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1288 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1290 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1291 if (y
< 0 || y
>= buffer
->Height
1292 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1293 /* completely above, below, or right */
1294 BZERO(indx
, n
* sizeof(GLuint
));
1299 /* left edge clippping */
1301 length
= (GLint
) n
- skip
;
1303 /* completely left of window */
1306 if (length
> buffer
->Width
) {
1307 length
= buffer
->Width
;
1310 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1311 /* right edge clipping */
1313 length
= buffer
->Width
- x
;
1315 /* completely to right of window */
1325 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);