1 /* $Id: s_span.c,v 1.15 2001/06/18 23:55:18 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 * fog - array of fog factor values in [0,1]
179 * index - array of [n] color indexes
180 * primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
183 _mesa_write_index_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
184 const GLdepth z
[], const GLfloat fog
[],
185 GLuint indexIn
[], const GLint coverage
[],
188 const GLuint modBits
= FOG_BIT
| BLEND_BIT
| MASKING_BIT
| LOGIC_OP_BIT
;
189 GLubyte mask
[MAX_WIDTH
];
190 GLuint indexBackup
[MAX_WIDTH
];
191 GLuint
*index
; /* points to indexIn or indexBackup */
192 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
194 /* init mask to 1's (all pixels are to be written) */
197 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
198 if ((n
= clip_span(ctx
,n
,x
,y
,mask
)) == 0) {
203 if ((primitive
==GL_BITMAP
&& (swrast
->_RasterMask
& modBits
))
204 || (swrast
->_RasterMask
& MULTI_DRAW_BIT
)) {
205 /* Make copy of color indexes */
206 MEMCPY( indexBackup
, indexIn
, n
* sizeof(GLuint
) );
214 /* Do the scissor test */
215 if (ctx
->Scissor
.Enabled
) {
216 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
221 /* Polygon Stippling */
222 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
223 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
226 if (ctx
->Stencil
.Enabled
) {
227 /* first stencil test */
228 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
232 else if (ctx
->Depth
.Test
) {
233 /* regular depth testing */
234 if (_mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
) == 0)
238 /* if we get here, something passed the depth test */
239 ctx
->OcclusionResult
= GL_TRUE
;
242 if (ctx
->Fog
.Enabled
) {
243 if (fog
&& !swrast
->_PreferPixelFog
)
244 _mesa_fog_ci_pixels( ctx
, n
, fog
, index
);
246 _mesa_depth_fog_ci_pixels( ctx
, n
, z
, index
);
249 /* Antialias coverage application */
252 for (i
= 0; i
< n
; i
++) {
253 ASSERT(coverage
[i
] < 16);
254 index
[i
] = (index
[i
] & ~0xf) | coverage
[i
];
258 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
259 /* draw to zero or two or more buffers */
260 multi_write_index_span( ctx
, n
, x
, y
, index
, mask
);
263 /* normal situation: draw to exactly one buffer */
264 if (ctx
->Color
.IndexLogicOpEnabled
) {
265 _mesa_logicop_ci_span( ctx
, n
, x
, y
, index
, mask
);
268 if (ctx
->Color
.IndexMask
== 0) {
271 else if (ctx
->Color
.IndexMask
!= 0xffffffff) {
272 _mesa_mask_index_span( ctx
, n
, x
, y
, index
);
276 (*swrast
->Driver
.WriteCI32Span
)( ctx
, n
, x
, y
, index
, mask
);
284 _mesa_write_monoindex_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
285 const GLdepth z
[], const GLfloat fog
[],
286 GLuint index
, const GLint coverage
[],
289 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
290 GLubyte mask
[MAX_WIDTH
];
293 /* init mask to 1's (all pixels are to be written) */
296 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
297 if ((n
= clip_span( ctx
, n
, x
, y
, mask
)) == 0) {
302 /* Do the scissor test */
303 if (ctx
->Scissor
.Enabled
) {
304 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
309 /* Polygon Stippling */
310 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
311 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
314 if (ctx
->Stencil
.Enabled
) {
315 /* first stencil test */
316 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
320 else if (ctx
->Depth
.Test
) {
321 /* regular depth testing */
322 if (_mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
) == 0)
326 /* if we get here, something passed the depth test */
327 ctx
->OcclusionResult
= GL_TRUE
;
329 if (ctx
->Color
.DrawBuffer
== GL_NONE
) {
330 /* write no pixels */
335 || ctx
->Color
.IndexLogicOpEnabled
336 || ctx
->Color
.IndexMask
!= 0xffffffff
338 /* different index per pixel */
339 GLuint indexes
[MAX_WIDTH
];
340 for (i
= 0; i
< n
; i
++) {
344 if (ctx
->Fog
.Enabled
) {
345 if (fog
&& !swrast
->_PreferPixelFog
)
346 _mesa_fog_ci_pixels( ctx
, n
, fog
, indexes
);
348 _mesa_depth_fog_ci_pixels( ctx
, n
, z
, indexes
);
351 /* Antialias coverage application */
354 for (i
= 0; i
< n
; i
++) {
355 ASSERT(coverage
[i
] < 16);
356 indexes
[i
] = (indexes
[i
] & ~0xf) | coverage
[i
];
360 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
361 /* draw to zero or two or more buffers */
362 multi_write_index_span( ctx
, n
, x
, y
, indexes
, mask
);
365 /* normal situation: draw to exactly one buffer */
366 if (ctx
->Color
.IndexLogicOpEnabled
) {
367 _mesa_logicop_ci_span( ctx
, n
, x
, y
, indexes
, mask
);
369 if (ctx
->Color
.IndexMask
== 0) {
372 else if (ctx
->Color
.IndexMask
!= 0xffffffff) {
373 _mesa_mask_index_span( ctx
, n
, x
, y
, indexes
);
375 (*swrast
->Driver
.WriteCI32Span
)( ctx
, n
, x
, y
, indexes
, mask
);
379 /* same color index for all pixels */
380 ASSERT(!ctx
->Color
.IndexLogicOpEnabled
);
381 ASSERT(ctx
->Color
.IndexMask
== 0xffffffff);
382 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
383 /* draw to zero or two or more buffers */
384 GLuint indexes
[MAX_WIDTH
];
385 for (i
= 0; i
< n
; i
++)
387 multi_write_index_span( ctx
, n
, x
, y
, indexes
, mask
);
390 /* normal situation: draw to exactly one buffer */
391 (*swrast
->Driver
.WriteMonoCISpan
)( ctx
, n
, x
, y
, index
, mask
);
399 * Draw to more than one RGBA color buffer (or none).
402 multi_write_rgba_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
403 CONST GLchan rgba
[][4], const GLubyte mask
[] )
405 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
407 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
409 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
412 /* loop over four possible dest color buffers */
413 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
414 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
415 GLchan rgbaTmp
[MAX_WIDTH
][4];
416 ASSERT(n
< MAX_WIDTH
);
418 if (bufferBit
== FRONT_LEFT_BIT
) {
419 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
420 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontLeftAlpha
;
422 else if (bufferBit
== FRONT_RIGHT_BIT
) {
423 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
424 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontRightAlpha
;
426 else if (bufferBit
== BACK_LEFT_BIT
) {
427 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
428 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackLeftAlpha
;
431 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
432 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackRightAlpha
;
435 /* make copy of incoming colors */
436 MEMCPY( rgbaTmp
, rgba
, 4 * n
* sizeof(GLchan
) );
438 if (ctx
->Color
.ColorLogicOpEnabled
) {
439 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgbaTmp
, mask
);
441 else if (ctx
->Color
.BlendEnabled
) {
442 _mesa_blend_span( ctx
, n
, x
, y
, rgbaTmp
, mask
);
444 if (colorMask
== 0x0) {
447 else if (colorMask
!= 0xffffffff) {
448 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgbaTmp
);
451 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
,
452 (const GLchan (*)[4]) rgbaTmp
, mask
);
453 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
454 _mesa_write_alpha_span( ctx
, n
, x
, y
,
455 (const GLchan (*)[4])rgbaTmp
, mask
);
460 /* restore default dest buffer */
461 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
467 _mesa_write_rgba_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
468 const GLdepth z
[], const GLfloat fog
[],
469 GLchan rgbaIn
[][4], const GLfloat coverage
[],
472 const GLuint modBits
= FOG_BIT
| BLEND_BIT
| MASKING_BIT
|
473 LOGIC_OP_BIT
| TEXTURE_BIT
;
474 GLubyte mask
[MAX_WIDTH
];
475 GLboolean write_all
= GL_TRUE
;
476 GLchan rgbaBackup
[MAX_WIDTH
][4];
478 const GLubyte
*Null
= 0;
479 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
481 /* init mask to 1's (all pixels are to be written) */
484 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
485 if ((n
= clip_span( ctx
,n
,x
,y
,mask
)) == 0) {
489 write_all
= GL_FALSE
;
492 if ((primitive
==GL_BITMAP
&& (swrast
->_RasterMask
& modBits
))
493 || (swrast
->_RasterMask
& MULTI_DRAW_BIT
)) {
494 /* must make a copy of the colors since they may be modified */
495 MEMCPY( rgbaBackup
, rgbaIn
, 4 * n
* sizeof(GLchan
) );
502 /* Do the scissor test */
503 if (ctx
->Scissor
.Enabled
) {
504 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
508 write_all
= GL_FALSE
;
511 /* Polygon Stippling */
512 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
513 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
514 write_all
= GL_FALSE
;
517 /* Do the alpha test */
518 if (ctx
->Color
.AlphaEnabled
) {
519 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4]) rgba
, mask
) == 0) {
522 write_all
= GL_FALSE
;
525 if (ctx
->Stencil
.Enabled
) {
526 /* first stencil test */
527 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
530 write_all
= GL_FALSE
;
532 else if (ctx
->Depth
.Test
) {
533 /* regular depth testing */
534 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
539 write_all
= GL_FALSE
;
543 /* if we get here, something passed the depth test */
544 ctx
->OcclusionResult
= GL_TRUE
;
547 if (ctx
->Fog
.Enabled
) {
548 if (fog
&& !swrast
->_PreferPixelFog
)
549 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
551 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
554 /* Antialias coverage application */
557 for (i
= 0; i
< n
; i
++) {
558 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
562 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
563 multi_write_rgba_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
, mask
);
566 /* normal: write to exactly one buffer */
567 /* logic op or blending */
568 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
570 if (ctx
->Color
.ColorLogicOpEnabled
) {
571 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
573 else if (ctx
->Color
.BlendEnabled
) {
574 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
577 /* Color component masking */
578 if (colorMask
== 0x0) {
581 else if (colorMask
!= 0xffffffff) {
582 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
586 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
,
587 (const GLchan (*)[4]) rgba
,
588 write_all
? Null
: mask
);
590 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
591 _mesa_write_alpha_span( ctx
, n
, x
, y
,
592 (const GLchan (*)[4]) rgba
,
593 write_all
? Null
: mask
);
601 * Write a horizontal span of color pixels to the frame buffer.
602 * The color is initially constant for the whole span.
603 * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
604 * Input: n - number of pixels in the span
605 * x, y - location of leftmost pixel in the span
606 * z - array of [n] z-values
607 * fog - array of fog factor values in [0,1]
608 * r, g, b, a - the color of the pixels
609 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
612 _mesa_write_monocolor_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
613 const GLdepth z
[], const GLfloat fog
[],
614 const GLchan color
[4], const GLfloat coverage
[],
617 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
619 GLubyte mask
[MAX_WIDTH
];
620 GLboolean write_all
= GL_TRUE
;
621 GLchan rgba
[MAX_WIDTH
][4];
622 const GLubyte
*Null
= 0;
623 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
625 /* init mask to 1's (all pixels are to be written) */
628 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
629 if ((n
= clip_span( ctx
,n
,x
,y
,mask
)) == 0) {
633 write_all
= GL_FALSE
;
636 /* Do the scissor test */
637 if (ctx
->Scissor
.Enabled
) {
638 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
642 write_all
= GL_FALSE
;
645 /* Polygon Stippling */
646 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
647 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
648 write_all
= GL_FALSE
;
651 /* Do the alpha test */
652 if (ctx
->Color
.AlphaEnabled
) {
653 for (i
= 0; i
< n
; i
++) {
654 rgba
[i
][ACOMP
] = color
[ACOMP
];
656 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4])rgba
, mask
) == 0) {
659 write_all
= GL_FALSE
;
662 if (ctx
->Stencil
.Enabled
) {
663 /* first stencil test */
664 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
667 write_all
= GL_FALSE
;
669 else if (ctx
->Depth
.Test
) {
670 /* regular depth testing */
671 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
676 write_all
= GL_FALSE
;
680 /* if we get here, something passed the depth test */
681 ctx
->OcclusionResult
= GL_TRUE
;
683 if (ctx
->Color
.DrawBuffer
== GL_NONE
) {
684 /* write no pixels */
688 if (ctx
->Color
.ColorLogicOpEnabled
|| colorMask
!= 0xffffffff ||
689 (swrast
->_RasterMask
& (BLEND_BIT
| FOG_BIT
)) || coverage
) {
690 /* assign same color to each pixel */
691 for (i
= 0; i
< n
; i
++) {
693 COPY_CHAN4(rgba
[i
], color
);
698 if (ctx
->Fog
.Enabled
) {
699 if (fog
&& !swrast
->_PreferPixelFog
)
700 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
702 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
705 /* Antialias coverage application */
708 for (i
= 0; i
< n
; i
++) {
709 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
713 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
714 multi_write_rgba_span( ctx
, n
, x
, y
,
715 (const GLchan (*)[4]) rgba
, mask
);
718 /* normal: write to exactly one buffer */
719 if (ctx
->Color
.ColorLogicOpEnabled
) {
720 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
722 else if (ctx
->Color
.BlendEnabled
) {
723 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
726 /* Color component masking */
727 if (colorMask
== 0x0) {
730 else if (colorMask
!= 0xffffffff) {
731 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
735 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
,
736 (const GLchan (*)[4]) rgba
,
737 write_all
? Null
: mask
);
738 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
739 _mesa_write_alpha_span( ctx
, n
, x
, y
,
740 (const GLchan (*)[4]) rgba
,
741 write_all
? Null
: mask
);
746 /* same color for all pixels */
747 ASSERT(!ctx
->Color
.BlendEnabled
);
748 ASSERT(!ctx
->Color
.ColorLogicOpEnabled
);
750 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
751 for (i
= 0; i
< n
; i
++) {
753 COPY_CHAN4(rgba
[i
], color
);
756 multi_write_rgba_span( ctx
, n
, x
, y
,
757 (const GLchan (*)[4]) rgba
, mask
);
760 (*swrast
->Driver
.WriteMonoRGBASpan
)( ctx
, n
, x
, y
, color
, mask
);
761 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
762 _mesa_write_mono_alpha_span( ctx
, n
, x
, y
, (GLchan
) color
[ACOMP
],
763 write_all
? Null
: mask
);
772 * Add specular color to base color. This is used only when
773 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
776 add_colors(GLuint n
, GLchan rgba
[][4], CONST GLchan specular
[][4] )
779 for (i
= 0; i
< n
; i
++) {
780 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
781 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
782 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
783 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
784 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
785 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
791 * Write a horizontal span of textured pixels to the frame buffer.
792 * The color of each pixel is different.
793 * Alpha-testing, stenciling, depth-testing, and blending are done
795 * Input: n - number of pixels in the span
796 * x, y - location of leftmost pixel in the span
797 * z - array of [n] z-values
798 * s, t - array of (s,t) texture coordinates for each pixel
799 * lambda - array of texture lambda values
800 * rgba - array of [n] color components
801 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
804 _mesa_write_texture_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
805 const GLdepth z
[], const GLfloat fog
[],
806 const GLfloat s
[], const GLfloat t
[],
807 const GLfloat u
[], GLfloat lambda
[],
808 GLchan rgbaIn
[][4], CONST GLchan spec
[][4],
809 const GLfloat coverage
[], GLenum primitive
)
811 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
812 GLubyte mask
[MAX_WIDTH
];
813 GLboolean write_all
= GL_TRUE
;
814 GLchan rgbaBackup
[MAX_WIDTH
][4];
815 GLchan (*rgba
)[4]; /* points to either rgbaIn or rgbaBackup */
816 const GLubyte
*Null
= 0;
817 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
819 /* init mask to 1's (all pixels are to be written) */
822 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
823 if ((n
=clip_span(ctx
, n
, x
, y
, mask
)) == 0) {
827 write_all
= GL_FALSE
;
831 if (primitive
==GL_BITMAP
|| (swrast
->_RasterMask
& MULTI_DRAW_BIT
)) {
832 /* must make a copy of the colors since they may be modified */
833 MEMCPY(rgbaBackup
, rgbaIn
, 4 * n
* sizeof(GLchan
));
840 /* Do the scissor test */
841 if (ctx
->Scissor
.Enabled
) {
842 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
846 write_all
= GL_FALSE
;
849 /* Polygon Stippling */
850 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
851 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
852 write_all
= GL_FALSE
;
855 /* Texture with alpha test*/
856 if (ctx
->Color
.AlphaEnabled
) {
857 /* Texturing without alpha is done after depth-testing which
858 gives a potential speed-up. */
859 ASSERT(ctx
->Texture
._ReallyEnabled
);
860 _swrast_texture_fragments( ctx
, 0, n
, s
, t
, u
, lambda
,
861 (CONST
GLchan (*)[4]) rgba
, rgba
);
863 /* Do the alpha test */
864 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4]) rgba
, mask
) == 0) {
867 write_all
= GL_FALSE
;
870 if (ctx
->Stencil
.Enabled
) {
871 /* first stencil test */
872 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
875 write_all
= GL_FALSE
;
877 else if (ctx
->Depth
.Test
) {
878 /* regular depth testing */
879 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
884 write_all
= GL_FALSE
;
888 /* if we get here, something passed the depth test */
889 ctx
->OcclusionResult
= GL_TRUE
;
891 /* Texture without alpha test */
892 if (! ctx
->Color
.AlphaEnabled
) {
893 ASSERT(ctx
->Texture
._ReallyEnabled
);
894 _swrast_texture_fragments( ctx
, 0, n
, s
, t
, u
, lambda
,
895 (CONST
GLchan (*)[4]) rgba
, rgba
);
898 /* Add base and specular colors */
900 (ctx
->Fog
.ColorSumEnabled
||
901 (ctx
->Light
.Enabled
&&
902 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)))
903 add_colors( n
, rgba
, spec
); /* rgba = rgba + spec */
906 if (ctx
->Fog
.Enabled
) {
907 if (fog
&& !swrast
->_PreferPixelFog
)
908 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
910 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
913 /* Antialias coverage application */
916 for (i
= 0; i
< n
; i
++) {
917 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
921 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
922 multi_write_rgba_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
, mask
);
925 /* normal: write to exactly one buffer */
926 if (ctx
->Color
.ColorLogicOpEnabled
) {
927 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
929 else if (ctx
->Color
.BlendEnabled
) {
930 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
932 if (colorMask
== 0x0) {
935 else if (colorMask
!= 0xffffffff) {
936 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
939 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
, (const GLchan (*)[4])rgba
,
940 write_all
? Null
: mask
);
941 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
942 _mesa_write_alpha_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
,
943 write_all
? Null
: mask
);
951 * As above but perform multiple stages of texture application.
954 _mesa_write_multitexture_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
955 const GLdepth z
[], const GLfloat fog
[],
956 CONST GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
957 CONST GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
958 CONST GLfloat u
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
959 GLfloat lambda
[][MAX_WIDTH
],
960 GLchan rgbaIn
[MAX_TEXTURE_UNITS
][4],
961 CONST GLchan spec
[MAX_TEXTURE_UNITS
][4],
962 const GLfloat coverage
[],
965 GLubyte mask
[MAX_WIDTH
];
966 GLboolean write_all
= GL_TRUE
;
967 GLchan rgbaBackup
[MAX_WIDTH
][4];
968 GLchan (*rgba
)[4]; /* points to either rgbaIn or rgbaBackup */
970 const GLubyte
*Null
= 0;
971 const GLuint texUnits
= ctx
->Const
.MaxTextureUnits
;
972 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
974 /* init mask to 1's (all pixels are to be written) */
977 if ((swrast
->_RasterMask
& WINCLIP_BIT
) || primitive
==GL_BITMAP
) {
978 if ((n
=clip_span(ctx
, n
, x
, y
, mask
)) == 0) {
982 write_all
= GL_FALSE
;
986 if (primitive
==GL_BITMAP
|| (swrast
->_RasterMask
& MULTI_DRAW_BIT
)
988 /* must make a copy of the colors since they may be modified */
989 MEMCPY(rgbaBackup
, rgbaIn
, 4 * n
* sizeof(GLchan
));
996 /* Do the scissor test */
997 if (ctx
->Scissor
.Enabled
) {
998 if ((n
= _mesa_scissor_span( ctx
, n
, x
, y
, mask
)) == 0) {
1002 write_all
= GL_FALSE
;
1005 /* Polygon Stippling */
1006 if (ctx
->Polygon
.StippleFlag
&& primitive
==GL_POLYGON
) {
1007 stipple_polygon_span( ctx
, n
, x
, y
, mask
);
1008 write_all
= GL_FALSE
;
1011 /* Texture with alpha test*/
1012 if (ctx
->Color
.AlphaEnabled
) {
1013 /* Texturing without alpha is done after depth-testing which
1014 * gives a potential speed-up.
1016 ASSERT(ctx
->Texture
._ReallyEnabled
);
1017 for (i
= 0; i
< texUnits
; i
++)
1018 _swrast_texture_fragments( ctx
, i
, n
, s
[i
], t
[i
], u
[i
], lambda
[i
],
1019 (CONST
GLchan (*)[4]) rgbaIn
, rgba
);
1021 /* Do the alpha test */
1022 if (_mesa_alpha_test( ctx
, n
, (const GLchan (*)[4])rgba
, mask
) == 0) {
1025 write_all
= GL_FALSE
;
1028 if (ctx
->Stencil
.Enabled
) {
1029 /* first stencil test */
1030 if (_mesa_stencil_and_ztest_span(ctx
, n
, x
, y
, z
, mask
) == GL_FALSE
) {
1033 write_all
= GL_FALSE
;
1035 else if (ctx
->Depth
.Test
) {
1036 /* regular depth testing */
1037 GLuint m
= _mesa_depth_test_span( ctx
, n
, x
, y
, z
, mask
);
1042 write_all
= GL_FALSE
;
1046 /* if we get here, something passed the depth test */
1047 ctx
->OcclusionResult
= GL_TRUE
;
1049 /* Texture without alpha test */
1050 if (! ctx
->Color
.AlphaEnabled
) {
1051 ASSERT(ctx
->Texture
._ReallyEnabled
);
1052 for (i
= 0; i
< texUnits
; i
++)
1053 _swrast_texture_fragments( ctx
, i
, n
, s
[i
], t
[i
], u
[i
], lambda
[i
],
1054 (CONST
GLchan (*)[4]) rgbaIn
, rgba
);
1057 /* Add base and specular colors */
1059 (ctx
->Fog
.ColorSumEnabled
||
1060 (ctx
->Light
.Enabled
&&
1061 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)))
1062 add_colors( n
, rgba
, spec
); /* rgba = rgba + spec */
1065 if (ctx
->Fog
.Enabled
) {
1066 if (fog
&& !swrast
->_PreferPixelFog
)
1067 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
1069 _mesa_depth_fog_rgba_pixels( ctx
, n
, z
, rgba
);
1072 /* Antialias coverage application */
1075 for (i
= 0; i
< n
; i
++) {
1076 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1080 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1081 multi_write_rgba_span( ctx
, n
, x
, y
, (const GLchan (*)[4]) rgba
, mask
);
1084 /* normal: write to exactly one buffer */
1085 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1087 if (ctx
->Color
.ColorLogicOpEnabled
) {
1088 _mesa_logicop_rgba_span( ctx
, n
, x
, y
, rgba
, mask
);
1090 else if (ctx
->Color
.BlendEnabled
) {
1091 _mesa_blend_span( ctx
, n
, x
, y
, rgba
, mask
);
1094 if (colorMask
== 0x0) {
1097 else if (colorMask
!= 0xffffffff) {
1098 _mesa_mask_rgba_span( ctx
, n
, x
, y
, rgba
);
1101 (*swrast
->Driver
.WriteRGBASpan
)( ctx
, n
, x
, y
, (const GLchan (*)[4])rgba
,
1102 write_all
? Null
: mask
);
1103 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1104 _mesa_write_alpha_span( ctx
, n
, x
, y
, (const GLchan (*)[4])rgba
,
1105 write_all
? Null
: mask
);
1113 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1114 * reading ouside the buffer's boundaries.
1117 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1118 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1120 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1121 if (y
< 0 || y
>= buffer
->Height
1122 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1123 /* completely above, below, or right */
1124 /* XXX maybe leave undefined? */
1125 BZERO(rgba
, 4 * n
* sizeof(GLchan
));
1130 /* left edge clippping */
1132 length
= (GLint
) n
- skip
;
1134 /* completely left of window */
1137 if (length
> buffer
->Width
) {
1138 length
= buffer
->Width
;
1141 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1142 /* right edge clipping */
1144 length
= buffer
->Width
- x
;
1146 /* completely to right of window */
1156 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1157 if (buffer
->UseSoftwareAlphaBuffers
) {
1158 _mesa_read_alpha_span( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1167 * Read CI pixels from frame buffer. Clipping will be done to prevent
1168 * reading ouside the buffer's boundaries.
1171 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1172 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1174 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1175 if (y
< 0 || y
>= buffer
->Height
1176 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1177 /* completely above, below, or right */
1178 BZERO(indx
, n
* sizeof(GLuint
));
1183 /* left edge clippping */
1185 length
= (GLint
) n
- skip
;
1187 /* completely left of window */
1190 if (length
> buffer
->Width
) {
1191 length
= buffer
->Width
;
1194 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1195 /* right edge clipping */
1197 length
= buffer
->Width
- x
;
1199 /* completely to right of window */
1209 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);