1 /* $Id: s_span.c,v 1.28 2002/01/31 00:27:43 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"
48 #include "s_scissor.h"
50 #include "s_stencil.h"
51 #include "s_texture.h"
55 * Init span's Z interpolation values to the RasterPos Z.
56 * Used during setup for glDraw/CopyPixels.
59 _mesa_span_default_z( GLcontext
*ctx
, struct sw_span
*span
)
61 if (ctx
->Visual
.depthBits
<= 16)
62 span
->z
= FloatToFixed(ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
);
64 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
);
66 span
->interpMask
|= SPAN_Z
;
71 * Init span's fog interpolation values to the RasterPos fog.
72 * Used during setup for glDraw/CopyPixels.
75 _mesa_span_default_fog( GLcontext
*ctx
, struct sw_span
*span
)
77 if (ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORDINATE_EXT
)
78 span
->fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterFogCoord
);
80 span
->fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
82 span
->interpMask
|= SPAN_FOG
;
87 * Init span's color or index interpolation values to the RasterPos color.
88 * Used during setup for glDraw/CopyPixels.
91 _mesa_span_default_color( GLcontext
*ctx
, struct sw_span
*span
)
93 if (ctx
->Visual
.rgbMode
) {
95 UNCLAMPED_FLOAT_TO_CHAN(r
, ctx
->Current
.RasterColor
[0]);
96 UNCLAMPED_FLOAT_TO_CHAN(g
, ctx
->Current
.RasterColor
[1]);
97 UNCLAMPED_FLOAT_TO_CHAN(b
, ctx
->Current
.RasterColor
[2]);
98 UNCLAMPED_FLOAT_TO_CHAN(a
, ctx
->Current
.RasterColor
[3]);
99 #if CHAN_TYPE == GL_FLOAT
105 span
->red
= IntToFixed(r
);
106 span
->green
= IntToFixed(g
);
107 span
->blue
= IntToFixed(b
);
108 span
->alpha
= IntToFixed(a
);
114 span
->interpMask
|= SPAN_RGBA
;
117 span
->index
= IntToFixed(ctx
->Current
.RasterIndex
);
119 span
->interpMask
|= SPAN_INDEX
;
124 /* Fill in the span.color.rgba array from the interpolation values */
126 interpolate_colors(GLcontext
*ctx
, struct sw_span
*span
)
128 GLfixed r
= span
->red
;
129 GLfixed g
= span
->green
;
130 GLfixed b
= span
->blue
;
131 GLfixed a
= span
->alpha
;
132 const GLint dr
= span
->redStep
;
133 const GLint dg
= span
->greenStep
;
134 const GLint db
= span
->blueStep
;
135 const GLint da
= span
->alphaStep
;
136 const GLuint n
= span
->end
;
137 GLchan (*rgba
)[4] = span
->color
.rgba
;
140 ASSERT(span
->interpMask
& SPAN_RGBA
);
142 if (span
->interpMask
& SPAN_FLAT
) {
145 color
[RCOMP
] = FixedToChan(r
);
146 color
[GCOMP
] = FixedToChan(g
);
147 color
[BCOMP
] = FixedToChan(b
);
148 color
[ACOMP
] = FixedToChan(a
);
149 for (i
= 0; i
< n
; i
++) {
150 COPY_CHAN4(span
->color
.rgba
[i
], color
);
155 for (i
= 0; i
< n
; i
++) {
156 rgba
[i
][RCOMP
] = FixedToChan(r
);
157 rgba
[i
][GCOMP
] = FixedToChan(g
);
158 rgba
[i
][BCOMP
] = FixedToChan(b
);
159 rgba
[i
][ACOMP
] = FixedToChan(a
);
166 span
->arrayMask
|= SPAN_RGBA
;
170 /* Fill in the span.color.index array from the interpolation values */
172 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
174 GLfixed index
= span
->index
;
175 const GLint indexStep
= span
->indexStep
;
176 const GLuint n
= span
->end
;
177 GLuint
*indexes
= span
->color
.index
;
179 ASSERT(span
->interpMask
& SPAN_INDEX
);
181 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
183 index
= FixedToInt(index
);
184 for (i
= 0; i
< n
; i
++) {
190 for (i
= 0; i
< n
; i
++) {
191 indexes
[i
] = FixedToInt(index
);
195 span
->arrayMask
|= SPAN_INDEX
;
199 /* Fill in the span.specArray array from the interpolation values */
201 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
203 if (span
->interpMask
& SPAN_FLAT
) {
205 const GLchan r
= FixedToChan(span
->specRed
);
206 const GLchan g
= FixedToChan(span
->specGreen
);
207 const GLchan b
= FixedToChan(span
->specBlue
);
209 for (i
= 0; i
< span
->end
; i
++) {
210 span
->specArray
[i
][RCOMP
] = r
;
211 span
->specArray
[i
][GCOMP
] = g
;
212 span
->specArray
[i
][BCOMP
] = b
;
217 #if CHAN_TYPE == GL_FLOAT
218 GLfloat r
= span
->specRed
;
219 GLfloat g
= span
->specGreen
;
220 GLfloat b
= span
->specBlue
;
222 GLfixed r
= span
->specRed
;
223 GLfixed g
= span
->specGreen
;
224 GLfixed b
= span
->specBlue
;
227 for (i
= 0; i
< span
->end
; i
++) {
228 span
->specArray
[i
][RCOMP
] = FixedToChan(r
);
229 span
->specArray
[i
][GCOMP
] = FixedToChan(g
);
230 span
->specArray
[i
][BCOMP
] = FixedToChan(b
);
231 r
+= span
->specRedStep
;
232 g
+= span
->specGreenStep
;
233 b
+= span
->specBlueStep
;
236 span
->arrayMask
|= SPAN_SPEC
;
240 /* Fill in the span.zArray array from the interpolation values */
242 interpolate_z(GLcontext
*ctx
, struct sw_span
*span
)
244 const GLuint n
= span
->end
;
247 ASSERT(span
->interpMask
& SPAN_Z
);
249 if (ctx
->Visual
.depthBits
<= 16) {
250 GLfixed zval
= span
->z
;
251 for (i
= 0; i
< n
; i
++) {
252 span
->zArray
[i
] = FixedToInt(zval
);
257 /* Deep Z buffer, no fixed->int shift */
258 GLfixed zval
= span
->z
;
259 for (i
= 0; i
< n
; i
++) {
260 span
->zArray
[i
] = zval
;
264 span
->arrayMask
|= SPAN_Z
;
269 /* Fill in the span.texcoords array from the interpolation values */
271 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
273 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
275 if (ctx
->Texture
._ReallyEnabled
& ~TEXTURE0_ANY
) {
276 if (span
->interpMask
& SPAN_LAMBDA
) {
277 /* multitexture, lambda */
279 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
280 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
281 const GLfloat ds
= span
->texStep
[u
][0];
282 const GLfloat dt
= span
->texStep
[u
][1];
283 const GLfloat dr
= span
->texStep
[u
][2];
284 const GLfloat dq
= span
->texStep
[u
][3];
285 GLfloat s
= span
->tex
[u
][0];
286 GLfloat t
= span
->tex
[u
][1];
287 GLfloat r
= span
->tex
[u
][2];
288 GLfloat q
= span
->tex
[u
][3];
290 for (i
= 0; i
< span
->end
; i
++) {
291 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
292 span
->texcoords
[u
][i
][0] = s
* invQ
;
293 span
->texcoords
[u
][i
][1] = t
* invQ
;
294 span
->texcoords
[u
][i
][2] = r
* invQ
;
295 span
->lambda
[u
][i
] = (GLfloat
)
296 (log(span
->rho
[u
] * invQ
* invQ
) * 1.442695F
* 0.5F
);
304 span
->arrayMask
|= SPAN_LAMBDA
;
307 /* multitexture, no lambda */
309 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
310 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
311 const GLfloat ds
= span
->texStep
[u
][0];
312 const GLfloat dt
= span
->texStep
[u
][1];
313 const GLfloat dr
= span
->texStep
[u
][2];
314 const GLfloat dq
= span
->texStep
[u
][3];
315 GLfloat s
= span
->tex
[u
][0];
316 GLfloat t
= span
->tex
[u
][1];
317 GLfloat r
= span
->tex
[u
][2];
318 GLfloat q
= span
->tex
[u
][3];
320 for (i
= 0; i
< span
->end
; i
++) {
321 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
322 span
->texcoords
[u
][i
][0] = s
* invQ
;
323 span
->texcoords
[u
][i
][1] = t
* invQ
;
324 span
->texcoords
[u
][i
][2] = r
* invQ
;
335 if (span
->interpMask
& SPAN_LAMBDA
) {
336 /* just texture unit 0, with lambda */
337 const GLfloat ds
= span
->texStep
[0][0];
338 const GLfloat dt
= span
->texStep
[0][1];
339 const GLfloat dr
= span
->texStep
[0][2];
340 const GLfloat dq
= span
->texStep
[0][3];
341 GLfloat s
= span
->tex
[0][0];
342 GLfloat t
= span
->tex
[0][1];
343 GLfloat r
= span
->tex
[0][2];
344 GLfloat q
= span
->tex
[0][3];
346 for (i
= 0; i
< span
->end
; i
++) {
347 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
348 span
->texcoords
[0][i
][0] = s
* invQ
;
349 span
->texcoords
[0][i
][1] = t
* invQ
;
350 span
->texcoords
[0][i
][2] = r
* invQ
;
351 span
->lambda
[0][i
] = (GLfloat
)
352 (log(span
->rho
[0] * invQ
* invQ
) * 1.442695F
* 0.5F
);
358 span
->arrayMask
|= SPAN_LAMBDA
;
361 /* just texture 0, witout lambda */
362 const GLfloat ds
= span
->texStep
[0][0];
363 const GLfloat dt
= span
->texStep
[0][1];
364 const GLfloat dr
= span
->texStep
[0][2];
365 const GLfloat dq
= span
->texStep
[0][3];
366 GLfloat s
= span
->tex
[0][0];
367 GLfloat t
= span
->tex
[0][1];
368 GLfloat r
= span
->tex
[0][2];
369 GLfloat q
= span
->tex
[0][3];
371 for (i
= 0; i
< span
->end
; i
++) {
372 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
373 span
->texcoords
[0][i
][0] = s
* invQ
;
374 span
->texcoords
[0][i
][1] = t
* invQ
;
375 span
->texcoords
[0][i
][2] = r
* invQ
;
387 * Apply the current polygon stipple pattern to a span of pixels.
390 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
392 const GLuint highbit
= 0x80000000;
393 GLuint i
, m
, stipple
;
395 stipple
= ctx
->PolygonStipple
[span
->y
% 32];
396 m
= highbit
>> (GLuint
) (span
->x
% 32);
398 for (i
= 0; i
< span
->end
; i
++) {
399 if ((m
& stipple
) == 0) {
407 span
->writeAll
= GL_FALSE
;
412 * Clip a pixel span to the current buffer/window boundaries.
413 * Return: GL_TRUE some pixel still visible
414 * GL_FALSE nothing visible
417 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
419 GLint x
= span
->x
, y
= span
->y
, n
= span
->end
;
421 /* Clip to top and bottom */
422 if (y
< 0 || y
>= ctx
->DrawBuffer
->Height
) {
427 /* Clip to the left */
430 /* completely off left side */
435 /* partially off left side */
436 span
->writeAll
= GL_FALSE
;
437 BZERO(span
->mask
, -x
* sizeof(GLubyte
));
443 if (x
+ n
> ctx
->DrawBuffer
->Width
) {
444 if (x
>= ctx
->DrawBuffer
->Width
) {
445 /* completely off right side */
450 /* partially off right side */
451 span
->end
= ctx
->DrawBuffer
->Width
- x
;
462 * Draw to more than one color buffer (or none).
465 multi_write_index_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
466 const GLuint indexes
[], const GLubyte mask
[] )
468 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
471 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
474 /* loop over four possible dest color buffers */
475 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
476 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
477 GLuint indexTmp
[MAX_WIDTH
];
478 ASSERT(n
< MAX_WIDTH
);
480 if (bufferBit
== FRONT_LEFT_BIT
)
481 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
482 else if (bufferBit
== FRONT_RIGHT_BIT
)
483 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
484 else if (bufferBit
== BACK_LEFT_BIT
)
485 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
487 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
489 /* make copy of incoming indexes */
490 MEMCPY( indexTmp
, indexes
, n
* sizeof(GLuint
) );
491 if (ctx
->Color
.IndexLogicOpEnabled
) {
492 _mesa_logicop_ci_span( ctx
, n
, x
, y
, indexTmp
, mask
);
494 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
495 _mesa_mask_index_span( ctx
, n
, x
, y
, indexTmp
);
497 (*swrast
->Driver
.WriteCI32Span
)( ctx
, n
, x
, y
, indexTmp
, mask
);
501 /* restore default dest buffer */
502 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
507 * Draw to more than one RGBA color buffer (or none).
508 * All fragment operations, up to (but not) blending/logicop should
509 * have been done first.
512 multi_write_rgba_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
513 CONST GLchan rgba
[][4], const GLubyte mask
[] )
515 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
517 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
519 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
522 /* loop over four possible dest color buffers */
523 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
524 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
525 GLchan rgbaTmp
[MAX_WIDTH
][4];
526 ASSERT(n
< MAX_WIDTH
);
528 if (bufferBit
== FRONT_LEFT_BIT
) {
529 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
530 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontLeftAlpha
;
532 else if (bufferBit
== FRONT_RIGHT_BIT
) {
533 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
534 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontRightAlpha
;
536 else if (bufferBit
== BACK_LEFT_BIT
) {
537 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
538 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackLeftAlpha
;
541 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
542 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackRightAlpha
;
545 /* make copy of incoming colors */
546 MEMCPY( rgbaTmp
, rgba
, 4 * n
* sizeof(GLchan
) );
548 if (ctx
->Color
.ColorLogicOpEnabled
) {
549 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgbaTmp
, mask
);
551 else if (ctx
->Color
.BlendEnabled
) {
552 _mesa_blend_span( ctx
, n
, x
, y
, rgbaTmp
, mask
);
554 if (colorMask
== 0x0) {
557 else if (colorMask
!= 0xffffffff) {
558 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgbaTmp
);
561 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
,
562 (const GLchan (*)[4]) rgbaTmp
, mask
);
563 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
564 _mesa_write_alpha_span( ctx
, n
, x
, y
,
565 (const GLchan (*)[4])rgbaTmp
, mask
);
570 /* restore default dest buffer */
571 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
577 * This function may modify any of the array values in the span.
578 * span->interpMask and span->arrayMask may be changed but will be restored
579 * to their original values before returning.
582 _mesa_write_index_span( GLcontext
*ctx
, struct sw_span
*span
,
585 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
586 const GLuint origInterpMask
= span
->interpMask
;
587 const GLuint origArrayMask
= span
->arrayMask
;
589 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
591 MEMSET(span
->mask
, 1, span
->end
);
592 span
->writeAll
= GL_TRUE
;
594 /* Window clipping */
595 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
596 if (clip_span(ctx
,span
) == GL_FALSE
) {
602 if (ctx
->Scissor
.Enabled
) {
603 if (_mesa_scissor_span( ctx
, span
) == GL_FALSE
) {
608 /* Polygon Stippling */
609 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
610 stipple_polygon_span(ctx
, span
);
613 /* Depth test and stencil */
614 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
615 if (span
->interpMask
& SPAN_Z
)
616 interpolate_z(ctx
, span
);
618 if (ctx
->Stencil
.Enabled
) {
619 if (_mesa_stencil_and_ztest_span(ctx
, span
) == GL_FALSE
) {
620 span
->arrayMask
= origArrayMask
;
625 ASSERT(ctx
->Depth
.Test
);
626 if (_mesa_depth_test_span(ctx
, span
) == 0) {
627 span
->arrayMask
= origArrayMask
;
633 /* if we get here, something passed the depth test */
634 ctx
->OcclusionResult
= GL_TRUE
;
636 /* we have to wait until after occlusion to do this test */
637 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
638 /* write no pixels */
639 span
->arrayMask
= origArrayMask
;
643 /* Interpolate the color indexes if needed */
644 if (span
->interpMask
& SPAN_INDEX
) {
645 interpolate_indexes(ctx
, span
);
646 /* clear the bit - this allows the WriteMonoCISpan optimization below */
647 span
->interpMask
&= ~SPAN_INDEX
;
651 /* XXX try to simplify the fog code! */
652 if (ctx
->Fog
.Enabled
) {
653 if ((span
->arrayMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
654 _mesa_fog_ci_pixels_with_array( ctx
, span
, span
->fogArray
,
656 else if ((span
->interpMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
657 _mesa_fog_ci_pixels( ctx
, span
, span
->color
.index
);
659 _mesa_depth_fog_ci_pixels( ctx
, span
, span
->color
.index
);
662 /* Antialias coverage application */
663 if (span
->arrayMask
& SPAN_COVERAGE
) {
665 GLuint
*index
= span
->color
.index
;
666 for (i
= 0; i
< span
->end
; i
++) {
667 ASSERT(span
->coverage
[i
] < 16);
668 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) (span
->coverage
[i
]));
672 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
673 /* draw to zero or two or more buffers */
674 multi_write_index_span( ctx
, span
->end
, span
->x
, span
->y
,
675 span
->color
.index
, span
->mask
);
678 /* normal situation: draw to exactly one buffer */
679 if (ctx
->Color
.IndexLogicOpEnabled
) {
680 _mesa_logicop_ci_span( ctx
, span
->end
, span
->x
, span
->y
,
681 span
->color
.index
, span
->mask
);
684 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
685 _mesa_mask_index_span( ctx
, span
->end
, span
->x
, span
->y
,
690 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
691 /* all pixels have same color index */
692 (*swrast
->Driver
.WriteMonoCISpan
)( ctx
, span
->end
, span
->x
, span
->y
,
693 FixedToInt(span
->index
),
697 (*swrast
->Driver
.WriteCI32Span
)( ctx
, span
->end
, span
->x
, span
->y
,
698 span
->color
.index
, span
->mask
);
702 span
->interpMask
= origInterpMask
;
703 span
->arrayMask
= origArrayMask
;
708 * This function may modify any of the array values in the span.
709 * span->interpMask and span->arrayMask may be changed but will be restored
710 * to their original values before returning.
713 _mesa_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
,
716 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
717 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
718 const GLuint origInterpMask
= span
->interpMask
;
719 const GLuint origArrayMask
= span
->arrayMask
;
722 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
723 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_RGBA
);
725 MEMSET(span
->mask
, 1, span
->end
);
726 span
->writeAll
= GL_TRUE
;
728 /* Determine if we have mono-chromatic colors */
729 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
730 span
->redStep
== 0 && span
->greenStep
== 0 &&
731 span
->blueStep
== 0 && span
->alphaStep
== 0;
733 /* Window clipping */
734 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
== GL_BITMAP
) {
735 if (clip_span(ctx
, span
) == GL_FALSE
) {
741 if (ctx
->Scissor
.Enabled
) {
742 if (!_mesa_scissor_span(ctx
, span
)) {
747 /* Polygon Stippling */
748 if (ctx
->Polygon
.StippleFlag
&& primitive
== GL_POLYGON
) {
749 stipple_polygon_span(ctx
, span
);
752 /* Do the alpha test */
753 if (ctx
->Color
.AlphaEnabled
) {
754 if (!_mesa_alpha_test(ctx
, span
)) {
755 span
->interpMask
= origInterpMask
;
756 span
->arrayMask
= origArrayMask
;
761 /* Stencil and Z testing */
762 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
763 if (span
->interpMask
& SPAN_Z
)
764 interpolate_z(ctx
, span
);
766 if (ctx
->Stencil
.Enabled
) {
767 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
768 span
->interpMask
= origInterpMask
;
769 span
->arrayMask
= origArrayMask
;
774 ASSERT(ctx
->Depth
.Test
);
775 ASSERT(span
->arrayMask
& SPAN_Z
);
776 /* regular depth testing */
777 if (!_mesa_depth_test_span(ctx
, span
)) {
778 span
->interpMask
= origInterpMask
;
779 span
->arrayMask
= origArrayMask
;
785 /* if we get here, something passed the depth test */
786 ctx
->OcclusionResult
= GL_TRUE
;
788 /* can't abort span-writing until after occlusion testing */
789 if (colorMask
== 0x0) {
790 span
->interpMask
= origInterpMask
;
791 span
->arrayMask
= origArrayMask
;
795 /* Now we may need to interpolate the colors */
796 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
797 interpolate_colors(ctx
, span
);
798 /* clear the bit - this allows the WriteMonoCISpan optimization below */
799 span
->interpMask
&= ~SPAN_RGBA
;
803 /* XXX try to simplify the fog code! */
804 if (ctx
->Fog
.Enabled
) {
805 if ((span
->arrayMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
806 _mesa_fog_rgba_pixels_with_array(ctx
, span
, span
->fogArray
,
808 else if ((span
->interpMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
809 _mesa_fog_rgba_pixels(ctx
, span
, span
->color
.rgba
);
811 if ((span
->interpMask
& SPAN_Z
) && (span
->arrayMask
& SPAN_Z
) == 0)
812 interpolate_z(ctx
, span
);
813 _mesa_depth_fog_rgba_pixels(ctx
, span
, span
->color
.rgba
);
815 monoColor
= GL_FALSE
;
818 /* Antialias coverage application */
819 if (span
->arrayMask
& SPAN_COVERAGE
) {
820 GLchan (*rgba
)[4] = span
->color
.rgba
;
822 for (i
= 0; i
< span
->end
; i
++) {
823 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * span
->coverage
[i
]);
825 monoColor
= GL_FALSE
;
828 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
829 multi_write_rgba_span( ctx
, span
->end
, span
->x
, span
->y
,
830 (const GLchan (*)[4]) span
->color
.rgba
,
834 /* normal: write to exactly one buffer */
835 if (ctx
->Color
.ColorLogicOpEnabled
) {
836 _mesa_logicop_rgba_span( ctx
, span
->end
, span
->x
, span
->y
,
837 span
->color
.rgba
, span
->mask
);
838 monoColor
= GL_FALSE
;
840 else if (ctx
->Color
.BlendEnabled
) {
841 _mesa_blend_span( ctx
, span
->end
, span
->x
, span
->y
,
842 span
->color
.rgba
, span
->mask
);
843 monoColor
= GL_FALSE
;
846 /* Color component masking */
847 if (colorMask
!= 0xffffffff) {
848 _mesa_mask_rgba_span( ctx
, span
->end
, span
->x
, span
->y
,
850 monoColor
= GL_FALSE
;
855 /* all pixels have same color */
857 color
[RCOMP
] = FixedToChan(span
->red
);
858 color
[GCOMP
] = FixedToChan(span
->green
);
859 color
[BCOMP
] = FixedToChan(span
->blue
);
860 color
[ACOMP
] = FixedToChan(span
->alpha
);
861 (*swrast
->Driver
.WriteMonoRGBASpan
)( ctx
, span
->end
, span
->x
, span
->y
,
865 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, span
->end
, span
->x
, span
->y
,
866 (const GLchan (*)[4]) span
->color
.rgba
,
867 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->mask
);
870 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
871 _mesa_write_alpha_span( ctx
, span
->end
, span
->x
, span
->y
,
872 (const GLchan (*)[4]) span
->color
.rgba
,
873 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->mask
);
877 span
->interpMask
= origInterpMask
;
878 span
->arrayMask
= origArrayMask
;
883 * Add specular color to base color. This is used only when
884 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
887 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
890 for (i
= 0; i
< n
; i
++) {
891 #if CHAN_TYPE == GL_FLOAT
893 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
894 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
895 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
897 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
898 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
899 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
900 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
901 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
902 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
909 * This function may modify any of the array values in the span.
910 * span->interpMask and span->arrayMask may be changed but will be restored
911 * to their original values before returning.
914 _mesa_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
,
917 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
918 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
919 const GLuint origArrayMask
= span
->arrayMask
;
921 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
922 ASSERT(ctx
->Texture
._ReallyEnabled
);
925 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
928 MEMSET(span
->mask
, 1, span
->end
);
929 span
->writeAll
= GL_TRUE
;
931 /* clip against window bounds */
932 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
933 if (clip_span(ctx
,span
) == GL_FALSE
) {
939 if (ctx
->Scissor
.Enabled
) {
940 if (_mesa_scissor_span( ctx
, span
) == GL_FALSE
) {
945 /* Polygon Stippling */
946 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
947 stipple_polygon_span( ctx
, span
);
950 /* Need texture coordinates now */
951 if ((span
->interpMask
& SPAN_TEXTURE
)
952 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
953 interpolate_texcoords(ctx
, span
);
955 /* Texture with alpha test */
956 if (ctx
->Color
.AlphaEnabled
) {
958 /* Now we need the rgba array, fill it in if needed */
959 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
960 interpolate_colors(ctx
, span
);
962 /* Texturing without alpha is done after depth-testing which
963 * gives a potential speed-up.
965 _swrast_multitexture_fragments( ctx
, span
);
967 /* Do the alpha test */
968 if (!_mesa_alpha_test(ctx
, span
)) {
969 span
->arrayMask
= origArrayMask
;
974 /* Stencil and Z testing */
975 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
976 if (span
->interpMask
& SPAN_Z
)
977 interpolate_z(ctx
, span
);
979 if (ctx
->Stencil
.Enabled
) {
980 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
981 span
->arrayMask
= origArrayMask
;
986 ASSERT(ctx
->Depth
.Test
);
987 ASSERT(span
->arrayMask
& SPAN_Z
);
988 /* regular depth testing */
989 if (!_mesa_depth_test_span(ctx
, span
)) {
990 span
->arrayMask
= origArrayMask
;
996 /* if we get here, some fragments passed the depth test */
997 ctx
->OcclusionResult
= GL_TRUE
;
999 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1000 * the occlusion test.
1002 if (colorMask
== 0x0) {
1003 span
->arrayMask
= origArrayMask
;
1007 /* Texture without alpha test */
1008 if (!ctx
->Color
.AlphaEnabled
) {
1010 /* Now we need the rgba array, fill it in if needed */
1011 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1012 interpolate_colors(ctx
, span
);
1014 _swrast_multitexture_fragments( ctx
, span
);
1017 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1019 /* Add base and specular colors */
1020 if (ctx
->Fog
.ColorSumEnabled
||
1021 (ctx
->Light
.Enabled
&&
1022 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1023 if (span
->interpMask
& SPAN_SPEC
) {
1024 interpolate_specular(ctx
, span
);
1026 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1027 add_colors( span
->end
, span
->color
.rgba
, span
->specArray
);
1031 /* XXX try to simplify the fog code! */
1032 if (ctx
->Fog
.Enabled
) {
1033 if ((span
->arrayMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
1034 _mesa_fog_rgba_pixels_with_array( ctx
, span
, span
->fogArray
,
1036 else if ((span
->interpMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
1037 _mesa_fog_rgba_pixels( ctx
, span
, span
->color
.rgba
);
1039 if ((span
->interpMask
& SPAN_Z
) && (span
->arrayMask
& SPAN_Z
) == 0)
1040 interpolate_z(ctx
, span
);
1041 _mesa_depth_fog_rgba_pixels(ctx
, span
, span
->color
.rgba
);
1045 /* Antialias coverage application */
1046 if (span
->arrayMask
& SPAN_COVERAGE
) {
1047 GLchan (*rgba
)[4] = span
->color
.rgba
;
1049 for (i
= 0; i
< span
->end
; i
++) {
1050 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * span
->coverage
[i
]);
1054 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1055 multi_write_rgba_span( ctx
, span
->end
, span
->x
, span
->y
,
1056 (const GLchan (*)[4]) span
->color
.rgba
,
1060 /* normal: write to exactly one buffer */
1061 if (ctx
->Color
.ColorLogicOpEnabled
) {
1062 _mesa_logicop_rgba_span( ctx
, span
->end
, span
->x
, span
->y
,
1063 span
->color
.rgba
, span
->mask
);
1065 else if (ctx
->Color
.BlendEnabled
) {
1066 _mesa_blend_span( ctx
, span
->end
, span
->x
, span
->y
,
1067 span
->color
.rgba
, span
->mask
);
1070 if (colorMask
!= 0xffffffff) {
1071 _mesa_mask_rgba_span( ctx
, span
->end
, span
->x
, span
->y
,
1075 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, span
->end
, span
->x
, span
->y
,
1076 (const GLchan (*)[4]) span
->color
.rgba
,
1077 span
->writeAll
? NULL
: span
->mask
);
1078 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1079 _mesa_write_alpha_span( ctx
, span
->end
, span
->x
, span
->y
,
1080 (const GLchan (*)[4]) span
->color
.rgba
,
1081 span
->writeAll
? NULL
: span
->mask
);
1085 span
->arrayMask
= origArrayMask
;
1091 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1092 * reading ouside the buffer's boundaries.
1095 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1096 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1098 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1099 if (y
< 0 || y
>= buffer
->Height
1100 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1101 /* completely above, below, or right */
1102 /* XXX maybe leave undefined? */
1103 BZERO(rgba
, 4 * n
* sizeof(GLchan
));
1108 /* left edge clippping */
1110 length
= (GLint
) n
- skip
;
1112 /* completely left of window */
1115 if (length
> buffer
->Width
) {
1116 length
= buffer
->Width
;
1119 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1120 /* right edge clipping */
1122 length
= buffer
->Width
- x
;
1124 /* completely to right of window */
1134 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1135 if (buffer
->UseSoftwareAlphaBuffers
) {
1136 _mesa_read_alpha_span( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1145 * Read CI pixels from frame buffer. Clipping will be done to prevent
1146 * reading ouside the buffer's boundaries.
1149 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1150 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1152 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1153 if (y
< 0 || y
>= buffer
->Height
1154 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1155 /* completely above, below, or right */
1156 BZERO(indx
, n
* sizeof(GLuint
));
1161 /* left edge clippping */
1163 length
= (GLint
) n
- skip
;
1165 /* completely left of window */
1168 if (length
> buffer
->Width
) {
1169 length
= buffer
->Width
;
1172 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1173 /* right edge clipping */
1175 length
= buffer
->Width
- x
;
1177 /* completely to right of window */
1187 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);