Optimized the interpolate_texcoords() function:
[mesa.git] / src / mesa / swrast / s_span.c
1 /* $Id: s_span.c,v 1.35 2002/02/17 01:49:31 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 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 * \file swrast/s_span.c
30 * \brief Span processing functions used by all rasterization functions.
31 * This is where all the per-fragment tests are performed
32 * \author Brian Paul
33 */
34
35 #include "glheader.h"
36 #include "colormac.h"
37 #include "context.h"
38 #include "macros.h"
39 #include "mem.h"
40
41 #include "s_alpha.h"
42 #include "s_alphabuf.h"
43 #include "s_blend.h"
44 #include "s_context.h"
45 #include "s_depth.h"
46 #include "s_fog.h"
47 #include "s_logic.h"
48 #include "s_masking.h"
49 #include "s_span.h"
50 #include "s_stencil.h"
51 #include "s_texture.h"
52
53
54 /**
55 * Init span's Z interpolation values to the RasterPos Z.
56 * Used during setup for glDraw/CopyPixels.
57 */
58 void
59 _mesa_span_default_z( GLcontext *ctx, struct sw_span *span )
60 {
61 if (ctx->Visual.depthBits <= 16)
62 span->z = FloatToFixed(ctx->Current.RasterPos[2] * ctx->DepthMax);
63 else
64 span->z = (GLint) (ctx->Current.RasterPos[2] * ctx->DepthMax);
65 span->zStep = 0;
66 span->interpMask |= SPAN_Z;
67 }
68
69
70 /**
71 * Init span's fog interpolation values to the RasterPos fog.
72 * Used during setup for glDraw/CopyPixels.
73 */
74 void
75 _mesa_span_default_fog( GLcontext *ctx, struct sw_span *span )
76 {
77 span->fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
78 span->fogStep = 0;
79 span->interpMask |= SPAN_FOG;
80 }
81
82
83 /**
84 * Init span's color or index interpolation values to the RasterPos color.
85 * Used during setup for glDraw/CopyPixels.
86 */
87 void
88 _mesa_span_default_color( GLcontext *ctx, struct sw_span *span )
89 {
90 if (ctx->Visual.rgbMode) {
91 GLchan r, g, b, a;
92 UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
93 UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
94 UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
95 UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
96 #if CHAN_TYPE == GL_FLOAT
97 span->red = r;
98 span->green = g;
99 span->blue = b;
100 span->alpha = a;
101 #else
102 span->red = IntToFixed(r);
103 span->green = IntToFixed(g);
104 span->blue = IntToFixed(b);
105 span->alpha = IntToFixed(a);
106 #endif
107 span->redStep = 0;
108 span->greenStep = 0;
109 span->blueStep = 0;
110 span->alphaStep = 0;
111 span->interpMask |= SPAN_RGBA;
112 }
113 else {
114 span->index = IntToFixed(ctx->Current.RasterIndex);
115 span->indexStep = 0;
116 span->interpMask |= SPAN_INDEX;
117 }
118 }
119
120
121 /* Fill in the span.color.rgba array from the interpolation values */
122 static void
123 interpolate_colors(GLcontext *ctx, struct sw_span *span)
124 {
125 GLfixed r = span->red;
126 GLfixed g = span->green;
127 GLfixed b = span->blue;
128 GLfixed a = span->alpha;
129 const GLint dr = span->redStep;
130 const GLint dg = span->greenStep;
131 const GLint db = span->blueStep;
132 const GLint da = span->alphaStep;
133 const GLuint n = span->end;
134 GLchan (*rgba)[4] = span->color.rgba;
135 GLuint i;
136
137 ASSERT(span->interpMask & SPAN_RGBA);
138
139 if (span->interpMask & SPAN_FLAT) {
140 /* constant color */
141 GLchan color[4];
142 color[RCOMP] = FixedToChan(r);
143 color[GCOMP] = FixedToChan(g);
144 color[BCOMP] = FixedToChan(b);
145 color[ACOMP] = FixedToChan(a);
146 for (i = 0; i < n; i++) {
147 COPY_CHAN4(span->color.rgba[i], color);
148 }
149 }
150 else {
151 /* interpolate */
152 for (i = 0; i < n; i++) {
153 rgba[i][RCOMP] = FixedToChan(r);
154 rgba[i][GCOMP] = FixedToChan(g);
155 rgba[i][BCOMP] = FixedToChan(b);
156 rgba[i][ACOMP] = FixedToChan(a);
157 r += dr;
158 g += dg;
159 b += db;
160 a += da;
161 }
162 }
163 span->arrayMask |= SPAN_RGBA;
164 }
165
166
167 /* Fill in the span.color.index array from the interpolation values */
168 static void
169 interpolate_indexes(GLcontext *ctx, struct sw_span *span)
170 {
171 GLfixed index = span->index;
172 const GLint indexStep = span->indexStep;
173 const GLuint n = span->end;
174 GLuint *indexes = span->color.index;
175 GLuint i;
176 ASSERT(span->interpMask & SPAN_INDEX);
177
178 if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
179 /* constant color */
180 index = FixedToInt(index);
181 for (i = 0; i < n; i++) {
182 indexes[i] = index;
183 }
184 }
185 else {
186 /* interpolate */
187 for (i = 0; i < n; i++) {
188 indexes[i] = FixedToInt(index);
189 index += indexStep;
190 }
191 }
192 span->arrayMask |= SPAN_INDEX;
193 }
194
195
196 /* Fill in the span.specArray array from the interpolation values */
197 static void
198 interpolate_specular(GLcontext *ctx, struct sw_span *span)
199 {
200 if (span->interpMask & SPAN_FLAT) {
201 /* constant color */
202 const GLchan r = FixedToChan(span->specRed);
203 const GLchan g = FixedToChan(span->specGreen);
204 const GLchan b = FixedToChan(span->specBlue);
205 GLuint i;
206 for (i = 0; i < span->end; i++) {
207 span->specArray[i][RCOMP] = r;
208 span->specArray[i][GCOMP] = g;
209 span->specArray[i][BCOMP] = b;
210 }
211 }
212 else {
213 /* interpolate */
214 #if CHAN_TYPE == GL_FLOAT
215 GLfloat r = span->specRed;
216 GLfloat g = span->specGreen;
217 GLfloat b = span->specBlue;
218 #else
219 GLfixed r = span->specRed;
220 GLfixed g = span->specGreen;
221 GLfixed b = span->specBlue;
222 #endif
223 GLuint i;
224 for (i = 0; i < span->end; i++) {
225 span->specArray[i][RCOMP] = FixedToChan(r);
226 span->specArray[i][GCOMP] = FixedToChan(g);
227 span->specArray[i][BCOMP] = FixedToChan(b);
228 r += span->specRedStep;
229 g += span->specGreenStep;
230 b += span->specBlueStep;
231 }
232 }
233 span->arrayMask |= SPAN_SPEC;
234 }
235
236
237 /* Fill in the span.zArray array from the interpolation values */
238 static void
239 interpolate_z(GLcontext *ctx, struct sw_span *span)
240 {
241 const GLuint n = span->end;
242 GLuint i;
243
244 ASSERT(span->interpMask & SPAN_Z);
245
246 if (ctx->Visual.depthBits <= 16) {
247 GLfixed zval = span->z;
248 for (i = 0; i < n; i++) {
249 span->zArray[i] = FixedToInt(zval);
250 zval += span->zStep;
251 }
252 }
253 else {
254 /* Deep Z buffer, no fixed->int shift */
255 GLfixed zval = span->z;
256 for (i = 0; i < n; i++) {
257 span->zArray[i] = zval;
258 zval += span->zStep;
259 }
260 }
261 span->arrayMask |= SPAN_Z;
262 }
263
264
265 /*
266 * Return log_base_2(x) / 2.
267 * We divide by two here since we didn't square rho in the triangle function.
268 */
269 #ifdef USE_IEEE
270
271 #if 0
272 /* This is pretty fast, but not accurate enough (only 2 fractional bits).
273 * Based on code from http://www.stereopsis.com/log2.html
274 */
275 static INLINE GLfloat HALF_LOG2(GLfloat x)
276 {
277 const GLfloat y = x * x * x * x;
278 const GLuint ix = *((GLuint *) &y);
279 const GLuint exp = (ix >> 23) & 0xFF;
280 const GLint log2 = ((GLint) exp) - 127;
281 return (GLfloat) log2 * (0.5 / 4.0); /* 4, because of x^4 above */
282 }
283 #endif
284
285 /* Pretty fast, and accurate.
286 * Based on code from http://www.flipcode.com/totd/
287 */
288 static INLINE GLfloat HALF_LOG2(GLfloat val)
289 {
290 GLint *exp_ptr = (GLint *) &val;
291 GLint x = *exp_ptr;
292 const GLint log_2 = ((x >> 23) & 255) - 128;
293 x &= ~(255 << 23);
294 x += 127 << 23;
295 *exp_ptr = x;
296 val = ((-1.0f/3) * val + 2) * val - 2.0f/3;
297 return 0.5F * (val + log_2);
298 }
299
300 #else /* USE_IEEE */
301
302 /* Slow, portable solution.
303 * NOTE: log_base_2(x) = log(x) / log(2)
304 * NOTE: 1.442695 = 1/log(2).
305 */
306 #define HALF_LOG2(x) ((GLfloat) (log(x) * (1.442695F * 0.5F)))
307
308 #endif /* USE_IEEE */
309
310
311
312 /*
313 * Fill in the span.texcoords array from the interpolation values.
314 * XXX We could optimize here for the case when dq = 0. That would
315 * usually be the case when using an orthographic projection.
316 */
317 static void
318 interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
319 {
320 ASSERT(span->interpMask & SPAN_TEXTURE);
321
322 if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) {
323 if (span->interpMask & SPAN_LAMBDA) {
324 /* multitexture, lambda */
325 GLuint u;
326 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
327 if (ctx->Texture.Unit[u]._ReallyEnabled) {
328 const GLfloat rho = span->rho[u];
329 const GLfloat ds = span->texStep[u][0];
330 const GLfloat dt = span->texStep[u][1];
331 const GLfloat dr = span->texStep[u][2];
332 const GLfloat dq = span->texStep[u][3];
333 GLfloat s = span->tex[u][0];
334 GLfloat t = span->tex[u][1];
335 GLfloat r = span->tex[u][2];
336 GLfloat q = span->tex[u][3];
337 GLuint i;
338 if (dq == 0.0) {
339 /* Ortho projection or polygon's parallel to window X axis */
340 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
341 const GLfloat lambda = HALF_LOG2(rho * invQ * invQ);
342 for (i = 0; i < span->end; i++) {
343 span->texcoords[u][i][0] = s * invQ;
344 span->texcoords[u][i][1] = t * invQ;
345 span->texcoords[u][i][2] = r * invQ;
346 span->lambda[u][i] = lambda;
347 s += ds;
348 t += dt;
349 r += dr;
350 }
351 }
352 else {
353 for (i = 0; i < span->end; i++) {
354 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
355 span->texcoords[u][i][0] = s * invQ;
356 span->texcoords[u][i][1] = t * invQ;
357 span->texcoords[u][i][2] = r * invQ;
358 span->lambda[u][i] = HALF_LOG2(rho * invQ * invQ);
359 s += ds;
360 t += dt;
361 r += dr;
362 q += dq;
363 }
364 }
365 }
366 }
367 span->arrayMask |= SPAN_LAMBDA;
368 }
369 else {
370 /* multitexture, no lambda */
371 GLuint u;
372 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
373 if (ctx->Texture.Unit[u]._ReallyEnabled) {
374 const GLfloat ds = span->texStep[u][0];
375 const GLfloat dt = span->texStep[u][1];
376 const GLfloat dr = span->texStep[u][2];
377 const GLfloat dq = span->texStep[u][3];
378 GLfloat s = span->tex[u][0];
379 GLfloat t = span->tex[u][1];
380 GLfloat r = span->tex[u][2];
381 GLfloat q = span->tex[u][3];
382 GLuint i;
383 if (dq == 0.0) {
384 /* Ortho projection or polygon's parallel to window X axis */
385 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
386 for (i = 0; i < span->end; i++) {
387 span->texcoords[u][i][0] = s * invQ;
388 span->texcoords[u][i][1] = t * invQ;
389 span->texcoords[u][i][2] = r * invQ;
390 s += ds;
391 t += dt;
392 r += dr;
393 }
394 }
395 else {
396 for (i = 0; i < span->end; i++) {
397 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
398 span->texcoords[u][i][0] = s * invQ;
399 span->texcoords[u][i][1] = t * invQ;
400 span->texcoords[u][i][2] = r * invQ;
401 s += ds;
402 t += dt;
403 r += dr;
404 q += dq;
405 }
406 }
407 }
408 }
409 }
410 }
411 else {
412 if (span->interpMask & SPAN_LAMBDA) {
413 /* just texture unit 0, with lambda */
414 const GLfloat rho = span->rho[0];
415 const GLfloat ds = span->texStep[0][0];
416 const GLfloat dt = span->texStep[0][1];
417 const GLfloat dr = span->texStep[0][2];
418 const GLfloat dq = span->texStep[0][3];
419 GLfloat s = span->tex[0][0];
420 GLfloat t = span->tex[0][1];
421 GLfloat r = span->tex[0][2];
422 GLfloat q = span->tex[0][3];
423 GLuint i;
424 if (dq == 0.0) {
425 /* Ortho projection or polygon's parallel to window X axis */
426 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
427 const GLfloat lambda = HALF_LOG2(rho * invQ * invQ);
428 for (i = 0; i < span->end; i++) {
429 span->texcoords[0][i][0] = s * invQ;
430 span->texcoords[0][i][1] = t * invQ;
431 span->texcoords[0][i][2] = r * invQ;
432 span->lambda[0][i] = lambda;
433 s += ds;
434 t += dt;
435 r += dr;
436 }
437 }
438 else {
439 for (i = 0; i < span->end; i++) {
440 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
441 span->texcoords[0][i][0] = s * invQ;
442 span->texcoords[0][i][1] = t * invQ;
443 span->texcoords[0][i][2] = r * invQ;
444 span->lambda[0][i] = HALF_LOG2(rho * invQ * invQ);
445 s += ds;
446 t += dt;
447 r += dr;
448 q += dq;
449 }
450 }
451 span->arrayMask |= SPAN_LAMBDA;
452 }
453 else {
454 /* just texture 0, without lambda */
455 const GLfloat ds = span->texStep[0][0];
456 const GLfloat dt = span->texStep[0][1];
457 const GLfloat dr = span->texStep[0][2];
458 const GLfloat dq = span->texStep[0][3];
459 GLfloat s = span->tex[0][0];
460 GLfloat t = span->tex[0][1];
461 GLfloat r = span->tex[0][2];
462 GLfloat q = span->tex[0][3];
463 GLuint i;
464 if (dq == 0.0) {
465 /* Ortho projection or polygon's parallel to window X axis */
466 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
467 for (i = 0; i < span->end; i++) {
468 span->texcoords[0][i][0] = s * invQ;
469 span->texcoords[0][i][1] = t * invQ;
470 span->texcoords[0][i][2] = r * invQ;
471 s += ds;
472 t += dt;
473 r += dr;
474 }
475 }
476 else {
477 for (i = 0; i < span->end; i++) {
478 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
479 span->texcoords[0][i][0] = s * invQ;
480 span->texcoords[0][i][1] = t * invQ;
481 span->texcoords[0][i][2] = r * invQ;
482 s += ds;
483 t += dt;
484 r += dr;
485 q += dq;
486 }
487 }
488 }
489 }
490 }
491
492
493 /**
494 * Apply the current polygon stipple pattern to a span of pixels.
495 */
496 static void
497 stipple_polygon_span( GLcontext *ctx, struct sw_span *span )
498 {
499 const GLuint highbit = 0x80000000;
500 const GLuint stipple = ctx->PolygonStipple[span->y % 32];
501 GLuint i, m;
502
503 ASSERT(ctx->Polygon.StippleFlag);
504 ASSERT((span->arrayMask & SPAN_XY) == 0);
505
506 m = highbit >> (GLuint) (span->x % 32);
507
508 for (i = 0; i < span->end; i++) {
509 if ((m & stipple) == 0) {
510 span->mask[i] = 0;
511 }
512 m = m >> 1;
513 if (m == 0) {
514 m = highbit;
515 }
516 }
517 span->writeAll = GL_FALSE;
518 }
519
520
521 /**
522 * Clip a pixel span to the current buffer/window boundaries:
523 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
524 * window clipping and scissoring.
525 * Return: GL_TRUE some pixels still visible
526 * GL_FALSE nothing visible
527 */
528 static GLuint
529 clip_span( GLcontext *ctx, struct sw_span *span )
530 {
531 const GLint xmin = ctx->DrawBuffer->_Xmin;
532 const GLint xmax = ctx->DrawBuffer->_Xmax;
533 const GLint ymin = ctx->DrawBuffer->_Ymin;
534 const GLint ymax = ctx->DrawBuffer->_Ymax;
535
536 if (span->arrayMask & SPAN_XY) {
537 /* arrays of x/y pixel coords */
538 const GLint *x = span->xArray;
539 const GLint *y = span->yArray;
540 const GLint n = span->end;
541 GLubyte *mask = span->mask;
542 GLint i;
543 if (span->arrayMask & SPAN_MASK) {
544 /* note: using & intead of && to reduce branches */
545 for (i = 0; i < n; i++) {
546 mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
547 & (y[i] >= ymin) & (y[i] < ymax);
548 }
549 }
550 else {
551 /* note: using & intead of && to reduce branches */
552 for (i = 0; i < n; i++) {
553 mask[i] = (x[i] >= xmin) & (x[i] < xmax)
554 & (y[i] >= ymin) & (y[i] < ymax);
555 }
556 }
557 return GL_TRUE; /* some pixels visible */
558 }
559 else {
560 /* horizontal span of pixels */
561 const GLint x = span->x;
562 const GLint y = span->y;
563 const GLint n = span->end;
564
565 /* Trivial rejection tests */
566 if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
567 span->end = 0;
568 return GL_FALSE; /* all pixels clipped */
569 }
570
571 /* Clip to the left */
572 if (x < xmin) {
573 ASSERT(x + n > xmin);
574 span->writeAll = GL_FALSE;
575 BZERO(span->mask, (xmin - x) * sizeof(GLubyte));
576 }
577
578 /* Clip to right */
579 if (x + n > xmax) {
580 ASSERT(x < xmax);
581 span->end = xmax - x;
582 }
583
584 return GL_TRUE; /* some pixels visible */
585 }
586 }
587
588
589
590 /**
591 * Draw to more than one color buffer (or none).
592 */
593 static void
594 multi_write_index_span( GLcontext *ctx, struct sw_span *span )
595 {
596 SWcontext *swrast = SWRAST_CONTEXT(ctx);
597 GLuint bufferBit;
598
599 /* loop over four possible dest color buffers */
600 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
601 if (bufferBit & ctx->Color.DrawDestMask) {
602 GLuint indexTmp[MAX_WIDTH];
603 ASSERT(span->end < MAX_WIDTH);
604
605 if (bufferBit == FRONT_LEFT_BIT)
606 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
607 else if (bufferBit == FRONT_RIGHT_BIT)
608 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
609 else if (bufferBit == BACK_LEFT_BIT)
610 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
611 else
612 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
613
614 /* make copy of incoming indexes */
615 MEMCPY( indexTmp, span->color.index, span->end * sizeof(GLuint) );
616
617 if (ctx->Color.IndexLogicOpEnabled) {
618 _mesa_logicop_ci_span(ctx, span, indexTmp);
619 }
620
621 if (ctx->Color.IndexMask != 0xffffffff) {
622 _mesa_mask_index_span(ctx, span, indexTmp);
623 }
624
625 if (span->arrayMask & SPAN_XY) {
626 /* array of pixel coords */
627 (*swrast->Driver.WriteCI32Pixels)(ctx, span->end,
628 span->xArray, span->yArray,
629 indexTmp, span->mask);
630 }
631 else {
632 /* horizontal run of pixels */
633 (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
634 indexTmp, span->mask);
635 }
636 }
637 }
638
639 /* restore default dest buffer */
640 (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer);
641 }
642
643
644 /**
645 * Draw to more than one RGBA color buffer (or none).
646 * All fragment operations, up to (but not) blending/logicop should
647 * have been done first.
648 */
649 static void
650 multi_write_rgba_span( GLcontext *ctx, struct sw_span *span )
651 {
652 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
653 GLuint bufferBit;
654 SWcontext *swrast = SWRAST_CONTEXT(ctx);
655
656 ASSERT(colorMask != 0x0);
657
658 if (ctx->Color.DrawBuffer == GL_NONE)
659 return;
660
661 /* loop over four possible dest color buffers */
662 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
663 if (bufferBit & ctx->Color.DrawDestMask) {
664 GLchan rgbaTmp[MAX_WIDTH][4];
665 ASSERT(span->end < MAX_WIDTH);
666
667 if (bufferBit == FRONT_LEFT_BIT) {
668 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
669 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha;
670 }
671 else if (bufferBit == FRONT_RIGHT_BIT) {
672 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
673 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha;
674 }
675 else if (bufferBit == BACK_LEFT_BIT) {
676 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
677 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha;
678 }
679 else {
680 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
681 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha;
682 }
683
684 /* make copy of incoming colors */
685 MEMCPY( rgbaTmp, span->color.rgba, 4 * span->end * sizeof(GLchan) );
686
687 if (ctx->Color.ColorLogicOpEnabled) {
688 _mesa_logicop_rgba_span(ctx, span, rgbaTmp);
689 }
690 else if (ctx->Color.BlendEnabled) {
691 _mesa_blend_span(ctx, span, rgbaTmp);
692 }
693
694 if (colorMask != 0xffffffff) {
695 _mesa_mask_rgba_span(ctx, span, rgbaTmp);
696 }
697
698 if (span->arrayMask & SPAN_XY) {
699 /* array of pixel coords */
700 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end,
701 span->xArray, span->yArray,
702 (const GLchan (*)[4]) rgbaTmp,
703 span->mask);
704 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
705 _mesa_write_alpha_pixels(ctx, span->end,
706 span->xArray, span->yArray,
707 (const GLchan (*)[4]) rgbaTmp,
708 span->mask);
709 }
710 }
711 else {
712 /* horizontal run of pixels */
713 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
714 (const GLchan (*)[4]) rgbaTmp,
715 span->mask);
716 if (swrast->_RasterMask & ALPHABUF_BIT) {
717 _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
718 (const GLchan (*)[4]) rgbaTmp,
719 span->mask);
720 }
721 }
722 }
723 }
724
725 /* restore default dest buffer */
726 (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer );
727 }
728
729
730
731 /**
732 * This function may modify any of the array values in the span.
733 * span->interpMask and span->arrayMask may be changed but will be restored
734 * to their original values before returning.
735 */
736 void
737 _mesa_write_index_span( GLcontext *ctx, struct sw_span *span,
738 GLenum primitive)
739 {
740 SWcontext *swrast = SWRAST_CONTEXT(ctx);
741 const GLuint origInterpMask = span->interpMask;
742 const GLuint origArrayMask = span->arrayMask;
743
744 ASSERT(span->end <= MAX_WIDTH);
745 ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
746 ASSERT((span->interpMask & span->arrayMask) == 0);
747
748 if (span->arrayMask & SPAN_MASK) {
749 /* mask was initialized by caller, probably glBitmap */
750 span->writeAll = GL_FALSE;
751 }
752 else {
753 MEMSET(span->mask, 1, span->end);
754 span->writeAll = GL_TRUE;
755 }
756
757 /* Clipping */
758 if ((swrast->_RasterMask & CLIP_BIT) || (primitive == GL_BITMAP)
759 || (primitive == GL_POINT) || (primitive == GL_LINE)) {
760 if (!clip_span(ctx, span)) {
761 return;
762 }
763 }
764
765 #ifdef DEBUG
766 if (span->arrayMask & SPAN_XY) {
767 int i;
768 for (i = 0; i < span->end; i++) {
769 if (span->mask[i]) {
770 assert(span->xArray[i] >= ctx->DrawBuffer->_Xmin);
771 assert(span->xArray[i] < ctx->DrawBuffer->_Xmax);
772 assert(span->yArray[i] >= ctx->DrawBuffer->_Ymin);
773 assert(span->yArray[i] < ctx->DrawBuffer->_Ymax);
774 }
775 }
776 }
777 #endif
778
779 /* Polygon Stippling */
780 if (ctx->Polygon.StippleFlag && primitive == GL_POLYGON) {
781 stipple_polygon_span(ctx, span);
782 }
783
784 /* Depth test and stencil */
785 if (ctx->Depth.Test || ctx->Stencil.Enabled) {
786 if (span->interpMask & SPAN_Z)
787 interpolate_z(ctx, span);
788
789 if (ctx->Stencil.Enabled) {
790 if (!_mesa_stencil_and_ztest_span(ctx, span)) {
791 span->arrayMask = origArrayMask;
792 return;
793 }
794 }
795 else {
796 ASSERT(ctx->Depth.Test);
797 if (!_mesa_depth_test_span(ctx, span)) {
798 span->arrayMask = origArrayMask;
799 return;
800 }
801 }
802 }
803
804 /* if we get here, something passed the depth test */
805 ctx->OcclusionResult = GL_TRUE;
806
807 /* we have to wait until after occlusion to do this test */
808 if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
809 /* write no pixels */
810 span->arrayMask = origArrayMask;
811 return;
812 }
813
814 /* Interpolate the color indexes if needed */
815 if (span->interpMask & SPAN_INDEX) {
816 interpolate_indexes(ctx, span);
817 /* clear the bit - this allows the WriteMonoCISpan optimization below */
818 span->interpMask &= ~SPAN_INDEX;
819 }
820
821 /* Fog */
822 /* XXX try to simplify the fog code! */
823 if (ctx->Fog.Enabled) {
824 if ((span->arrayMask & SPAN_FOG) && !swrast->_PreferPixelFog)
825 _mesa_fog_ci_pixels_with_array( ctx, span, span->fogArray,
826 span->color.index);
827 else if ((span->interpMask & SPAN_FOG) && !swrast->_PreferPixelFog)
828 _mesa_fog_ci_pixels( ctx, span, span->color.index);
829 else
830 _mesa_depth_fog_ci_pixels( ctx, span, span->color.index);
831 }
832
833 /* Antialias coverage application */
834 if (span->arrayMask & SPAN_COVERAGE) {
835 GLuint i;
836 GLuint *index = span->color.index;
837 for (i = 0; i < span->end; i++) {
838 ASSERT(span->coverage[i] < 16);
839 index[i] = (index[i] & ~0xf) | ((GLuint) (span->coverage[i]));
840 }
841 }
842
843 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
844 /* draw to zero or two or more buffers */
845 multi_write_index_span(ctx, span);
846 }
847 else {
848 /* normal situation: draw to exactly one buffer */
849 if (ctx->Color.IndexLogicOpEnabled) {
850 _mesa_logicop_ci_span(ctx, span, span->color.index);
851 }
852
853 if (ctx->Color.IndexMask != 0xffffffff) {
854 _mesa_mask_index_span(ctx, span, span->color.index);
855 }
856
857 /* write pixels */
858 if (span->arrayMask & SPAN_XY) {
859 /* array of pixel coords */
860 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
861 /* all pixels have same color index */
862 (*swrast->Driver.WriteMonoCIPixels)(ctx, span->end,
863 span->xArray, span->yArray,
864 FixedToInt(span->index),
865 span->mask);
866 }
867 else {
868 (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, span->xArray,
869 span->yArray, span->color.index,
870 span->mask );
871 }
872 }
873 else {
874 /* horizontal run of pixels */
875 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
876 /* all pixels have same color index */
877 (*swrast->Driver.WriteMonoCISpan)(ctx, span->end, span->x, span->y,
878 FixedToInt(span->index),
879 span->mask);
880 }
881 else {
882 (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
883 span->color.index, span->mask);
884 }
885 }
886 }
887
888 span->interpMask = origInterpMask;
889 span->arrayMask = origArrayMask;
890 }
891
892
893 /**
894 * This function may modify any of the array values in the span.
895 * span->interpMask and span->arrayMask may be changed but will be restored
896 * to their original values before returning.
897 */
898 void
899 _mesa_write_rgba_span( GLcontext *ctx, struct sw_span *span,
900 GLenum primitive)
901 {
902 SWcontext *swrast = SWRAST_CONTEXT(ctx);
903 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
904 const GLuint origInterpMask = span->interpMask;
905 const GLuint origArrayMask = span->arrayMask;
906 GLboolean monoColor;
907
908 ASSERT(span->end <= MAX_WIDTH);
909 ASSERT((span->interpMask & span->arrayMask) == 0);
910 ASSERT((span->interpMask | span->arrayMask) & SPAN_RGBA);
911 #ifdef DEBUG
912 if (ctx->Fog.Enabled)
913 ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG);
914 if (ctx->Depth.Test)
915 ASSERT((span->interpMask | span->arrayMask) & SPAN_Z);
916 #endif
917
918 /*
919 printf("%s() interp 0x%x array 0x%x p=0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask, primitive);
920 */
921
922 if (span->arrayMask & SPAN_MASK) {
923 /* mask was initialized by caller, probably glBitmap */
924 span->writeAll = GL_FALSE;
925 }
926 else {
927 MEMSET(span->mask, 1, span->end);
928 span->writeAll = GL_TRUE;
929 }
930
931 /* Determine if we have mono-chromatic colors */
932 monoColor = (span->interpMask & SPAN_RGBA) &&
933 span->redStep == 0 && span->greenStep == 0 &&
934 span->blueStep == 0 && span->alphaStep == 0;
935
936 /* Clipping */
937 if ((swrast->_RasterMask & CLIP_BIT) || (primitive == GL_BITMAP)
938 || (primitive == GL_POINT) || (primitive == GL_LINE)) {
939 if (!clip_span(ctx, span)) {
940 return;
941 }
942 }
943
944 #ifdef DEBUG
945 if (span->arrayMask & SPAN_XY) {
946 int i;
947 for (i = 0; i < span->end; i++) {
948 if (span->mask[i]) {
949 assert(span->xArray[i] >= ctx->DrawBuffer->_Xmin);
950 assert(span->xArray[i] < ctx->DrawBuffer->_Xmax);
951 assert(span->yArray[i] >= ctx->DrawBuffer->_Ymin);
952 assert(span->yArray[i] < ctx->DrawBuffer->_Ymax);
953 }
954 }
955 }
956 #endif
957
958 /* Polygon Stippling */
959 if (ctx->Polygon.StippleFlag && primitive == GL_POLYGON) {
960 stipple_polygon_span(ctx, span);
961 }
962
963 /* Do the alpha test */
964 if (ctx->Color.AlphaEnabled) {
965 if (!_mesa_alpha_test(ctx, span)) {
966 span->interpMask = origInterpMask;
967 span->arrayMask = origArrayMask;
968 return;
969 }
970 }
971
972 /* Stencil and Z testing */
973 if (ctx->Stencil.Enabled || ctx->Depth.Test) {
974 if (span->interpMask & SPAN_Z)
975 interpolate_z(ctx, span);
976
977 if (ctx->Stencil.Enabled) {
978 if (!_mesa_stencil_and_ztest_span(ctx, span)) {
979 span->interpMask = origInterpMask;
980 span->arrayMask = origArrayMask;
981 return;
982 }
983 }
984 else {
985 ASSERT(ctx->Depth.Test);
986 ASSERT(span->arrayMask & SPAN_Z);
987 /* regular depth testing */
988 if (!_mesa_depth_test_span(ctx, span)) {
989 span->interpMask = origInterpMask;
990 span->arrayMask = origArrayMask;
991 return;
992 }
993 }
994 }
995
996 /* if we get here, something passed the depth test */
997 ctx->OcclusionResult = GL_TRUE;
998
999 /* can't abort span-writing until after occlusion testing */
1000 if (colorMask == 0x0) {
1001 span->interpMask = origInterpMask;
1002 span->arrayMask = origArrayMask;
1003 return;
1004 }
1005
1006 /* Now we may need to interpolate the colors */
1007 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) {
1008 interpolate_colors(ctx, span);
1009 /* clear the bit - this allows the WriteMonoCISpan optimization below */
1010 span->interpMask &= ~SPAN_RGBA;
1011 }
1012
1013 /* Fog */
1014 /* XXX try to simplify the fog code! */
1015 if (ctx->Fog.Enabled) {
1016 if ((span->arrayMask & SPAN_FOG) && !swrast->_PreferPixelFog) {
1017 _mesa_fog_rgba_pixels_with_array(ctx, span, span->fogArray,
1018 span->color.rgba);
1019 }
1020 else if ((span->interpMask & SPAN_FOG) && !swrast->_PreferPixelFog) {
1021 _mesa_fog_rgba_pixels(ctx, span, span->color.rgba);
1022 }
1023 else {
1024 if ((span->interpMask & SPAN_Z) && (span->arrayMask & SPAN_Z) == 0)
1025 interpolate_z(ctx, span);
1026 _mesa_depth_fog_rgba_pixels(ctx, span, span->color.rgba);
1027 }
1028 monoColor = GL_FALSE;
1029 }
1030
1031 /* Antialias coverage application */
1032 if (span->arrayMask & SPAN_COVERAGE) {
1033 GLchan (*rgba)[4] = span->color.rgba;
1034 GLuint i;
1035 for (i = 0; i < span->end; i++) {
1036 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * span->coverage[i]);
1037 }
1038 monoColor = GL_FALSE;
1039 }
1040
1041 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1042 multi_write_rgba_span(ctx, span);
1043 }
1044 else {
1045 /* normal: write to exactly one buffer */
1046 if (ctx->Color.ColorLogicOpEnabled) {
1047 _mesa_logicop_rgba_span(ctx, span, span->color.rgba);
1048 monoColor = GL_FALSE;
1049 }
1050 else if (ctx->Color.BlendEnabled) {
1051 _mesa_blend_span(ctx, span, span->color.rgba);
1052 monoColor = GL_FALSE;
1053 }
1054
1055 /* Color component masking */
1056 if (colorMask != 0xffffffff) {
1057 _mesa_mask_rgba_span(ctx, span, span->color.rgba);
1058 monoColor = GL_FALSE;
1059 }
1060
1061 /* write pixels */
1062 if (span->arrayMask & SPAN_XY) {
1063 /* array of pixel coords */
1064 /* XXX test for mono color */
1065 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->xArray,
1066 span->yArray, (const GLchan (*)[4]) span->color.rgba, span->mask);
1067 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1068 _mesa_write_alpha_pixels(ctx, span->end,
1069 span->xArray, span->yArray,
1070 (const GLchan (*)[4]) span->color.rgba,
1071 span->mask);
1072 }
1073 }
1074 else {
1075 /* horizontal run of pixels */
1076 if (monoColor) {
1077 /* all pixels have same color */
1078 GLchan color[4];
1079 color[RCOMP] = FixedToChan(span->red);
1080 color[GCOMP] = FixedToChan(span->green);
1081 color[BCOMP] = FixedToChan(span->blue);
1082 color[ACOMP] = FixedToChan(span->alpha);
1083 (*swrast->Driver.WriteMonoRGBASpan)(ctx, span->end, span->x,
1084 span->y, color, span->mask);
1085 /* XXX software alpha buffer writes! */
1086 }
1087 else {
1088 /* each pixel is a different color */
1089 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
1090 (const GLchan (*)[4]) span->color.rgba,
1091 span->writeAll ? ((const GLubyte *) NULL) : span->mask);
1092 if (swrast->_RasterMask & ALPHABUF_BIT) {
1093 _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
1094 (const GLchan (*)[4]) span->color.rgba,
1095 span->writeAll ? ((const GLubyte *) NULL) : span->mask);
1096 }
1097 }
1098 }
1099 }
1100
1101 span->interpMask = origInterpMask;
1102 span->arrayMask = origArrayMask;
1103 }
1104
1105
1106 /**
1107 * Add specular color to base color. This is used only when
1108 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1109 */
1110 static void
1111 add_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] )
1112 {
1113 GLuint i;
1114 for (i = 0; i < n; i++) {
1115 #if CHAN_TYPE == GL_FLOAT
1116 /* no clamping */
1117 rgba[i][RCOMP] += specular[i][RCOMP];
1118 rgba[i][GCOMP] += specular[i][GCOMP];
1119 rgba[i][BCOMP] += specular[i][BCOMP];
1120 #else
1121 GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
1122 GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
1123 GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
1124 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1125 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1126 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1127 #endif
1128 }
1129 }
1130
1131
1132 /**
1133 * This function may modify any of the array values in the span.
1134 * span->interpMask and span->arrayMask may be changed but will be restored
1135 * to their original values before returning.
1136 */
1137 void
1138 _mesa_write_texture_span( GLcontext *ctx, struct sw_span *span,
1139 GLenum primitive )
1140 {
1141 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1142 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1143 const GLuint origArrayMask = span->arrayMask;
1144
1145 ASSERT(span->end <= MAX_WIDTH);
1146 ASSERT((span->interpMask & span->arrayMask) == 0);
1147 ASSERT(ctx->Texture._ReallyEnabled);
1148
1149 /*
1150 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1151 */
1152
1153 if (span->arrayMask & SPAN_MASK) {
1154 /* mask was initialized by caller, probably glBitmap */
1155 span->writeAll = GL_FALSE;
1156 }
1157 else {
1158 MEMSET(span->mask, 1, span->end);
1159 span->writeAll = GL_TRUE;
1160 }
1161
1162 /* Clipping */
1163 if ((swrast->_RasterMask & CLIP_BIT) || (primitive == GL_BITMAP)
1164 || (primitive == GL_POINT) || (primitive == GL_LINE)) {
1165 if (!clip_span(ctx, span)) {
1166 return;
1167 }
1168 }
1169
1170 #ifdef DEBUG
1171 if (span->arrayMask & SPAN_XY) {
1172 int i;
1173 for (i = 0; i < span->end; i++) {
1174 if (span->mask[i]) {
1175 assert(span->xArray[i] >= ctx->DrawBuffer->_Xmin);
1176 assert(span->xArray[i] < ctx->DrawBuffer->_Xmax);
1177 assert(span->yArray[i] >= ctx->DrawBuffer->_Ymin);
1178 assert(span->yArray[i] < ctx->DrawBuffer->_Ymax);
1179 }
1180 }
1181 }
1182 #endif
1183
1184 /* Polygon Stippling */
1185 if (ctx->Polygon.StippleFlag && primitive == GL_POLYGON) {
1186 stipple_polygon_span(ctx, span);
1187 }
1188
1189 /* Need texture coordinates now */
1190 if ((span->interpMask & SPAN_TEXTURE)
1191 && (span->arrayMask & SPAN_TEXTURE) == 0)
1192 interpolate_texcoords(ctx, span);
1193
1194 /* Texture with alpha test */
1195 if (ctx->Color.AlphaEnabled) {
1196
1197 /* Now we need the rgba array, fill it in if needed */
1198 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1199 interpolate_colors(ctx, span);
1200
1201 /* Texturing without alpha is done after depth-testing which
1202 * gives a potential speed-up.
1203 */
1204 _swrast_multitexture_fragments( ctx, span );
1205
1206 /* Do the alpha test */
1207 if (!_mesa_alpha_test(ctx, span)) {
1208 span->arrayMask = origArrayMask;
1209 return;
1210 }
1211 }
1212
1213 /* Stencil and Z testing */
1214 if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1215 if (span->interpMask & SPAN_Z)
1216 interpolate_z(ctx, span);
1217
1218 if (ctx->Stencil.Enabled) {
1219 if (!_mesa_stencil_and_ztest_span(ctx, span)) {
1220 span->arrayMask = origArrayMask;
1221 return;
1222 }
1223 }
1224 else {
1225 ASSERT(ctx->Depth.Test);
1226 ASSERT(span->arrayMask & SPAN_Z);
1227 /* regular depth testing */
1228 if (!_mesa_depth_test_span(ctx, span)) {
1229 span->arrayMask = origArrayMask;
1230 return;
1231 }
1232 }
1233 }
1234
1235 /* if we get here, some fragments passed the depth test */
1236 ctx->OcclusionResult = GL_TRUE;
1237
1238 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1239 * the occlusion test.
1240 */
1241 if (colorMask == 0x0) {
1242 span->arrayMask = origArrayMask;
1243 return;
1244 }
1245
1246 /* Texture without alpha test */
1247 if (!ctx->Color.AlphaEnabled) {
1248
1249 /* Now we need the rgba array, fill it in if needed */
1250 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1251 interpolate_colors(ctx, span);
1252
1253 _swrast_multitexture_fragments( ctx, span );
1254 }
1255
1256 ASSERT(span->arrayMask & SPAN_RGBA);
1257
1258 /* Add base and specular colors */
1259 if (ctx->Fog.ColorSumEnabled ||
1260 (ctx->Light.Enabled &&
1261 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1262 if (span->interpMask & SPAN_SPEC) {
1263 interpolate_specular(ctx, span);
1264 }
1265 ASSERT(span->arrayMask & SPAN_SPEC);
1266 add_colors( span->end, span->color.rgba, span->specArray );
1267 }
1268
1269 /* Fog */
1270 /* XXX try to simplify the fog code! */
1271 if (ctx->Fog.Enabled) {
1272 if ((span->arrayMask & SPAN_FOG) && !swrast->_PreferPixelFog) {
1273 _mesa_fog_rgba_pixels_with_array( ctx, span, span->fogArray,
1274 span->color.rgba);
1275 }
1276 else if ((span->interpMask & SPAN_FOG) && !swrast->_PreferPixelFog) {
1277 _mesa_fog_rgba_pixels( ctx, span, span->color.rgba );
1278 }
1279 else {
1280 if ((span->interpMask & SPAN_Z) && (span->arrayMask & SPAN_Z) == 0)
1281 interpolate_z(ctx, span);
1282 _mesa_depth_fog_rgba_pixels(ctx, span, span->color.rgba);
1283 }
1284 }
1285
1286 /* Antialias coverage application */
1287 if (span->arrayMask & SPAN_COVERAGE) {
1288 GLchan (*rgba)[4] = span->color.rgba;
1289 GLuint i;
1290 for (i = 0; i < span->end; i++) {
1291 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * span->coverage[i]);
1292 }
1293 }
1294
1295 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1296 multi_write_rgba_span(ctx, span);
1297 }
1298 else {
1299 /* normal: write to exactly one buffer */
1300 if (ctx->Color.ColorLogicOpEnabled) {
1301 _mesa_logicop_rgba_span(ctx, span, span->color.rgba);
1302 }
1303 else if (ctx->Color.BlendEnabled) {
1304 _mesa_blend_span(ctx, span, span->color.rgba);
1305 }
1306
1307 if (colorMask != 0xffffffff) {
1308 _mesa_mask_rgba_span(ctx, span, span->color.rgba);
1309 }
1310
1311
1312 if (span->arrayMask & SPAN_XY) {
1313 /* array of pixel coords */
1314 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->xArray,
1315 span->yArray, (const GLchan (*)[4]) span->color.rgba, span->mask);
1316 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1317 _mesa_write_alpha_pixels(ctx, span->end,
1318 span->xArray, span->yArray,
1319 (const GLchan (*)[4]) span->color.rgba,
1320 span->mask);
1321 }
1322 }
1323 else {
1324 /* horizontal run of pixels */
1325 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
1326 (const GLchan (*)[4]) span->color.rgba,
1327 span->writeAll ? NULL : span->mask);
1328 if (swrast->_RasterMask & ALPHABUF_BIT) {
1329 _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
1330 (const GLchan (*)[4]) span->color.rgba,
1331 span->writeAll ? NULL : span->mask);
1332 }
1333 }
1334 }
1335
1336 span->arrayMask = origArrayMask;
1337 }
1338
1339
1340
1341 /**
1342 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1343 * reading ouside the buffer's boundaries.
1344 */
1345 void
1346 _mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
1347 GLuint n, GLint x, GLint y, GLchan rgba[][4] )
1348 {
1349 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1350 if (y < 0 || y >= buffer->Height
1351 || x + (GLint) n < 0 || x >= buffer->Width) {
1352 /* completely above, below, or right */
1353 /* XXX maybe leave undefined? */
1354 BZERO(rgba, 4 * n * sizeof(GLchan));
1355 }
1356 else {
1357 GLint skip, length;
1358 if (x < 0) {
1359 /* left edge clippping */
1360 skip = -x;
1361 length = (GLint) n - skip;
1362 if (length < 0) {
1363 /* completely left of window */
1364 return;
1365 }
1366 if (length > buffer->Width) {
1367 length = buffer->Width;
1368 }
1369 }
1370 else if ((GLint) (x + n) > buffer->Width) {
1371 /* right edge clipping */
1372 skip = 0;
1373 length = buffer->Width - x;
1374 if (length < 0) {
1375 /* completely to right of window */
1376 return;
1377 }
1378 }
1379 else {
1380 /* no clipping */
1381 skip = 0;
1382 length = (GLint) n;
1383 }
1384
1385 (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
1386 if (buffer->UseSoftwareAlphaBuffers) {
1387 _mesa_read_alpha_span(ctx, length, x + skip, y, rgba + skip);
1388 }
1389 }
1390 }
1391
1392
1393 /**
1394 * Read CI pixels from frame buffer. Clipping will be done to prevent
1395 * reading ouside the buffer's boundaries.
1396 */
1397 void
1398 _mesa_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
1399 GLuint n, GLint x, GLint y, GLuint indx[] )
1400 {
1401 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1402 if (y < 0 || y >= buffer->Height
1403 || x + (GLint) n < 0 || x >= buffer->Width) {
1404 /* completely above, below, or right */
1405 BZERO(indx, n * sizeof(GLuint));
1406 }
1407 else {
1408 GLint skip, length;
1409 if (x < 0) {
1410 /* left edge clippping */
1411 skip = -x;
1412 length = (GLint) n - skip;
1413 if (length < 0) {
1414 /* completely left of window */
1415 return;
1416 }
1417 if (length > buffer->Width) {
1418 length = buffer->Width;
1419 }
1420 }
1421 else if ((GLint) (x + n) > buffer->Width) {
1422 /* right edge clipping */
1423 skip = 0;
1424 length = buffer->Width - x;
1425 if (length < 0) {
1426 /* completely to right of window */
1427 return;
1428 }
1429 }
1430 else {
1431 /* no clipping */
1432 skip = 0;
1433 length = (GLint) n;
1434 }
1435
1436 (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
1437 }
1438 }