bd2d1838ed4258ab214c88d346f180d3a4838ac1
[mesa.git] / src / mesa / swrast / s_span.c
1 /* $Id: s_span.c,v 1.21 2002/01/10 16:54:29 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 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 "context.h"
37 #include "macros.h"
38 #include "mem.h"
39
40 #include "s_alpha.h"
41 #include "s_alphabuf.h"
42 #include "s_blend.h"
43 #include "s_context.h"
44 #include "s_depth.h"
45 #include "s_fog.h"
46 #include "s_logic.h"
47 #include "s_masking.h"
48 #include "s_scissor.h"
49 #include "s_span.h"
50 #include "s_stencil.h"
51 #include "s_texture.h"
52
53 INLINE
54 static void SET_MASK_TO_ONE(struct sw_span *span) {
55 SW_SPAN_SET_FLAG(span->filledMask);
56 /* init mask to 1's (all pixels are to be written) */
57 MEMSET(span->mask, 1, span->end);
58 }
59
60
61 /*
62 * Apply the current polygon stipple pattern to a span of pixels.
63 */
64 static void
65 old_stipple_polygon_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
66 GLubyte mask[] )
67 {
68 const GLuint highbit = 0x80000000;
69 GLuint i, m, stipple;
70
71 stipple = ctx->PolygonStipple[y % 32];
72 m = highbit >> (GLuint) (x % 32);
73
74 for (i = 0; i < n; i++) {
75 if ((m & stipple) == 0) {
76 mask[i] = 0;
77 }
78 m = m >> 1;
79 if (m == 0) {
80 m = highbit;
81 }
82 }
83 }
84
85 /*
86 * Apply the current polygon stipple pattern to a span of pixels.
87 */
88 static void
89 stipple_polygon_span( GLcontext *ctx, struct sw_span *span)
90 {
91 const GLuint highbit = 0x80000000;
92 GLuint i, m, stipple;
93
94 ASSERT (span->filledMask == GL_TRUE);
95
96 stipple = ctx->PolygonStipple[span->y % 32];
97 m = highbit >> (GLuint) (span->x % 32);
98
99 for (i = 0; i < span->end; i++) {
100 if ((m & stipple) == 0) {
101 span->mask[i] = 0;
102 }
103 m = m >> 1;
104 if (m == 0) {
105 m = highbit;
106 }
107 }
108 span->write_all = GL_FALSE;
109 }
110
111
112
113 /*
114 * Clip a pixel span to the current buffer/window boundaries.
115 * Return: 'n' such that pixel 'n', 'n+1' etc. are clipped,
116 * as a special case:
117 * 0 = all pixels clipped
118 */
119 static GLuint
120 old_clip_span( GLcontext *ctx, GLint n, GLint x, GLint y, GLubyte mask[] )
121 {
122 /* Clip to top and bottom */
123 if (y < 0 || y >= ctx->DrawBuffer->Height) {
124 return 0;
125 }
126
127 /* Clip to the left */
128 if (x < 0) {
129 if (x + n <= 0) {
130 /* completely off left side */
131 return 0;
132 }
133 else {
134 /* partially off left side */
135 BZERO(mask, -x * sizeof(GLubyte));
136 }
137 }
138
139 /* Clip to right */
140 if (x + n > ctx->DrawBuffer->Width) {
141 if (x >= ctx->DrawBuffer->Width) {
142 /* completely off right side */
143 return 0;
144 }
145 else {
146 /* partially off right side */
147 return ctx->DrawBuffer->Width - x;
148 }
149 }
150
151 return n;
152 }
153
154
155 /*
156 * Clip a pixel span to the current buffer/window boundaries.
157 * Return: GL_TRUE some pixel still visible
158 * GL_FALSE nothing visible
159 */
160 static GLuint
161 clip_span( GLcontext *ctx, struct sw_span *span)
162 {
163 GLint x = span->x, y = span->y, n = span->end;
164
165 ASSERT (span->filledMask == GL_TRUE);
166
167 /* Clip to top and bottom */
168 if (y < 0 || y >= ctx->DrawBuffer->Height) {
169 span->end = 0;
170 return GL_FALSE;
171 }
172
173 /* Clip to the left */
174 if (x < 0) {
175 if (x + n <= 0) {
176 /* completely off left side */
177 span->end = 0;
178 return GL_FALSE;
179 }
180 else {
181 /* partially off left side */
182 span->write_all = GL_FALSE;
183 BZERO(span->mask, -x * sizeof(GLubyte));
184 return GL_TRUE;
185 }
186 }
187
188 /* Clip to right */
189 if (x + n > ctx->DrawBuffer->Width) {
190 if (x >= ctx->DrawBuffer->Width) {
191 /* completely off right side */
192 span->end = 0;
193 return GL_FALSE;
194 }
195 else {
196 /* partially off right side */
197 span->end = ctx->DrawBuffer->Width - x;
198 return GL_TRUE;
199 }
200 }
201
202 return GL_TRUE;
203 }
204
205
206
207 /*
208 * Draw to more than one color buffer (or none).
209 */
210 static void
211 multi_write_index_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
212 const GLuint indexes[], const GLubyte mask[] )
213 {
214 SWcontext *swrast = SWRAST_CONTEXT(ctx);
215 GLuint bufferBit;
216
217 if (ctx->Color.DrawBuffer == GL_NONE)
218 return;
219
220 /* loop over four possible dest color buffers */
221 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
222 if (bufferBit & ctx->Color.DrawDestMask) {
223 GLuint indexTmp[MAX_WIDTH];
224 ASSERT(n < MAX_WIDTH);
225
226 if (bufferBit == FRONT_LEFT_BIT)
227 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
228 else if (bufferBit == FRONT_RIGHT_BIT)
229 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
230 else if (bufferBit == BACK_LEFT_BIT)
231 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
232 else
233 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
234
235 /* make copy of incoming indexes */
236 MEMCPY( indexTmp, indexes, n * sizeof(GLuint) );
237 if (ctx->Color.IndexLogicOpEnabled) {
238 _mesa_logicop_ci_span( ctx, n, x, y, indexTmp, mask );
239 }
240 if (ctx->Color.IndexMask == 0) {
241 break;
242 }
243 else if (ctx->Color.IndexMask != 0xffffffff) {
244 _mesa_mask_index_span( ctx, n, x, y, indexTmp );
245 }
246 (*swrast->Driver.WriteCI32Span)( ctx, n, x, y, indexTmp, mask );
247 }
248 }
249
250 /* restore default dest buffer */
251 (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer);
252 }
253
254
255 /*
256 * Draw to more than one RGBA color buffer (or none).
257 */
258 static void
259 multi_write_rgba_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
260 CONST GLchan rgba[][4], const GLubyte mask[] )
261 {
262 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
263 GLuint bufferBit;
264 SWcontext *swrast = SWRAST_CONTEXT(ctx);
265
266 if (ctx->Color.DrawBuffer == GL_NONE)
267 return;
268
269 /* loop over four possible dest color buffers */
270 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
271 if (bufferBit & ctx->Color.DrawDestMask) {
272 GLchan rgbaTmp[MAX_WIDTH][4];
273 ASSERT(n < MAX_WIDTH);
274
275 if (bufferBit == FRONT_LEFT_BIT) {
276 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
277 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha;
278 }
279 else if (bufferBit == FRONT_RIGHT_BIT) {
280 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
281 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha;
282 }
283 else if (bufferBit == BACK_LEFT_BIT) {
284 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
285 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha;
286 }
287 else {
288 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
289 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha;
290 }
291
292 /* make copy of incoming colors */
293 MEMCPY( rgbaTmp, rgba, 4 * n * sizeof(GLchan) );
294
295 if (ctx->Color.ColorLogicOpEnabled) {
296 _mesa_logicop_rgba_span( ctx, n, x, y, rgbaTmp, mask );
297 }
298 else if (ctx->Color.BlendEnabled) {
299 _mesa_blend_span( ctx, n, x, y, rgbaTmp, mask );
300 }
301 if (colorMask == 0x0) {
302 break;
303 }
304 else if (colorMask != 0xffffffff) {
305 _mesa_mask_rgba_span( ctx, n, x, y, rgbaTmp );
306 }
307
308 (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y,
309 (const GLchan (*)[4]) rgbaTmp, mask );
310 if (swrast->_RasterMask & ALPHABUF_BIT) {
311 _mesa_write_alpha_span( ctx, n, x, y,
312 (const GLchan (*)[4])rgbaTmp, mask );
313 }
314 }
315 }
316
317 /* restore default dest buffer */
318 (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer );
319 }
320
321
322
323 /*
324 * Write a horizontal span of color index pixels to the frame buffer.
325 * Stenciling, Depth-testing, etc. are done as needed.
326 * Input: n - number of pixels in the span
327 * x, y - location of leftmost pixel in the span
328 * z - array of [n] z-values
329 * fog - array of fog factor values in [0,1]
330 * index - array of [n] color indexes
331 * primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
332 */
333 void
334 _old_write_index_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
335 const GLdepth z[], const GLfloat fog[],
336 GLuint indexIn[], const GLint coverage[],
337 GLenum primitive )
338 {
339 const GLuint modBits = FOG_BIT | BLEND_BIT | MASKING_BIT | LOGIC_OP_BIT;
340 GLubyte mask[MAX_WIDTH];
341 GLuint indexBackup[MAX_WIDTH];
342 GLuint *index; /* points to indexIn or indexBackup */
343 SWcontext *swrast = SWRAST_CONTEXT(ctx);
344
345 /* init mask to 1's (all pixels are to be written) */
346 MEMSET(mask, 1, n);
347
348 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
349 if ((n = old_clip_span(ctx,n,x,y,mask)) == 0) {
350 return;
351 }
352 }
353
354 if ((primitive==GL_BITMAP && (swrast->_RasterMask & modBits))
355 || (swrast->_RasterMask & MULTI_DRAW_BIT)) {
356 /* Make copy of color indexes */
357 MEMCPY( indexBackup, indexIn, n * sizeof(GLuint) );
358 index = indexBackup;
359 }
360 else {
361 index = indexIn;
362 }
363
364
365 /* Do the scissor test */
366 if (ctx->Scissor.Enabled) {
367 if ((n = _old_scissor_span( ctx, n, x, y, mask )) == 0) {
368 return;
369 }
370 }
371
372 /* Polygon Stippling */
373 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
374 old_stipple_polygon_span( ctx, n, x, y, mask );
375 }
376
377 if (ctx->Stencil.Enabled) {
378 /* first stencil test */
379 if (_old_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
380 return;
381 }
382 }
383 else if (ctx->Depth.Test) {
384 /* regular depth testing */
385 if (_old_depth_test_span( ctx, n, x, y, z, mask ) == 0)
386 return;
387 }
388
389 /* if we get here, something passed the depth test */
390 ctx->OcclusionResult = GL_TRUE;
391
392 /* Per-pixel fog */
393 if (ctx->Fog.Enabled) {
394 if (fog && !swrast->_PreferPixelFog)
395 _old_fog_ci_pixels( ctx, n, fog, index );
396 else
397 _old_depth_fog_ci_pixels( ctx, n, z, index );
398 }
399
400 /* Antialias coverage application */
401 if (coverage) {
402 GLuint i;
403 for (i = 0; i < n; i++) {
404 ASSERT(coverage[i] < 16);
405 index[i] = (index[i] & ~0xf) | coverage[i];
406 }
407 }
408
409 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
410 /* draw to zero or two or more buffers */
411 multi_write_index_span( ctx, n, x, y, index, mask );
412 }
413 else {
414 /* normal situation: draw to exactly one buffer */
415 if (ctx->Color.IndexLogicOpEnabled) {
416 _mesa_logicop_ci_span( ctx, n, x, y, index, mask );
417 }
418
419 if (ctx->Color.IndexMask == 0) {
420 return;
421 }
422 else if (ctx->Color.IndexMask != 0xffffffff) {
423 _mesa_mask_index_span( ctx, n, x, y, index );
424 }
425
426 /* write pixels */
427 (*swrast->Driver.WriteCI32Span)( ctx, n, x, y, index, mask );
428 }
429 }
430
431
432 /*
433 * Apply fragment processing to a span of RGBA fragments.
434 * Input:
435 * n - number of fragments in the span
436 * x,y - location of first (left) fragment
437 * fog - array of fog factor values in [0,1]
438 */
439 void
440 _old_write_rgba_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
441 const GLdepth z[], const GLfloat fog[],
442 GLchan rgbaIn[][4], const GLfloat coverage[],
443 GLenum primitive )
444 {
445 const GLuint modBits = FOG_BIT | BLEND_BIT | MASKING_BIT |
446 LOGIC_OP_BIT | TEXTURE_BIT;
447 GLubyte mask[MAX_WIDTH];
448 GLboolean write_all = GL_TRUE;
449 GLchan rgbaBackup[MAX_WIDTH][4];
450 GLchan (*rgba)[4];
451 SWcontext *swrast = SWRAST_CONTEXT(ctx);
452
453 /* init mask to 1's (all pixels are to be written) */
454 MEMSET(mask, 1, n);
455
456 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
457 if ((n = old_clip_span( ctx,n,x,y,mask)) == 0) {
458 return;
459 }
460 if (mask[0] == 0)
461 write_all = GL_FALSE;
462 }
463
464 if ((primitive==GL_BITMAP && (swrast->_RasterMask & modBits))
465 || (swrast->_RasterMask & MULTI_DRAW_BIT)) {
466 /* must make a copy of the colors since they may be modified */
467 MEMCPY( rgbaBackup, rgbaIn, 4 * n * sizeof(GLchan) );
468 rgba = rgbaBackup;
469 }
470 else {
471 rgba = rgbaIn;
472 }
473
474 /* Do the scissor test */
475 if (ctx->Scissor.Enabled) {
476 if ((n = _old_scissor_span( ctx, n, x, y, mask )) == 0) {
477 return;
478 }
479 if (mask[0] == 0)
480 write_all = GL_FALSE;
481 }
482
483 /* Polygon Stippling */
484 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
485 old_stipple_polygon_span( ctx, n, x, y, mask );
486 write_all = GL_FALSE;
487 }
488
489 /* Do the alpha test */
490 if (ctx->Color.AlphaEnabled) {
491 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4]) rgba, mask ) == 0) {
492 return;
493 }
494 write_all = GL_FALSE;
495 }
496
497 if (ctx->Stencil.Enabled) {
498 /* first stencil test */
499 if (_old_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
500 return;
501 }
502 write_all = GL_FALSE;
503 }
504 else if (ctx->Depth.Test) {
505 /* regular depth testing */
506 GLuint m = _old_depth_test_span( ctx, n, x, y, z, mask );
507 if (m == 0) {
508 return;
509 }
510 if (m < n) {
511 write_all = GL_FALSE;
512 }
513 }
514
515 /* if we get here, something passed the depth test */
516 ctx->OcclusionResult = GL_TRUE;
517
518 /* Per-pixel fog */
519 if (ctx->Fog.Enabled) {
520 if (fog && !swrast->_PreferPixelFog)
521 _old_fog_rgba_pixels( ctx, n, fog, rgba );
522 else
523 _old_depth_fog_rgba_pixels( ctx, n, z, rgba );
524 }
525
526 /* Antialias coverage application */
527 if (coverage) {
528 GLuint i;
529 for (i = 0; i < n; i++) {
530 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
531 }
532 }
533
534 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
535 multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask );
536 }
537 else {
538 /* normal: write to exactly one buffer */
539 /* logic op or blending */
540 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
541
542 if (ctx->Color.ColorLogicOpEnabled) {
543 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
544 }
545 else if (ctx->Color.BlendEnabled) {
546 _mesa_blend_span( ctx, n, x, y, rgba, mask );
547 }
548
549 /* Color component masking */
550 if (colorMask == 0x0) {
551 return;
552 }
553 else if (colorMask != 0xffffffff) {
554 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
555 }
556
557 /* write pixels */
558 (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y,
559 (const GLchan (*)[4]) rgba,
560 write_all ? ((const GLubyte *) NULL) : mask );
561
562 if (swrast->_RasterMask & ALPHABUF_BIT) {
563 _mesa_write_alpha_span( ctx, n, x, y,
564 (const GLchan (*)[4]) rgba,
565 write_all ? ((const GLubyte *) NULL) : mask );
566 }
567 }
568 }
569
570
571 /*
572 * Write a horizontal span of color index pixels to the frame buffer.
573 * Stenciling, Depth-testing, etc. are done as needed.
574 * Input: primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
575 */
576 void
577 _mesa_write_index_span( GLcontext *ctx, struct sw_span *span,
578 GLenum primitive )
579 {
580 const GLuint modBits = FOG_BIT | BLEND_BIT | MASKING_BIT | LOGIC_OP_BIT;
581 GLuint indexBackup[MAX_WIDTH];
582 GLuint *index; /* points to indexIn or indexBackup */
583 SWcontext *swrast = SWRAST_CONTEXT(ctx);
584
585
586 SET_MASK_TO_ONE(span);
587
588 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
589 if (clip_span(ctx,span) == GL_FALSE) {
590 return;
591 }
592 }
593
594 if ((primitive==GL_BITMAP && (swrast->_RasterMask & modBits))
595 || (swrast->_RasterMask & MULTI_DRAW_BIT)) {
596 /* Make copy of color indexes */
597 MEMCPY( indexBackup, span->color.index, span->end * sizeof(GLuint) );
598 index = indexBackup;
599 }
600 else {
601 index = span->color.index;
602 }
603
604
605 /* Do the scissor test */
606 if (ctx->Scissor.Enabled) {
607 if (_mesa_scissor_span( ctx, span ) == GL_FALSE) {
608 return;
609 }
610 }
611
612 /* Polygon Stippling */
613 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
614 stipple_polygon_span(ctx, span);
615 }
616
617
618 /* I have to think where to put this!! */
619 if (span->activeMask & SPAN_Z) {
620 SW_SPAN_SET_FLAG(span->filledDepth);
621
622 if (ctx->Visual.depthBits <= 16) {
623 GLuint i;
624 GLfixed zval = span->z;
625 for (i = 0; i < span->end; i++) {
626 span->depth[i] = FixedToInt(zval);
627 zval += span->zStep;
628 }
629 }
630 else {
631 /* Deep Z buffer, no fixed->int shift */
632 GLuint i;
633 GLfixed zval = span->z;
634 for (i = 0; i < span->end; i++) {
635 span->depth[i] = zval;
636 zval += span->zStep;
637 }
638 }
639 }
640
641
642 if (ctx->Stencil.Enabled) {
643 /* first stencil test */
644 if (_mesa_stencil_and_ztest_span(ctx, span) == GL_FALSE)
645 return;
646 }
647 else if (ctx->Depth.Test) {
648 /* regular depth testing */
649 if (_mesa_depth_test_span(ctx, span) == 0)
650 return;
651 }
652
653 /* if we get here, something passed the depth test */
654 ctx->OcclusionResult = GL_TRUE;
655
656 if (ctx->Color.DrawBuffer == GL_NONE) {
657 /* write no pixels */
658 return;
659 }
660
661 if (ctx->Fog.Enabled) {
662 /* Is this the right 'if' ?? */
663 if ((span->activeMask & SPAN_FOG) && !swrast->_PreferPixelFog)
664 _mesa_fog_ci_pixels( ctx, span, index);
665 else
666 _mesa_depth_fog_ci_pixels( ctx, span, index);
667 }
668
669 /* Antialias coverage application */
670 #if 0
671 if (span->coverage) {
672 GLuint i;
673 for (i = 0; i < span->end; i++) {
674 ASSERT(span->coverage[i] < 16);
675 index[i] = (index[i] & ~0xf) | span->coverage[i];
676 }
677 }
678 #endif
679
680 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
681 /* draw to zero or two or more buffers */
682 multi_write_index_span( ctx, span->end, span->x, span->y,
683 index, span->mask );
684 }
685 else {
686 /* normal situation: draw to exactly one buffer */
687 if (ctx->Color.IndexLogicOpEnabled) {
688 _mesa_logicop_ci_span( ctx, span->end, span->x, span->y,
689 index, span->mask );
690 }
691
692 if (ctx->Color.IndexMask == 0) {
693 return;
694 }
695 else if (ctx->Color.IndexMask != 0xffffffff) {
696 _mesa_mask_index_span( ctx, span->end, span->x, span->y, index );
697 }
698
699 /* write pixels */
700 (*swrast->Driver.WriteCI32Span)( ctx, span->end, span->x,
701 span->y, index, span->mask );
702 }
703 }
704
705
706
707
708 void
709 _mesa_write_monoindex_span( GLcontext *ctx, struct sw_span *span,
710 GLuint index, GLenum primitive )
711 {
712 SWcontext *swrast = SWRAST_CONTEXT(ctx);
713 GLuint i;
714
715
716 SET_MASK_TO_ONE(span);
717
718 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
719 if (clip_span(ctx,span) == GL_FALSE) {
720 return;
721 }
722 }
723
724 /* Do the scissor test */
725 if (ctx->Scissor.Enabled) {
726 if (_mesa_scissor_span( ctx, span ) == GL_FALSE) {
727 return;
728 }
729 }
730
731 /* Polygon Stippling */
732 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
733 stipple_polygon_span( ctx, span);
734 }
735
736
737 /* I have to think where to put this!! */
738 if (span->activeMask & SPAN_Z) {
739 SW_SPAN_SET_FLAG(span->filledDepth);
740
741 if (ctx->Visual.depthBits <= 16) {
742 GLuint i;
743 GLfixed zval = span->z;
744 for (i = 0; i < span->end; i++) {
745 span->depth[i] = FixedToInt(zval);
746 zval += span->zStep;
747 }
748 }
749 else {
750 /* Deep Z buffer, no fixed->int shift */
751 GLuint i;
752 GLfixed zval = span->z;
753 for (i = 0; i < span->end; i++) {
754 span->depth[i] = zval;
755 zval += span->zStep;
756 }
757 }
758 }
759
760 if (ctx->Stencil.Enabled) {
761 /* first stencil test */
762 if (_mesa_stencil_and_ztest_span(ctx, span) == GL_FALSE)
763 return;
764 }
765 else if (ctx->Depth.Test) {
766 /* regular depth testing */
767 if (_mesa_depth_test_span( ctx, span) == 0)
768 return;
769 }
770
771 /* if we get here, something passed the depth test */
772 ctx->OcclusionResult = GL_TRUE;
773
774 if (ctx->Color.DrawBuffer == GL_NONE) {
775 /* write no pixels */
776 return;
777 }
778
779 if (ctx->Fog.Enabled
780 || ctx->Color.IndexLogicOpEnabled
781 || ctx->Color.IndexMask != 0xffffffff
782 #if 0
783 || span->coverage) {
784 #else
785 ) {
786 #endif
787 /* different index per pixel */
788 GLuint indexes[MAX_WIDTH];
789 for (i = 0; i < span->end; i++) {
790 indexes[i] = index;
791 }
792
793 if (ctx->Fog.Enabled) {
794 /* Is this the right 'if' ?? */
795 if ((span->activeMask & SPAN_FOG) && !swrast->_PreferPixelFog)
796 _mesa_fog_ci_pixels( ctx, span, indexes );
797 else
798 _mesa_depth_fog_ci_pixels( ctx, span, indexes );
799 }
800
801 /* Antialias coverage application */
802 #if 0
803 if (span->coverage) {
804 GLuint i;
805 for (i = 0; i < span->end; i++) {
806 ASSERT(span->coverage[i] < 16);
807 indexes[i] = (indexes[i] & ~0xf) | span->coverage[i];
808 }
809 }
810 #endif
811
812 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
813 /* draw to zero or two or more buffers */
814 multi_write_index_span( ctx, span->end, span->x, span->y, indexes, span->mask );
815 }
816 else {
817 /* normal situation: draw to exactly one buffer */
818 if (ctx->Color.IndexLogicOpEnabled) {
819 _mesa_logicop_ci_span( ctx, span->end, span->x, span->y, indexes, span->mask );
820 }
821 if (ctx->Color.IndexMask == 0) {
822 return;
823 }
824 else if (ctx->Color.IndexMask != 0xffffffff) {
825 _mesa_mask_index_span( ctx, span->end, span->x, span->y, indexes );
826 }
827 (*swrast->Driver.WriteCI32Span)( ctx, span->end, span->x, span->y, indexes, span->mask );
828 }
829 }
830 else {
831 /* same color index for all pixels */
832 ASSERT(!ctx->Color.IndexLogicOpEnabled);
833 ASSERT(ctx->Color.IndexMask == 0xffffffff);
834 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
835 /* draw to zero or two or more buffers */
836 GLuint indexes[MAX_WIDTH];
837 for (i = 0; i < span->end; i++)
838 indexes[i] = index;
839 multi_write_index_span( ctx, span->end, span->x, span->y, indexes, span->mask );
840 }
841 else {
842 /* normal situation: draw to exactly one buffer */
843 (*swrast->Driver.WriteMonoCISpan)( ctx, span->end, span->x, span->y, index, span->mask );
844 }
845 }
846 }
847
848
849
850 /*
851 * Apply fragment processing to a span of RGBA fragments.
852 * Input:
853 */
854 void
855 _mesa_write_rgba_span( GLcontext *ctx, struct sw_span *span,
856 GLenum primitive )
857 {
858 const GLuint modBits = FOG_BIT | BLEND_BIT | MASKING_BIT |
859 LOGIC_OP_BIT | TEXTURE_BIT;
860 GLchan rgbaBackup[MAX_WIDTH][4];
861 GLchan (*rgba)[4];
862 SWcontext *swrast = SWRAST_CONTEXT(ctx);
863
864
865 SET_MASK_TO_ONE(span);
866
867 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
868 if (clip_span( ctx,span ) == GL_FALSE) {
869 return;
870 }
871 }
872
873
874 /* Do the scissor test */
875 if (ctx->Scissor.Enabled) {
876 if (_mesa_scissor_span( ctx, span ) == GL_FALSE) {
877 return;
878 }
879 }
880
881
882 /* Polygon Stippling */
883 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
884 stipple_polygon_span( ctx, span);
885 }
886
887
888 if ((primitive==GL_BITMAP && (swrast->_RasterMask & modBits))
889 || (swrast->_RasterMask & MULTI_DRAW_BIT)) {
890 /* must make a copy of the colors since they may be modified */
891 MEMCPY( rgbaBackup, span->color.rgba, 4 * span->end * sizeof(GLchan) );
892 rgba = rgbaBackup;
893 }
894 else {
895 rgba = span->color.rgba;
896 }
897
898
899 /* Do the alpha test */
900 if (ctx->Color.AlphaEnabled) {
901 if (_mesa_alpha_test( ctx, span->end, (const GLchan (*)[4]) rgba, span->mask ) == 0) {
902 return;
903 }
904 span->write_all = GL_FALSE;
905 }
906
907 /* I have to think where to put this!! */
908 if (span->activeMask & SPAN_Z) {
909 SW_SPAN_SET_FLAG(span->filledDepth);
910
911 if (ctx->Visual.depthBits <= 16) {
912 GLuint i;
913 GLfixed zval = span->z;
914 for (i = 0; i < span->end; i++) {
915 span->depth[i] = FixedToInt(zval);
916 zval += span->zStep;
917 }
918 }
919 else {
920 /* Deep Z buffer, no fixed->int shift */
921 GLuint i;
922 GLfixed zval = span->z;
923 for (i = 0; i < span->end; i++) {
924 span->depth[i] = zval;
925 zval += span->zStep;
926 }
927 }
928 }
929
930 if (ctx->Stencil.Enabled) {
931 /* first stencil test */
932 if (_mesa_stencil_and_ztest_span(ctx, span) == GL_FALSE)
933 return;
934 }
935 else if (ctx->Depth.Test) {
936 /* regular depth testing */
937 if (_mesa_depth_test_span(ctx, span) == GL_FALSE)
938 return;
939 }
940
941 /* if we get here, something passed the depth test */
942 ctx->OcclusionResult = GL_TRUE;
943
944 /* Per-pixel fog */
945 if (ctx->Fog.Enabled) {
946 /* Is this the right 'if' ?? */
947 if ((span->activeMask & SPAN_FOG) && !swrast->_PreferPixelFog)
948 _mesa_fog_rgba_pixels( ctx, span, rgba );
949 else
950 _mesa_depth_fog_rgba_pixels( ctx, span, rgba );
951 }
952
953 /* Antialias coverage application */
954 #if 0
955 if (span->coverage) {
956 GLuint i;
957 for (i = 0; i < span->end; i++) {
958 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * span->coverage[i]);
959 }
960 }
961 #endif
962
963 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
964 multi_write_rgba_span( ctx, span->end, span->x, span->y, (const GLchan (*)[4]) rgba, span->mask );
965 }
966 else {
967 /* normal: write to exactly one buffer */
968 /* logic op or blending */
969 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
970
971 if (ctx->Color.ColorLogicOpEnabled) {
972 _mesa_logicop_rgba_span( ctx, span->end, span->x, span->y, rgba, span->mask );
973 }
974 else if (ctx->Color.BlendEnabled) {
975 _mesa_blend_span( ctx, span->end, span->x, span->y, rgba, span->mask );
976 }
977
978 /* Color component masking */
979 if (colorMask == 0x0) {
980 return;
981 }
982 else if (colorMask != 0xffffffff) {
983 _mesa_mask_rgba_span( ctx, span->end, span->x, span->y, rgba );
984 }
985
986 /* write pixels */
987 (*swrast->Driver.WriteRGBASpan)( ctx, span->end, span->x, span->y,
988 (const GLchan (*)[4]) rgba,
989 span->write_all ? ((const GLubyte *) NULL) : span->mask );
990
991 if (swrast->_RasterMask & ALPHABUF_BIT) {
992 _mesa_write_alpha_span( ctx, span->end, span->x, span->y,
993 (const GLchan (*)[4]) rgba,
994 span->write_all ? ((const GLubyte *) NULL) : span->mask );
995 }
996 }
997 }
998
999
1000 /*
1001 * Write a horizontal span of color pixels to the frame buffer.
1002 * The color is initially constant for the whole span.
1003 * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
1004 * Input: r, g, b, a - the color of the pixels
1005 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
1006 */
1007 void
1008 _mesa_write_monocolor_span( GLcontext *ctx, struct sw_span *span,
1009 const GLchan color[4], GLenum primitive )
1010 {
1011 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1012 GLuint i;
1013 GLchan rgba[MAX_WIDTH][4];
1014 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1015
1016
1017 SET_MASK_TO_ONE(span);
1018
1019 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
1020 if (clip_span(ctx,span) == GL_FALSE) {
1021 return;
1022 }
1023 }
1024
1025 /* Do the scissor test */
1026 if (ctx->Scissor.Enabled) {
1027 if (_mesa_scissor_span( ctx, span ) == GL_FALSE) {
1028 return;
1029 }
1030 }
1031
1032 /* Polygon Stippling */
1033 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
1034 stipple_polygon_span( ctx, span);
1035 }
1036
1037 /* Do the alpha test */
1038 if (ctx->Color.AlphaEnabled) {
1039 for (i = 0; i < span->end; i++) {
1040 rgba[i][ACOMP] = color[ACOMP];
1041 }
1042 if (_mesa_alpha_test( ctx, span->end, (const GLchan (*)[4])rgba, span->mask ) == 0) {
1043 return;
1044 }
1045 span->write_all = GL_FALSE;
1046 }
1047
1048 /* I have to think where to put this!! */
1049 if (span->activeMask & SPAN_Z) {
1050 SW_SPAN_SET_FLAG(span->filledDepth);
1051
1052 if (ctx->Visual.depthBits <= 16) {
1053 GLuint i;
1054 GLfixed zval = span->z;
1055 for (i = 0; i < span->end; i++) {
1056 span->depth[i] = FixedToInt(zval);
1057 zval += span->zStep;
1058 }
1059 }
1060 else {
1061 /* Deep Z buffer, no fixed->int shift */
1062 GLuint i;
1063 GLfixed zval = span->z;
1064 for (i = 0; i < span->end; i++) {
1065 span->depth[i] = zval;
1066 zval += span->zStep;
1067 }
1068 }
1069 }
1070
1071 if (ctx->Stencil.Enabled) {
1072 /* first stencil test */
1073 if (_mesa_stencil_and_ztest_span(ctx, span) == GL_FALSE)
1074 return;
1075 }
1076 else if (ctx->Depth.Test) {
1077 /* regular depth testing */
1078 if (_mesa_depth_test_span(ctx, span) == 0)
1079 return;
1080 }
1081
1082 /* if we get here, something passed the depth test */
1083 ctx->OcclusionResult = GL_TRUE;
1084
1085 if (ctx->Color.DrawBuffer == GL_NONE) {
1086 /* write no pixels */
1087 return;
1088 }
1089
1090 if (ctx->Color.ColorLogicOpEnabled || colorMask != 0xffffffff ||
1091 #if 0
1092 (swrast->_RasterMask & (BLEND_BIT | FOG_BIT)) || coverage) {
1093 #else
1094 (swrast->_RasterMask & (BLEND_BIT | FOG_BIT))) {
1095 #endif
1096 /* assign same color to each pixel */
1097 SW_SPAN_SET_FLAG(span->filledColor);
1098 for (i = 0; i < span->end; i++) {
1099 if (span->mask[i]) {
1100 COPY_CHAN4(rgba[i], color);
1101 }
1102 }
1103
1104 /* Per-pixel fog */
1105 if (ctx->Fog.Enabled) {
1106 /* Is this the right 'if' ?? */
1107 if ((span->activeMask & SPAN_FOG) && !swrast->_PreferPixelFog)
1108 _mesa_fog_rgba_pixels( ctx, span, rgba );
1109 else
1110 _mesa_depth_fog_rgba_pixels( ctx, span, rgba );
1111 }
1112
1113 /* Antialias coverage application */
1114 #if 0
1115 if (span->coverage) {
1116 GLuint i;
1117 for (i = 0; i < span->end; i++) {
1118 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * span->coverage[i]);
1119 }
1120 }
1121 #endif
1122
1123 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1124 multi_write_rgba_span( ctx, span->end, span->x, span->y,
1125 (const GLchan (*)[4]) rgba, span->mask );
1126 }
1127 else {
1128 /* normal: write to exactly one buffer */
1129 if (ctx->Color.ColorLogicOpEnabled) {
1130 _mesa_logicop_rgba_span( ctx, span->end, span->x, span->y, rgba, span->mask );
1131 }
1132 else if (ctx->Color.BlendEnabled) {
1133 _mesa_blend_span( ctx, span->end, span->x, span->y, rgba, span->mask );
1134 }
1135
1136 /* Color component masking */
1137 if (colorMask == 0x0) {
1138 return;
1139 }
1140 else if (colorMask != 0xffffffff) {
1141 _mesa_mask_rgba_span( ctx, span->end, span->x, span->y, rgba );
1142 }
1143
1144 /* write pixels */
1145 (*swrast->Driver.WriteRGBASpan)( ctx, span->end, span->x, span->y,
1146 (const GLchan (*)[4]) rgba,
1147 span->write_all ? ((const GLubyte *) NULL) : span->mask );
1148 if (swrast->_RasterMask & ALPHABUF_BIT) {
1149 _mesa_write_alpha_span( ctx, span->end, span->x, span->y,
1150 (const GLchan (*)[4]) rgba,
1151 span->write_all ? ((const GLubyte *) NULL) : span->mask );
1152 }
1153 }
1154 }
1155 else {
1156 /* same color for all pixels */
1157 ASSERT(!ctx->Color.BlendEnabled);
1158 ASSERT(!ctx->Color.ColorLogicOpEnabled);
1159
1160 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1161 SW_SPAN_SET_FLAG(span->filledColor);
1162 for (i = 0; i < span->end; i++) {
1163 if (span->mask[i]) {
1164 COPY_CHAN4(rgba[i], color);
1165 }
1166 }
1167 multi_write_rgba_span( ctx, span->end, span->x, span->y,
1168 (const GLchan (*)[4]) rgba, span->mask );
1169 }
1170 else {
1171 (*swrast->Driver.WriteMonoRGBASpan)( ctx, span->end, span->x, span->y, color, span->mask );
1172 if (swrast->_RasterMask & ALPHABUF_BIT) {
1173 _mesa_write_mono_alpha_span( ctx, span->end, span->x, span->y, (GLchan) color[ACOMP],
1174 span->write_all ? ((const GLubyte *) NULL) : span->mask );
1175 }
1176 }
1177 }
1178 }
1179
1180
1181
1182 /*
1183 * Add specular color to base color. This is used only when
1184 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1185 */
1186 static void
1187 add_colors(CONST struct sw_span *span, GLchan rgba[][4])
1188 {
1189 GLuint i;
1190 ASSERT(span->filledSpecular == GL_TRUE);
1191 ASSERT(span->filledColor == GL_TRUE);
1192
1193 for (i = 0; i < span->end; i++) {
1194 #if CHAN_TYPE == GL_FLOAT
1195 /* no clamping */
1196 rgba[i][RCOMP] += span->specular[i][RCOMP];
1197 rgba[i][GCOMP] += span->specular[i][GCOMP];
1198 rgba[i][BCOMP] += span->specular[i][BCOMP];
1199 #else
1200 GLint r = rgba[i][RCOMP] + span->specular[i][RCOMP];
1201 GLint g = rgba[i][GCOMP] + span->specular[i][GCOMP];
1202 GLint b = rgba[i][BCOMP] + span->specular[i][BCOMP];
1203 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1204 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1205 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1206 #endif
1207 }
1208 }
1209
1210
1211 /*
1212 * Write a horizontal span of textured pixels to the frame buffer.
1213 * The color of each pixel is different.
1214 * Depth-testing, stenciling, scissor-testing etc. should already
1215 * have been done,
1216 * only if alpha-testing is used, depth-testing is still done in this
1217 * function.
1218 * Input: n - number of pixels in the span
1219 * x, y - location of leftmost pixel in the span
1220 * z - array of [n] z-values
1221 * s, t - array of (s,t) texture coordinates for each pixel
1222 * lambda - array of texture lambda values
1223 * rgba - array of [n] color components
1224 * mask - masked pixels
1225 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
1226 * Contributed by Klaus Niederkrueger.
1227 */
1228 static void
1229 masked_texture_span( GLcontext *ctx, struct sw_span *span)
1230 {
1231 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1232 GLchan rgbaBackup[MAX_WIDTH][4];
1233 GLchan (*rgba)[4]; /* points to either span->color.rgba or rgbaBackup */
1234 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1235
1236
1237 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1238 /* must make a copy of the colors since they may be modified */
1239 MEMCPY(rgbaBackup, span->color.rgba, 4 * span->end * sizeof(GLchan));
1240 rgba = rgbaBackup;
1241 }
1242 else {
1243 rgba = span->color.rgba;
1244 }
1245
1246
1247 ASSERT(ctx->Texture._ReallyEnabled);
1248 _swrast_texture_fragments( ctx, 0, span, rgba );
1249
1250
1251 /* Texture with alpha test */
1252 if (ctx->Color.AlphaEnabled) {
1253 /* Do the alpha test */
1254 if (_mesa_alpha_test( ctx, span->end, (const GLchan (*)[4]) rgba, span->mask ) == 0) {
1255 return;
1256 }
1257 span->write_all = GL_FALSE;
1258
1259 /* Depth test usually in 'rasterize_span' but if alpha test
1260 needed, we have to wait for that test before depth test can
1261 be done. */
1262 if (ctx->Stencil.Enabled) {
1263 /* first stencil test */
1264 if (_mesa_stencil_and_ztest_span(ctx, span) == GL_FALSE)
1265 return;
1266 }
1267 else if (ctx->Depth.Test) {
1268 /* regular depth testing */
1269 if (_mesa_depth_test_span(ctx, span) == 0)
1270 return;
1271 }
1272 }
1273
1274 /* if we get here, something passed the depth test */
1275 ctx->OcclusionResult = GL_TRUE;
1276
1277
1278 /* Add base and specular colors */
1279 if ((span->activeMask & SPAN_SPEC) && /* Is this right test ???*/
1280 (ctx->Fog.ColorSumEnabled ||
1281 (ctx->Light.Enabled &&
1282 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)))
1283 add_colors(span, rgba); /* rgba = rgba + spec */
1284
1285 /* Per-pixel fog */
1286 if (ctx->Fog.Enabled) {
1287 /* Is this the right 'if' ?? */
1288 if ((span->activeMask & SPAN_FOG) && !swrast->_PreferPixelFog)
1289 _mesa_fog_rgba_pixels(ctx, span, rgba);
1290 else
1291 _mesa_depth_fog_rgba_pixels(ctx, span, rgba);
1292 }
1293
1294 /* Antialias coverage application */
1295 #if 0
1296 if (span->coverage) {
1297 GLuint i;
1298 for (i = 0; i < span->end; i++) {
1299 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * span->coverage[i]);
1300 }
1301 }
1302 #endif
1303
1304 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1305 multi_write_rgba_span( ctx, span->end, span->x, span->y, (const GLchan (*)[4]) rgba, span->mask );
1306 }
1307 else {
1308 /* normal: write to exactly one buffer */
1309 if (ctx->Color.ColorLogicOpEnabled) {
1310 _mesa_logicop_rgba_span( ctx, span->end, span->x, span->y, rgba, span->mask );
1311 }
1312 else if (ctx->Color.BlendEnabled) {
1313 _mesa_blend_span( ctx, span->end, span->x, span->y, rgba, span->mask );
1314 }
1315 if (colorMask == 0x0) {
1316 return;
1317 }
1318 else if (colorMask != 0xffffffff) {
1319 _mesa_mask_rgba_span( ctx, span->end, span->x, span->y, rgba );
1320 }
1321
1322 (*swrast->Driver.WriteRGBASpan)( ctx, span->end, span->x, span->y, (const GLchan (*)[4])rgba,
1323 span->write_all ? NULL : span->mask );
1324 if (swrast->_RasterMask & ALPHABUF_BIT) {
1325 _mesa_write_alpha_span( ctx, span->end, span->x, span->y, (const GLchan (*)[4]) rgba,
1326 span->write_all ? NULL : span->mask );
1327 }
1328 }
1329 }
1330
1331
1332 /*
1333 * As above but perform multiple stages of texture application.
1334 * Contributed by Klaus Niederkrueger.
1335 */
1336 static void
1337 masked_multitexture_span( GLcontext *ctx, struct sw_span *span)
1338 {
1339 GLchan rgbaBackup[MAX_WIDTH][4];
1340 GLchan (*rgba)[4]; /* points to either span->color.rgba or rgbaBackup */
1341 GLuint i;
1342 const GLuint texUnits = ctx->Const.MaxTextureUnits;
1343 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1344
1345
1346 if ( (swrast->_RasterMask & MULTI_DRAW_BIT) || texUnits > 1) {
1347 /* must make a copy of the colors since they may be modified */
1348 MEMCPY(rgbaBackup, span->color.rgba, 4 * span->end * sizeof(GLchan));
1349 rgba = rgbaBackup;
1350 }
1351 else {
1352 rgba = span->color.rgba;
1353 }
1354
1355
1356 ASSERT(ctx->Texture._ReallyEnabled);
1357 for (i = 0; i < texUnits; i++)
1358 _swrast_texture_fragments( ctx, i, span, rgba );
1359
1360 /* Texture with alpha test */
1361 if (ctx->Color.AlphaEnabled) {
1362 /* Do the alpha test */
1363 if (_mesa_alpha_test( ctx, span->end, (const GLchan (*)[4])rgba, span->mask ) == 0) {
1364 return;
1365 }
1366 span->write_all = GL_FALSE;
1367 /* Depth test usually in 'rasterize_span' but if alpha test
1368 needed, we have to wait for that test before depth test can
1369 be done. */
1370 if (ctx->Stencil.Enabled) {
1371 /* first stencil test */
1372 if (_mesa_stencil_and_ztest_span(ctx, span) == GL_FALSE)
1373 return;
1374 }
1375 else if (ctx->Depth.Test) {
1376 /* regular depth testing */
1377 if (_mesa_depth_test_span(ctx, span) == GL_FALSE)
1378 return;
1379 }
1380 }
1381
1382 /* if we get here, something passed the depth test */
1383 ctx->OcclusionResult = GL_TRUE;
1384
1385
1386 /* Add base and specular colors */
1387 if ((span->activeMask & SPAN_SPEC) && /* Is this right test ???*/
1388 (ctx->Fog.ColorSumEnabled ||
1389 (ctx->Light.Enabled &&
1390 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)))
1391 add_colors(span, rgba); /* rgba = rgba + spec */
1392
1393 /* Per-pixel fog */
1394 if (ctx->Fog.Enabled) {
1395 /* Is this the right 'if' ?? */
1396 if ((span->activeMask & SPAN_FOG) && !swrast->_PreferPixelFog)
1397 _mesa_fog_rgba_pixels( ctx, span, rgba );
1398 else
1399 _mesa_depth_fog_rgba_pixels( ctx, span, rgba );
1400 }
1401
1402 /* Antialias coverage application */
1403 #if 0
1404 if (span->coverage) {
1405 GLuint i;
1406 for (i = 0; i < span->end; i++) {
1407 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * span->coverage[i]);
1408 }
1409 }
1410 #endif
1411
1412 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1413 multi_write_rgba_span( ctx, span->end, span->x, span->y, (const GLchan (*)[4]) rgba, span->mask );
1414 }
1415 else {
1416 /* normal: write to exactly one buffer */
1417 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1418
1419 if (ctx->Color.ColorLogicOpEnabled) {
1420 _mesa_logicop_rgba_span( ctx, span->end, span->x, span->y, rgba, span->mask );
1421 }
1422 else if (ctx->Color.BlendEnabled) {
1423 _mesa_blend_span( ctx, span->end, span->x, span->y, rgba, span->mask );
1424 }
1425
1426 if (colorMask == 0x0) {
1427 return;
1428 }
1429 else if (colorMask != 0xffffffff) {
1430 _mesa_mask_rgba_span( ctx, span->end, span->x, span->y, rgba );
1431 }
1432
1433 (*swrast->Driver.WriteRGBASpan)( ctx, span->end, span->x, span->y, (const GLchan (*)[4])rgba,
1434 span->write_all ? NULL : span->mask );
1435 if (swrast->_RasterMask & ALPHABUF_BIT) {
1436 _mesa_write_alpha_span( ctx, span->end, span->x, span->y, (const GLchan (*)[4])rgba,
1437 span->write_all ? NULL : span->mask );
1438 }
1439 }
1440 }
1441
1442
1443 /*
1444 * Generate arrays of fragment colors, z, fog, texcoords, etc from a
1445 * triangle span object. Then call the span/fragment processsing
1446 * functions in s_span.[ch]. This is used by a bunch of the textured
1447 * triangle functions.
1448 * Contributed by Klaus Niederkrueger.
1449 */
1450 void
1451 _mesa_rasterize_span(GLcontext *ctx, struct sw_span *span)
1452 {
1453 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1454
1455 SET_MASK_TO_ONE(span);
1456
1457
1458 if (swrast->_RasterMask & WINCLIP_BIT) {
1459 if (clip_span(ctx, span) == GL_FALSE) {
1460 return;
1461 }
1462 }
1463
1464 /* Do the scissor test */
1465 if (ctx->Scissor.Enabled) {
1466 if (_mesa_scissor_span( ctx, span ) == GL_FALSE) {
1467 return;
1468 }
1469 }
1470
1471 /* Polygon Stippling */
1472 if (ctx->Polygon.StippleFlag) {
1473 stipple_polygon_span( ctx, span );
1474 }
1475
1476 /* I have to think where to put this!! */
1477 if (span->activeMask & SPAN_Z) {
1478 SW_SPAN_SET_FLAG(span->filledDepth);
1479
1480 if (ctx->Visual.depthBits <= 16) {
1481 GLuint i;
1482 GLfixed zval = span->z;
1483 for (i = 0; i < span->end; i++) {
1484 span->depth[i] = FixedToInt(zval);
1485 zval += span->zStep;
1486 }
1487 }
1488 else {
1489 /* Deep Z buffer, no fixed->int shift */
1490 GLuint i;
1491 GLfixed zval = span->z;
1492 for (i = 0; i < span->end; i++) {
1493 span->depth[i] = zval;
1494 zval += span->zStep;
1495 }
1496 }
1497 }
1498
1499 /* Correct order: texturing --> alpha test --> depth test. But if
1500 no alpha test needed, we can do here the depth test and
1501 potentially avoid some of the texturing (otherwise alpha test,
1502 depth test etc. happens in masked_texture_span(). */
1503 if (span->activeMask & SPAN_Z && !ctx->Color.AlphaEnabled) {
1504 if (ctx->Stencil.Enabled) {
1505 /* first stencil test */
1506 if (_mesa_stencil_and_ztest_span(ctx, span) == GL_FALSE)
1507 return;
1508 }
1509 else if (ctx->Depth.Test) {
1510 /* regular depth testing */
1511 if (_mesa_depth_test_span( ctx, span) == 0) {
1512 return;
1513 }
1514 }
1515 }
1516
1517 if (span->activeMask & SPAN_RGBA) {
1518 ASSERT(span->filledColor == GL_FALSE);
1519 SW_SPAN_SET_FLAG(span->filledColor);
1520 if (span->activeMask & SPAN_FLAT) {
1521 GLuint i;
1522 GLchan color[4];
1523 color[RCOMP] = FixedToChan(span->red);
1524 color[GCOMP] = FixedToChan(span->green);
1525 color[BCOMP] = FixedToChan(span->blue);
1526 color[ACOMP] = FixedToChan(span->alpha);
1527 for (i = 0; i < span->end; i++) {
1528 COPY_CHAN4(span->color.rgba[i], color);
1529 }
1530 }
1531 else {
1532 /* smooth interpolation */
1533 #if CHAN_TYPE == GL_FLOAT
1534 GLfloat r = span->red;
1535 GLfloat g = span->green;
1536 GLfloat b = span->blue;
1537 GLfloat a = span->alpha;
1538 #else
1539 GLfixed r = span->red;
1540 GLfixed g = span->green;
1541 GLfixed b = span->blue;
1542 GLfixed a = span->alpha;
1543 #endif
1544 GLuint i;
1545 for (i = 0; i < span->end; i++) {
1546 span->color.rgba[i][RCOMP] = FixedToChan(r);
1547 span->color.rgba[i][GCOMP] = FixedToChan(g);
1548 span->color.rgba[i][BCOMP] = FixedToChan(b);
1549 span->color.rgba[i][ACOMP] = FixedToChan(a);
1550 r += span->redStep;
1551 g += span->greenStep;
1552 b += span->blueStep;
1553 a += span->alphaStep;
1554 }
1555 }
1556 }
1557
1558 if (span->activeMask & SPAN_SPEC) {
1559 SW_SPAN_SET_FLAG(span->filledSpecular);
1560 if (span->activeMask & SPAN_FLAT) {
1561 const GLchan r = FixedToChan(span->specRed);
1562 const GLchan g = FixedToChan(span->specGreen);
1563 const GLchan b = FixedToChan(span->specBlue);
1564 GLuint i;
1565 for (i = 0; i < span->end; i++) {
1566 span->specular[i][RCOMP] = r;
1567 span->specular[i][GCOMP] = g;
1568 span->specular[i][BCOMP] = b;
1569 }
1570 }
1571 else {
1572 /* smooth interpolation */
1573 #if CHAN_TYPE == GL_FLOAT
1574 GLfloat r = span->specRed;
1575 GLfloat g = span->specGreen;
1576 GLfloat b = span->specBlue;
1577 #else
1578 GLfixed r = span->specRed;
1579 GLfixed g = span->specGreen;
1580 GLfixed b = span->specBlue;
1581 #endif
1582 GLuint i;
1583 for (i = 0; i < span->end; i++) {
1584 span->specular[i][RCOMP] = FixedToChan(r);
1585 span->specular[i][GCOMP] = FixedToChan(g);
1586 span->specular[i][BCOMP] = FixedToChan(b);
1587 r += span->specRedStep;
1588 g += span->specGreenStep;
1589 b += span->specBlueStep;
1590 }
1591 }
1592 }
1593
1594 if (span->activeMask & SPAN_INDEX) {
1595 SW_SPAN_SET_FLAG(span->filledColor);
1596 if (span->activeMask & SPAN_FLAT) {
1597 GLuint i;
1598 const GLint indx = FixedToInt(span->index);
1599 for (i = 0; i < span->end; i++) {
1600 span->color.index[i] = indx;
1601 }
1602 }
1603 else {
1604 /* smooth interpolation */
1605 GLuint i;
1606 GLfixed ind = span->index;
1607 for (i = 0; i < span->end; i++) {
1608 span->color.index[i] = FixedToInt(ind);
1609 ind += span->indexStep;
1610 }
1611 }
1612 }
1613
1614 if (span->activeMask & SPAN_TEXTURE) {
1615 if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) {
1616 /* multitexture */
1617 if (span->activeMask & SPAN_LAMBDA) {
1618 /* with lambda */
1619 GLuint u;
1620 /* multitexture, lambda */
1621 for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
1622 if (ctx->Texture.Unit[u]._ReallyEnabled) {
1623 GLfloat s = span->tex[u][0];
1624 GLfloat t = span->tex[u][1];
1625 GLfloat r = span->tex[u][2];
1626 GLfloat q = span->tex[u][3];
1627 GLuint i;
1628 SW_SPAN_SET_FLAG(span->filledLambda[u]);
1629 SW_SPAN_SET_FLAG(span->filledTex[u]);
1630 for (i = 0; i < span->end; i++) {
1631 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
1632 span->texcoords[u][i][0] = s * invQ;
1633 span->texcoords[u][i][1] = t * invQ;
1634 span->texcoords[u][i][2] = r * invQ;
1635 span->lambda[u][i] = (GLfloat)
1636 (log(span->rho[u] * invQ * invQ) * 1.442695F * 0.5F);
1637 s += span->texStep[u][0];
1638 t += span->texStep[u][1];
1639 r += span->texStep[u][2];
1640 q += span->texStep[u][3];
1641 }
1642 }
1643 }
1644 }
1645 else {
1646 /* without lambda */
1647 GLuint u;
1648 /* multitexture, no lambda */
1649 for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
1650 if (ctx->Texture.Unit[u]._ReallyEnabled) {
1651 GLfloat s = span->tex[u][0];
1652 GLfloat t = span->tex[u][1];
1653 GLfloat r = span->tex[u][2];
1654 GLfloat q = span->tex[u][3];
1655 GLuint i;
1656 SW_SPAN_SET_FLAG(span->filledTex[u]);
1657 for (i = 0; i < span->end; i++) {
1658 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
1659 span->texcoords[u][i][0] = s * invQ;
1660 span->texcoords[u][i][1] = t * invQ;
1661 span->texcoords[u][i][2] = r * invQ;
1662 s += span->texStep[u][0];
1663 t += span->texStep[u][1];
1664 r += span->texStep[u][2];
1665 q += span->texStep[u][3];
1666 }
1667 }
1668 }
1669 }
1670 }
1671 else {
1672 /* just texture unit 0 */
1673 #ifdef DEBUG
1674 {GLint i;
1675 for (i=0; i<MAX_TEXTURE_UNITS; i++) {
1676 ASSERT(span->filledTex[i] == GL_FALSE &&
1677 span->filledLambda[i] == GL_FALSE);
1678 }}
1679 #endif
1680 if (span->activeMask & SPAN_LAMBDA) {
1681 /* with lambda */
1682 GLfloat s = span->tex[0][0];
1683 GLfloat t = span->tex[0][1];
1684 GLfloat r = span->tex[0][2];
1685 GLfloat q = span->tex[0][3];
1686 GLuint i;
1687 SW_SPAN_SET_FLAG(span->filledLambda[0]);
1688 SW_SPAN_SET_FLAG(span->filledTex[0]);
1689 /* single texture, lambda */
1690 for (i = 0; i < span->end; i++) {
1691 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
1692 span->texcoords[0][i][0] = s * invQ;
1693 span->texcoords[0][i][1] = t * invQ;
1694 span->texcoords[0][i][2] = r * invQ;
1695 span->lambda[0][i] = (GLfloat)
1696 (log(span->rho[0] * invQ * invQ) * 1.442695F * 0.5F);
1697 s += span->texStep[0][0];
1698 t += span->texStep[0][1];
1699 r += span->texStep[0][2];
1700 q += span->texStep[0][3];
1701 }
1702 }
1703 else {
1704 /* without lambda */
1705 GLfloat s = span->tex[0][0];
1706 GLfloat t = span->tex[0][1];
1707 GLfloat r = span->tex[0][2];
1708 GLfloat q = span->tex[0][3];
1709 GLuint i;
1710 SW_SPAN_SET_FLAG(span->filledTex[0]);
1711 /* single texture, no lambda */
1712 for (i = 0; i < span->end; i++) {
1713 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
1714 span->texcoords[0][i][0] = s * invQ;
1715 span->texcoords[0][i][1] = t * invQ;
1716 span->texcoords[0][i][2] = r * invQ;
1717 s += span->texStep[0][0];
1718 t += span->texStep[0][1];
1719 r += span->texStep[0][2];
1720 q += span->texStep[0][3];
1721 }
1722 }
1723 }
1724 }
1725 /* XXX keep this? */
1726 if (span->activeMask & SPAN_INT_TEXTURE) {
1727 GLfixed s = span->intTex[0];
1728 GLfixed t = span->intTex[1];
1729 GLuint i;
1730 for (i = 0; i < span->end; i++) {
1731 span->itexcoords[i][0] = FixedToInt(s);
1732 span->itexcoords[i][1] = FixedToInt(t);
1733 s += span->intTexStep[0];
1734 t += span->intTexStep[1];
1735 }
1736 }
1737
1738 /* examine activeMask and call a s_span.c function */
1739 if (span->activeMask & SPAN_TEXTURE) {
1740
1741 if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) {
1742 /* multi texture */
1743 masked_multitexture_span(ctx, span);
1744 }
1745 else {
1746 /* single texture */
1747 masked_texture_span(ctx, span);
1748 }
1749 }
1750 else {
1751 _mesa_problem(ctx, "rasterize_span() should only be used for texturing");
1752 }
1753
1754 }
1755
1756 /*
1757 * Add specular color to base color. This is used only when
1758 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1759 */
1760 static void
1761 _old_add_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] )
1762 {
1763 GLuint i;
1764 for (i = 0; i < n; i++) {
1765 #if CHAN_TYPE == GL_FLOAT
1766 /* no clamping */
1767 rgba[i][RCOMP] += specular[i][RCOMP];
1768 rgba[i][GCOMP] += specular[i][GCOMP];
1769 rgba[i][BCOMP] += specular[i][BCOMP];
1770 #else
1771 GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
1772 GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
1773 GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
1774 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1775 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1776 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1777 #endif
1778 }
1779 }
1780
1781
1782 /*
1783 * Write a horizontal span of textured pixels to the frame buffer.
1784 * The color of each pixel is different.
1785 * Alpha-testing, stenciling, depth-testing, and blending are done
1786 * as needed.
1787 * Input: n - number of pixels in the span
1788 * x, y - location of leftmost pixel in the span
1789 * z - array of [n] z-values
1790 * fog - array of fog factor values in [0,1]
1791 * s, t - array of (s,t) texture coordinates for each pixel
1792 * lambda - array of texture lambda values
1793 * rgba - array of [n] color components
1794 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
1795 */
1796 void
1797 _old_write_texture_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
1798 const GLdepth z[], const GLfloat fog[],
1799 GLfloat texcoord[][4],
1800 GLfloat lambda[],
1801 GLchan rgbaIn[][4], GLchan spec[][4],
1802 const GLfloat coverage[], GLenum primitive )
1803 {
1804 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1805 GLubyte mask[MAX_WIDTH];
1806 GLboolean write_all = GL_TRUE;
1807 GLchan rgbaBackup[MAX_WIDTH][4];
1808 GLchan (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */
1809 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1810
1811 /* init mask to 1's (all pixels are to be written) */
1812 MEMSET(mask, 1, n);
1813
1814 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
1815 if ((n=old_clip_span(ctx, n, x, y, mask)) == 0) {
1816 return;
1817 }
1818 if (mask[0] == 0)
1819 write_all = GL_FALSE;
1820 }
1821
1822
1823 if (primitive==GL_BITMAP || (swrast->_RasterMask & MULTI_DRAW_BIT)) {
1824 /* must make a copy of the colors since they may be modified */
1825 MEMCPY(rgbaBackup, rgbaIn, 4 * n * sizeof(GLchan));
1826 rgba = rgbaBackup;
1827 }
1828 else {
1829 rgba = rgbaIn;
1830 }
1831
1832 /* Do the scissor test */
1833 if (ctx->Scissor.Enabled) {
1834 if ((n = _old_scissor_span( ctx, n, x, y, mask )) == 0) {
1835 return;
1836 }
1837 if (mask[0] == 0)
1838 write_all = GL_FALSE;
1839 }
1840
1841 /* Polygon Stippling */
1842 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
1843 old_stipple_polygon_span( ctx, n, x, y, mask );
1844 write_all = GL_FALSE;
1845 }
1846
1847 /* Texture with alpha test */
1848 if (ctx->Color.AlphaEnabled) {
1849 /* Texturing without alpha is done after depth-testing which
1850 gives a potential speed-up. */
1851 ASSERT(ctx->Texture._ReallyEnabled);
1852 _old_swrast_texture_fragments( ctx, 0, n, texcoord, lambda,
1853 (CONST GLchan (*)[4]) rgba, rgba );
1854
1855 /* Do the alpha test */
1856 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4]) rgba, mask ) == 0) {
1857 return;
1858 }
1859 write_all = GL_FALSE;
1860 }
1861
1862 if (ctx->Stencil.Enabled) {
1863 /* first stencil test */
1864 if (_old_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
1865 return;
1866 }
1867 write_all = GL_FALSE;
1868 }
1869 else if (ctx->Depth.Test) {
1870 /* regular depth testing */
1871 GLuint m = _old_depth_test_span( ctx, n, x, y, z, mask );
1872 if (m == 0) {
1873 return;
1874 }
1875 if (m < n) {
1876 write_all = GL_FALSE;
1877 }
1878 }
1879
1880 /* if we get here, something passed the depth test */
1881 ctx->OcclusionResult = GL_TRUE;
1882
1883 /* Texture without alpha test */
1884 if (! ctx->Color.AlphaEnabled) {
1885 ASSERT(ctx->Texture._ReallyEnabled);
1886 _old_swrast_texture_fragments( ctx, 0, n, texcoord, lambda,
1887 (CONST GLchan (*)[4]) rgba, rgba );
1888 }
1889
1890 /* Add base and specular colors */
1891 if (spec &&
1892 (ctx->Fog.ColorSumEnabled ||
1893 (ctx->Light.Enabled &&
1894 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)))
1895 _old_add_colors( n, rgba, spec ); /* rgba = rgba + spec */
1896
1897 /* Per-pixel fog */
1898 if (ctx->Fog.Enabled) {
1899 if (fog && !swrast->_PreferPixelFog)
1900 _old_fog_rgba_pixels( ctx, n, fog, rgba );
1901 else
1902 _old_depth_fog_rgba_pixels( ctx, n, z, rgba );
1903 }
1904
1905 /* Antialias coverage application */
1906 if (coverage) {
1907 GLuint i;
1908 for (i = 0; i < n; i++) {
1909 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
1910 }
1911 }
1912
1913 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1914 multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask );
1915 }
1916 else {
1917 /* normal: write to exactly one buffer */
1918 if (ctx->Color.ColorLogicOpEnabled) {
1919 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
1920 }
1921 else if (ctx->Color.BlendEnabled) {
1922 _mesa_blend_span( ctx, n, x, y, rgba, mask );
1923 }
1924 if (colorMask == 0x0) {
1925 return;
1926 }
1927 else if (colorMask != 0xffffffff) {
1928 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
1929 }
1930
1931 (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLchan (*)[4])rgba,
1932 write_all ? ((const GLubyte *) NULL) : mask );
1933 if (swrast->_RasterMask & ALPHABUF_BIT) {
1934 _mesa_write_alpha_span( ctx, n, x, y, (const GLchan (*)[4]) rgba,
1935 write_all ? ((const GLubyte *) NULL) : mask );
1936 }
1937 }
1938 }
1939
1940
1941
1942 /*
1943 * As above but perform multiple stages of texture application.
1944 */
1945 void
1946 _old_write_multitexture_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
1947 const GLdepth z[], const GLfloat fog[],
1948 GLfloat texcoord[MAX_TEXTURE_UNITS][MAX_WIDTH][4],
1949 GLfloat lambda[][MAX_WIDTH],
1950 GLchan rgbaIn[MAX_TEXTURE_UNITS][4],
1951 GLchan spec[MAX_TEXTURE_UNITS][4],
1952 const GLfloat coverage[],
1953 GLenum primitive )
1954 {
1955 GLubyte mask[MAX_WIDTH];
1956 GLboolean write_all = GL_TRUE;
1957 GLchan rgbaBackup[MAX_WIDTH][4];
1958 GLchan (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */
1959 GLuint i;
1960 const GLubyte *Null = 0;
1961 const GLuint texUnits = ctx->Const.MaxTextureUnits;
1962 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1963
1964 /* init mask to 1's (all pixels are to be written) */
1965 MEMSET(mask, 1, n);
1966
1967 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
1968 if ((n=old_clip_span(ctx, n, x, y, mask)) == 0) {
1969 return;
1970 }
1971 if (mask[0] == 0)
1972 write_all = GL_FALSE;
1973 }
1974
1975
1976 if (primitive==GL_BITMAP || (swrast->_RasterMask & MULTI_DRAW_BIT)
1977 || texUnits > 1) {
1978 /* must make a copy of the colors since they may be modified */
1979 MEMCPY(rgbaBackup, rgbaIn, 4 * n * sizeof(GLchan));
1980 rgba = rgbaBackup;
1981 }
1982 else {
1983 rgba = rgbaIn;
1984 }
1985
1986 /* Do the scissor test */
1987 if (ctx->Scissor.Enabled) {
1988 if ((n = _old_scissor_span( ctx, n, x, y, mask )) == 0) {
1989 return;
1990 }
1991 if (mask[0] == 0)
1992 write_all = GL_FALSE;
1993 }
1994
1995 /* Polygon Stippling */
1996 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
1997 old_stipple_polygon_span( ctx, n, x, y, mask );
1998 write_all = GL_FALSE;
1999 }
2000
2001 /* Texture with alpha test */
2002 if (ctx->Color.AlphaEnabled) {
2003 /* Texturing without alpha is done after depth-testing which
2004 * gives a potential speed-up.
2005 */
2006 ASSERT(ctx->Texture._ReallyEnabled);
2007 for (i = 0; i < texUnits; i++)
2008 _old_swrast_texture_fragments( ctx, i, n, texcoord[i], lambda[i],
2009 (CONST GLchan (*)[4]) rgbaIn, rgba );
2010
2011 /* Do the alpha test */
2012 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4])rgba, mask ) == 0) {
2013 return;
2014 }
2015 write_all = GL_FALSE;
2016 }
2017
2018 if (ctx->Stencil.Enabled) {
2019 /* first stencil test */
2020 if (_old_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
2021 return;
2022 }
2023 write_all = GL_FALSE;
2024 }
2025 else if (ctx->Depth.Test) {
2026 /* regular depth testing */
2027 GLuint m = _old_depth_test_span( ctx, n, x, y, z, mask );
2028 if (m == 0) {
2029 return;
2030 }
2031 if (m < n) {
2032 write_all = GL_FALSE;
2033 }
2034 }
2035
2036 /* if we get here, something passed the depth test */
2037 ctx->OcclusionResult = GL_TRUE;
2038
2039 /* Texture without alpha test */
2040 if (! ctx->Color.AlphaEnabled) {
2041 ASSERT(ctx->Texture._ReallyEnabled);
2042 for (i = 0; i < texUnits; i++)
2043 _old_swrast_texture_fragments( ctx, i, n, texcoord[i], lambda[i],
2044 (CONST GLchan (*)[4]) rgbaIn, rgba );
2045 }
2046
2047 /* Add base and specular colors */
2048 if (spec &&
2049 (ctx->Fog.ColorSumEnabled ||
2050 (ctx->Light.Enabled &&
2051 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)))
2052 _old_add_colors( n, rgba, spec ); /* rgba = rgba + spec */
2053
2054 /* Per-pixel fog */
2055 if (ctx->Fog.Enabled) {
2056 if (fog && !swrast->_PreferPixelFog)
2057 _old_fog_rgba_pixels( ctx, n, fog, rgba );
2058 else
2059 _old_depth_fog_rgba_pixels( ctx, n, z, rgba );
2060 }
2061
2062 /* Antialias coverage application */
2063 if (coverage) {
2064 GLuint i;
2065 for (i = 0; i < n; i++) {
2066 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
2067 }
2068 }
2069
2070 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
2071 multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask );
2072 }
2073 else {
2074 /* normal: write to exactly one buffer */
2075 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
2076
2077 if (ctx->Color.ColorLogicOpEnabled) {
2078 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
2079 }
2080 else if (ctx->Color.BlendEnabled) {
2081 _mesa_blend_span( ctx, n, x, y, rgba, mask );
2082 }
2083
2084 if (colorMask == 0x0) {
2085 return;
2086 }
2087 else if (colorMask != 0xffffffff) {
2088 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
2089 }
2090
2091 (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLchan (*)[4])rgba,
2092 write_all ? Null : mask );
2093 if (swrast->_RasterMask & ALPHABUF_BIT) {
2094 _mesa_write_alpha_span( ctx, n, x, y, (const GLchan (*)[4])rgba,
2095 write_all ? Null : mask );
2096 }
2097 }
2098 }
2099
2100
2101 /*
2102 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
2103 * reading ouside the buffer's boundaries.
2104 */
2105 void
2106 _mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
2107 GLuint n, GLint x, GLint y, GLchan rgba[][4] )
2108 {
2109 SWcontext *swrast = SWRAST_CONTEXT(ctx);
2110 if (y < 0 || y >= buffer->Height
2111 || x + (GLint) n < 0 || x >= buffer->Width) {
2112 /* completely above, below, or right */
2113 /* XXX maybe leave undefined? */
2114 BZERO(rgba, 4 * n * sizeof(GLchan));
2115 }
2116 else {
2117 GLint skip, length;
2118 if (x < 0) {
2119 /* left edge clippping */
2120 skip = -x;
2121 length = (GLint) n - skip;
2122 if (length < 0) {
2123 /* completely left of window */
2124 return;
2125 }
2126 if (length > buffer->Width) {
2127 length = buffer->Width;
2128 }
2129 }
2130 else if ((GLint) (x + n) > buffer->Width) {
2131 /* right edge clipping */
2132 skip = 0;
2133 length = buffer->Width - x;
2134 if (length < 0) {
2135 /* completely to right of window */
2136 return;
2137 }
2138 }
2139 else {
2140 /* no clipping */
2141 skip = 0;
2142 length = (GLint) n;
2143 }
2144
2145 (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
2146 if (buffer->UseSoftwareAlphaBuffers) {
2147 _mesa_read_alpha_span( ctx, length, x + skip, y, rgba + skip );
2148 }
2149 }
2150 }
2151
2152
2153
2154
2155 /*
2156 * Read CI pixels from frame buffer. Clipping will be done to prevent
2157 * reading ouside the buffer's boundaries.
2158 */
2159 void
2160 _mesa_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
2161 GLuint n, GLint x, GLint y, GLuint indx[] )
2162 {
2163 SWcontext *swrast = SWRAST_CONTEXT(ctx);
2164 if (y < 0 || y >= buffer->Height
2165 || x + (GLint) n < 0 || x >= buffer->Width) {
2166 /* completely above, below, or right */
2167 BZERO(indx, n * sizeof(GLuint));
2168 }
2169 else {
2170 GLint skip, length;
2171 if (x < 0) {
2172 /* left edge clippping */
2173 skip = -x;
2174 length = (GLint) n - skip;
2175 if (length < 0) {
2176 /* completely left of window */
2177 return;
2178 }
2179 if (length > buffer->Width) {
2180 length = buffer->Width;
2181 }
2182 }
2183 else if ((GLint) (x + n) > buffer->Width) {
2184 /* right edge clipping */
2185 skip = 0;
2186 length = buffer->Width - x;
2187 if (length < 0) {
2188 /* completely to right of window */
2189 return;
2190 }
2191 }
2192 else {
2193 /* no clipping */
2194 skip = 0;
2195 length = (GLint) n;
2196 }
2197
2198 (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
2199 }
2200 }