added missing \'s
[mesa.git] / src / mesa / swrast / s_span.c
1 /* $Id: s_span.c,v 1.15 2001/06/18 23:55:18 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 /*
29 * pixel span rasterization:
30 * These functions implement the rasterization pipeline.
31 */
32
33
34 #include "glheader.h"
35 #include "colormac.h"
36 #include "macros.h"
37 #include "mem.h"
38
39 #include "s_alpha.h"
40 #include "s_alphabuf.h"
41 #include "s_blend.h"
42 #include "s_context.h"
43 #include "s_depth.h"
44 #include "s_fog.h"
45 #include "s_logic.h"
46 #include "s_masking.h"
47 #include "s_scissor.h"
48 #include "s_span.h"
49 #include "s_stencil.h"
50 #include "s_texture.h"
51
52
53
54 /*
55 * Apply the current polygon stipple pattern to a span of pixels.
56 */
57 static void
58 stipple_polygon_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
59 GLubyte mask[] )
60 {
61 const GLuint highbit = 0x80000000;
62 GLuint i, m, stipple;
63
64 stipple = ctx->PolygonStipple[y % 32];
65 m = highbit >> (GLuint) (x % 32);
66
67 for (i = 0; i < n; i++) {
68 if ((m & stipple) == 0) {
69 mask[i] = 0;
70 }
71 m = m >> 1;
72 if (m == 0) {
73 m = highbit;
74 }
75 }
76 }
77
78
79
80 /*
81 * Clip a pixel span to the current buffer/window boundaries.
82 * Return: 'n' such that pixel 'n', 'n+1' etc. are clipped,
83 * as a special case:
84 * 0 = all pixels clipped
85 */
86 static GLuint
87 clip_span( GLcontext *ctx, GLint n, GLint x, GLint y, GLubyte mask[] )
88 {
89 /* Clip to top and bottom */
90 if (y < 0 || y >= ctx->DrawBuffer->Height) {
91 return 0;
92 }
93
94 /* Clip to the left */
95 if (x < 0) {
96 if (x + n <= 0) {
97 /* completely off left side */
98 return 0;
99 }
100 else {
101 /* partially off left side */
102 BZERO(mask, -x * sizeof(GLubyte));
103 }
104 }
105
106 /* Clip to right */
107 if (x + n > ctx->DrawBuffer->Width) {
108 if (x >= ctx->DrawBuffer->Width) {
109 /* completely off right side */
110 return 0;
111 }
112 else {
113 /* partially off right side */
114 return ctx->DrawBuffer->Width - x;
115 }
116 }
117
118 return n;
119 }
120
121
122
123 /*
124 * Draw to more than one color buffer (or none).
125 */
126 static void
127 multi_write_index_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
128 const GLuint indexes[], const GLubyte mask[] )
129 {
130 SWcontext *swrast = SWRAST_CONTEXT(ctx);
131 GLuint bufferBit;
132
133 if (ctx->Color.DrawBuffer == GL_NONE)
134 return;
135
136 /* loop over four possible dest color buffers */
137 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
138 if (bufferBit & ctx->Color.DrawDestMask) {
139 GLuint indexTmp[MAX_WIDTH];
140 ASSERT(n < MAX_WIDTH);
141
142 if (bufferBit == FRONT_LEFT_BIT)
143 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
144 else if (bufferBit == FRONT_RIGHT_BIT)
145 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
146 else if (bufferBit == BACK_LEFT_BIT)
147 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
148 else
149 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
150
151 /* make copy of incoming indexes */
152 MEMCPY( indexTmp, indexes, n * sizeof(GLuint) );
153 if (ctx->Color.IndexLogicOpEnabled) {
154 _mesa_logicop_ci_span( ctx, n, x, y, indexTmp, mask );
155 }
156 if (ctx->Color.IndexMask == 0) {
157 break;
158 }
159 else if (ctx->Color.IndexMask != 0xffffffff) {
160 _mesa_mask_index_span( ctx, n, x, y, indexTmp );
161 }
162 (*swrast->Driver.WriteCI32Span)( ctx, n, x, y, indexTmp, mask );
163 }
164 }
165
166 /* restore default dest buffer */
167 (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer);
168 }
169
170
171
172 /*
173 * Write a horizontal span of color index pixels to the frame buffer.
174 * Stenciling, Depth-testing, etc. are done as needed.
175 * Input: n - number of pixels in the span
176 * x, y - location of leftmost pixel in the span
177 * z - array of [n] z-values
178 * fog - array of fog factor values in [0,1]
179 * index - array of [n] color indexes
180 * primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
181 */
182 void
183 _mesa_write_index_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
184 const GLdepth z[], const GLfloat fog[],
185 GLuint indexIn[], const GLint coverage[],
186 GLenum primitive )
187 {
188 const GLuint modBits = FOG_BIT | BLEND_BIT | MASKING_BIT | LOGIC_OP_BIT;
189 GLubyte mask[MAX_WIDTH];
190 GLuint indexBackup[MAX_WIDTH];
191 GLuint *index; /* points to indexIn or indexBackup */
192 SWcontext *swrast = SWRAST_CONTEXT(ctx);
193
194 /* init mask to 1's (all pixels are to be written) */
195 MEMSET(mask, 1, n);
196
197 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
198 if ((n = clip_span(ctx,n,x,y,mask)) == 0) {
199 return;
200 }
201 }
202
203 if ((primitive==GL_BITMAP && (swrast->_RasterMask & modBits))
204 || (swrast->_RasterMask & MULTI_DRAW_BIT)) {
205 /* Make copy of color indexes */
206 MEMCPY( indexBackup, indexIn, n * sizeof(GLuint) );
207 index = indexBackup;
208 }
209 else {
210 index = indexIn;
211 }
212
213
214 /* Do the scissor test */
215 if (ctx->Scissor.Enabled) {
216 if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) {
217 return;
218 }
219 }
220
221 /* Polygon Stippling */
222 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
223 stipple_polygon_span( ctx, n, x, y, mask );
224 }
225
226 if (ctx->Stencil.Enabled) {
227 /* first stencil test */
228 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
229 return;
230 }
231 }
232 else if (ctx->Depth.Test) {
233 /* regular depth testing */
234 if (_mesa_depth_test_span( ctx, n, x, y, z, mask ) == 0)
235 return;
236 }
237
238 /* if we get here, something passed the depth test */
239 ctx->OcclusionResult = GL_TRUE;
240
241 /* Per-pixel fog */
242 if (ctx->Fog.Enabled) {
243 if (fog && !swrast->_PreferPixelFog)
244 _mesa_fog_ci_pixels( ctx, n, fog, index );
245 else
246 _mesa_depth_fog_ci_pixels( ctx, n, z, index );
247 }
248
249 /* Antialias coverage application */
250 if (coverage) {
251 GLuint i;
252 for (i = 0; i < n; i++) {
253 ASSERT(coverage[i] < 16);
254 index[i] = (index[i] & ~0xf) | coverage[i];
255 }
256 }
257
258 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
259 /* draw to zero or two or more buffers */
260 multi_write_index_span( ctx, n, x, y, index, mask );
261 }
262 else {
263 /* normal situation: draw to exactly one buffer */
264 if (ctx->Color.IndexLogicOpEnabled) {
265 _mesa_logicop_ci_span( ctx, n, x, y, index, mask );
266 }
267
268 if (ctx->Color.IndexMask == 0) {
269 return;
270 }
271 else if (ctx->Color.IndexMask != 0xffffffff) {
272 _mesa_mask_index_span( ctx, n, x, y, index );
273 }
274
275 /* write pixels */
276 (*swrast->Driver.WriteCI32Span)( ctx, n, x, y, index, mask );
277 }
278 }
279
280
281
282
283 void
284 _mesa_write_monoindex_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
285 const GLdepth z[], const GLfloat fog[],
286 GLuint index, const GLint coverage[],
287 GLenum primitive )
288 {
289 SWcontext *swrast = SWRAST_CONTEXT(ctx);
290 GLubyte mask[MAX_WIDTH];
291 GLuint i;
292
293 /* init mask to 1's (all pixels are to be written) */
294 MEMSET(mask, 1, n);
295
296 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
297 if ((n = clip_span( ctx, n, x, y, mask)) == 0) {
298 return;
299 }
300 }
301
302 /* Do the scissor test */
303 if (ctx->Scissor.Enabled) {
304 if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) {
305 return;
306 }
307 }
308
309 /* Polygon Stippling */
310 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
311 stipple_polygon_span( ctx, n, x, y, mask );
312 }
313
314 if (ctx->Stencil.Enabled) {
315 /* first stencil test */
316 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
317 return;
318 }
319 }
320 else if (ctx->Depth.Test) {
321 /* regular depth testing */
322 if (_mesa_depth_test_span( ctx, n, x, y, z, mask ) == 0)
323 return;
324 }
325
326 /* if we get here, something passed the depth test */
327 ctx->OcclusionResult = GL_TRUE;
328
329 if (ctx->Color.DrawBuffer == GL_NONE) {
330 /* write no pixels */
331 return;
332 }
333
334 if (ctx->Fog.Enabled
335 || ctx->Color.IndexLogicOpEnabled
336 || ctx->Color.IndexMask != 0xffffffff
337 || coverage) {
338 /* different index per pixel */
339 GLuint indexes[MAX_WIDTH];
340 for (i = 0; i < n; i++) {
341 indexes[i] = index;
342 }
343
344 if (ctx->Fog.Enabled) {
345 if (fog && !swrast->_PreferPixelFog)
346 _mesa_fog_ci_pixels( ctx, n, fog, indexes );
347 else
348 _mesa_depth_fog_ci_pixels( ctx, n, z, indexes );
349 }
350
351 /* Antialias coverage application */
352 if (coverage) {
353 GLuint i;
354 for (i = 0; i < n; i++) {
355 ASSERT(coverage[i] < 16);
356 indexes[i] = (indexes[i] & ~0xf) | coverage[i];
357 }
358 }
359
360 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
361 /* draw to zero or two or more buffers */
362 multi_write_index_span( ctx, n, x, y, indexes, mask );
363 }
364 else {
365 /* normal situation: draw to exactly one buffer */
366 if (ctx->Color.IndexLogicOpEnabled) {
367 _mesa_logicop_ci_span( ctx, n, x, y, indexes, mask );
368 }
369 if (ctx->Color.IndexMask == 0) {
370 return;
371 }
372 else if (ctx->Color.IndexMask != 0xffffffff) {
373 _mesa_mask_index_span( ctx, n, x, y, indexes );
374 }
375 (*swrast->Driver.WriteCI32Span)( ctx, n, x, y, indexes, mask );
376 }
377 }
378 else {
379 /* same color index for all pixels */
380 ASSERT(!ctx->Color.IndexLogicOpEnabled);
381 ASSERT(ctx->Color.IndexMask == 0xffffffff);
382 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
383 /* draw to zero or two or more buffers */
384 GLuint indexes[MAX_WIDTH];
385 for (i = 0; i < n; i++)
386 indexes[i] = index;
387 multi_write_index_span( ctx, n, x, y, indexes, mask );
388 }
389 else {
390 /* normal situation: draw to exactly one buffer */
391 (*swrast->Driver.WriteMonoCISpan)( ctx, n, x, y, index, mask );
392 }
393 }
394 }
395
396
397
398 /*
399 * Draw to more than one RGBA color buffer (or none).
400 */
401 static void
402 multi_write_rgba_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
403 CONST GLchan rgba[][4], const GLubyte mask[] )
404 {
405 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
406 GLuint bufferBit;
407 SWcontext *swrast = SWRAST_CONTEXT(ctx);
408
409 if (ctx->Color.DrawBuffer == GL_NONE)
410 return;
411
412 /* loop over four possible dest color buffers */
413 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
414 if (bufferBit & ctx->Color.DrawDestMask) {
415 GLchan rgbaTmp[MAX_WIDTH][4];
416 ASSERT(n < MAX_WIDTH);
417
418 if (bufferBit == FRONT_LEFT_BIT) {
419 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
420 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha;
421 }
422 else if (bufferBit == FRONT_RIGHT_BIT) {
423 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
424 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha;
425 }
426 else if (bufferBit == BACK_LEFT_BIT) {
427 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
428 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha;
429 }
430 else {
431 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
432 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha;
433 }
434
435 /* make copy of incoming colors */
436 MEMCPY( rgbaTmp, rgba, 4 * n * sizeof(GLchan) );
437
438 if (ctx->Color.ColorLogicOpEnabled) {
439 _mesa_logicop_rgba_span( ctx, n, x, y, rgbaTmp, mask );
440 }
441 else if (ctx->Color.BlendEnabled) {
442 _mesa_blend_span( ctx, n, x, y, rgbaTmp, mask );
443 }
444 if (colorMask == 0x0) {
445 break;
446 }
447 else if (colorMask != 0xffffffff) {
448 _mesa_mask_rgba_span( ctx, n, x, y, rgbaTmp );
449 }
450
451 (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y,
452 (const GLchan (*)[4]) rgbaTmp, mask );
453 if (swrast->_RasterMask & ALPHABUF_BIT) {
454 _mesa_write_alpha_span( ctx, n, x, y,
455 (const GLchan (*)[4])rgbaTmp, mask );
456 }
457 }
458 }
459
460 /* restore default dest buffer */
461 (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer );
462 }
463
464
465
466 void
467 _mesa_write_rgba_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
468 const GLdepth z[], const GLfloat fog[],
469 GLchan rgbaIn[][4], const GLfloat coverage[],
470 GLenum primitive )
471 {
472 const GLuint modBits = FOG_BIT | BLEND_BIT | MASKING_BIT |
473 LOGIC_OP_BIT | TEXTURE_BIT;
474 GLubyte mask[MAX_WIDTH];
475 GLboolean write_all = GL_TRUE;
476 GLchan rgbaBackup[MAX_WIDTH][4];
477 GLchan (*rgba)[4];
478 const GLubyte *Null = 0;
479 SWcontext *swrast = SWRAST_CONTEXT(ctx);
480
481 /* init mask to 1's (all pixels are to be written) */
482 MEMSET(mask, 1, n);
483
484 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
485 if ((n = clip_span( ctx,n,x,y,mask)) == 0) {
486 return;
487 }
488 if (mask[0] == 0)
489 write_all = GL_FALSE;
490 }
491
492 if ((primitive==GL_BITMAP && (swrast->_RasterMask & modBits))
493 || (swrast->_RasterMask & MULTI_DRAW_BIT)) {
494 /* must make a copy of the colors since they may be modified */
495 MEMCPY( rgbaBackup, rgbaIn, 4 * n * sizeof(GLchan) );
496 rgba = rgbaBackup;
497 }
498 else {
499 rgba = rgbaIn;
500 }
501
502 /* Do the scissor test */
503 if (ctx->Scissor.Enabled) {
504 if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) {
505 return;
506 }
507 if (mask[0] == 0)
508 write_all = GL_FALSE;
509 }
510
511 /* Polygon Stippling */
512 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
513 stipple_polygon_span( ctx, n, x, y, mask );
514 write_all = GL_FALSE;
515 }
516
517 /* Do the alpha test */
518 if (ctx->Color.AlphaEnabled) {
519 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4]) rgba, mask ) == 0) {
520 return;
521 }
522 write_all = GL_FALSE;
523 }
524
525 if (ctx->Stencil.Enabled) {
526 /* first stencil test */
527 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
528 return;
529 }
530 write_all = GL_FALSE;
531 }
532 else if (ctx->Depth.Test) {
533 /* regular depth testing */
534 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
535 if (m == 0) {
536 return;
537 }
538 if (m < n) {
539 write_all = GL_FALSE;
540 }
541 }
542
543 /* if we get here, something passed the depth test */
544 ctx->OcclusionResult = GL_TRUE;
545
546 /* Per-pixel fog */
547 if (ctx->Fog.Enabled) {
548 if (fog && !swrast->_PreferPixelFog)
549 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
550 else
551 _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba );
552 }
553
554 /* Antialias coverage application */
555 if (coverage) {
556 GLuint i;
557 for (i = 0; i < n; i++) {
558 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
559 }
560 }
561
562 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
563 multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask );
564 }
565 else {
566 /* normal: write to exactly one buffer */
567 /* logic op or blending */
568 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
569
570 if (ctx->Color.ColorLogicOpEnabled) {
571 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
572 }
573 else if (ctx->Color.BlendEnabled) {
574 _mesa_blend_span( ctx, n, x, y, rgba, mask );
575 }
576
577 /* Color component masking */
578 if (colorMask == 0x0) {
579 return;
580 }
581 else if (colorMask != 0xffffffff) {
582 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
583 }
584
585 /* write pixels */
586 (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y,
587 (const GLchan (*)[4]) rgba,
588 write_all ? Null : mask );
589
590 if (swrast->_RasterMask & ALPHABUF_BIT) {
591 _mesa_write_alpha_span( ctx, n, x, y,
592 (const GLchan (*)[4]) rgba,
593 write_all ? Null : mask );
594 }
595 }
596 }
597
598
599
600 /*
601 * Write a horizontal span of color pixels to the frame buffer.
602 * The color is initially constant for the whole span.
603 * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
604 * Input: n - number of pixels in the span
605 * x, y - location of leftmost pixel in the span
606 * z - array of [n] z-values
607 * fog - array of fog factor values in [0,1]
608 * r, g, b, a - the color of the pixels
609 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
610 */
611 void
612 _mesa_write_monocolor_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
613 const GLdepth z[], const GLfloat fog[],
614 const GLchan color[4], const GLfloat coverage[],
615 GLenum primitive )
616 {
617 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
618 GLuint i;
619 GLubyte mask[MAX_WIDTH];
620 GLboolean write_all = GL_TRUE;
621 GLchan rgba[MAX_WIDTH][4];
622 const GLubyte *Null = 0;
623 SWcontext *swrast = SWRAST_CONTEXT(ctx);
624
625 /* init mask to 1's (all pixels are to be written) */
626 MEMSET(mask, 1, n);
627
628 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
629 if ((n = clip_span( ctx,n,x,y,mask)) == 0) {
630 return;
631 }
632 if (mask[0] == 0)
633 write_all = GL_FALSE;
634 }
635
636 /* Do the scissor test */
637 if (ctx->Scissor.Enabled) {
638 if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) {
639 return;
640 }
641 if (mask[0] == 0)
642 write_all = GL_FALSE;
643 }
644
645 /* Polygon Stippling */
646 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
647 stipple_polygon_span( ctx, n, x, y, mask );
648 write_all = GL_FALSE;
649 }
650
651 /* Do the alpha test */
652 if (ctx->Color.AlphaEnabled) {
653 for (i = 0; i < n; i++) {
654 rgba[i][ACOMP] = color[ACOMP];
655 }
656 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4])rgba, mask ) == 0) {
657 return;
658 }
659 write_all = GL_FALSE;
660 }
661
662 if (ctx->Stencil.Enabled) {
663 /* first stencil test */
664 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
665 return;
666 }
667 write_all = GL_FALSE;
668 }
669 else if (ctx->Depth.Test) {
670 /* regular depth testing */
671 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
672 if (m == 0) {
673 return;
674 }
675 if (m < n) {
676 write_all = GL_FALSE;
677 }
678 }
679
680 /* if we get here, something passed the depth test */
681 ctx->OcclusionResult = GL_TRUE;
682
683 if (ctx->Color.DrawBuffer == GL_NONE) {
684 /* write no pixels */
685 return;
686 }
687
688 if (ctx->Color.ColorLogicOpEnabled || colorMask != 0xffffffff ||
689 (swrast->_RasterMask & (BLEND_BIT | FOG_BIT)) || coverage) {
690 /* assign same color to each pixel */
691 for (i = 0; i < n; i++) {
692 if (mask[i]) {
693 COPY_CHAN4(rgba[i], color);
694 }
695 }
696
697 /* Per-pixel fog */
698 if (ctx->Fog.Enabled) {
699 if (fog && !swrast->_PreferPixelFog)
700 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
701 else
702 _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba );
703 }
704
705 /* Antialias coverage application */
706 if (coverage) {
707 GLuint i;
708 for (i = 0; i < n; i++) {
709 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
710 }
711 }
712
713 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
714 multi_write_rgba_span( ctx, n, x, y,
715 (const GLchan (*)[4]) rgba, mask );
716 }
717 else {
718 /* normal: write to exactly one buffer */
719 if (ctx->Color.ColorLogicOpEnabled) {
720 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
721 }
722 else if (ctx->Color.BlendEnabled) {
723 _mesa_blend_span( ctx, n, x, y, rgba, mask );
724 }
725
726 /* Color component masking */
727 if (colorMask == 0x0) {
728 return;
729 }
730 else if (colorMask != 0xffffffff) {
731 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
732 }
733
734 /* write pixels */
735 (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y,
736 (const GLchan (*)[4]) rgba,
737 write_all ? Null : mask );
738 if (swrast->_RasterMask & ALPHABUF_BIT) {
739 _mesa_write_alpha_span( ctx, n, x, y,
740 (const GLchan (*)[4]) rgba,
741 write_all ? Null : mask );
742 }
743 }
744 }
745 else {
746 /* same color for all pixels */
747 ASSERT(!ctx->Color.BlendEnabled);
748 ASSERT(!ctx->Color.ColorLogicOpEnabled);
749
750 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
751 for (i = 0; i < n; i++) {
752 if (mask[i]) {
753 COPY_CHAN4(rgba[i], color);
754 }
755 }
756 multi_write_rgba_span( ctx, n, x, y,
757 (const GLchan (*)[4]) rgba, mask );
758 }
759 else {
760 (*swrast->Driver.WriteMonoRGBASpan)( ctx, n, x, y, color, mask );
761 if (swrast->_RasterMask & ALPHABUF_BIT) {
762 _mesa_write_mono_alpha_span( ctx, n, x, y, (GLchan) color[ACOMP],
763 write_all ? Null : mask );
764 }
765 }
766 }
767 }
768
769
770
771 /*
772 * Add specular color to base color. This is used only when
773 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
774 */
775 static void
776 add_colors(GLuint n, GLchan rgba[][4], CONST GLchan specular[][4] )
777 {
778 GLuint i;
779 for (i = 0; i < n; i++) {
780 GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
781 GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
782 GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
783 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
784 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
785 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
786 }
787 }
788
789
790 /*
791 * Write a horizontal span of textured pixels to the frame buffer.
792 * The color of each pixel is different.
793 * Alpha-testing, stenciling, depth-testing, and blending are done
794 * as needed.
795 * Input: n - number of pixels in the span
796 * x, y - location of leftmost pixel in the span
797 * z - array of [n] z-values
798 * s, t - array of (s,t) texture coordinates for each pixel
799 * lambda - array of texture lambda values
800 * rgba - array of [n] color components
801 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
802 */
803 void
804 _mesa_write_texture_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
805 const GLdepth z[], const GLfloat fog[],
806 const GLfloat s[], const GLfloat t[],
807 const GLfloat u[], GLfloat lambda[],
808 GLchan rgbaIn[][4], CONST GLchan spec[][4],
809 const GLfloat coverage[], GLenum primitive )
810 {
811 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
812 GLubyte mask[MAX_WIDTH];
813 GLboolean write_all = GL_TRUE;
814 GLchan rgbaBackup[MAX_WIDTH][4];
815 GLchan (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */
816 const GLubyte *Null = 0;
817 SWcontext *swrast = SWRAST_CONTEXT(ctx);
818
819 /* init mask to 1's (all pixels are to be written) */
820 MEMSET(mask, 1, n);
821
822 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
823 if ((n=clip_span(ctx, n, x, y, mask)) == 0) {
824 return;
825 }
826 if (mask[0] == 0)
827 write_all = GL_FALSE;
828 }
829
830
831 if (primitive==GL_BITMAP || (swrast->_RasterMask & MULTI_DRAW_BIT)) {
832 /* must make a copy of the colors since they may be modified */
833 MEMCPY(rgbaBackup, rgbaIn, 4 * n * sizeof(GLchan));
834 rgba = rgbaBackup;
835 }
836 else {
837 rgba = rgbaIn;
838 }
839
840 /* Do the scissor test */
841 if (ctx->Scissor.Enabled) {
842 if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) {
843 return;
844 }
845 if (mask[0] == 0)
846 write_all = GL_FALSE;
847 }
848
849 /* Polygon Stippling */
850 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
851 stipple_polygon_span( ctx, n, x, y, mask );
852 write_all = GL_FALSE;
853 }
854
855 /* Texture with alpha test*/
856 if (ctx->Color.AlphaEnabled) {
857 /* Texturing without alpha is done after depth-testing which
858 gives a potential speed-up. */
859 ASSERT(ctx->Texture._ReallyEnabled);
860 _swrast_texture_fragments( ctx, 0, n, s, t, u, lambda,
861 (CONST GLchan (*)[4]) rgba, rgba );
862
863 /* Do the alpha test */
864 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4]) rgba, mask ) == 0) {
865 return;
866 }
867 write_all = GL_FALSE;
868 }
869
870 if (ctx->Stencil.Enabled) {
871 /* first stencil test */
872 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
873 return;
874 }
875 write_all = GL_FALSE;
876 }
877 else if (ctx->Depth.Test) {
878 /* regular depth testing */
879 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
880 if (m == 0) {
881 return;
882 }
883 if (m < n) {
884 write_all = GL_FALSE;
885 }
886 }
887
888 /* if we get here, something passed the depth test */
889 ctx->OcclusionResult = GL_TRUE;
890
891 /* Texture without alpha test */
892 if (! ctx->Color.AlphaEnabled) {
893 ASSERT(ctx->Texture._ReallyEnabled);
894 _swrast_texture_fragments( ctx, 0, n, s, t, u, lambda,
895 (CONST GLchan (*)[4]) rgba, rgba );
896 }
897
898 /* Add base and specular colors */
899 if (spec &&
900 (ctx->Fog.ColorSumEnabled ||
901 (ctx->Light.Enabled &&
902 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)))
903 add_colors( n, rgba, spec ); /* rgba = rgba + spec */
904
905 /* Per-pixel fog */
906 if (ctx->Fog.Enabled) {
907 if (fog && !swrast->_PreferPixelFog)
908 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
909 else
910 _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba );
911 }
912
913 /* Antialias coverage application */
914 if (coverage) {
915 GLuint i;
916 for (i = 0; i < n; i++) {
917 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
918 }
919 }
920
921 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
922 multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask );
923 }
924 else {
925 /* normal: write to exactly one buffer */
926 if (ctx->Color.ColorLogicOpEnabled) {
927 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
928 }
929 else if (ctx->Color.BlendEnabled) {
930 _mesa_blend_span( ctx, n, x, y, rgba, mask );
931 }
932 if (colorMask == 0x0) {
933 return;
934 }
935 else if (colorMask != 0xffffffff) {
936 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
937 }
938
939 (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLchan (*)[4])rgba,
940 write_all ? Null : mask );
941 if (swrast->_RasterMask & ALPHABUF_BIT) {
942 _mesa_write_alpha_span( ctx, n, x, y, (const GLchan (*)[4]) rgba,
943 write_all ? Null : mask );
944 }
945 }
946 }
947
948
949
950 /*
951 * As above but perform multiple stages of texture application.
952 */
953 void
954 _mesa_write_multitexture_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
955 const GLdepth z[], const GLfloat fog[],
956 CONST GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH],
957 CONST GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH],
958 CONST GLfloat u[MAX_TEXTURE_UNITS][MAX_WIDTH],
959 GLfloat lambda[][MAX_WIDTH],
960 GLchan rgbaIn[MAX_TEXTURE_UNITS][4],
961 CONST GLchan spec[MAX_TEXTURE_UNITS][4],
962 const GLfloat coverage[],
963 GLenum primitive )
964 {
965 GLubyte mask[MAX_WIDTH];
966 GLboolean write_all = GL_TRUE;
967 GLchan rgbaBackup[MAX_WIDTH][4];
968 GLchan (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */
969 GLuint i;
970 const GLubyte *Null = 0;
971 const GLuint texUnits = ctx->Const.MaxTextureUnits;
972 SWcontext *swrast = SWRAST_CONTEXT(ctx);
973
974 /* init mask to 1's (all pixels are to be written) */
975 MEMSET(mask, 1, n);
976
977 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
978 if ((n=clip_span(ctx, n, x, y, mask)) == 0) {
979 return;
980 }
981 if (mask[0] == 0)
982 write_all = GL_FALSE;
983 }
984
985
986 if (primitive==GL_BITMAP || (swrast->_RasterMask & MULTI_DRAW_BIT)
987 || texUnits > 1) {
988 /* must make a copy of the colors since they may be modified */
989 MEMCPY(rgbaBackup, rgbaIn, 4 * n * sizeof(GLchan));
990 rgba = rgbaBackup;
991 }
992 else {
993 rgba = rgbaIn;
994 }
995
996 /* Do the scissor test */
997 if (ctx->Scissor.Enabled) {
998 if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) {
999 return;
1000 }
1001 if (mask[0] == 0)
1002 write_all = GL_FALSE;
1003 }
1004
1005 /* Polygon Stippling */
1006 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
1007 stipple_polygon_span( ctx, n, x, y, mask );
1008 write_all = GL_FALSE;
1009 }
1010
1011 /* Texture with alpha test*/
1012 if (ctx->Color.AlphaEnabled) {
1013 /* Texturing without alpha is done after depth-testing which
1014 * gives a potential speed-up.
1015 */
1016 ASSERT(ctx->Texture._ReallyEnabled);
1017 for (i = 0; i < texUnits; i++)
1018 _swrast_texture_fragments( ctx, i, n, s[i], t[i], u[i], lambda[i],
1019 (CONST GLchan (*)[4]) rgbaIn, rgba );
1020
1021 /* Do the alpha test */
1022 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4])rgba, mask ) == 0) {
1023 return;
1024 }
1025 write_all = GL_FALSE;
1026 }
1027
1028 if (ctx->Stencil.Enabled) {
1029 /* first stencil test */
1030 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
1031 return;
1032 }
1033 write_all = GL_FALSE;
1034 }
1035 else if (ctx->Depth.Test) {
1036 /* regular depth testing */
1037 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
1038 if (m == 0) {
1039 return;
1040 }
1041 if (m < n) {
1042 write_all = GL_FALSE;
1043 }
1044 }
1045
1046 /* if we get here, something passed the depth test */
1047 ctx->OcclusionResult = GL_TRUE;
1048
1049 /* Texture without alpha test */
1050 if (! ctx->Color.AlphaEnabled) {
1051 ASSERT(ctx->Texture._ReallyEnabled);
1052 for (i = 0; i < texUnits; i++)
1053 _swrast_texture_fragments( ctx, i, n, s[i], t[i], u[i], lambda[i],
1054 (CONST GLchan (*)[4]) rgbaIn, rgba );
1055 }
1056
1057 /* Add base and specular colors */
1058 if (spec &&
1059 (ctx->Fog.ColorSumEnabled ||
1060 (ctx->Light.Enabled &&
1061 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)))
1062 add_colors( n, rgba, spec ); /* rgba = rgba + spec */
1063
1064 /* Per-pixel fog */
1065 if (ctx->Fog.Enabled) {
1066 if (fog && !swrast->_PreferPixelFog)
1067 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
1068 else
1069 _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba );
1070 }
1071
1072 /* Antialias coverage application */
1073 if (coverage) {
1074 GLuint i;
1075 for (i = 0; i < n; i++) {
1076 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
1077 }
1078 }
1079
1080 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1081 multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask );
1082 }
1083 else {
1084 /* normal: write to exactly one buffer */
1085 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1086
1087 if (ctx->Color.ColorLogicOpEnabled) {
1088 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
1089 }
1090 else if (ctx->Color.BlendEnabled) {
1091 _mesa_blend_span( ctx, n, x, y, rgba, mask );
1092 }
1093
1094 if (colorMask == 0x0) {
1095 return;
1096 }
1097 else if (colorMask != 0xffffffff) {
1098 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
1099 }
1100
1101 (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLchan (*)[4])rgba,
1102 write_all ? Null : mask );
1103 if (swrast->_RasterMask & ALPHABUF_BIT) {
1104 _mesa_write_alpha_span( ctx, n, x, y, (const GLchan (*)[4])rgba,
1105 write_all ? Null : mask );
1106 }
1107 }
1108 }
1109
1110
1111
1112 /*
1113 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1114 * reading ouside the buffer's boundaries.
1115 */
1116 void
1117 _mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
1118 GLuint n, GLint x, GLint y, GLchan rgba[][4] )
1119 {
1120 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1121 if (y < 0 || y >= buffer->Height
1122 || x + (GLint) n < 0 || x >= buffer->Width) {
1123 /* completely above, below, or right */
1124 /* XXX maybe leave undefined? */
1125 BZERO(rgba, 4 * n * sizeof(GLchan));
1126 }
1127 else {
1128 GLint skip, length;
1129 if (x < 0) {
1130 /* left edge clippping */
1131 skip = -x;
1132 length = (GLint) n - skip;
1133 if (length < 0) {
1134 /* completely left of window */
1135 return;
1136 }
1137 if (length > buffer->Width) {
1138 length = buffer->Width;
1139 }
1140 }
1141 else if ((GLint) (x + n) > buffer->Width) {
1142 /* right edge clipping */
1143 skip = 0;
1144 length = buffer->Width - x;
1145 if (length < 0) {
1146 /* completely to right of window */
1147 return;
1148 }
1149 }
1150 else {
1151 /* no clipping */
1152 skip = 0;
1153 length = (GLint) n;
1154 }
1155
1156 (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
1157 if (buffer->UseSoftwareAlphaBuffers) {
1158 _mesa_read_alpha_span( ctx, length, x + skip, y, rgba + skip );
1159 }
1160 }
1161 }
1162
1163
1164
1165
1166 /*
1167 * Read CI pixels from frame buffer. Clipping will be done to prevent
1168 * reading ouside the buffer's boundaries.
1169 */
1170 void
1171 _mesa_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
1172 GLuint n, GLint x, GLint y, GLuint indx[] )
1173 {
1174 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1175 if (y < 0 || y >= buffer->Height
1176 || x + (GLint) n < 0 || x >= buffer->Width) {
1177 /* completely above, below, or right */
1178 BZERO(indx, n * sizeof(GLuint));
1179 }
1180 else {
1181 GLint skip, length;
1182 if (x < 0) {
1183 /* left edge clippping */
1184 skip = -x;
1185 length = (GLint) n - skip;
1186 if (length < 0) {
1187 /* completely left of window */
1188 return;
1189 }
1190 if (length > buffer->Width) {
1191 length = buffer->Width;
1192 }
1193 }
1194 else if ((GLint) (x + n) > buffer->Width) {
1195 /* right edge clipping */
1196 skip = 0;
1197 length = buffer->Width - x;
1198 if (length < 0) {
1199 /* completely to right of window */
1200 return;
1201 }
1202 }
1203 else {
1204 /* no clipping */
1205 skip = 0;
1206 length = (GLint) n;
1207 }
1208
1209 (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
1210 }
1211 }