added dispatch override mechanism, used by trace extension
[mesa.git] / src / mesa / swrast / s_span.c
1 /* $Id: s_span.c,v 1.6 2001/01/05 21:28:31 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 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 MEMSET(mask, 0, -x);
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 gl_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 (gl_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 gl_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 (gl_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 (ctx->Color.IndexLogicOpEnabled) {
339 _mesa_logicop_ci_span( ctx, n, x, y, indexes, mask );
340 }
341
342 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
343 /* draw to zero or two or more buffers */
344 multi_write_index_span( ctx, n, x, y, indexes, mask );
345 }
346 else {
347 /* normal situation: draw to exactly one buffer */
348 if (ctx->Color.IndexLogicOpEnabled) {
349 _mesa_logicop_ci_span( ctx, n, x, y, indexes, mask );
350 }
351 if (ctx->Color.IndexMask == 0) {
352 return;
353 }
354 else if (ctx->Color.IndexMask != 0xffffffff) {
355 _mesa_mask_index_span( ctx, n, x, y, indexes );
356 }
357 (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, indexes, mask );
358 }
359 }
360 else {
361 /* same color index for all pixels */
362 ASSERT(!ctx->Color.IndexLogicOpEnabled);
363 ASSERT(ctx->Color.IndexMask == 0xffffffff);
364 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
365 /* draw to zero or two or more buffers */
366 GLuint indexes[MAX_WIDTH];
367 for (i = 0; i < n; i++)
368 indexes[i] = index;
369 multi_write_index_span( ctx, n, x, y, indexes, mask );
370 }
371 else {
372 /* normal situation: draw to exactly one buffer */
373 (*ctx->Driver.WriteMonoCISpan)( ctx, n, x, y, index, mask );
374 }
375 }
376 }
377
378
379
380 /*
381 * Draw to more than one RGBA color buffer (or none).
382 */
383 static void multi_write_rgba_span( GLcontext *ctx, GLuint n,
384 GLint x, GLint y, CONST GLchan rgba[][4],
385 const GLubyte mask[] )
386 {
387 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
388 GLuint bufferBit;
389 SWcontext *swrast = SWRAST_CONTEXT(ctx);
390
391 if (ctx->Color.DrawBuffer == GL_NONE)
392 return;
393
394 /* loop over four possible dest color buffers */
395 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
396 if (bufferBit & ctx->Color.DrawDestMask) {
397 GLchan rgbaTmp[MAX_WIDTH][4];
398 ASSERT(n < MAX_WIDTH);
399
400 if (bufferBit == FRONT_LEFT_BIT) {
401 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
402 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha;
403 }
404 else if (bufferBit == FRONT_RIGHT_BIT) {
405 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
406 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha;
407 }
408 else if (bufferBit == BACK_LEFT_BIT) {
409 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
410 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha;
411 }
412 else {
413 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
414 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha;
415 }
416
417 /* make copy of incoming colors */
418 MEMCPY( rgbaTmp, rgba, 4 * n * sizeof(GLchan) );
419
420 if (ctx->Color.ColorLogicOpEnabled) {
421 _mesa_logicop_rgba_span( ctx, n, x, y, rgbaTmp, mask );
422 }
423 else if (ctx->Color.BlendEnabled) {
424 _mesa_blend_span( ctx, n, x, y, rgbaTmp, mask );
425 }
426 if (colorMask == 0x0) {
427 break;
428 }
429 else if (colorMask != 0xffffffff) {
430 _mesa_mask_rgba_span( ctx, n, x, y, rgbaTmp );
431 }
432
433 (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y,
434 (const GLchan (*)[4]) rgbaTmp, mask );
435 if (swrast->_RasterMask & ALPHABUF_BIT) {
436 _mesa_write_alpha_span( ctx, n, x, y,
437 (const GLchan (*)[4])rgbaTmp, mask );
438 }
439 }
440 }
441
442 /* restore default dest buffer */
443 (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer );
444 }
445
446
447
448 void gl_write_rgba_span( GLcontext *ctx,
449 GLuint n, GLint x, GLint y, const GLdepth z[],
450 const GLfixed *fog,
451 GLchan rgbaIn[][4],
452 GLenum primitive )
453 {
454 const GLuint modBits = FOG_BIT | BLEND_BIT | MASKING_BIT |
455 LOGIC_OP_BIT | TEXTURE_BIT;
456 GLubyte mask[MAX_WIDTH];
457 GLboolean write_all = GL_TRUE;
458 GLchan rgbaBackup[MAX_WIDTH][4];
459 GLchan (*rgba)[4];
460 const GLubyte *Null = 0;
461 SWcontext *swrast = SWRAST_CONTEXT(ctx);
462
463 /* init mask to 1's (all pixels are to be written) */
464 MEMSET(mask, 1, n);
465
466 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
467 if ((n = clip_span( ctx,n,x,y,mask)) == 0) {
468 return;
469 }
470 if (mask[0] == 0)
471 write_all = GL_FALSE;
472 }
473
474 if ((primitive==GL_BITMAP && (swrast->_RasterMask & modBits))
475 || (swrast->_RasterMask & MULTI_DRAW_BIT)) {
476 /* must make a copy of the colors since they may be modified */
477 MEMCPY( rgbaBackup, rgbaIn, 4 * n * sizeof(GLchan) );
478 rgba = rgbaBackup;
479 }
480 else {
481 rgba = rgbaIn;
482 }
483
484 /* Do the scissor test */
485 if (ctx->Scissor.Enabled) {
486 if (gl_scissor_span( ctx, n, x, y, mask ) == 0) {
487 return;
488 }
489 write_all = GL_FALSE;
490 }
491
492 /* Polygon Stippling */
493 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
494 stipple_polygon_span( ctx, n, x, y, mask );
495 write_all = GL_FALSE;
496 }
497
498 /* Do the alpha test */
499 if (ctx->Color.AlphaEnabled) {
500 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4]) rgba, mask ) == 0) {
501 return;
502 }
503 write_all = GL_FALSE;
504 }
505
506 if (ctx->Stencil.Enabled) {
507 /* first stencil test */
508 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
509 return;
510 }
511 write_all = GL_FALSE;
512 }
513 else if (ctx->Depth.Test) {
514 /* regular depth testing */
515 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
516 if (m == 0) {
517 return;
518 }
519 if (m < n) {
520 write_all = GL_FALSE;
521 }
522 }
523
524 /* if we get here, something passed the depth test */
525 ctx->OcclusionResult = GL_TRUE;
526
527 /* Per-pixel fog */
528 if (ctx->Fog.Enabled) {
529 if (fog && !swrast->_PreferPixelFog)
530 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
531 else
532 _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba );
533 }
534
535 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
536 multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask );
537 }
538 else {
539 /* normal: write to exactly one buffer */
540 /* logic op or blending */
541 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
542
543 if (ctx->Color.ColorLogicOpEnabled) {
544 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
545 }
546 else if (ctx->Color.BlendEnabled) {
547 _mesa_blend_span( ctx, n, x, y, rgba, mask );
548 }
549
550 /* Color component masking */
551 if (colorMask == 0x0) {
552 return;
553 }
554 else if (colorMask != 0xffffffff) {
555 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
556 }
557
558 /* write pixels */
559 (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y,
560 (const GLchan (*)[4]) rgba,
561 write_all ? Null : mask );
562
563 if (swrast->_RasterMask & ALPHABUF_BIT) {
564 _mesa_write_alpha_span( ctx, n, x, y,
565 (const GLchan (*)[4]) rgba,
566 write_all ? Null : mask );
567 }
568 }
569 }
570
571
572
573 /*
574 * Write a horizontal span of color pixels to the frame buffer.
575 * The color is initially constant for the whole span.
576 * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
577 * Input: n - number of pixels in the span
578 * x, y - location of leftmost pixel in the span
579 * z - array of [n] z-values
580 * r, g, b, a - the color of the pixels
581 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
582 */
583 void gl_write_monocolor_span( GLcontext *ctx,
584 GLuint n, GLint x, GLint y, const GLdepth z[],
585 const GLfixed fog[],
586 const GLchan color[4],
587 GLenum primitive )
588 {
589 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
590 GLuint i;
591 GLubyte mask[MAX_WIDTH];
592 GLboolean write_all = GL_TRUE;
593 GLchan rgba[MAX_WIDTH][4];
594 const GLubyte *Null = 0;
595 SWcontext *swrast = SWRAST_CONTEXT(ctx);
596
597 /* init mask to 1's (all pixels are to be written) */
598 MEMSET(mask, 1, n);
599
600 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
601 if ((n = clip_span( ctx,n,x,y,mask)) == 0) {
602 return;
603 }
604 if (mask[0] == 0)
605 write_all = GL_FALSE;
606 }
607
608 /* Do the scissor test */
609 if (ctx->Scissor.Enabled) {
610 if (gl_scissor_span( ctx, n, x, y, mask ) == 0) {
611 return;
612 }
613 write_all = GL_FALSE;
614 }
615
616 /* Polygon Stippling */
617 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
618 stipple_polygon_span( ctx, n, x, y, mask );
619 write_all = GL_FALSE;
620 }
621
622 /* Do the alpha test */
623 if (ctx->Color.AlphaEnabled) {
624 for (i = 0; i < n; i++) {
625 rgba[i][ACOMP] = color[ACOMP];
626 }
627 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4])rgba, mask ) == 0) {
628 return;
629 }
630 write_all = GL_FALSE;
631 }
632
633 if (ctx->Stencil.Enabled) {
634 /* first stencil test */
635 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
636 return;
637 }
638 write_all = GL_FALSE;
639 }
640 else if (ctx->Depth.Test) {
641 /* regular depth testing */
642 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
643 if (m == 0) {
644 return;
645 }
646 if (m < n) {
647 write_all = GL_FALSE;
648 }
649 }
650
651 /* if we get here, something passed the depth test */
652 ctx->OcclusionResult = GL_TRUE;
653
654 if (ctx->Color.DrawBuffer == GL_NONE) {
655 /* write no pixels */
656 return;
657 }
658
659 if (ctx->Color.ColorLogicOpEnabled || colorMask != 0xffffffff ||
660 (swrast->_RasterMask & (BLEND_BIT | FOG_BIT))) {
661 /* assign same color to each pixel */
662 for (i = 0; i < n; i++) {
663 if (mask[i]) {
664 COPY_CHAN4(rgba[i], color);
665 }
666 }
667
668 /* Per-pixel fog */
669 if (ctx->Fog.Enabled) {
670 if (fog && !swrast->_PreferPixelFog)
671 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
672 else
673 _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba );
674 }
675
676 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
677 multi_write_rgba_span( ctx, n, x, y,
678 (const GLchan (*)[4]) rgba, mask );
679 }
680 else {
681 /* normal: write to exactly one buffer */
682 if (ctx->Color.ColorLogicOpEnabled) {
683 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
684 }
685 else if (ctx->Color.BlendEnabled) {
686 _mesa_blend_span( ctx, n, x, y, rgba, mask );
687 }
688
689 /* Color component masking */
690 if (colorMask == 0x0) {
691 return;
692 }
693 else if (colorMask != 0xffffffff) {
694 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
695 }
696
697 /* write pixels */
698 (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y,
699 (const GLchan (*)[4]) rgba,
700 write_all ? Null : mask );
701 if (swrast->_RasterMask & ALPHABUF_BIT) {
702 _mesa_write_alpha_span( ctx, n, x, y,
703 (const GLchan (*)[4]) rgba,
704 write_all ? Null : mask );
705 }
706 }
707 }
708 else {
709 /* same color for all pixels */
710 ASSERT(!ctx->Color.BlendEnabled);
711 ASSERT(!ctx->Color.ColorLogicOpEnabled);
712
713 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
714 for (i = 0; i < n; i++) {
715 if (mask[i]) {
716 COPY_CHAN4(rgba[i], color);
717 }
718 }
719 multi_write_rgba_span( ctx, n, x, y,
720 (const GLchan (*)[4]) rgba, mask );
721 }
722 else {
723 (*ctx->Driver.WriteMonoRGBASpan)( ctx, n, x, y, color, mask );
724 if (swrast->_RasterMask & ALPHABUF_BIT) {
725 _mesa_write_mono_alpha_span( ctx, n, x, y, (GLchan) color[ACOMP],
726 write_all ? Null : mask );
727 }
728 }
729 }
730 }
731
732
733
734 /*
735 * Add specular color to base color. This is used only when
736 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
737 */
738 static void add_colors(GLuint n, GLchan rgba[][4], CONST GLchan specular[][4] )
739 {
740 GLuint i;
741 for (i = 0; i < n; i++) {
742 GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
743 GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
744 GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
745 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
746 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
747 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
748 }
749 }
750
751
752 /*
753 * Write a horizontal span of textured pixels to the frame buffer.
754 * The color of each pixel is different.
755 * Alpha-testing, stenciling, depth-testing, and blending are done
756 * as needed.
757 * Input: n - number of pixels in the span
758 * x, y - location of leftmost pixel in the span
759 * z - array of [n] z-values
760 * s, t - array of (s,t) texture coordinates for each pixel
761 * lambda - array of texture lambda values
762 * rgba - array of [n] color components
763 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
764 */
765 void gl_write_texture_span( GLcontext *ctx,
766 GLuint n, GLint x, GLint y, const GLdepth z[],
767 const GLfixed fog[],
768 const GLfloat s[], const GLfloat t[],
769 const GLfloat u[], GLfloat lambda[],
770 GLchan rgbaIn[][4], CONST GLchan spec[][4],
771 GLenum primitive )
772 {
773 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
774 GLubyte mask[MAX_WIDTH];
775 GLboolean write_all = GL_TRUE;
776 GLchan rgbaBackup[MAX_WIDTH][4];
777 GLchan (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */
778 const GLubyte *Null = 0;
779 SWcontext *swrast = SWRAST_CONTEXT(ctx);
780
781 /* init mask to 1's (all pixels are to be written) */
782 MEMSET(mask, 1, n);
783
784 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
785 if ((n=clip_span(ctx, n, x, y, mask)) == 0) {
786 return;
787 }
788 if (mask[0] == 0)
789 write_all = GL_FALSE;
790 }
791
792
793 if (primitive==GL_BITMAP || (swrast->_RasterMask & MULTI_DRAW_BIT)) {
794 /* must make a copy of the colors since they may be modified */
795 MEMCPY(rgbaBackup, rgbaIn, 4 * n * sizeof(GLchan));
796 rgba = rgbaBackup;
797 }
798 else {
799 rgba = rgbaIn;
800 }
801
802 /* Do the scissor test */
803 if (ctx->Scissor.Enabled) {
804 if (gl_scissor_span( ctx, n, x, y, mask ) == 0) {
805 return;
806 }
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, 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, rgba, rgba );
855 }
856
857 /* Add base and specular colors */
858 if (spec &&
859 (ctx->Fog.ColorSumEnabled ||
860 (ctx->Light.Enabled && ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)))
861 add_colors( n, rgba, spec ); /* rgba = rgba + spec */
862
863 /* Per-pixel fog */
864 if (ctx->Fog.Enabled) {
865 if (fog && !swrast->_PreferPixelFog)
866 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
867 else
868 _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba );
869 }
870
871 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
872 multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask );
873 }
874 else {
875 /* normal: write to exactly one buffer */
876 if (ctx->Color.ColorLogicOpEnabled) {
877 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
878 }
879 else if (ctx->Color.BlendEnabled) {
880 _mesa_blend_span( ctx, n, x, y, rgba, mask );
881 }
882 if (colorMask == 0x0) {
883 return;
884 }
885 else if (colorMask != 0xffffffff) {
886 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
887 }
888
889 (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLchan (*)[4])rgba,
890 write_all ? Null : mask );
891 if (swrast->_RasterMask & ALPHABUF_BIT) {
892 _mesa_write_alpha_span( ctx, n, x, y, (const GLchan (*)[4]) rgba,
893 write_all ? Null : mask );
894 }
895 }
896 }
897
898
899
900 /*
901 * As above but perform multiple stages of texture application.
902 */
903 void
904 gl_write_multitexture_span( GLcontext *ctx,
905 GLuint n, GLint x, GLint y,
906 const GLdepth z[],
907 const GLfixed fog[],
908 CONST GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH],
909 CONST GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH],
910 CONST GLfloat u[MAX_TEXTURE_UNITS][MAX_WIDTH],
911 GLfloat lambda[][MAX_WIDTH],
912 GLchan rgbaIn[MAX_TEXTURE_UNITS][4],
913 CONST GLchan spec[MAX_TEXTURE_UNITS][4],
914 GLenum primitive )
915 {
916 GLubyte mask[MAX_WIDTH];
917 GLboolean write_all = GL_TRUE;
918 GLchan rgbaBackup[MAX_WIDTH][4];
919 GLchan (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */
920 GLuint i;
921 const GLubyte *Null = 0;
922 const GLuint texUnits = ctx->Const.MaxTextureUnits;
923 SWcontext *swrast = SWRAST_CONTEXT(ctx);
924
925 /* init mask to 1's (all pixels are to be written) */
926 MEMSET(mask, 1, n);
927
928 if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
929 if ((n=clip_span(ctx, n, x, y, mask)) == 0) {
930 return;
931 }
932 if (mask[0] == 0)
933 write_all = GL_FALSE;
934 }
935
936
937 if (primitive==GL_BITMAP || (swrast->_RasterMask & MULTI_DRAW_BIT)
938 || texUnits > 1) {
939 /* must make a copy of the colors since they may be modified */
940 MEMCPY(rgbaBackup, rgbaIn, 4 * n * sizeof(GLchan));
941 rgba = rgbaBackup;
942 }
943 else {
944 rgba = rgbaIn;
945 }
946
947 /* Do the scissor test */
948 if (ctx->Scissor.Enabled) {
949 if (gl_scissor_span( ctx, n, x, y, mask ) == 0) {
950 return;
951 }
952 write_all = GL_FALSE;
953 }
954
955 /* Polygon Stippling */
956 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
957 stipple_polygon_span( ctx, n, x, y, mask );
958 write_all = GL_FALSE;
959 }
960
961 /* Texture with alpha test*/
962 if (ctx->Color.AlphaEnabled) {
963 /* Texturing without alpha is done after depth-testing which
964 * gives a potential speed-up.
965 */
966 ASSERT(ctx->Texture._ReallyEnabled);
967 for (i = 0; i < texUnits; i++)
968 _swrast_texture_fragments( ctx, i, n, s[i], t[i], u[i],
969 lambda[i], rgbaIn, rgba );
970
971 /* Do the alpha test */
972 if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4])rgba, mask ) == 0) {
973 return;
974 }
975 write_all = GL_FALSE;
976 }
977
978 if (ctx->Stencil.Enabled) {
979 /* first stencil test */
980 if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) {
981 return;
982 }
983 write_all = GL_FALSE;
984 }
985 else if (ctx->Depth.Test) {
986 /* regular depth testing */
987 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
988 if (m == 0) {
989 return;
990 }
991 if (m < n) {
992 write_all = GL_FALSE;
993 }
994 }
995
996 /* if we get here, something passed the depth test */
997 ctx->OcclusionResult = GL_TRUE;
998
999 /* Texture without alpha test */
1000 if (! ctx->Color.AlphaEnabled) {
1001 ASSERT(ctx->Texture._ReallyEnabled);
1002 for (i = 0; i < texUnits; i++)
1003 _swrast_texture_fragments( ctx, i, n, s[i], t[i], u[i],
1004 lambda[i], rgbaIn, rgba );
1005 }
1006
1007 /* Add base and specular colors */
1008 if (spec &&
1009 (ctx->Fog.ColorSumEnabled ||
1010 (ctx->Light.Enabled &&
1011 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)))
1012 add_colors( n, rgba, spec ); /* rgba = rgba + spec */
1013
1014 /* Per-pixel fog */
1015 if (ctx->Fog.Enabled) {
1016 if (fog && !swrast->_PreferPixelFog)
1017 _mesa_fog_rgba_pixels( ctx, n, fog, rgba );
1018 else
1019 _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba );
1020 }
1021
1022 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1023 multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask );
1024 }
1025 else {
1026 /* normal: write to exactly one buffer */
1027 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1028
1029 if (ctx->Color.ColorLogicOpEnabled) {
1030 _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask );
1031 }
1032 else if (ctx->Color.BlendEnabled) {
1033 _mesa_blend_span( ctx, n, x, y, rgba, mask );
1034 }
1035
1036 if (colorMask == 0x0) {
1037 return;
1038 }
1039 else if (colorMask != 0xffffffff) {
1040 _mesa_mask_rgba_span( ctx, n, x, y, rgba );
1041 }
1042
1043 (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLchan (*)[4])rgba,
1044 write_all ? Null : mask );
1045 if (swrast->_RasterMask & ALPHABUF_BIT) {
1046 _mesa_write_alpha_span( ctx, n, x, y, (const GLchan (*)[4])rgba,
1047 write_all ? Null : mask );
1048 }
1049 }
1050 }
1051
1052
1053
1054 /*
1055 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1056 * reading ouside the buffer's boundaries.
1057 */
1058 void gl_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
1059 GLuint n, GLint x, GLint y,
1060 GLchan rgba[][4] )
1061 {
1062 if (y < 0 || y >= buffer->Height
1063 || x + (GLint) n < 0 || x >= buffer->Width) {
1064 /* completely above, below, or right */
1065 /* XXX maybe leave undefined? */
1066 BZERO(rgba, 4 * n * sizeof(GLchan));
1067 }
1068 else {
1069 GLint skip, length;
1070 if (x < 0) {
1071 /* left edge clippping */
1072 skip = -x;
1073 length = (GLint) n - skip;
1074 if (length < 0) {
1075 /* completely left of window */
1076 return;
1077 }
1078 if (length > buffer->Width) {
1079 length = buffer->Width;
1080 }
1081 }
1082 else if ((GLint) (x + n) > buffer->Width) {
1083 /* right edge clipping */
1084 skip = 0;
1085 length = buffer->Width - x;
1086 if (length < 0) {
1087 /* completely to right of window */
1088 return;
1089 }
1090 }
1091 else {
1092 /* no clipping */
1093 skip = 0;
1094 length = (GLint) n;
1095 }
1096
1097 (*ctx->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
1098 if (buffer->UseSoftwareAlphaBuffers) {
1099 _mesa_read_alpha_span( ctx, length, x + skip, y, rgba + skip );
1100 }
1101 }
1102 }
1103
1104
1105
1106
1107 /*
1108 * Read CI pixels from frame buffer. Clipping will be done to prevent
1109 * reading ouside the buffer's boundaries.
1110 */
1111 void gl_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
1112 GLuint n, GLint x, GLint y, GLuint indx[] )
1113 {
1114 if (y < 0 || y >= buffer->Height
1115 || x + (GLint) n < 0 || x >= buffer->Width) {
1116 /* completely above, below, or right */
1117 BZERO(indx, n * sizeof(GLuint));
1118 }
1119 else {
1120 GLint skip, length;
1121 if (x < 0) {
1122 /* left edge clippping */
1123 skip = -x;
1124 length = (GLint) n - skip;
1125 if (length < 0) {
1126 /* completely left of window */
1127 return;
1128 }
1129 if (length > buffer->Width) {
1130 length = buffer->Width;
1131 }
1132 }
1133 else if ((GLint) (x + n) > buffer->Width) {
1134 /* right edge clipping */
1135 skip = 0;
1136 length = buffer->Width - x;
1137 if (length < 0) {
1138 /* completely to right of window */
1139 return;
1140 }
1141 }
1142 else {
1143 /* no clipping */
1144 skip = 0;
1145 length = (GLint) n;
1146 }
1147
1148 (*ctx->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
1149 }
1150 }