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