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