Apply antialiasing coverage factor to alpha after texture application,
[mesa.git] / src / mesa / swrast / s_span.c
1 /* $Id: s_span.c,v 1.14 2001/05/15 21:30:27 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27
28 /*
29 * pixel span rasterization:
30 * These functions implement the rasterization pipeline.
31 */
32
33
34 #include "glheader.h"
35 #include "colormac.h"
36 #include "macros.h"
37 #include "mem.h"
38
39 #include "s_alpha.h"
40 #include "s_alphabuf.h"
41 #include "s_blend.h"
42 #include "s_context.h"
43 #include "s_depth.h"
44 #include "s_fog.h"
45 #include "s_logic.h"
46 #include "s_masking.h"
47 #include "s_scissor.h"
48 #include "s_span.h"
49 #include "s_stencil.h"
50 #include "s_texture.h"
51
52
53
54 /*
55 * Apply the current polygon stipple pattern to a span of pixels.
56 */
57 static void
58 stipple_polygon_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
59 GLubyte mask[] )
60 {
61 const GLuint highbit = 0x80000000;
62 GLuint i, m, stipple;
63
64 stipple = ctx->PolygonStipple[y % 32];
65 m = highbit >> (GLuint) (x % 32);
66
67 for (i = 0; i < n; i++) {
68 if ((m & stipple) == 0) {
69 mask[i] = 0;
70 }
71 m = m >> 1;
72 if (m == 0) {
73 m = highbit;
74 }
75 }
76 }
77
78
79
80 /*
81 * Clip a pixel span to the current buffer/window boundaries.
82 * Return: 'n' such that pixel 'n', 'n+1' etc. are clipped,
83 * as a special case:
84 * 0 = all pixels clipped
85 */
86 static GLuint
87 clip_span( GLcontext *ctx, GLint n, GLint x, GLint y, GLubyte mask[] )
88 {
89 /* Clip to top and bottom */
90 if (y < 0 || y >= ctx->DrawBuffer->Height) {
91 return 0;
92 }
93
94 /* Clip to the left */
95 if (x < 0) {
96 if (x + n <= 0) {
97 /* completely off left side */
98 return 0;
99 }
100 else {
101 /* partially off left side */
102 BZERO(mask, -x * sizeof(GLubyte));
103 }
104 }
105
106 /* Clip to right */
107 if (x + n > ctx->DrawBuffer->Width) {
108 if (x >= ctx->DrawBuffer->Width) {
109 /* completely off right side */
110 return 0;
111 }
112 else {
113 /* partially off right side */
114 return ctx->DrawBuffer->Width - x;
115 }
116 }
117
118 return n;
119 }
120
121
122
123 /*
124 * Draw to more than one color buffer (or none).
125 */
126 static void
127 multi_write_index_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
128 const GLuint indexes[], const GLubyte mask[] )
129 {
130 SWcontext *swrast = SWRAST_CONTEXT(ctx);
131 GLuint bufferBit;
132
133 if (ctx->Color.DrawBuffer == GL_NONE)
134 return;
135
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);
141
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);
148 else
149 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
150
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 );
155 }
156 if (ctx->Color.IndexMask == 0) {
157 break;
158 }
159 else if (ctx->Color.IndexMask != 0xffffffff) {
160 _mesa_mask_index_span( ctx, n, x, y, indexTmp );
161 }
162 (*swrast->Driver.WriteCI32Span)( ctx, n, x, y, indexTmp, mask );
163 }
164 }
165
166 /* restore default dest buffer */
167 (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer);
168 }
169
170
171
172 /*
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
180 */
181 void
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[],
185 GLenum primitive )
186 {
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);
192
193 /* init mask to 1's (all pixels are to be written) */
194 MEMSET(mask, 1, n);
195
196 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
197 if ((n = clip_span(ctx,n,x,y,mask)) == 0) {
198 return;
199 }
200 }
201
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) );
206 index = indexBackup;
207 }
208 else {
209 index = indexIn;
210 }
211
212
213 /* Do the scissor test */
214 if (ctx->Scissor.Enabled) {
215 if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) {
216 return;
217 }
218 }
219
220 /* Polygon Stippling */
221 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
222 stipple_polygon_span( ctx, n, x, y, mask );
223 }
224
225 if (ctx->Stencil.Enabled) {
226 /* first stencil test */
227 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
228 return;
229 }
230 }
231 else if (ctx->Depth.Test) {
232 /* regular depth testing */
233 if (_mesa_depth_test_span( ctx, n, x, y, z, mask ) == 0)
234 return;
235 }
236
237 /* if we get here, something passed the depth test */
238 ctx->OcclusionResult = GL_TRUE;
239
240 /* Per-pixel fog */
241 if (ctx->Fog.Enabled) {
242 if (fog && !swrast->_PreferPixelFog)
243 _mesa_fog_ci_pixels( ctx, n, fog, index );
244 else
245 _mesa_depth_fog_ci_pixels( ctx, n, z, index );
246 }
247
248 /* Antialias coverage application */
249 if (coverage) {
250 GLuint i;
251 for (i = 0; i < n; i++) {
252 ASSERT(coverage[i] < 16);
253 index[i] = (index[i] & ~0xf) | coverage[i];
254 }
255 }
256
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 );
260 }
261 else {
262 /* normal situation: draw to exactly one buffer */
263 if (ctx->Color.IndexLogicOpEnabled) {
264 _mesa_logicop_ci_span( ctx, n, x, y, index, mask );
265 }
266
267 if (ctx->Color.IndexMask == 0) {
268 return;
269 }
270 else if (ctx->Color.IndexMask != 0xffffffff) {
271 _mesa_mask_index_span( ctx, n, x, y, index );
272 }
273
274 /* write pixels */
275 (*swrast->Driver.WriteCI32Span)( ctx, n, x, y, index, mask );
276 }
277 }
278
279
280
281
282 void
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[],
286 GLenum primitive )
287 {
288 SWcontext *swrast = SWRAST_CONTEXT(ctx);
289 GLubyte mask[MAX_WIDTH];
290 GLuint i;
291
292 /* init mask to 1's (all pixels are to be written) */
293 MEMSET(mask, 1, n);
294
295 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
296 if ((n = clip_span( ctx, n, x, y, mask)) == 0) {
297 return;
298 }
299 }
300
301 /* Do the scissor test */
302 if (ctx->Scissor.Enabled) {
303 if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) {
304 return;
305 }
306 }
307
308 /* Polygon Stippling */
309 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
310 stipple_polygon_span( ctx, n, x, y, mask );
311 }
312
313 if (ctx->Stencil.Enabled) {
314 /* first stencil test */
315 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
316 return;
317 }
318 }
319 else if (ctx->Depth.Test) {
320 /* regular depth testing */
321 if (_mesa_depth_test_span( ctx, n, x, y, z, mask ) == 0)
322 return;
323 }
324
325 /* if we get here, something passed the depth test */
326 ctx->OcclusionResult = GL_TRUE;
327
328 if (ctx->Color.DrawBuffer == GL_NONE) {
329 /* write no pixels */
330 return;
331 }
332
333 if (ctx->Fog.Enabled
334 || ctx->Color.IndexLogicOpEnabled
335 || ctx->Color.IndexMask != 0xffffffff
336 || coverage) {
337 /* different index per pixel */
338 GLuint indexes[MAX_WIDTH];
339 for (i = 0; i < n; i++) {
340 indexes[i] = index;
341 }
342
343 if (ctx->Fog.Enabled) {
344 if (fog && !swrast->_PreferPixelFog)
345 _mesa_fog_ci_pixels( ctx, n, fog, indexes );
346 else
347 _mesa_depth_fog_ci_pixels( ctx, n, z, indexes );
348 }
349
350 /* Antialias coverage application */
351 if (coverage) {
352 GLuint i;
353 for (i = 0; i < n; i++) {
354 ASSERT(coverage[i] < 16);
355 indexes[i] = (indexes[i] & ~0xf) | coverage[i];
356 }
357 }
358
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 );
362 }
363 else {
364 /* normal situation: draw to exactly one buffer */
365 if (ctx->Color.IndexLogicOpEnabled) {
366 _mesa_logicop_ci_span( ctx, n, x, y, indexes, mask );
367 }
368 if (ctx->Color.IndexMask == 0) {
369 return;
370 }
371 else if (ctx->Color.IndexMask != 0xffffffff) {
372 _mesa_mask_index_span( ctx, n, x, y, indexes );
373 }
374 (*swrast->Driver.WriteCI32Span)( ctx, n, x, y, indexes, mask );
375 }
376 }
377 else {
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++)
385 indexes[i] = index;
386 multi_write_index_span( ctx, n, x, y, indexes, mask );
387 }
388 else {
389 /* normal situation: draw to exactly one buffer */
390 (*swrast->Driver.WriteMonoCISpan)( ctx, n, x, y, index, mask );
391 }
392 }
393 }
394
395
396
397 /*
398 * Draw to more than one RGBA color buffer (or none).
399 */
400 static void
401 multi_write_rgba_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
402 CONST GLchan rgba[][4], const GLubyte mask[] )
403 {
404 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
405 GLuint bufferBit;
406 SWcontext *swrast = SWRAST_CONTEXT(ctx);
407
408 if (ctx->Color.DrawBuffer == GL_NONE)
409 return;
410
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);
416
417 if (bufferBit == FRONT_LEFT_BIT) {
418 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
419 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha;
420 }
421 else if (bufferBit == FRONT_RIGHT_BIT) {
422 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
423 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha;
424 }
425 else if (bufferBit == BACK_LEFT_BIT) {
426 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
427 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha;
428 }
429 else {
430 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
431 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha;
432 }
433
434 /* make copy of incoming colors */
435 MEMCPY( rgbaTmp, rgba, 4 * n * sizeof(GLchan) );
436
437 if (ctx->Color.ColorLogicOpEnabled) {
438 _mesa_logicop_rgba_span( ctx, n, x, y, rgbaTmp, mask );
439 }
440 else if (ctx->Color.BlendEnabled) {
441 _mesa_blend_span( ctx, n, x, y, rgbaTmp, mask );
442 }
443 if (colorMask == 0x0) {
444 break;
445 }
446 else if (colorMask != 0xffffffff) {
447 _mesa_mask_rgba_span( ctx, n, x, y, rgbaTmp );
448 }
449
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 );
455 }
456 }
457 }
458
459 /* restore default dest buffer */
460 (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer );
461 }
462
463
464
465 void
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[],
469 GLenum primitive )
470 {
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];
476 GLchan (*rgba)[4];
477 const GLubyte *Null = 0;
478 SWcontext *swrast = SWRAST_CONTEXT(ctx);
479
480 /* init mask to 1's (all pixels are to be written) */
481 MEMSET(mask, 1, n);
482
483 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
484 if ((n = clip_span( ctx,n,x,y,mask)) == 0) {
485 return;
486 }
487 if (mask[0] == 0)
488 write_all = GL_FALSE;
489 }
490
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) );
495 rgba = rgbaBackup;
496 }
497 else {
498 rgba = rgbaIn;
499 }
500
501 /* Do the scissor test */
502 if (ctx->Scissor.Enabled) {
503 if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) {
504 return;
505 }
506 if (mask[0] == 0)
507 write_all = GL_FALSE;
508 }
509
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;
514 }
515
516 /* Do the alpha test */
517 if (ctx->Color.AlphaEnabled) {
518 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4]) rgba, mask ) == 0) {
519 return;
520 }
521 write_all = GL_FALSE;
522 }
523
524 if (ctx->Stencil.Enabled) {
525 /* first stencil test */
526 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
527 return;
528 }
529 write_all = GL_FALSE;
530 }
531 else if (ctx->Depth.Test) {
532 /* regular depth testing */
533 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
534 if (m == 0) {
535 return;
536 }
537 if (m < n) {
538 write_all = GL_FALSE;
539 }
540 }
541
542 /* if we get here, something passed the depth test */
543 ctx->OcclusionResult = GL_TRUE;
544
545 /* Per-pixel fog */
546 if (ctx->Fog.Enabled) {
547 if (fog && !swrast->_PreferPixelFog)
548 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
549 else
550 _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba );
551 }
552
553 /* Antialias coverage application */
554 if (coverage) {
555 GLuint i;
556 for (i = 0; i < n; i++) {
557 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
558 }
559 }
560
561 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
562 multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask );
563 }
564 else {
565 /* normal: write to exactly one buffer */
566 /* logic op or blending */
567 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
568
569 if (ctx->Color.ColorLogicOpEnabled) {
570 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
571 }
572 else if (ctx->Color.BlendEnabled) {
573 _mesa_blend_span( ctx, n, x, y, rgba, mask );
574 }
575
576 /* Color component masking */
577 if (colorMask == 0x0) {
578 return;
579 }
580 else if (colorMask != 0xffffffff) {
581 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
582 }
583
584 /* write pixels */
585 (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y,
586 (const GLchan (*)[4]) rgba,
587 write_all ? Null : mask );
588
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 );
593 }
594 }
595 }
596
597
598
599 /*
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.
608 */
609 void
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[],
613 GLenum primitive )
614 {
615 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
616 GLuint i;
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);
622
623 /* init mask to 1's (all pixels are to be written) */
624 MEMSET(mask, 1, n);
625
626 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
627 if ((n = clip_span( ctx,n,x,y,mask)) == 0) {
628 return;
629 }
630 if (mask[0] == 0)
631 write_all = GL_FALSE;
632 }
633
634 /* Do the scissor test */
635 if (ctx->Scissor.Enabled) {
636 if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) {
637 return;
638 }
639 if (mask[0] == 0)
640 write_all = GL_FALSE;
641 }
642
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;
647 }
648
649 /* Do the alpha test */
650 if (ctx->Color.AlphaEnabled) {
651 for (i = 0; i < n; i++) {
652 rgba[i][ACOMP] = color[ACOMP];
653 }
654 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4])rgba, mask ) == 0) {
655 return;
656 }
657 write_all = GL_FALSE;
658 }
659
660 if (ctx->Stencil.Enabled) {
661 /* first stencil test */
662 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
663 return;
664 }
665 write_all = GL_FALSE;
666 }
667 else if (ctx->Depth.Test) {
668 /* regular depth testing */
669 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
670 if (m == 0) {
671 return;
672 }
673 if (m < n) {
674 write_all = GL_FALSE;
675 }
676 }
677
678 /* if we get here, something passed the depth test */
679 ctx->OcclusionResult = GL_TRUE;
680
681 if (ctx->Color.DrawBuffer == GL_NONE) {
682 /* write no pixels */
683 return;
684 }
685
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++) {
690 if (mask[i]) {
691 COPY_CHAN4(rgba[i], color);
692 }
693 }
694
695 /* Per-pixel fog */
696 if (ctx->Fog.Enabled) {
697 if (fog && !swrast->_PreferPixelFog)
698 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
699 else
700 _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba );
701 }
702
703 /* Antialias coverage application */
704 if (coverage) {
705 GLuint i;
706 for (i = 0; i < n; i++) {
707 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
708 }
709 }
710
711 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
712 multi_write_rgba_span( ctx, n, x, y,
713 (const GLchan (*)[4]) rgba, mask );
714 }
715 else {
716 /* normal: write to exactly one buffer */
717 if (ctx->Color.ColorLogicOpEnabled) {
718 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
719 }
720 else if (ctx->Color.BlendEnabled) {
721 _mesa_blend_span( ctx, n, x, y, rgba, mask );
722 }
723
724 /* Color component masking */
725 if (colorMask == 0x0) {
726 return;
727 }
728 else if (colorMask != 0xffffffff) {
729 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
730 }
731
732 /* write pixels */
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 );
740 }
741 }
742 }
743 else {
744 /* same color for all pixels */
745 ASSERT(!ctx->Color.BlendEnabled);
746 ASSERT(!ctx->Color.ColorLogicOpEnabled);
747
748 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
749 for (i = 0; i < n; i++) {
750 if (mask[i]) {
751 COPY_CHAN4(rgba[i], color);
752 }
753 }
754 multi_write_rgba_span( ctx, n, x, y,
755 (const GLchan (*)[4]) rgba, mask );
756 }
757 else {
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 );
762 }
763 }
764 }
765 }
766
767
768
769 /*
770 * Add specular color to base color. This is used only when
771 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
772 */
773 static void
774 add_colors(GLuint n, GLchan rgba[][4], CONST GLchan specular[][4] )
775 {
776 GLuint i;
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);
784 }
785 }
786
787
788 /*
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
792 * as needed.
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.
800 */
801 void
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 )
808 {
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);
816
817 /* init mask to 1's (all pixels are to be written) */
818 MEMSET(mask, 1, n);
819
820 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
821 if ((n=clip_span(ctx, n, x, y, mask)) == 0) {
822 return;
823 }
824 if (mask[0] == 0)
825 write_all = GL_FALSE;
826 }
827
828
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));
832 rgba = rgbaBackup;
833 }
834 else {
835 rgba = rgbaIn;
836 }
837
838 /* Do the scissor test */
839 if (ctx->Scissor.Enabled) {
840 if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) {
841 return;
842 }
843 if (mask[0] == 0)
844 write_all = GL_FALSE;
845 }
846
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;
851 }
852
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 );
860
861 /* Do the alpha test */
862 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4]) rgba, mask ) == 0) {
863 return;
864 }
865 write_all = GL_FALSE;
866 }
867
868 if (ctx->Stencil.Enabled) {
869 /* first stencil test */
870 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
871 return;
872 }
873 write_all = GL_FALSE;
874 }
875 else if (ctx->Depth.Test) {
876 /* regular depth testing */
877 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
878 if (m == 0) {
879 return;
880 }
881 if (m < n) {
882 write_all = GL_FALSE;
883 }
884 }
885
886 /* if we get here, something passed the depth test */
887 ctx->OcclusionResult = GL_TRUE;
888
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 );
894 }
895
896 /* Add base and specular colors */
897 if (spec &&
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 */
902
903 /* Per-pixel fog */
904 if (ctx->Fog.Enabled) {
905 if (fog && !swrast->_PreferPixelFog)
906 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
907 else
908 _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba );
909 }
910
911 /* Antialias coverage application */
912 if (coverage) {
913 GLuint i;
914 for (i = 0; i < n; i++) {
915 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
916 }
917 }
918
919 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
920 multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask );
921 }
922 else {
923 /* normal: write to exactly one buffer */
924 if (ctx->Color.ColorLogicOpEnabled) {
925 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
926 }
927 else if (ctx->Color.BlendEnabled) {
928 _mesa_blend_span( ctx, n, x, y, rgba, mask );
929 }
930 if (colorMask == 0x0) {
931 return;
932 }
933 else if (colorMask != 0xffffffff) {
934 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
935 }
936
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 );
942 }
943 }
944 }
945
946
947
948 /*
949 * As above but perform multiple stages of texture application.
950 */
951 void
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[],
961 GLenum primitive )
962 {
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 */
967 GLuint i;
968 const GLubyte *Null = 0;
969 const GLuint texUnits = ctx->Const.MaxTextureUnits;
970 SWcontext *swrast = SWRAST_CONTEXT(ctx);
971
972 /* init mask to 1's (all pixels are to be written) */
973 MEMSET(mask, 1, n);
974
975 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
976 if ((n=clip_span(ctx, n, x, y, mask)) == 0) {
977 return;
978 }
979 if (mask[0] == 0)
980 write_all = GL_FALSE;
981 }
982
983
984 if (primitive==GL_BITMAP || (swrast->_RasterMask & MULTI_DRAW_BIT)
985 || texUnits > 1) {
986 /* must make a copy of the colors since they may be modified */
987 MEMCPY(rgbaBackup, rgbaIn, 4 * n * sizeof(GLchan));
988 rgba = rgbaBackup;
989 }
990 else {
991 rgba = rgbaIn;
992 }
993
994 /* Do the scissor test */
995 if (ctx->Scissor.Enabled) {
996 if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) {
997 return;
998 }
999 if (mask[0] == 0)
1000 write_all = GL_FALSE;
1001 }
1002
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;
1007 }
1008
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.
1013 */
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 );
1018
1019 /* Do the alpha test */
1020 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4])rgba, mask ) == 0) {
1021 return;
1022 }
1023 write_all = GL_FALSE;
1024 }
1025
1026 if (ctx->Stencil.Enabled) {
1027 /* first stencil test */
1028 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
1029 return;
1030 }
1031 write_all = GL_FALSE;
1032 }
1033 else if (ctx->Depth.Test) {
1034 /* regular depth testing */
1035 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
1036 if (m == 0) {
1037 return;
1038 }
1039 if (m < n) {
1040 write_all = GL_FALSE;
1041 }
1042 }
1043
1044 /* if we get here, something passed the depth test */
1045 ctx->OcclusionResult = GL_TRUE;
1046
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 );
1053 }
1054
1055 /* Add base and specular colors */
1056 if (spec &&
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 */
1061
1062 /* Per-pixel fog */
1063 if (ctx->Fog.Enabled) {
1064 if (fog && !swrast->_PreferPixelFog)
1065 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
1066 else
1067 _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba );
1068 }
1069
1070 /* Antialias coverage application */
1071 if (coverage) {
1072 GLuint i;
1073 for (i = 0; i < n; i++) {
1074 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
1075 }
1076 }
1077
1078 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1079 multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask );
1080 }
1081 else {
1082 /* normal: write to exactly one buffer */
1083 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1084
1085 if (ctx->Color.ColorLogicOpEnabled) {
1086 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
1087 }
1088 else if (ctx->Color.BlendEnabled) {
1089 _mesa_blend_span( ctx, n, x, y, rgba, mask );
1090 }
1091
1092 if (colorMask == 0x0) {
1093 return;
1094 }
1095 else if (colorMask != 0xffffffff) {
1096 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
1097 }
1098
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 );
1104 }
1105 }
1106 }
1107
1108
1109
1110 /*
1111 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1112 * reading ouside the buffer's boundaries.
1113 */
1114 void
1115 _mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
1116 GLuint n, GLint x, GLint y, GLchan rgba[][4] )
1117 {
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));
1124 }
1125 else {
1126 GLint skip, length;
1127 if (x < 0) {
1128 /* left edge clippping */
1129 skip = -x;
1130 length = (GLint) n - skip;
1131 if (length < 0) {
1132 /* completely left of window */
1133 return;
1134 }
1135 if (length > buffer->Width) {
1136 length = buffer->Width;
1137 }
1138 }
1139 else if ((GLint) (x + n) > buffer->Width) {
1140 /* right edge clipping */
1141 skip = 0;
1142 length = buffer->Width - x;
1143 if (length < 0) {
1144 /* completely to right of window */
1145 return;
1146 }
1147 }
1148 else {
1149 /* no clipping */
1150 skip = 0;
1151 length = (GLint) n;
1152 }
1153
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 );
1157 }
1158 }
1159 }
1160
1161
1162
1163
1164 /*
1165 * Read CI pixels from frame buffer. Clipping will be done to prevent
1166 * reading ouside the buffer's boundaries.
1167 */
1168 void
1169 _mesa_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
1170 GLuint n, GLint x, GLint y, GLuint indx[] )
1171 {
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));
1177 }
1178 else {
1179 GLint skip, length;
1180 if (x < 0) {
1181 /* left edge clippping */
1182 skip = -x;
1183 length = (GLint) n - skip;
1184 if (length < 0) {
1185 /* completely left of window */
1186 return;
1187 }
1188 if (length > buffer->Width) {
1189 length = buffer->Width;
1190 }
1191 }
1192 else if ((GLint) (x + n) > buffer->Width) {
1193 /* right edge clipping */
1194 skip = 0;
1195 length = buffer->Width - x;
1196 if (length < 0) {
1197 /* completely to right of window */
1198 return;
1199 }
1200 }
1201 else {
1202 /* no clipping */
1203 skip = 0;
1204 length = (GLint) n;
1205 }
1206
1207 (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
1208 }
1209 }