1 /* $Id: s_span.c,v 1.14 2001/05/15 21:30:27 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.
40 #include "s_alphabuf.h"
42 #include "s_context.h"
46 #include "s_masking.h"
47 #include "s_scissor.h"
49 #include "s_stencil.h"
50 #include "s_texture.h"
55 * Apply the current polygon stipple pattern to a span of pixels.
58 stipple_polygon_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
61 const GLuint highbit
= 0x80000000;
64 stipple
= ctx
->PolygonStipple
[y
% 32];
65 m
= highbit
>> (GLuint
) (x
% 32);
67 for (i
= 0; i
< n
; i
++) {
68 if ((m
& stipple
) == 0) {
81 * Clip a pixel span to the current buffer/window boundaries.
82 * Return: 'n' such that pixel 'n', 'n+1' etc. are clipped,
84 * 0 = all pixels clipped
87 clip_span( GLcontext
*ctx
, GLint n
, GLint x
, GLint y
, GLubyte mask
[] )
89 /* Clip to top and bottom */
90 if (y
< 0 || y
>= ctx
->DrawBuffer
->Height
) {
94 /* Clip to the left */
97 /* completely off left side */
101 /* partially off left side */
102 BZERO(mask
, -x
* sizeof(GLubyte
));
107 if (x
+ n
> ctx
->DrawBuffer
->Width
) {
108 if (x
>= ctx
->DrawBuffer
->Width
) {
109 /* completely off right side */
113 /* partially off right side */
114 return ctx
->DrawBuffer
->Width
- x
;
124 * Draw to more than one color buffer (or none).
127 multi_write_index_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
128 const GLuint indexes
[], const GLubyte mask
[] )
130 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
133 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
136 /* loop over four possible dest color buffers */
137 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
138 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
139 GLuint indexTmp
[MAX_WIDTH
];
140 ASSERT(n
< MAX_WIDTH
);
142 if (bufferBit
== FRONT_LEFT_BIT
)
143 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
144 else if (bufferBit
== FRONT_RIGHT_BIT
)
145 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
146 else if (bufferBit
== BACK_LEFT_BIT
)
147 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
149 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
151 /* make copy of incoming indexes */
152 MEMCPY( indexTmp
, indexes
, n
* sizeof(GLuint
) );
153 if (ctx
->Color
.IndexLogicOpEnabled
) {
154 _mesa_logicop_ci_span( ctx
, n
, x
, y
, indexTmp
, mask
);
156 if (ctx
->Color
.IndexMask
== 0) {
159 else if (ctx
->Color
.IndexMask
!= 0xffffffff) {
160 _mesa_mask_index_span( ctx
, n
, x
, y
, indexTmp
);
162 (*swrast
->Driver
.WriteCI32Span
)( ctx
, n
, x
, y
, indexTmp
, mask
);
166 /* restore default dest buffer */
167 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
173 * Write a horizontal span of color index pixels to the frame buffer.
174 * Stenciling, Depth-testing, etc. are done as needed.
175 * Input: n - number of pixels in the span
176 * x, y - location of leftmost pixel in the span
177 * z - array of [n] z-values
178 * index - array of [n] color indexes
179 * primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
182 _mesa_write_index_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
183 const GLdepth z
[], const GLfloat fog
[],
184 GLuint indexIn
[], const GLint coverage
[],
187 const GLuint modBits
= FOG_BIT
| BLEND_BIT
| MASKING_BIT
| LOGIC_OP_BIT
;
188 GLubyte mask
[MAX_WIDTH
];
189 GLuint indexBackup
[MAX_WIDTH
];
190 GLuint
*index
; /* points to indexIn or indexBackup */
191 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
193 /* init mask to 1's (all pixels are to be written) */
196 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
197 if ((n
= clip_span(ctx
,n
,x
,y
,mask
)) == 0) {
202 if ((primitive
==GL_BITMAP
&& (swrast
->_RasterMask
& modBits
))
203 || (swrast
->_RasterMask
& MULTI_DRAW_BIT
)) {
204 /* Make copy of color indexes */
205 MEMCPY( indexBackup
, indexIn
, n
* sizeof(GLuint
) );
213 /* Do the scissor test */
214 if (ctx
->Scissor
.Enabled
) {
215 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
220 /* Polygon Stippling */
221 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
222 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
225 if (ctx
->Stencil
.Enabled
) {
226 /* first stencil test */
227 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
231 else if (ctx
->Depth
.Test
) {
232 /* regular depth testing */
233 if (_mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
) == 0)
237 /* if we get here, something passed the depth test */
238 ctx
->OcclusionResult
= GL_TRUE
;
241 if (ctx
->Fog
.Enabled
) {
242 if (fog
&& !swrast
->_PreferPixelFog
)
243 _mesa_fog_ci_pixels( ctx
, n
, fog
, index
);
245 _mesa_depth_fog_ci_pixels( ctx
, n
, z
, index
);
248 /* Antialias coverage application */
251 for (i
= 0; i
< n
; i
++) {
252 ASSERT(coverage
[i
] < 16);
253 index
[i
] = (index
[i
] & ~0xf) | coverage
[i
];
257 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
258 /* draw to zero or two or more buffers */
259 multi_write_index_span( ctx
, n
, x
, y
, index
, mask
);
262 /* normal situation: draw to exactly one buffer */
263 if (ctx
->Color
.IndexLogicOpEnabled
) {
264 _mesa_logicop_ci_span( ctx
, n
, x
, y
, index
, mask
);
267 if (ctx
->Color
.IndexMask
== 0) {
270 else if (ctx
->Color
.IndexMask
!= 0xffffffff) {
271 _mesa_mask_index_span( ctx
, n
, x
, y
, index
);
275 (*swrast
->Driver
.WriteCI32Span
)( ctx
, n
, x
, y
, index
, mask
);
283 _mesa_write_monoindex_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
284 const GLdepth z
[], const GLfloat fog
[],
285 GLuint index
, const GLint coverage
[],
288 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
289 GLubyte mask
[MAX_WIDTH
];
292 /* init mask to 1's (all pixels are to be written) */
295 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
296 if ((n
= clip_span( ctx
, n
, x
, y
, mask
)) == 0) {
301 /* Do the scissor test */
302 if (ctx
->Scissor
.Enabled
) {
303 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
308 /* Polygon Stippling */
309 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
310 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
313 if (ctx
->Stencil
.Enabled
) {
314 /* first stencil test */
315 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
319 else if (ctx
->Depth
.Test
) {
320 /* regular depth testing */
321 if (_mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
) == 0)
325 /* if we get here, something passed the depth test */
326 ctx
->OcclusionResult
= GL_TRUE
;
328 if (ctx
->Color
.DrawBuffer
== GL_NONE
) {
329 /* write no pixels */
334 || ctx
->Color
.IndexLogicOpEnabled
335 || ctx
->Color
.IndexMask
!= 0xffffffff
337 /* different index per pixel */
338 GLuint indexes
[MAX_WIDTH
];
339 for (i
= 0; i
< n
; i
++) {
343 if (ctx
->Fog
.Enabled
) {
344 if (fog
&& !swrast
->_PreferPixelFog
)
345 _mesa_fog_ci_pixels( ctx
, n
, fog
, indexes
);
347 _mesa_depth_fog_ci_pixels( ctx
, n
, z
, indexes
);
350 /* Antialias coverage application */
353 for (i
= 0; i
< n
; i
++) {
354 ASSERT(coverage
[i
] < 16);
355 indexes
[i
] = (indexes
[i
] & ~0xf) | coverage
[i
];
359 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
360 /* draw to zero or two or more buffers */
361 multi_write_index_span( ctx
, n
, x
, y
, indexes
, mask
);
364 /* normal situation: draw to exactly one buffer */
365 if (ctx
->Color
.IndexLogicOpEnabled
) {
366 _mesa_logicop_ci_span( ctx
, n
, x
, y
, indexes
, mask
);
368 if (ctx
->Color
.IndexMask
== 0) {
371 else if (ctx
->Color
.IndexMask
!= 0xffffffff) {
372 _mesa_mask_index_span( ctx
, n
, x
, y
, indexes
);
374 (*swrast
->Driver
.WriteCI32Span
)( ctx
, n
, x
, y
, indexes
, mask
);
378 /* same color index for all pixels */
379 ASSERT(!ctx
->Color
.IndexLogicOpEnabled
);
380 ASSERT(ctx
->Color
.IndexMask
== 0xffffffff);
381 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
382 /* draw to zero or two or more buffers */
383 GLuint indexes
[MAX_WIDTH
];
384 for (i
= 0; i
< n
; i
++)
386 multi_write_index_span( ctx
, n
, x
, y
, indexes
, mask
);
389 /* normal situation: draw to exactly one buffer */
390 (*swrast
->Driver
.WriteMonoCISpan
)( ctx
, n
, x
, y
, index
, mask
);
398 * Draw to more than one RGBA color buffer (or none).
401 multi_write_rgba_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
402 CONST GLchan rgba
[][4], const GLubyte mask
[] )
404 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
406 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
408 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
411 /* loop over four possible dest color buffers */
412 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
413 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
414 GLchan rgbaTmp
[MAX_WIDTH
][4];
415 ASSERT(n
< MAX_WIDTH
);
417 if (bufferBit
== FRONT_LEFT_BIT
) {
418 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
419 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontLeftAlpha
;
421 else if (bufferBit
== FRONT_RIGHT_BIT
) {
422 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
423 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontRightAlpha
;
425 else if (bufferBit
== BACK_LEFT_BIT
) {
426 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
427 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackLeftAlpha
;
430 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
431 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackRightAlpha
;
434 /* make copy of incoming colors */
435 MEMCPY( rgbaTmp
, rgba
, 4 * n
* sizeof(GLchan
) );
437 if (ctx
->Color
.ColorLogicOpEnabled
) {
438 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgbaTmp
, mask
);
440 else if (ctx
->Color
.BlendEnabled
) {
441 _mesa_blend_span( ctx
, n
, x
, y
, rgbaTmp
, mask
);
443 if (colorMask
== 0x0) {
446 else if (colorMask
!= 0xffffffff) {
447 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgbaTmp
);
450 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
,
451 (const GLchan (*)[4]) rgbaTmp
, mask
);
452 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
453 _mesa_write_alpha_span( ctx
, n
, x
, y
,
454 (const GLchan (*)[4])rgbaTmp
, mask
);
459 /* restore default dest buffer */
460 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
466 _mesa_write_rgba_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
467 const GLdepth z
[], const GLfloat fog
[],
468 GLchan rgbaIn
[][4], const GLfloat coverage
[],
471 const GLuint modBits
= FOG_BIT
| BLEND_BIT
| MASKING_BIT
|
472 LOGIC_OP_BIT
| TEXTURE_BIT
;
473 GLubyte mask
[MAX_WIDTH
];
474 GLboolean write_all
= GL_TRUE
;
475 GLchan rgbaBackup
[MAX_WIDTH
][4];
477 const GLubyte
*Null
= 0;
478 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
480 /* init mask to 1's (all pixels are to be written) */
483 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
484 if ((n
= clip_span( ctx
,n
,x
,y
,mask
)) == 0) {
488 write_all
= GL_FALSE
;
491 if ((primitive
==GL_BITMAP
&& (swrast
->_RasterMask
& modBits
))
492 || (swrast
->_RasterMask
& MULTI_DRAW_BIT
)) {
493 /* must make a copy of the colors since they may be modified */
494 MEMCPY( rgbaBackup
, rgbaIn
, 4 * n
* sizeof(GLchan
) );
501 /* Do the scissor test */
502 if (ctx
->Scissor
.Enabled
) {
503 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
507 write_all
= GL_FALSE
;
510 /* Polygon Stippling */
511 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
512 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
513 write_all
= GL_FALSE
;
516 /* Do the alpha test */
517 if (ctx
->Color
.AlphaEnabled
) {
518 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4]) rgba
, mask
) == 0) {
521 write_all
= GL_FALSE
;
524 if (ctx
->Stencil
.Enabled
) {
525 /* first stencil test */
526 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
529 write_all
= GL_FALSE
;
531 else if (ctx
->Depth
.Test
) {
532 /* regular depth testing */
533 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
538 write_all
= GL_FALSE
;
542 /* if we get here, something passed the depth test */
543 ctx
->OcclusionResult
= GL_TRUE
;
546 if (ctx
->Fog
.Enabled
) {
547 if (fog
&& !swrast
->_PreferPixelFog
)
548 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
550 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
553 /* Antialias coverage application */
556 for (i
= 0; i
< n
; i
++) {
557 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
561 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
562 multi_write_rgba_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
, mask
);
565 /* normal: write to exactly one buffer */
566 /* logic op or blending */
567 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
569 if (ctx
->Color
.ColorLogicOpEnabled
) {
570 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
572 else if (ctx
->Color
.BlendEnabled
) {
573 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
576 /* Color component masking */
577 if (colorMask
== 0x0) {
580 else if (colorMask
!= 0xffffffff) {
581 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
585 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
,
586 (const GLchan (*)[4]) rgba
,
587 write_all
? Null
: mask
);
589 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
590 _mesa_write_alpha_span( ctx
, n
, x
, y
,
591 (const GLchan (*)[4]) rgba
,
592 write_all
? Null
: mask
);
600 * Write a horizontal span of color pixels to the frame buffer.
601 * The color is initially constant for the whole span.
602 * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
603 * Input: n - number of pixels in the span
604 * x, y - location of leftmost pixel in the span
605 * z - array of [n] z-values
606 * r, g, b, a - the color of the pixels
607 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
610 _mesa_write_monocolor_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
611 const GLdepth z
[], const GLfloat fog
[],
612 const GLchan color
[4], const GLfloat coverage
[],
615 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
617 GLubyte mask
[MAX_WIDTH
];
618 GLboolean write_all
= GL_TRUE
;
619 GLchan rgba
[MAX_WIDTH
][4];
620 const GLubyte
*Null
= 0;
621 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
623 /* init mask to 1's (all pixels are to be written) */
626 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
627 if ((n
= clip_span( ctx
,n
,x
,y
,mask
)) == 0) {
631 write_all
= GL_FALSE
;
634 /* Do the scissor test */
635 if (ctx
->Scissor
.Enabled
) {
636 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
640 write_all
= GL_FALSE
;
643 /* Polygon Stippling */
644 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
645 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
646 write_all
= GL_FALSE
;
649 /* Do the alpha test */
650 if (ctx
->Color
.AlphaEnabled
) {
651 for (i
= 0; i
< n
; i
++) {
652 rgba
[i
][ACOMP
] = color
[ACOMP
];
654 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4])rgba
, mask
) == 0) {
657 write_all
= GL_FALSE
;
660 if (ctx
->Stencil
.Enabled
) {
661 /* first stencil test */
662 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
665 write_all
= GL_FALSE
;
667 else if (ctx
->Depth
.Test
) {
668 /* regular depth testing */
669 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
674 write_all
= GL_FALSE
;
678 /* if we get here, something passed the depth test */
679 ctx
->OcclusionResult
= GL_TRUE
;
681 if (ctx
->Color
.DrawBuffer
== GL_NONE
) {
682 /* write no pixels */
686 if (ctx
->Color
.ColorLogicOpEnabled
|| colorMask
!= 0xffffffff ||
687 (swrast
->_RasterMask
& (BLEND_BIT
| FOG_BIT
)) || coverage
) {
688 /* assign same color to each pixel */
689 for (i
= 0; i
< n
; i
++) {
691 COPY_CHAN4(rgba
[i
], color
);
696 if (ctx
->Fog
.Enabled
) {
697 if (fog
&& !swrast
->_PreferPixelFog
)
698 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
700 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
703 /* Antialias coverage application */
706 for (i
= 0; i
< n
; i
++) {
707 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
711 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
712 multi_write_rgba_span( ctx
, n
, x
, y
,
713 (const GLchan (*)[4]) rgba
, mask
);
716 /* normal: write to exactly one buffer */
717 if (ctx
->Color
.ColorLogicOpEnabled
) {
718 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
720 else if (ctx
->Color
.BlendEnabled
) {
721 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
724 /* Color component masking */
725 if (colorMask
== 0x0) {
728 else if (colorMask
!= 0xffffffff) {
729 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
733 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
,
734 (const GLchan (*)[4]) rgba
,
735 write_all
? Null
: mask
);
736 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
737 _mesa_write_alpha_span( ctx
, n
, x
, y
,
738 (const GLchan (*)[4]) rgba
,
739 write_all
? Null
: mask
);
744 /* same color for all pixels */
745 ASSERT(!ctx
->Color
.BlendEnabled
);
746 ASSERT(!ctx
->Color
.ColorLogicOpEnabled
);
748 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
749 for (i
= 0; i
< n
; i
++) {
751 COPY_CHAN4(rgba
[i
], color
);
754 multi_write_rgba_span( ctx
, n
, x
, y
,
755 (const GLchan (*)[4]) rgba
, mask
);
758 (*swrast
->Driver
.WriteMonoRGBASpan
)( ctx
, n
, x
, y
, color
, mask
);
759 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
760 _mesa_write_mono_alpha_span( ctx
, n
, x
, y
, (GLchan
) color
[ACOMP
],
761 write_all
? Null
: mask
);
770 * Add specular color to base color. This is used only when
771 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
774 add_colors(GLuint n
, GLchan rgba
[][4], CONST GLchan specular
[][4] )
777 for (i
= 0; i
< n
; i
++) {
778 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
779 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
780 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
781 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
782 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
783 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
789 * Write a horizontal span of textured pixels to the frame buffer.
790 * The color of each pixel is different.
791 * Alpha-testing, stenciling, depth-testing, and blending are done
793 * Input: n - number of pixels in the span
794 * x, y - location of leftmost pixel in the span
795 * z - array of [n] z-values
796 * s, t - array of (s,t) texture coordinates for each pixel
797 * lambda - array of texture lambda values
798 * rgba - array of [n] color components
799 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
802 _mesa_write_texture_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
803 const GLdepth z
[], const GLfloat fog
[],
804 const GLfloat s
[], const GLfloat t
[],
805 const GLfloat u
[], GLfloat lambda
[],
806 GLchan rgbaIn
[][4], CONST GLchan spec
[][4],
807 const GLfloat coverage
[], GLenum primitive
)
809 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
810 GLubyte mask
[MAX_WIDTH
];
811 GLboolean write_all
= GL_TRUE
;
812 GLchan rgbaBackup
[MAX_WIDTH
][4];
813 GLchan (*rgba
)[4]; /* points to either rgbaIn or rgbaBackup */
814 const GLubyte
*Null
= 0;
815 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
817 /* init mask to 1's (all pixels are to be written) */
820 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
821 if ((n
=clip_span(ctx
, n
, x
, y
, mask
)) == 0) {
825 write_all
= GL_FALSE
;
829 if (primitive
==GL_BITMAP
|| (swrast
->_RasterMask
& MULTI_DRAW_BIT
)) {
830 /* must make a copy of the colors since they may be modified */
831 MEMCPY(rgbaBackup
, rgbaIn
, 4 * n
* sizeof(GLchan
));
838 /* Do the scissor test */
839 if (ctx
->Scissor
.Enabled
) {
840 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
844 write_all
= GL_FALSE
;
847 /* Polygon Stippling */
848 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
849 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
850 write_all
= GL_FALSE
;
853 /* Texture with alpha test*/
854 if (ctx
->Color
.AlphaEnabled
) {
855 /* Texturing without alpha is done after depth-testing which
856 gives a potential speed-up. */
857 ASSERT(ctx
->Texture
._ReallyEnabled
);
858 _swrast_texture_fragments( ctx
, 0, n
, s
, t
, u
, lambda
,
859 (CONST
GLchan (*)[4]) rgba
, rgba
);
861 /* Do the alpha test */
862 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4]) rgba
, mask
) == 0) {
865 write_all
= GL_FALSE
;
868 if (ctx
->Stencil
.Enabled
) {
869 /* first stencil test */
870 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
873 write_all
= GL_FALSE
;
875 else if (ctx
->Depth
.Test
) {
876 /* regular depth testing */
877 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
882 write_all
= GL_FALSE
;
886 /* if we get here, something passed the depth test */
887 ctx
->OcclusionResult
= GL_TRUE
;
889 /* Texture without alpha test */
890 if (! ctx
->Color
.AlphaEnabled
) {
891 ASSERT(ctx
->Texture
._ReallyEnabled
);
892 _swrast_texture_fragments( ctx
, 0, n
, s
, t
, u
, lambda
,
893 (CONST
GLchan (*)[4]) rgba
, rgba
);
896 /* Add base and specular colors */
898 (ctx
->Fog
.ColorSumEnabled
||
899 (ctx
->Light
.Enabled
&&
900 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)))
901 add_colors( n
, rgba
, spec
); /* rgba = rgba + spec */
904 if (ctx
->Fog
.Enabled
) {
905 if (fog
&& !swrast
->_PreferPixelFog
)
906 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
908 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
911 /* Antialias coverage application */
914 for (i
= 0; i
< n
; i
++) {
915 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
919 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
920 multi_write_rgba_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
, mask
);
923 /* normal: write to exactly one buffer */
924 if (ctx
->Color
.ColorLogicOpEnabled
) {
925 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
927 else if (ctx
->Color
.BlendEnabled
) {
928 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
930 if (colorMask
== 0x0) {
933 else if (colorMask
!= 0xffffffff) {
934 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
937 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
, (const GLchan (*)[4])rgba
,
938 write_all
? Null
: mask
);
939 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
940 _mesa_write_alpha_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
,
941 write_all
? Null
: mask
);
949 * As above but perform multiple stages of texture application.
952 _mesa_write_multitexture_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
953 const GLdepth z
[], const GLfloat fog
[],
954 CONST GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
955 CONST GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
956 CONST GLfloat u
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
957 GLfloat lambda
[][MAX_WIDTH
],
958 GLchan rgbaIn
[MAX_TEXTURE_UNITS
][4],
959 CONST GLchan spec
[MAX_TEXTURE_UNITS
][4],
960 const GLfloat coverage
[],
963 GLubyte mask
[MAX_WIDTH
];
964 GLboolean write_all
= GL_TRUE
;
965 GLchan rgbaBackup
[MAX_WIDTH
][4];
966 GLchan (*rgba
)[4]; /* points to either rgbaIn or rgbaBackup */
968 const GLubyte
*Null
= 0;
969 const GLuint texUnits
= ctx
->Const
.MaxTextureUnits
;
970 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
972 /* init mask to 1's (all pixels are to be written) */
975 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
976 if ((n
=clip_span(ctx
, n
, x
, y
, mask
)) == 0) {
980 write_all
= GL_FALSE
;
984 if (primitive
==GL_BITMAP
|| (swrast
->_RasterMask
& MULTI_DRAW_BIT
)
986 /* must make a copy of the colors since they may be modified */
987 MEMCPY(rgbaBackup
, rgbaIn
, 4 * n
* sizeof(GLchan
));
994 /* Do the scissor test */
995 if (ctx
->Scissor
.Enabled
) {
996 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
1000 write_all
= GL_FALSE
;
1003 /* Polygon Stippling */
1004 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
1005 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
1006 write_all
= GL_FALSE
;
1009 /* Texture with alpha test*/
1010 if (ctx
->Color
.AlphaEnabled
) {
1011 /* Texturing without alpha is done after depth-testing which
1012 * gives a potential speed-up.
1014 ASSERT(ctx
->Texture
._ReallyEnabled
);
1015 for (i
= 0; i
< texUnits
; i
++)
1016 _swrast_texture_fragments( ctx
, i
, n
, s
[i
], t
[i
], u
[i
], lambda
[i
],
1017 (CONST
GLchan (*)[4]) rgbaIn
, rgba
);
1019 /* Do the alpha test */
1020 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4])rgba
, mask
) == 0) {
1023 write_all
= GL_FALSE
;
1026 if (ctx
->Stencil
.Enabled
) {
1027 /* first stencil test */
1028 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
1031 write_all
= GL_FALSE
;
1033 else if (ctx
->Depth
.Test
) {
1034 /* regular depth testing */
1035 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
1040 write_all
= GL_FALSE
;
1044 /* if we get here, something passed the depth test */
1045 ctx
->OcclusionResult
= GL_TRUE
;
1047 /* Texture without alpha test */
1048 if (! ctx
->Color
.AlphaEnabled
) {
1049 ASSERT(ctx
->Texture
._ReallyEnabled
);
1050 for (i
= 0; i
< texUnits
; i
++)
1051 _swrast_texture_fragments( ctx
, i
, n
, s
[i
], t
[i
], u
[i
], lambda
[i
],
1052 (CONST
GLchan (*)[4]) rgbaIn
, rgba
);
1055 /* Add base and specular colors */
1057 (ctx
->Fog
.ColorSumEnabled
||
1058 (ctx
->Light
.Enabled
&&
1059 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)))
1060 add_colors( n
, rgba
, spec
); /* rgba = rgba + spec */
1063 if (ctx
->Fog
.Enabled
) {
1064 if (fog
&& !swrast
->_PreferPixelFog
)
1065 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
1067 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
1070 /* Antialias coverage application */
1073 for (i
= 0; i
< n
; i
++) {
1074 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1078 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1079 multi_write_rgba_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
, mask
);
1082 /* normal: write to exactly one buffer */
1083 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1085 if (ctx
->Color
.ColorLogicOpEnabled
) {
1086 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
1088 else if (ctx
->Color
.BlendEnabled
) {
1089 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
1092 if (colorMask
== 0x0) {
1095 else if (colorMask
!= 0xffffffff) {
1096 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
1099 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
, (const GLchan (*)[4])rgba
,
1100 write_all
? Null
: mask
);
1101 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1102 _mesa_write_alpha_span( ctx
, n
, x
, y
, (const GLchan (*)[4])rgba
,
1103 write_all
? Null
: mask
);
1111 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1112 * reading ouside the buffer's boundaries.
1115 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1116 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1118 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1119 if (y
< 0 || y
>= buffer
->Height
1120 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1121 /* completely above, below, or right */
1122 /* XXX maybe leave undefined? */
1123 BZERO(rgba
, 4 * n
* sizeof(GLchan
));
1128 /* left edge clippping */
1130 length
= (GLint
) n
- skip
;
1132 /* completely left of window */
1135 if (length
> buffer
->Width
) {
1136 length
= buffer
->Width
;
1139 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1140 /* right edge clipping */
1142 length
= buffer
->Width
- x
;
1144 /* completely to right of window */
1154 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1155 if (buffer
->UseSoftwareAlphaBuffers
) {
1156 _mesa_read_alpha_span( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1165 * Read CI pixels from frame buffer. Clipping will be done to prevent
1166 * reading ouside the buffer's boundaries.
1169 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1170 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1172 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1173 if (y
< 0 || y
>= buffer
->Height
1174 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1175 /* completely above, below, or right */
1176 BZERO(indx
, n
* sizeof(GLuint
));
1181 /* left edge clippping */
1183 length
= (GLint
) n
- skip
;
1185 /* completely left of window */
1188 if (length
> buffer
->Width
) {
1189 length
= buffer
->Width
;
1192 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1193 /* right edge clipping */
1195 length
= buffer
->Width
- x
;
1197 /* completely to right of window */
1207 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);