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