1 /* $Id: s_span.c,v 1.19 2001/11/19 01:18:28 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 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"
56 * Apply the current polygon stipple pattern to a span of pixels.
59 stipple_polygon_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
62 const GLuint highbit
= 0x80000000;
65 stipple
= ctx
->PolygonStipple
[y
% 32];
66 m
= highbit
>> (GLuint
) (x
% 32);
68 for (i
= 0; i
< n
; i
++) {
69 if ((m
& stipple
) == 0) {
82 * Clip a pixel span to the current buffer/window boundaries.
83 * Return: 'n' such that pixel 'n', 'n+1' etc. are clipped,
85 * 0 = all pixels clipped
88 clip_span( GLcontext
*ctx
, GLint n
, GLint x
, GLint y
, GLubyte mask
[] )
90 /* Clip to top and bottom */
91 if (y
< 0 || y
>= ctx
->DrawBuffer
->Height
) {
95 /* Clip to the left */
98 /* completely off left side */
102 /* partially off left side */
103 BZERO(mask
, -x
* sizeof(GLubyte
));
108 if (x
+ n
> ctx
->DrawBuffer
->Width
) {
109 if (x
>= ctx
->DrawBuffer
->Width
) {
110 /* completely off right side */
114 /* partially off right side */
115 return ctx
->DrawBuffer
->Width
- x
;
125 * Draw to more than one color buffer (or none).
128 multi_write_index_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
129 const GLuint indexes
[], const GLubyte mask
[] )
131 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
134 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
137 /* loop over four possible dest color buffers */
138 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
139 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
140 GLuint indexTmp
[MAX_WIDTH
];
141 ASSERT(n
< MAX_WIDTH
);
143 if (bufferBit
== FRONT_LEFT_BIT
)
144 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
145 else if (bufferBit
== FRONT_RIGHT_BIT
)
146 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
147 else if (bufferBit
== BACK_LEFT_BIT
)
148 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
150 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
152 /* make copy of incoming indexes */
153 MEMCPY( indexTmp
, indexes
, n
* sizeof(GLuint
) );
154 if (ctx
->Color
.IndexLogicOpEnabled
) {
155 _mesa_logicop_ci_span( ctx
, n
, x
, y
, indexTmp
, mask
);
157 if (ctx
->Color
.IndexMask
== 0) {
160 else if (ctx
->Color
.IndexMask
!= 0xffffffff) {
161 _mesa_mask_index_span( ctx
, n
, x
, y
, indexTmp
);
163 (*swrast
->Driver
.WriteCI32Span
)( ctx
, n
, x
, y
, indexTmp
, mask
);
167 /* restore default dest buffer */
168 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
174 * Write a horizontal span of color index pixels to the frame buffer.
175 * Stenciling, Depth-testing, etc. are done as needed.
176 * Input: n - number of pixels in the span
177 * x, y - location of leftmost pixel in the span
178 * z - array of [n] z-values
179 * fog - array of fog factor values in [0,1]
180 * index - array of [n] color indexes
181 * primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
184 _mesa_write_index_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
185 const GLdepth z
[], const GLfloat fog
[],
186 GLuint indexIn
[], const GLint coverage
[],
189 const GLuint modBits
= FOG_BIT
| BLEND_BIT
| MASKING_BIT
| LOGIC_OP_BIT
;
190 GLubyte mask
[MAX_WIDTH
];
191 GLuint indexBackup
[MAX_WIDTH
];
192 GLuint
*index
; /* points to indexIn or indexBackup */
193 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
195 /* init mask to 1's (all pixels are to be written) */
198 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
199 if ((n
= clip_span(ctx
,n
,x
,y
,mask
)) == 0) {
204 if ((primitive
==GL_BITMAP
&& (swrast
->_RasterMask
& modBits
))
205 || (swrast
->_RasterMask
& MULTI_DRAW_BIT
)) {
206 /* Make copy of color indexes */
207 MEMCPY( indexBackup
, indexIn
, n
* sizeof(GLuint
) );
215 /* Do the scissor test */
216 if (ctx
->Scissor
.Enabled
) {
217 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
222 /* Polygon Stippling */
223 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
224 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
227 if (ctx
->Stencil
.Enabled
) {
228 /* first stencil test */
229 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
233 else if (ctx
->Depth
.Test
) {
234 /* regular depth testing */
235 if (_mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
) == 0)
239 /* if we get here, something passed the depth test */
240 ctx
->OcclusionResult
= GL_TRUE
;
243 if (ctx
->Fog
.Enabled
) {
244 if (fog
&& !swrast
->_PreferPixelFog
)
245 _mesa_fog_ci_pixels( ctx
, n
, fog
, index
);
247 _mesa_depth_fog_ci_pixels( ctx
, n
, z
, index
);
250 /* Antialias coverage application */
253 for (i
= 0; i
< n
; i
++) {
254 ASSERT(coverage
[i
] < 16);
255 index
[i
] = (index
[i
] & ~0xf) | coverage
[i
];
259 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
260 /* draw to zero or two or more buffers */
261 multi_write_index_span( ctx
, n
, x
, y
, index
, mask
);
264 /* normal situation: draw to exactly one buffer */
265 if (ctx
->Color
.IndexLogicOpEnabled
) {
266 _mesa_logicop_ci_span( ctx
, n
, x
, y
, index
, mask
);
269 if (ctx
->Color
.IndexMask
== 0) {
272 else if (ctx
->Color
.IndexMask
!= 0xffffffff) {
273 _mesa_mask_index_span( ctx
, n
, x
, y
, index
);
277 (*swrast
->Driver
.WriteCI32Span
)( ctx
, n
, x
, y
, index
, mask
);
285 _mesa_write_monoindex_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
286 const GLdepth z
[], const GLfloat fog
[],
287 GLuint index
, const GLint coverage
[],
290 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
291 GLubyte mask
[MAX_WIDTH
];
294 /* init mask to 1's (all pixels are to be written) */
297 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
298 if ((n
= clip_span( ctx
, n
, x
, y
, mask
)) == 0) {
303 /* Do the scissor test */
304 if (ctx
->Scissor
.Enabled
) {
305 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
310 /* Polygon Stippling */
311 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
312 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
315 if (ctx
->Stencil
.Enabled
) {
316 /* first stencil test */
317 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
321 else if (ctx
->Depth
.Test
) {
322 /* regular depth testing */
323 if (_mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
) == 0)
327 /* if we get here, something passed the depth test */
328 ctx
->OcclusionResult
= GL_TRUE
;
330 if (ctx
->Color
.DrawBuffer
== GL_NONE
) {
331 /* write no pixels */
336 || ctx
->Color
.IndexLogicOpEnabled
337 || ctx
->Color
.IndexMask
!= 0xffffffff
339 /* different index per pixel */
340 GLuint indexes
[MAX_WIDTH
];
341 for (i
= 0; i
< n
; i
++) {
345 if (ctx
->Fog
.Enabled
) {
346 if (fog
&& !swrast
->_PreferPixelFog
)
347 _mesa_fog_ci_pixels( ctx
, n
, fog
, indexes
);
349 _mesa_depth_fog_ci_pixels( ctx
, n
, z
, indexes
);
352 /* Antialias coverage application */
355 for (i
= 0; i
< n
; i
++) {
356 ASSERT(coverage
[i
] < 16);
357 indexes
[i
] = (indexes
[i
] & ~0xf) | coverage
[i
];
361 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
362 /* draw to zero or two or more buffers */
363 multi_write_index_span( ctx
, n
, x
, y
, indexes
, mask
);
366 /* normal situation: draw to exactly one buffer */
367 if (ctx
->Color
.IndexLogicOpEnabled
) {
368 _mesa_logicop_ci_span( ctx
, n
, x
, y
, indexes
, mask
);
370 if (ctx
->Color
.IndexMask
== 0) {
373 else if (ctx
->Color
.IndexMask
!= 0xffffffff) {
374 _mesa_mask_index_span( ctx
, n
, x
, y
, indexes
);
376 (*swrast
->Driver
.WriteCI32Span
)( ctx
, n
, x
, y
, indexes
, mask
);
380 /* same color index for all pixels */
381 ASSERT(!ctx
->Color
.IndexLogicOpEnabled
);
382 ASSERT(ctx
->Color
.IndexMask
== 0xffffffff);
383 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
384 /* draw to zero or two or more buffers */
385 GLuint indexes
[MAX_WIDTH
];
386 for (i
= 0; i
< n
; i
++)
388 multi_write_index_span( ctx
, n
, x
, y
, indexes
, mask
);
391 /* normal situation: draw to exactly one buffer */
392 (*swrast
->Driver
.WriteMonoCISpan
)( ctx
, n
, x
, y
, index
, mask
);
400 * Draw to more than one RGBA color buffer (or none).
403 multi_write_rgba_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
404 CONST GLchan rgba
[][4], const GLubyte mask
[] )
406 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
408 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
410 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
413 /* loop over four possible dest color buffers */
414 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
415 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
416 GLchan rgbaTmp
[MAX_WIDTH
][4];
417 ASSERT(n
< MAX_WIDTH
);
419 if (bufferBit
== FRONT_LEFT_BIT
) {
420 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
421 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontLeftAlpha
;
423 else if (bufferBit
== FRONT_RIGHT_BIT
) {
424 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
425 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontRightAlpha
;
427 else if (bufferBit
== BACK_LEFT_BIT
) {
428 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
429 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackLeftAlpha
;
432 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
433 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackRightAlpha
;
436 /* make copy of incoming colors */
437 MEMCPY( rgbaTmp
, rgba
, 4 * n
* sizeof(GLchan
) );
439 if (ctx
->Color
.ColorLogicOpEnabled
) {
440 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgbaTmp
, mask
);
442 else if (ctx
->Color
.BlendEnabled
) {
443 _mesa_blend_span( ctx
, n
, x
, y
, rgbaTmp
, mask
);
445 if (colorMask
== 0x0) {
448 else if (colorMask
!= 0xffffffff) {
449 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgbaTmp
);
452 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
,
453 (const GLchan (*)[4]) rgbaTmp
, mask
);
454 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
455 _mesa_write_alpha_span( ctx
, n
, x
, y
,
456 (const GLchan (*)[4])rgbaTmp
, mask
);
461 /* restore default dest buffer */
462 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
468 * Apply fragment processing to a span of RGBA fragments.
470 * n - number of fragments in the span
471 * x,y - location of first (left) fragment
472 * fog - array of fog factor values in [0,1]
475 _mesa_write_rgba_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
476 const GLdepth z
[], const GLfloat fog
[],
477 GLchan rgbaIn
[][4], const GLfloat coverage
[],
480 const GLuint modBits
= FOG_BIT
| BLEND_BIT
| MASKING_BIT
|
481 LOGIC_OP_BIT
| TEXTURE_BIT
;
482 GLubyte mask
[MAX_WIDTH
];
483 GLboolean write_all
= GL_TRUE
;
484 GLchan rgbaBackup
[MAX_WIDTH
][4];
486 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
488 /* init mask to 1's (all pixels are to be written) */
491 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
492 if ((n
= clip_span( ctx
,n
,x
,y
,mask
)) == 0) {
496 write_all
= GL_FALSE
;
499 if ((primitive
==GL_BITMAP
&& (swrast
->_RasterMask
& modBits
))
500 || (swrast
->_RasterMask
& MULTI_DRAW_BIT
)) {
501 /* must make a copy of the colors since they may be modified */
502 MEMCPY( rgbaBackup
, rgbaIn
, 4 * n
* sizeof(GLchan
) );
509 /* Do the scissor test */
510 if (ctx
->Scissor
.Enabled
) {
511 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
515 write_all
= GL_FALSE
;
518 /* Polygon Stippling */
519 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
520 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
521 write_all
= GL_FALSE
;
524 /* Do the alpha test */
525 if (ctx
->Color
.AlphaEnabled
) {
526 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4]) rgba
, mask
) == 0) {
529 write_all
= GL_FALSE
;
532 if (ctx
->Stencil
.Enabled
) {
533 /* first stencil test */
534 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
537 write_all
= GL_FALSE
;
539 else if (ctx
->Depth
.Test
) {
540 /* regular depth testing */
541 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
546 write_all
= GL_FALSE
;
550 /* if we get here, something passed the depth test */
551 ctx
->OcclusionResult
= GL_TRUE
;
554 if (ctx
->Fog
.Enabled
) {
555 if (fog
&& !swrast
->_PreferPixelFog
)
556 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
558 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
561 /* Antialias coverage application */
564 for (i
= 0; i
< n
; i
++) {
565 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
569 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
570 multi_write_rgba_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
, mask
);
573 /* normal: write to exactly one buffer */
574 /* logic op or blending */
575 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
577 if (ctx
->Color
.ColorLogicOpEnabled
) {
578 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
580 else if (ctx
->Color
.BlendEnabled
) {
581 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
584 /* Color component masking */
585 if (colorMask
== 0x0) {
588 else if (colorMask
!= 0xffffffff) {
589 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
593 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
,
594 (const GLchan (*)[4]) rgba
,
595 write_all
? ((const GLubyte
*) NULL
) : mask
);
597 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
598 _mesa_write_alpha_span( ctx
, n
, x
, y
,
599 (const GLchan (*)[4]) rgba
,
600 write_all
? ((const GLubyte
*) NULL
) : mask
);
608 * Write a horizontal span of color pixels to the frame buffer.
609 * The color is initially constant for the whole span.
610 * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
611 * Input: n - number of pixels in the span
612 * x, y - location of leftmost pixel in the span
613 * z - array of [n] z-values
614 * fog - array of fog factor values in [0,1]
615 * r, g, b, a - the color of the pixels
616 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
619 _mesa_write_monocolor_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
620 const GLdepth z
[], const GLfloat fog
[],
621 const GLchan color
[4], const GLfloat coverage
[],
624 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
626 GLubyte mask
[MAX_WIDTH
];
627 GLboolean write_all
= GL_TRUE
;
628 GLchan rgba
[MAX_WIDTH
][4];
629 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
631 /* init mask to 1's (all pixels are to be written) */
634 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
635 if ((n
= clip_span( ctx
,n
,x
,y
,mask
)) == 0) {
639 write_all
= GL_FALSE
;
642 /* Do the scissor test */
643 if (ctx
->Scissor
.Enabled
) {
644 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
648 write_all
= GL_FALSE
;
651 /* Polygon Stippling */
652 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
653 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
654 write_all
= GL_FALSE
;
657 /* Do the alpha test */
658 if (ctx
->Color
.AlphaEnabled
) {
659 for (i
= 0; i
< n
; i
++) {
660 rgba
[i
][ACOMP
] = color
[ACOMP
];
662 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4])rgba
, mask
) == 0) {
665 write_all
= GL_FALSE
;
668 if (ctx
->Stencil
.Enabled
) {
669 /* first stencil test */
670 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
673 write_all
= GL_FALSE
;
675 else if (ctx
->Depth
.Test
) {
676 /* regular depth testing */
677 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
682 write_all
= GL_FALSE
;
686 /* if we get here, something passed the depth test */
687 ctx
->OcclusionResult
= GL_TRUE
;
689 if (ctx
->Color
.DrawBuffer
== GL_NONE
) {
690 /* write no pixels */
694 if (ctx
->Color
.ColorLogicOpEnabled
|| colorMask
!= 0xffffffff ||
695 (swrast
->_RasterMask
& (BLEND_BIT
| FOG_BIT
)) || coverage
) {
696 /* assign same color to each pixel */
697 for (i
= 0; i
< n
; i
++) {
699 COPY_CHAN4(rgba
[i
], color
);
704 if (ctx
->Fog
.Enabled
) {
705 if (fog
&& !swrast
->_PreferPixelFog
)
706 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
708 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
711 /* Antialias coverage application */
714 for (i
= 0; i
< n
; i
++) {
715 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
719 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
720 multi_write_rgba_span( ctx
, n
, x
, y
,
721 (const GLchan (*)[4]) rgba
, mask
);
724 /* normal: write to exactly one buffer */
725 if (ctx
->Color
.ColorLogicOpEnabled
) {
726 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
728 else if (ctx
->Color
.BlendEnabled
) {
729 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
732 /* Color component masking */
733 if (colorMask
== 0x0) {
736 else if (colorMask
!= 0xffffffff) {
737 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
741 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
,
742 (const GLchan (*)[4]) rgba
,
743 write_all
? ((const GLubyte
*) NULL
) : mask
);
744 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
745 _mesa_write_alpha_span( ctx
, n
, x
, y
,
746 (const GLchan (*)[4]) rgba
,
747 write_all
? ((const GLubyte
*) NULL
) : mask
);
752 /* same color for all pixels */
753 ASSERT(!ctx
->Color
.BlendEnabled
);
754 ASSERT(!ctx
->Color
.ColorLogicOpEnabled
);
756 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
757 for (i
= 0; i
< n
; i
++) {
759 COPY_CHAN4(rgba
[i
], color
);
762 multi_write_rgba_span( ctx
, n
, x
, y
,
763 (const GLchan (*)[4]) rgba
, mask
);
766 (*swrast
->Driver
.WriteMonoRGBASpan
)( ctx
, n
, x
, y
, color
, mask
);
767 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
768 _mesa_write_mono_alpha_span( ctx
, n
, x
, y
, (GLchan
) color
[ACOMP
],
769 write_all
? ((const GLubyte
*) NULL
) : mask
);
778 * Add specular color to base color. This is used only when
779 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
782 add_colors(GLuint n
, GLchan rgba
[][4], CONST GLchan specular
[][4] )
785 for (i
= 0; i
< n
; i
++) {
786 #if CHAN_TYPE == GL_FLOAT
788 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
789 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
790 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
792 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
793 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
794 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
795 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
796 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
797 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
804 * Write a horizontal span of textured pixels to the frame buffer.
805 * The color of each pixel is different.
806 * Depth-testing, stenciling, scissor-testing etc. should already
808 * only if alpha-testing is used, depth-testing is still done in this
810 * Input: n - number of pixels in the span
811 * x, y - location of leftmost pixel in the span
812 * z - array of [n] z-values
813 * s, t - array of (s,t) texture coordinates for each pixel
814 * lambda - array of texture lambda values
815 * rgba - array of [n] color components
816 * mask - masked pixels
817 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
818 * Contributed by Klaus Niederkrueger.
821 masked_texture_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
822 const GLdepth z
[], const GLfloat fog
[],
823 const GLfloat s
[], const GLfloat t
[],
824 const GLfloat u
[], GLfloat lambda
[],
825 GLchan rgbaIn
[][4], CONST GLchan spec
[][4],
826 const GLfloat coverage
[], GLubyte mask
[],
827 GLboolean write_all
)
829 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
830 GLchan rgbaBackup
[MAX_WIDTH
][4];
831 GLchan (*rgba
)[4]; /* points to either rgbaIn or rgbaBackup */
832 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
835 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
836 /* must make a copy of the colors since they may be modified */
837 MEMCPY(rgbaBackup
, rgbaIn
, 4 * n
* sizeof(GLchan
));
845 ASSERT(ctx
->Texture
._ReallyEnabled
);
846 _swrast_texture_fragments( ctx
, 0, n
, s
, t
, u
, lambda
,
847 (CONST
GLchan (*)[4]) rgba
, rgba
);
850 /* Texture with alpha test */
851 if (ctx
->Color
.AlphaEnabled
) {
852 /* Do the alpha test */
853 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4]) rgba
, mask
) == 0) {
856 write_all
= GL_FALSE
;
858 /* Depth test usually in 'rasterize_span' but if alpha test
859 needed, we have to wait for that test before depth test can
861 if (ctx
->Stencil
.Enabled
) {
862 /* first stencil test */
863 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
866 write_all
= GL_FALSE
;
868 else if (ctx
->Depth
.Test
) {
869 /* regular depth testing */
870 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
875 write_all
= GL_FALSE
;
880 /* if we get here, something passed the depth test */
881 ctx
->OcclusionResult
= GL_TRUE
;
884 /* Add base and specular colors */
886 (ctx
->Fog
.ColorSumEnabled
||
887 (ctx
->Light
.Enabled
&&
888 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)))
889 add_colors( n
, rgba
, spec
); /* rgba = rgba + spec */
892 if (ctx
->Fog
.Enabled
) {
893 if (fog
&& !swrast
->_PreferPixelFog
)
894 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
896 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
899 /* Antialias coverage application */
902 for (i
= 0; i
< n
; i
++) {
903 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
907 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
908 multi_write_rgba_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
, mask
);
911 /* normal: write to exactly one buffer */
912 if (ctx
->Color
.ColorLogicOpEnabled
) {
913 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
915 else if (ctx
->Color
.BlendEnabled
) {
916 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
918 if (colorMask
== 0x0) {
921 else if (colorMask
!= 0xffffffff) {
922 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
925 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
, (const GLchan (*)[4])rgba
,
926 write_all
? NULL
: mask
);
927 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
928 _mesa_write_alpha_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
,
929 write_all
? NULL
: mask
);
936 * As above but perform multiple stages of texture application.
937 * Contributed by Klaus Niederkrueger.
940 masked_multitexture_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
941 const GLdepth z
[], const GLfloat fog
[],
942 CONST GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
943 CONST GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
944 CONST GLfloat u
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
945 GLfloat lambda
[][MAX_WIDTH
],
946 GLchan rgbaIn
[MAX_TEXTURE_UNITS
][4],
947 CONST GLchan spec
[MAX_TEXTURE_UNITS
][4],
948 const GLfloat coverage
[], GLubyte mask
[],
949 GLboolean write_all
)
951 GLchan rgbaBackup
[MAX_WIDTH
][4];
952 GLchan (*rgba
)[4]; /* points to either rgbaIn or rgbaBackup */
954 const GLuint texUnits
= ctx
->Const
.MaxTextureUnits
;
955 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
958 if ( (swrast
->_RasterMask
& MULTI_DRAW_BIT
) || texUnits
> 1) {
959 /* must make a copy of the colors since they may be modified */
960 MEMCPY(rgbaBackup
, rgbaIn
, 4 * n
* sizeof(GLchan
));
968 ASSERT(ctx
->Texture
._ReallyEnabled
);
969 for (i
= 0; i
< texUnits
; i
++)
970 _swrast_texture_fragments( ctx
, i
, n
, s
[i
], t
[i
], u
[i
], lambda
[i
],
971 (CONST
GLchan (*)[4]) rgbaIn
, rgba
);
973 /* Texture with alpha test */
974 if (ctx
->Color
.AlphaEnabled
) {
975 /* Do the alpha test */
976 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4])rgba
, mask
) == 0) {
979 write_all
= GL_FALSE
;
980 /* Depth test usually in 'rasterize_span' but if alpha test
981 needed, we have to wait for that test before depth test can
983 if (ctx
->Stencil
.Enabled
) {
984 /* first stencil test */
985 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
988 write_all
= GL_FALSE
;
990 else if (ctx
->Depth
.Test
) {
991 /* regular depth testing */
992 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
997 write_all
= GL_FALSE
;
1002 /* if we get here, something passed the depth test */
1003 ctx
->OcclusionResult
= GL_TRUE
;
1006 /* Add base and specular colors */
1008 (ctx
->Fog
.ColorSumEnabled
||
1009 (ctx
->Light
.Enabled
&&
1010 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)))
1011 add_colors( n
, rgba
, spec
); /* rgba = rgba + spec */
1014 if (ctx
->Fog
.Enabled
) {
1015 if (fog
&& !swrast
->_PreferPixelFog
)
1016 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
1018 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
1021 /* Antialias coverage application */
1024 for (i
= 0; i
< n
; i
++) {
1025 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1029 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1030 multi_write_rgba_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
, mask
);
1033 /* normal: write to exactly one buffer */
1034 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1036 if (ctx
->Color
.ColorLogicOpEnabled
) {
1037 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
1039 else if (ctx
->Color
.BlendEnabled
) {
1040 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
1043 if (colorMask
== 0x0) {
1046 else if (colorMask
!= 0xffffffff) {
1047 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
1050 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
, (const GLchan (*)[4])rgba
,
1051 write_all
? NULL
: mask
);
1052 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1053 _mesa_write_alpha_span( ctx
, n
, x
, y
, (const GLchan (*)[4])rgba
,
1054 write_all
? NULL
: mask
);
1061 * Generate arrays of fragment colors, z, fog, texcoords, etc from a
1062 * triangle span object. Then call the span/fragment processsing
1063 * functions in s_span.[ch]. This is used by a bunch of the textured
1064 * triangle functions.
1065 * Contributed by Klaus Niederkrueger.
1068 _mesa_rasterize_span(GLcontext
*ctx
, struct triangle_span
*span
)
1070 DEFARRAY(GLubyte
, mask
, MAX_WIDTH
);
1071 DEFMARRAY(GLchan
, rgba
, MAX_WIDTH
, 4);
1072 DEFMARRAY(GLchan
, spec
, MAX_WIDTH
, 4);
1073 DEFARRAY(GLuint
, index
, MAX_WIDTH
);
1074 DEFARRAY(GLuint
, z
, MAX_WIDTH
);
1075 DEFARRAY(GLfloat
, fog
, MAX_WIDTH
);
1076 DEFARRAY(GLfloat
, sTex
, MAX_WIDTH
);
1077 DEFARRAY(GLfloat
, tTex
, MAX_WIDTH
);
1078 DEFARRAY(GLfloat
, rTex
, MAX_WIDTH
);
1079 DEFARRAY(GLfloat
, lambda
, MAX_WIDTH
);
1080 DEFMARRAY(GLfloat
, msTex
, MAX_TEXTURE_UNITS
, MAX_WIDTH
);
1081 DEFMARRAY(GLfloat
, mtTex
, MAX_TEXTURE_UNITS
, MAX_WIDTH
);
1082 DEFMARRAY(GLfloat
, mrTex
, MAX_TEXTURE_UNITS
, MAX_WIDTH
);
1083 DEFMARRAY(GLfloat
, mLambda
, MAX_TEXTURE_UNITS
, MAX_WIDTH
);
1085 GLboolean write_all
= GL_TRUE
;
1086 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1088 CHECKARRAY(mask
, return);
1089 CHECKARRAY(rgba
, return);
1090 CHECKARRAY(spec
, return);
1091 CHECKARRAY(index
, return);
1092 CHECKARRAY(z
, return);
1093 CHECKARRAY(fog
, return);
1094 CHECKARRAY(sTex
, return);
1095 CHECKARRAY(tTex
, return);
1096 CHECKARRAY(rTex
, return);
1097 CHECKARRAY(lambda
, return);
1098 CHECKARRAY(msTex
, return);
1099 CHECKARRAY(mtTex
, return);
1100 CHECKARRAY(mrTex
, return);
1101 CHECKARRAY(mLambda
, return);
1103 /* init mask to 1's (all pixels are to be written) */
1104 MEMSET(mask
, 1, span
->count
);
1106 if (swrast
->_RasterMask
& WINCLIP_BIT
) {
1107 if ((span
->count
= clip_span(ctx
, span
->count
, span
->x
, span
->y
, mask
))
1112 write_all
= GL_FALSE
;
1115 /* Do the scissor test */
1116 if (ctx
->Scissor
.Enabled
) {
1117 if ((span
->count
= _mesa_scissor_span(ctx
, span
->count
, span
->x
, span
->y
, mask
)) == 0) {
1121 write_all
= GL_FALSE
;
1124 /* Polygon Stippling */
1125 if (ctx
->Polygon
.StippleFlag
) {
1126 stipple_polygon_span( ctx
, span
->count
, span
->x
, span
->y
, mask
);
1127 write_all
= GL_FALSE
;
1132 if (span
->activeMask
& SPAN_Z
) {
1133 if (ctx
->Visual
.depthBits
<= 16) {
1135 GLfixed zval
= span
->z
;
1136 for (i
= 0; i
< span
->count
; i
++) {
1137 z
[i
] = FixedToInt(zval
);
1138 zval
+= span
->zStep
;
1142 /* Deep Z buffer, no fixed->int shift */
1144 GLfixed zval
= span
->z
;
1145 for (i
= 0; i
< span
->count
; i
++) {
1147 zval
+= span
->zStep
;
1152 /* Correct order: texturing --> alpha test --> depth test. But if
1153 no alpha test needed, we can do here the depth test and
1154 potentially avoid some of the texturing (otherwise alpha test,
1155 depth test etc. happens in masked_texture_span(). */
1156 if (!ctx
->Color
.AlphaEnabled
) {
1157 if (ctx
->Stencil
.Enabled
) {
1158 /* first stencil test */
1159 if (_mesa_stencil_and_ztest_span(ctx
, span
->count
, span
->x
,
1160 span
->y
, z
, mask
) == GL_FALSE
) {
1163 write_all
= GL_FALSE
;
1165 else if (ctx
->Depth
.Test
) {
1166 /* regular depth testing */
1167 GLuint m
= _mesa_depth_test_span( ctx
, span
->count
, span
->x
,
1172 if (m
< span
->count
) {
1173 write_all
= GL_FALSE
;
1178 if (span
->activeMask
& SPAN_RGBA
) {
1179 if (span
->activeMask
& SPAN_FLAT
) {
1182 color
[RCOMP
] = FixedToChan(span
->red
);
1183 color
[GCOMP
] = FixedToChan(span
->green
);
1184 color
[BCOMP
] = FixedToChan(span
->blue
);
1185 color
[ACOMP
] = FixedToChan(span
->alpha
);
1186 for (i
= 0; i
< span
->count
; i
++) {
1187 COPY_CHAN4(rgba
[i
], color
);
1191 /* smooth interpolation */
1192 #if CHAN_TYPE == GL_FLOAT
1193 GLfloat r
= span
->red
;
1194 GLfloat g
= span
->green
;
1195 GLfloat b
= span
->blue
;
1196 GLfloat a
= span
->alpha
;
1198 GLfixed r
= span
->red
;
1199 GLfixed g
= span
->green
;
1200 GLfixed b
= span
->blue
;
1201 GLfixed a
= span
->alpha
;
1204 for (i
= 0; i
< span
->count
; i
++) {
1205 rgba
[i
][RCOMP
] = FixedToChan(r
);
1206 rgba
[i
][GCOMP
] = FixedToChan(g
);
1207 rgba
[i
][BCOMP
] = FixedToChan(b
);
1208 rgba
[i
][ACOMP
] = FixedToChan(a
);
1210 g
+= span
->greenStep
;
1211 b
+= span
->blueStep
;
1212 a
+= span
->alphaStep
;
1217 if (span
->activeMask
& SPAN_SPEC
) {
1218 if (span
->activeMask
& SPAN_FLAT
) {
1219 const GLchan r
= FixedToChan(span
->specRed
);
1220 const GLchan g
= FixedToChan(span
->specGreen
);
1221 const GLchan b
= FixedToChan(span
->specBlue
);
1223 for (i
= 0; i
< span
->count
; i
++) {
1230 /* smooth interpolation */
1231 #if CHAN_TYPE == GL_FLOAT
1232 GLfloat r
= span
->specRed
;
1233 GLfloat g
= span
->specGreen
;
1234 GLfloat b
= span
->specBlue
;
1236 GLfixed r
= span
->specRed
;
1237 GLfixed g
= span
->specGreen
;
1238 GLfixed b
= span
->specBlue
;
1241 for (i
= 0; i
< span
->count
; i
++) {
1242 spec
[i
][RCOMP
] = FixedToChan(r
);
1243 spec
[i
][GCOMP
] = FixedToChan(g
);
1244 spec
[i
][BCOMP
] = FixedToChan(b
);
1245 r
+= span
->specRedStep
;
1246 g
+= span
->specGreenStep
;
1247 b
+= span
->specBlueStep
;
1252 if (span
->activeMask
& SPAN_INDEX
) {
1253 if (span
->activeMask
& SPAN_FLAT
) {
1255 const GLint indx
= FixedToInt(span
->index
);
1256 for (i
= 0; i
< span
->count
; i
++) {
1261 /* smooth interpolation */
1263 GLfixed ind
= span
->index
;
1264 for (i
= 0; i
< span
->count
; i
++) {
1265 index
[i
] = FixedToInt(ind
);
1266 ind
+= span
->indexStep
;
1271 if (span
->activeMask
& SPAN_FOG
) {
1273 GLfloat f
= span
->fog
;
1274 for (i
= 0; i
< span
->count
; i
++) {
1279 if (span
->activeMask
& SPAN_TEXTURE
) {
1280 if (ctx
->Texture
._ReallyEnabled
& ~TEXTURE0_ANY
) {
1282 if (span
->activeMask
& SPAN_LAMBDA
) {
1285 /* multitexture, lambda */
1286 for (u
= 0; u
< MAX_TEXTURE_UNITS
; u
++) {
1287 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
1288 GLfloat s
= span
->tex
[u
][0];
1289 GLfloat t
= span
->tex
[u
][1];
1290 GLfloat r
= span
->tex
[u
][2];
1291 GLfloat q
= span
->tex
[u
][3];
1293 for (i
= 0; i
< span
->count
; i
++) {
1294 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
1295 msTex
[u
][i
] = s
* invQ
;
1296 mtTex
[u
][i
] = t
* invQ
;
1297 mrTex
[u
][i
] = r
* invQ
;
1298 mLambda
[u
][i
] = (GLfloat
)
1299 (log(span
->rho
[u
] * invQ
* invQ
) * 1.442695F
* 0.5F
);
1300 s
+= span
->texStep
[u
][0];
1301 t
+= span
->texStep
[u
][1];
1302 r
+= span
->texStep
[u
][2];
1303 q
+= span
->texStep
[u
][3];
1309 /* without lambda */
1311 /* multitexture, no lambda */
1312 for (u
= 0; u
< MAX_TEXTURE_UNITS
; u
++) {
1313 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
1314 GLfloat s
= span
->tex
[u
][0];
1315 GLfloat t
= span
->tex
[u
][1];
1316 GLfloat r
= span
->tex
[u
][2];
1317 GLfloat q
= span
->tex
[u
][3];
1319 for (i
= 0; i
< span
->count
; i
++) {
1320 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
1321 msTex
[u
][i
] = s
* invQ
;
1322 mtTex
[u
][i
] = t
* invQ
;
1323 mrTex
[u
][i
] = r
* invQ
;
1324 s
+= span
->texStep
[u
][0];
1325 t
+= span
->texStep
[u
][1];
1326 r
+= span
->texStep
[u
][2];
1327 q
+= span
->texStep
[u
][3];
1334 /* just texture unit 0 */
1335 if (span
->activeMask
& SPAN_LAMBDA
) {
1337 GLfloat s
= span
->tex
[0][0];
1338 GLfloat t
= span
->tex
[0][1];
1339 GLfloat r
= span
->tex
[0][2];
1340 GLfloat q
= span
->tex
[0][3];
1342 /* single texture, lambda */
1343 for (i
= 0; i
< span
->count
; i
++) {
1344 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
1348 lambda
[i
] = (GLfloat
)
1349 (log(span
->rho
[0] * invQ
* invQ
) * 1.442695F
* 0.5F
);
1350 s
+= span
->texStep
[0][0];
1351 t
+= span
->texStep
[0][1];
1352 r
+= span
->texStep
[0][2];
1353 q
+= span
->texStep
[0][3];
1357 /* without lambda */
1358 GLfloat s
= span
->tex
[0][0];
1359 GLfloat t
= span
->tex
[0][1];
1360 GLfloat r
= span
->tex
[0][2];
1361 GLfloat q
= span
->tex
[0][3];
1363 /* single texture, no lambda */
1364 for (i
= 0; i
< span
->count
; i
++) {
1365 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
1369 s
+= span
->texStep
[0][0];
1370 t
+= span
->texStep
[0][1];
1371 r
+= span
->texStep
[0][2];
1372 q
+= span
->texStep
[0][3];
1377 /* XXX keep this? */
1378 if (span
->activeMask
& SPAN_INT_TEXTURE
) {
1379 GLint intTexcoord
[MAX_WIDTH
][2];
1380 GLfixed s
= span
->intTex
[0];
1381 GLfixed t
= span
->intTex
[1];
1383 for (i
= 0; i
< span
->count
; i
++) {
1384 intTexcoord
[i
][0] = FixedToInt(s
);
1385 intTexcoord
[i
][1] = FixedToInt(t
);
1386 s
+= span
->intTexStep
[0];
1387 t
+= span
->intTexStep
[1];
1391 /* examine activeMask and call a s_span.c function */
1392 if (span
->activeMask
& SPAN_TEXTURE
) {
1393 const GLfloat
*fogPtr
;
1394 if (span
->activeMask
& SPAN_FOG
)
1399 if (ctx
->Texture
._ReallyEnabled
& ~TEXTURE0_ANY
) {
1400 if (span
->activeMask
& SPAN_SPEC
) {
1401 masked_multitexture_span(ctx
, span
->count
, span
->x
, span
->y
,
1403 (const GLfloat (*)[MAX_WIDTH
]) msTex
,
1404 (const GLfloat (*)[MAX_WIDTH
]) mtTex
,
1405 (const GLfloat (*)[MAX_WIDTH
]) mrTex
,
1406 (GLfloat (*)[MAX_WIDTH
]) mLambda
,
1407 rgba
, (CONST
GLchan (*)[4]) spec
,
1408 NULL
, mask
, write_all
);
1411 masked_multitexture_span(ctx
, span
->count
, span
->x
, span
->y
,
1413 (const GLfloat (*)[MAX_WIDTH
]) msTex
,
1414 (const GLfloat (*)[MAX_WIDTH
]) mtTex
,
1415 (const GLfloat (*)[MAX_WIDTH
]) mrTex
,
1416 (GLfloat (*)[MAX_WIDTH
]) mLambda
,
1417 rgba
, NULL
, NULL
, mask
, write_all
);
1421 /* single texture */
1422 if (span
->activeMask
& SPAN_SPEC
) {
1423 masked_texture_span(ctx
, span
->count
, span
->x
, span
->y
,
1424 z
, fogPtr
, sTex
, tTex
, rTex
,
1426 (CONST
GLchan (*)[4]) spec
,
1427 NULL
, mask
, write_all
);
1430 masked_texture_span(ctx
, span
->count
, span
->x
, span
->y
,
1431 z
, fogPtr
, sTex
, tTex
, rTex
,
1432 lambda
, rgba
, NULL
, NULL
,
1438 _mesa_problem(ctx
, "rasterize_span() should only be used for texturing");
1454 UNDEFARRAY(mLambda
);
1459 * Write a horizontal span of textured pixels to the frame buffer.
1460 * The color of each pixel is different.
1461 * Alpha-testing, stenciling, depth-testing, and blending are done
1463 * Input: n - number of pixels in the span
1464 * x, y - location of leftmost pixel in the span
1465 * z - array of [n] z-values
1466 * fog - array of fog factor values in [0,1]
1467 * s, t - array of (s,t) texture coordinates for each pixel
1468 * lambda - array of texture lambda values
1469 * rgba - array of [n] color components
1470 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
1473 _mesa_write_texture_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
1474 const GLdepth z
[], const GLfloat fog
[],
1475 const GLfloat s
[], const GLfloat t
[],
1476 const GLfloat u
[], GLfloat lambda
[],
1477 GLchan rgbaIn
[][4], CONST GLchan spec
[][4],
1478 const GLfloat coverage
[], GLenum primitive
)
1480 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1481 GLubyte mask
[MAX_WIDTH
];
1482 GLboolean write_all
= GL_TRUE
;
1483 GLchan rgbaBackup
[MAX_WIDTH
][4];
1484 GLchan (*rgba
)[4]; /* points to either rgbaIn or rgbaBackup */
1485 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1487 /* init mask to 1's (all pixels are to be written) */
1490 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
1491 if ((n
=clip_span(ctx
, n
, x
, y
, mask
)) == 0) {
1495 write_all
= GL_FALSE
;
1499 if (primitive
==GL_BITMAP
|| (swrast
->_RasterMask
& MULTI_DRAW_BIT
)) {
1500 /* must make a copy of the colors since they may be modified */
1501 MEMCPY(rgbaBackup
, rgbaIn
, 4 * n
* sizeof(GLchan
));
1508 /* Do the scissor test */
1509 if (ctx
->Scissor
.Enabled
) {
1510 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
1514 write_all
= GL_FALSE
;
1517 /* Polygon Stippling */
1518 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
1519 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
1520 write_all
= GL_FALSE
;
1523 /* Texture with alpha test */
1524 if (ctx
->Color
.AlphaEnabled
) {
1525 /* Texturing without alpha is done after depth-testing which
1526 gives a potential speed-up. */
1527 ASSERT(ctx
->Texture
._ReallyEnabled
);
1528 _swrast_texture_fragments( ctx
, 0, n
, s
, t
, u
, lambda
,
1529 (CONST
GLchan (*)[4]) rgba
, rgba
);
1531 /* Do the alpha test */
1532 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4]) rgba
, mask
) == 0) {
1535 write_all
= GL_FALSE
;
1538 if (ctx
->Stencil
.Enabled
) {
1539 /* first stencil test */
1540 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
1543 write_all
= GL_FALSE
;
1545 else if (ctx
->Depth
.Test
) {
1546 /* regular depth testing */
1547 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
1552 write_all
= GL_FALSE
;
1556 /* if we get here, something passed the depth test */
1557 ctx
->OcclusionResult
= GL_TRUE
;
1559 /* Texture without alpha test */
1560 if (! ctx
->Color
.AlphaEnabled
) {
1561 ASSERT(ctx
->Texture
._ReallyEnabled
);
1562 _swrast_texture_fragments( ctx
, 0, n
, s
, t
, u
, lambda
,
1563 (CONST
GLchan (*)[4]) rgba
, rgba
);
1566 /* Add base and specular colors */
1568 (ctx
->Fog
.ColorSumEnabled
||
1569 (ctx
->Light
.Enabled
&&
1570 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)))
1571 add_colors( n
, rgba
, spec
); /* rgba = rgba + spec */
1574 if (ctx
->Fog
.Enabled
) {
1575 if (fog
&& !swrast
->_PreferPixelFog
)
1576 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
1578 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
1581 /* Antialias coverage application */
1584 for (i
= 0; i
< n
; i
++) {
1585 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1589 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1590 multi_write_rgba_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
, mask
);
1593 /* normal: write to exactly one buffer */
1594 if (ctx
->Color
.ColorLogicOpEnabled
) {
1595 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
1597 else if (ctx
->Color
.BlendEnabled
) {
1598 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
1600 if (colorMask
== 0x0) {
1603 else if (colorMask
!= 0xffffffff) {
1604 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
1607 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
, (const GLchan (*)[4])rgba
,
1608 write_all
? ((const GLubyte
*) NULL
) : mask
);
1609 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1610 _mesa_write_alpha_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
,
1611 write_all
? ((const GLubyte
*) NULL
) : mask
);
1619 * As above but perform multiple stages of texture application.
1622 _mesa_write_multitexture_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
1623 const GLdepth z
[], const GLfloat fog
[],
1624 CONST GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
1625 CONST GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
1626 CONST GLfloat u
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
1627 GLfloat lambda
[][MAX_WIDTH
],
1628 GLchan rgbaIn
[MAX_TEXTURE_UNITS
][4],
1629 CONST GLchan spec
[MAX_TEXTURE_UNITS
][4],
1630 const GLfloat coverage
[],
1633 GLubyte mask
[MAX_WIDTH
];
1634 GLboolean write_all
= GL_TRUE
;
1635 GLchan rgbaBackup
[MAX_WIDTH
][4];
1636 GLchan (*rgba
)[4]; /* points to either rgbaIn or rgbaBackup */
1638 const GLubyte
*Null
= 0;
1639 const GLuint texUnits
= ctx
->Const
.MaxTextureUnits
;
1640 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1642 /* init mask to 1's (all pixels are to be written) */
1645 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
1646 if ((n
=clip_span(ctx
, n
, x
, y
, mask
)) == 0) {
1650 write_all
= GL_FALSE
;
1654 if (primitive
==GL_BITMAP
|| (swrast
->_RasterMask
& MULTI_DRAW_BIT
)
1656 /* must make a copy of the colors since they may be modified */
1657 MEMCPY(rgbaBackup
, rgbaIn
, 4 * n
* sizeof(GLchan
));
1664 /* Do the scissor test */
1665 if (ctx
->Scissor
.Enabled
) {
1666 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
1670 write_all
= GL_FALSE
;
1673 /* Polygon Stippling */
1674 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
1675 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
1676 write_all
= GL_FALSE
;
1679 /* Texture with alpha test */
1680 if (ctx
->Color
.AlphaEnabled
) {
1681 /* Texturing without alpha is done after depth-testing which
1682 * gives a potential speed-up.
1684 ASSERT(ctx
->Texture
._ReallyEnabled
);
1685 for (i
= 0; i
< texUnits
; i
++)
1686 _swrast_texture_fragments( ctx
, i
, n
, s
[i
], t
[i
], u
[i
], lambda
[i
],
1687 (CONST
GLchan (*)[4]) rgbaIn
, rgba
);
1689 /* Do the alpha test */
1690 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4])rgba
, mask
) == 0) {
1693 write_all
= GL_FALSE
;
1696 if (ctx
->Stencil
.Enabled
) {
1697 /* first stencil test */
1698 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
1701 write_all
= GL_FALSE
;
1703 else if (ctx
->Depth
.Test
) {
1704 /* regular depth testing */
1705 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
1710 write_all
= GL_FALSE
;
1714 /* if we get here, something passed the depth test */
1715 ctx
->OcclusionResult
= GL_TRUE
;
1717 /* Texture without alpha test */
1718 if (! ctx
->Color
.AlphaEnabled
) {
1719 ASSERT(ctx
->Texture
._ReallyEnabled
);
1720 for (i
= 0; i
< texUnits
; i
++)
1721 _swrast_texture_fragments( ctx
, i
, n
, s
[i
], t
[i
], u
[i
], lambda
[i
],
1722 (CONST
GLchan (*)[4]) rgbaIn
, rgba
);
1725 /* Add base and specular colors */
1727 (ctx
->Fog
.ColorSumEnabled
||
1728 (ctx
->Light
.Enabled
&&
1729 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)))
1730 add_colors( n
, rgba
, spec
); /* rgba = rgba + spec */
1733 if (ctx
->Fog
.Enabled
) {
1734 if (fog
&& !swrast
->_PreferPixelFog
)
1735 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
1737 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
1740 /* Antialias coverage application */
1743 for (i
= 0; i
< n
; i
++) {
1744 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1748 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1749 multi_write_rgba_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
, mask
);
1752 /* normal: write to exactly one buffer */
1753 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1755 if (ctx
->Color
.ColorLogicOpEnabled
) {
1756 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
1758 else if (ctx
->Color
.BlendEnabled
) {
1759 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
1762 if (colorMask
== 0x0) {
1765 else if (colorMask
!= 0xffffffff) {
1766 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
1769 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
, (const GLchan (*)[4])rgba
,
1770 write_all
? Null
: mask
);
1771 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1772 _mesa_write_alpha_span( ctx
, n
, x
, y
, (const GLchan (*)[4])rgba
,
1773 write_all
? Null
: mask
);
1780 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1781 * reading ouside the buffer's boundaries.
1784 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1785 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1787 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1788 if (y
< 0 || y
>= buffer
->Height
1789 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1790 /* completely above, below, or right */
1791 /* XXX maybe leave undefined? */
1792 BZERO(rgba
, 4 * n
* sizeof(GLchan
));
1797 /* left edge clippping */
1799 length
= (GLint
) n
- skip
;
1801 /* completely left of window */
1804 if (length
> buffer
->Width
) {
1805 length
= buffer
->Width
;
1808 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1809 /* right edge clipping */
1811 length
= buffer
->Width
- x
;
1813 /* completely to right of window */
1823 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1824 if (buffer
->UseSoftwareAlphaBuffers
) {
1825 _mesa_read_alpha_span( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1834 * Read CI pixels from frame buffer. Clipping will be done to prevent
1835 * reading ouside the buffer's boundaries.
1838 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1839 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1841 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1842 if (y
< 0 || y
>= buffer
->Height
1843 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1844 /* completely above, below, or right */
1845 BZERO(indx
, n
* sizeof(GLuint
));
1850 /* left edge clippping */
1852 length
= (GLint
) n
- skip
;
1854 /* completely left of window */
1857 if (length
> buffer
->Width
) {
1858 length
= buffer
->Width
;
1861 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1862 /* right edge clipping */
1864 length
= buffer
->Width
- x
;
1866 /* completely to right of window */
1876 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);