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