1 /* $Id: s_span.c,v 1.26 2002/01/28 03:42:28 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 if (ctx
->Fog
.Enabled
) {
652 if ((span
->arrayMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
653 _mesa_fog_ci_pixels_with_array( ctx
, span
, span
->fogArray
,
655 else if ((span
->interpMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
656 _mesa_fog_ci_pixels( ctx
, span
, span
->color
.index
);
658 _mesa_depth_fog_ci_pixels( ctx
, span
, span
->color
.index
);
661 /* Antialias coverage application */
662 if (span
->arrayMask
& SPAN_COVERAGE
) {
664 GLuint
*index
= span
->color
.index
;
665 for (i
= 0; i
< span
->end
; i
++) {
666 ASSERT(span
->coverage
[i
] < 16);
667 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) (span
->coverage
[i
]));
671 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
672 /* draw to zero or two or more buffers */
673 multi_write_index_span( ctx
, span
->end
, span
->x
, span
->y
,
674 span
->color
.index
, span
->mask
);
677 /* normal situation: draw to exactly one buffer */
678 if (ctx
->Color
.IndexLogicOpEnabled
) {
679 _mesa_logicop_ci_span( ctx
, span
->end
, span
->x
, span
->y
,
680 span
->color
.index
, span
->mask
);
683 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
684 _mesa_mask_index_span( ctx
, span
->end
, span
->x
, span
->y
,
689 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
690 /* all pixels have same color index */
691 (*swrast
->Driver
.WriteMonoCISpan
)( ctx
, span
->end
, span
->x
, span
->y
,
692 FixedToInt(span
->index
),
696 (*swrast
->Driver
.WriteCI32Span
)( ctx
, span
->end
, span
->x
, span
->y
,
697 span
->color
.index
, span
->mask
);
701 span
->interpMask
= origInterpMask
;
702 span
->arrayMask
= origArrayMask
;
707 * This function may modify any of the array values in the span.
708 * span->interpMask and span->arrayMask may be changed but will be restored
709 * to their original values before returning.
712 _mesa_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
,
715 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
716 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
717 const GLuint origInterpMask
= span
->interpMask
;
718 const GLuint origArrayMask
= span
->arrayMask
;
721 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
723 MEMSET(span
->mask
, 1, span
->end
);
724 span
->writeAll
= GL_TRUE
;
726 /* Determine if we have mono-chromatic colors */
727 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
728 span
->redStep
== 0 && span
->greenStep
== 0 &&
729 span
->blueStep
== 0 && span
->alphaStep
== 0;
731 /* Window clipping */
732 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
== GL_BITMAP
) {
733 if (clip_span(ctx
, span
) == GL_FALSE
) {
739 if (ctx
->Scissor
.Enabled
) {
740 if (!_mesa_scissor_span(ctx
, span
)) {
745 /* Polygon Stippling */
746 if (ctx
->Polygon
.StippleFlag
&& primitive
== GL_POLYGON
) {
747 stipple_polygon_span(ctx
, span
);
750 /* Now we may need to interpolate the colors */
751 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
752 interpolate_colors(ctx
, span
);
753 /* clear the bit - this allows the WriteMonoCISpan optimization below */
754 span
->interpMask
&= ~SPAN_RGBA
;
757 /* Do the alpha test */
758 if (ctx
->Color
.AlphaEnabled
) {
759 if (!_mesa_alpha_test(ctx
, span
,
760 (const GLchan (*)[4]) span
->color
.rgba
)) {
761 span
->interpMask
= origInterpMask
;
762 span
->arrayMask
= origArrayMask
;
767 /* Stencil and Z testing */
768 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
769 if (span
->interpMask
& SPAN_Z
)
770 interpolate_z(ctx
, span
);
772 if (ctx
->Stencil
.Enabled
) {
773 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
774 span
->interpMask
= origInterpMask
;
775 span
->arrayMask
= origArrayMask
;
780 ASSERT(ctx
->Depth
.Test
);
781 ASSERT(span
->arrayMask
& SPAN_Z
);
782 /* regular depth testing */
783 if (!_mesa_depth_test_span(ctx
, span
)) {
784 span
->interpMask
= origInterpMask
;
785 span
->arrayMask
= origArrayMask
;
791 /* if we get here, something passed the depth test */
792 ctx
->OcclusionResult
= GL_TRUE
;
794 /* can't abort span-writing until after occlusion testing */
795 if (colorMask
== 0x0) {
796 span
->interpMask
= origInterpMask
;
797 span
->arrayMask
= origArrayMask
;
802 if (ctx
->Fog
.Enabled
) {
803 if ((span
->arrayMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
804 _mesa_fog_rgba_pixels_with_array(ctx
, span
, span
->fogArray
,
806 else if ((span
->interpMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
807 _mesa_fog_rgba_pixels(ctx
, span
, span
->color
.rgba
);
809 if ((span
->interpMask
& SPAN_Z
) && (span
->arrayMask
& SPAN_Z
) == 0)
810 interpolate_z(ctx
, span
);
811 _mesa_depth_fog_rgba_pixels(ctx
, span
, span
->color
.rgba
);
813 monoColor
= GL_FALSE
;
816 /* Antialias coverage application */
817 if (span
->arrayMask
& SPAN_COVERAGE
) {
818 GLchan (*rgba
)[4] = span
->color
.rgba
;
820 for (i
= 0; i
< span
->end
; i
++) {
821 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * span
->coverage
[i
]);
823 monoColor
= GL_FALSE
;
826 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
827 multi_write_rgba_span( ctx
, span
->end
, span
->x
, span
->y
,
828 (const GLchan (*)[4]) span
->color
.rgba
,
832 /* normal: write to exactly one buffer */
833 if (ctx
->Color
.ColorLogicOpEnabled
) {
834 _mesa_logicop_rgba_span( ctx
, span
->end
, span
->x
, span
->y
,
835 span
->color
.rgba
, span
->mask
);
836 monoColor
= GL_FALSE
;
838 else if (ctx
->Color
.BlendEnabled
) {
839 _mesa_blend_span( ctx
, span
->end
, span
->x
, span
->y
,
840 span
->color
.rgba
, span
->mask
);
841 monoColor
= GL_FALSE
;
844 /* Color component masking */
845 if (colorMask
!= 0xffffffff) {
846 _mesa_mask_rgba_span( ctx
, span
->end
, span
->x
, span
->y
,
848 monoColor
= GL_FALSE
;
853 /* all pixels have same color */
855 color
[RCOMP
] = FixedToChan(span
->red
);
856 color
[GCOMP
] = FixedToChan(span
->green
);
857 color
[BCOMP
] = FixedToChan(span
->blue
);
858 color
[ACOMP
] = FixedToChan(span
->alpha
);
859 (*swrast
->Driver
.WriteMonoRGBASpan
)( ctx
, span
->end
, span
->x
, span
->y
,
863 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, span
->end
, span
->x
, span
->y
,
864 (const GLchan (*)[4]) span
->color
.rgba
,
865 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->mask
);
868 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
869 _mesa_write_alpha_span( ctx
, span
->end
, span
->x
, span
->y
,
870 (const GLchan (*)[4]) span
->color
.rgba
,
871 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->mask
);
875 span
->interpMask
= origInterpMask
;
876 span
->arrayMask
= origArrayMask
;
881 * Add specular color to base color. This is used only when
882 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
885 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
888 for (i
= 0; i
< n
; i
++) {
889 #if CHAN_TYPE == GL_FLOAT
891 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
892 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
893 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
895 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
896 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
897 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
898 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
899 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
900 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
907 * This function may modify any of the array values in the span.
908 * span->interpMask and span->arrayMask may be changed but will be restored
909 * to their original values before returning.
912 _mesa_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
,
915 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
916 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
917 const GLuint origArrayMask
= span
->arrayMask
;
919 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
921 /* printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);*/
923 ASSERT(ctx
->Texture
._ReallyEnabled
);
925 MEMSET(span
->mask
, 1, span
->end
);
926 span
->writeAll
= GL_TRUE
;
928 /* clip against window bounds */
929 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
930 if (clip_span(ctx
,span
) == GL_FALSE
) {
936 if (ctx
->Scissor
.Enabled
) {
937 if (_mesa_scissor_span( ctx
, span
) == GL_FALSE
) {
942 /* Polygon Stippling */
943 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
944 stipple_polygon_span( ctx
, span
);
947 /* Need texture coordinates now */
948 if ((span
->interpMask
& SPAN_TEXTURE
)
949 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
950 interpolate_texcoords(ctx
, span
);
952 /* Texture with alpha test */
953 if (ctx
->Color
.AlphaEnabled
) {
955 /* Now we need the rgba array, fill it in if needed */
956 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
957 interpolate_colors(ctx
, span
);
959 /* Texturing without alpha is done after depth-testing which
960 * gives a potential speed-up.
962 _swrast_multitexture_fragments( ctx
, span
);
964 /* Do the alpha test */
965 if (!_old_alpha_test(ctx
, span
->end
,
966 (CONST
GLchan (*)[4]) span
->color
.rgba
,
968 span
->arrayMask
= origArrayMask
;
973 /* Stencil and Z testing */
974 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
975 if (span
->interpMask
& SPAN_Z
)
976 interpolate_z(ctx
, span
);
978 if (ctx
->Stencil
.Enabled
) {
979 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
980 span
->arrayMask
= origArrayMask
;
985 ASSERT(ctx
->Depth
.Test
);
986 ASSERT(span
->arrayMask
& SPAN_Z
);
987 /* regular depth testing */
988 if (!_mesa_depth_test_span(ctx
, span
)) {
989 span
->arrayMask
= origArrayMask
;
995 /* if we get here, some fragments passed the depth test */
996 ctx
->OcclusionResult
= GL_TRUE
;
998 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
999 * the occlusion test.
1001 if (colorMask
== 0x0) {
1002 span
->arrayMask
= origArrayMask
;
1006 /* Texture without alpha test */
1007 if (!ctx
->Color
.AlphaEnabled
) {
1009 /* Now we need the rgba array, fill it in if needed */
1010 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1011 interpolate_colors(ctx
, span
);
1013 _swrast_multitexture_fragments( ctx
, span
);
1016 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1018 /* Add base and specular colors */
1019 if (ctx
->Fog
.ColorSumEnabled
||
1020 (ctx
->Light
.Enabled
&&
1021 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1022 if (span
->interpMask
& SPAN_SPEC
) {
1023 interpolate_specular(ctx
, span
);
1025 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1026 add_colors( span
->end
, span
->color
.rgba
, span
->specArray
);
1030 if (ctx
->Fog
.Enabled
) {
1032 if ((span
->interpMask
& SPAN_FOG
) && (span
->arrayMask
& SPAN_FOG
) == 0)
1033 interpolate_fog(ctx
, span
);
1035 if ((span
->arrayMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
1036 _mesa_fog_rgba_pixels_with_array( ctx
, span
, span
->fogArray
,
1038 else if ((span
->interpMask
& SPAN_FOG
) && !swrast
->_PreferPixelFog
)
1039 _mesa_fog_rgba_pixels( ctx
, span
, span
->color
.rgba
);
1041 if ((span
->interpMask
& SPAN_Z
) && (span
->arrayMask
& SPAN_Z
) == 0)
1042 interpolate_z(ctx
, span
);
1043 _mesa_depth_fog_rgba_pixels(ctx
, span
, span
->color
.rgba
);
1047 /* Antialias coverage application */
1048 if (span
->arrayMask
& SPAN_COVERAGE
) {
1049 GLchan (*rgba
)[4] = span
->color
.rgba
;
1051 for (i
= 0; i
< span
->end
; i
++) {
1052 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * span
->coverage
[i
]);
1056 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1057 multi_write_rgba_span( ctx
, span
->end
, span
->x
, span
->y
,
1058 (const GLchan (*)[4]) span
->color
.rgba
,
1062 /* normal: write to exactly one buffer */
1063 if (ctx
->Color
.ColorLogicOpEnabled
) {
1064 _mesa_logicop_rgba_span( ctx
, span
->end
, span
->x
, span
->y
,
1065 span
->color
.rgba
, span
->mask
);
1067 else if (ctx
->Color
.BlendEnabled
) {
1068 _mesa_blend_span( ctx
, span
->end
, span
->x
, span
->y
,
1069 span
->color
.rgba
, span
->mask
);
1072 if (colorMask
!= 0xffffffff) {
1073 _mesa_mask_rgba_span( ctx
, span
->end
, span
->x
, span
->y
,
1077 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, span
->end
, span
->x
, span
->y
,
1078 (const GLchan (*)[4]) span
->color
.rgba
,
1079 span
->writeAll
? NULL
: span
->mask
);
1080 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1081 _mesa_write_alpha_span( ctx
, span
->end
, span
->x
, span
->y
,
1082 (const GLchan (*)[4]) span
->color
.rgba
,
1083 span
->writeAll
? NULL
: span
->mask
);
1087 span
->arrayMask
= origArrayMask
;
1093 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1094 * reading ouside the buffer's boundaries.
1097 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1098 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1100 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1101 if (y
< 0 || y
>= buffer
->Height
1102 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1103 /* completely above, below, or right */
1104 /* XXX maybe leave undefined? */
1105 BZERO(rgba
, 4 * n
* sizeof(GLchan
));
1110 /* left edge clippping */
1112 length
= (GLint
) n
- skip
;
1114 /* completely left of window */
1117 if (length
> buffer
->Width
) {
1118 length
= buffer
->Width
;
1121 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1122 /* right edge clipping */
1124 length
= buffer
->Width
- x
;
1126 /* completely to right of window */
1136 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1137 if (buffer
->UseSoftwareAlphaBuffers
) {
1138 _mesa_read_alpha_span( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1147 * Read CI pixels from frame buffer. Clipping will be done to prevent
1148 * reading ouside the buffer's boundaries.
1151 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1152 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1154 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1155 if (y
< 0 || y
>= buffer
->Height
1156 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1157 /* completely above, below, or right */
1158 BZERO(indx
, n
* sizeof(GLuint
));
1163 /* left edge clippping */
1165 length
= (GLint
) n
- skip
;
1167 /* completely left of window */
1170 if (length
> buffer
->Width
) {
1171 length
= buffer
->Width
;
1174 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1175 /* right edge clipping */
1177 length
= buffer
->Width
- x
;
1179 /* completely to right of window */
1189 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);