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