replace _mesa_ prefix with _swrast_, remove s_histogram.[ch]
[mesa.git] / src / mesa / swrast / s_span.c
1 /* $Id: s_span.c,v 1.60 2003/03/25 02:23:47 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 _swrast_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 _swrast_span_default_fog( GLcontext *ctx, struct sw_span *span )
77 {
78 span->fog = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
79 span->fogStep = span->dfogdx = span->dfogdy = 0.0F;
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 _swrast_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 _swrast_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 _swrast_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 GLfloat
325 _swrast_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 const GLboolean needLambda = (obj->MinFilter != obj->MagFilter)
365 || ctx->FragmentProgram.Enabled;
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 texcoord[i][3] = q;
389 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
390 dqdx, dqdy, texW, texH,
391 s, t, q, invQ);
392 s += dsdx;
393 t += dtdx;
394 r += drdx;
395 q += dqdx;
396 }
397 span->arrayMask |= SPAN_LAMBDA;
398 }
399 else {
400 GLfloat (*texcoord)[4] = span->array->texcoords[u];
401 GLfloat *lambda = span->array->lambda[u];
402 const GLfloat dsdx = span->texStepX[u][0];
403 const GLfloat dtdx = span->texStepX[u][1];
404 const GLfloat drdx = span->texStepX[u][2];
405 const GLfloat dqdx = span->texStepX[u][3];
406 GLfloat s = span->tex[u][0];
407 GLfloat t = span->tex[u][1];
408 GLfloat r = span->tex[u][2];
409 GLfloat q = span->tex[u][3];
410 GLuint i;
411 if (dqdx == 0.0) {
412 /* Ortho projection or polygon's parallel to window X axis */
413 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
414 for (i = 0; i < span->end; i++) {
415 texcoord[i][0] = s * invQ;
416 texcoord[i][1] = t * invQ;
417 texcoord[i][2] = r * invQ;
418 lambda[i] = 0.0;
419 s += dsdx;
420 t += dtdx;
421 r += drdx;
422 }
423 }
424 else {
425 for (i = 0; i < span->end; i++) {
426 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
427 texcoord[i][0] = s * invQ;
428 texcoord[i][1] = t * invQ;
429 texcoord[i][2] = r * invQ;
430 lambda[i] = 0.0;
431 s += dsdx;
432 t += dtdx;
433 r += drdx;
434 q += dqdx;
435 }
436 }
437 } /* lambda */
438 } /* if */
439 } /* for */
440 }
441 else {
442 /* single texture */
443 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
444 const struct gl_texture_image *img = obj->Image[obj->BaseLevel];
445 const GLboolean needLambda = (obj->MinFilter != obj->MagFilter)
446 || ctx->FragmentProgram.Enabled;
447 span->arrayMask |= SPAN_TEXTURE;
448 if (needLambda) {
449 /* just texture unit 0, with lambda */
450 GLfloat (*texcoord)[4] = span->array->texcoords[0];
451 GLfloat *lambda = span->array->lambda[0];
452 const GLfloat texW = (GLfloat) img->WidthScale;
453 const GLfloat texH = (GLfloat) img->HeightScale;
454 const GLfloat dsdx = span->texStepX[0][0];
455 const GLfloat dsdy = span->texStepY[0][0];
456 const GLfloat dtdx = span->texStepX[0][1];
457 const GLfloat dtdy = span->texStepY[0][1];
458 const GLfloat drdx = span->texStepX[0][2];
459 const GLfloat dqdx = span->texStepX[0][3];
460 const GLfloat dqdy = span->texStepY[0][3];
461 GLfloat s = span->tex[0][0];
462 GLfloat t = span->tex[0][1];
463 GLfloat r = span->tex[0][2];
464 GLfloat q = span->tex[0][3];
465 GLuint i;
466 for (i = 0; i < span->end; i++) {
467 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
468 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
469 dqdx, dqdy, texW, texH,
470 s, t, q, invQ);
471 texcoord[i][0] = s * invQ;
472 texcoord[i][1] = t * invQ;
473 texcoord[i][2] = r * invQ;
474 texcoord[i][3] = q;
475 s += dsdx;
476 t += dtdx;
477 r += drdx;
478 q += dqdx;
479 }
480 span->arrayMask |= SPAN_LAMBDA;
481 }
482 else {
483 /* just texture 0, without lambda */
484 GLfloat (*texcoord)[4] = span->array->texcoords[0];
485 const GLfloat dsdx = span->texStepX[0][0];
486 const GLfloat dtdx = span->texStepX[0][1];
487 const GLfloat drdx = span->texStepX[0][2];
488 const GLfloat dqdx = span->texStepX[0][3];
489 GLfloat s = span->tex[0][0];
490 GLfloat t = span->tex[0][1];
491 GLfloat r = span->tex[0][2];
492 GLfloat q = span->tex[0][3];
493 GLuint i;
494 if (dqdx == 0.0) {
495 /* Ortho projection or polygon's parallel to window X axis */
496 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
497 for (i = 0; i < span->end; i++) {
498 texcoord[i][0] = s * invQ;
499 texcoord[i][1] = t * invQ;
500 texcoord[i][2] = r * invQ;
501 s += dsdx;
502 t += dtdx;
503 r += drdx;
504 }
505 }
506 else {
507 for (i = 0; i < span->end; i++) {
508 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
509 texcoord[i][0] = s * invQ;
510 texcoord[i][1] = t * invQ;
511 texcoord[i][2] = r * invQ;
512 s += dsdx;
513 t += dtdx;
514 r += drdx;
515 q += dqdx;
516 }
517 }
518 }
519 }
520 }
521
522
523 /**
524 * Apply the current polygon stipple pattern to a span of pixels.
525 */
526 static void
527 stipple_polygon_span( GLcontext *ctx, struct sw_span *span )
528 {
529 const GLuint highbit = 0x80000000;
530 const GLuint stipple = ctx->PolygonStipple[span->y % 32];
531 GLubyte *mask = span->array->mask;
532 GLuint i, m;
533
534 ASSERT(ctx->Polygon.StippleFlag);
535 ASSERT((span->arrayMask & SPAN_XY) == 0);
536
537 m = highbit >> (GLuint) (span->x % 32);
538
539 for (i = 0; i < span->end; i++) {
540 if ((m & stipple) == 0) {
541 mask[i] = 0;
542 }
543 m = m >> 1;
544 if (m == 0) {
545 m = highbit;
546 }
547 }
548 span->writeAll = GL_FALSE;
549 }
550
551
552 /**
553 * Clip a pixel span to the current buffer/window boundaries:
554 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
555 * window clipping and scissoring.
556 * Return: GL_TRUE some pixels still visible
557 * GL_FALSE nothing visible
558 */
559 static GLuint
560 clip_span( GLcontext *ctx, struct sw_span *span )
561 {
562 const GLint xmin = ctx->DrawBuffer->_Xmin;
563 const GLint xmax = ctx->DrawBuffer->_Xmax;
564 const GLint ymin = ctx->DrawBuffer->_Ymin;
565 const GLint ymax = ctx->DrawBuffer->_Ymax;
566
567 if (span->arrayMask & SPAN_XY) {
568 /* arrays of x/y pixel coords */
569 const GLint *x = span->array->x;
570 const GLint *y = span->array->y;
571 const GLint n = span->end;
572 GLubyte *mask = span->array->mask;
573 GLint i;
574 if (span->arrayMask & SPAN_MASK) {
575 /* note: using & intead of && to reduce branches */
576 for (i = 0; i < n; i++) {
577 mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
578 & (y[i] >= ymin) & (y[i] < ymax);
579 }
580 }
581 else {
582 /* note: using & intead of && to reduce branches */
583 for (i = 0; i < n; i++) {
584 mask[i] = (x[i] >= xmin) & (x[i] < xmax)
585 & (y[i] >= ymin) & (y[i] < ymax);
586 }
587 }
588 return GL_TRUE; /* some pixels visible */
589 }
590 else {
591 /* horizontal span of pixels */
592 const GLint x = span->x;
593 const GLint y = span->y;
594 const GLint n = span->end;
595
596 /* Trivial rejection tests */
597 if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
598 span->end = 0;
599 return GL_FALSE; /* all pixels clipped */
600 }
601
602 /* Clip to the left */
603 if (x < xmin) {
604 ASSERT(x + n > xmin);
605 span->writeAll = GL_FALSE;
606 _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
607 }
608
609 /* Clip to right */
610 if (x + n > xmax) {
611 ASSERT(x < xmax);
612 span->end = xmax - x;
613 }
614
615 return GL_TRUE; /* some pixels visible */
616 }
617 }
618
619
620
621 /**
622 * Draw to more than one color buffer (or none).
623 */
624 static void
625 multi_write_index_span( GLcontext *ctx, struct sw_span *span )
626 {
627 SWcontext *swrast = SWRAST_CONTEXT(ctx);
628 GLuint bufferBit;
629
630 /* loop over four possible dest color buffers */
631 for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) {
632 if (bufferBit & ctx->Color._DrawDestMask) {
633 GLuint indexTmp[MAX_WIDTH];
634 ASSERT(span->end < MAX_WIDTH);
635
636 /* Set the current read/draw buffer */
637 swrast->CurrentBuffer = bufferBit;
638 (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
639
640 /* make copy of incoming indexes */
641 MEMCPY( indexTmp, span->array->index, span->end * sizeof(GLuint) );
642
643 if (ctx->Color.IndexLogicOpEnabled) {
644 _swrast_logicop_ci_span(ctx, span, indexTmp);
645 }
646
647 if (ctx->Color.IndexMask != 0xffffffff) {
648 _swrast_mask_index_span(ctx, span, indexTmp);
649 }
650
651 if (span->arrayMask & SPAN_XY) {
652 /* array of pixel coords */
653 (*swrast->Driver.WriteCI32Pixels)(ctx, span->end,
654 span->array->x, span->array->y,
655 indexTmp, span->array->mask);
656 }
657 else {
658 /* horizontal run of pixels */
659 (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
660 indexTmp, span->array->mask);
661 }
662 }
663 }
664
665 /* restore default dest buffer */
666 _swrast_use_draw_buffer(ctx);
667 }
668
669
670 /**
671 * Draw to more than one RGBA color buffer (or none).
672 * All fragment operations, up to (but not) blending/logicop should
673 * have been done first.
674 */
675 static void
676 multi_write_rgba_span( GLcontext *ctx, struct sw_span *span )
677 {
678 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
679 GLuint bufferBit;
680 SWcontext *swrast = SWRAST_CONTEXT(ctx);
681
682 ASSERT(colorMask != 0x0);
683
684 if (ctx->Color.DrawBuffer == GL_NONE)
685 return;
686
687 /* loop over four possible dest color buffers */
688 for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) {
689 if (bufferBit & ctx->Color._DrawDestMask) {
690 GLchan rgbaTmp[MAX_WIDTH][4];
691 ASSERT(span->end < MAX_WIDTH);
692
693 /* Set the current read/draw buffer */
694 swrast->CurrentBuffer = bufferBit;
695 (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
696
697 /* make copy of incoming colors */
698 MEMCPY( rgbaTmp, span->array->rgba, 4 * span->end * sizeof(GLchan) );
699
700 if (ctx->Color.ColorLogicOpEnabled) {
701 _swrast_logicop_rgba_span(ctx, span, rgbaTmp);
702 }
703 else if (ctx->Color.BlendEnabled) {
704 _swrast_blend_span(ctx, span, rgbaTmp);
705 }
706
707 if (colorMask != 0xffffffff) {
708 _swrast_mask_rgba_span(ctx, span, rgbaTmp);
709 }
710
711 if (span->arrayMask & SPAN_XY) {
712 /* array of pixel coords */
713 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end,
714 span->array->x, span->array->y,
715 (const GLchan (*)[4]) rgbaTmp,
716 span->array->mask);
717 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
718 _swrast_write_alpha_pixels(ctx, span->end,
719 span->array->x, span->array->y,
720 (const GLchan (*)[4]) rgbaTmp,
721 span->array->mask);
722 }
723 }
724 else {
725 /* horizontal run of pixels */
726 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
727 (const GLchan (*)[4]) rgbaTmp,
728 span->array->mask);
729 if (swrast->_RasterMask & ALPHABUF_BIT) {
730 _swrast_write_alpha_span(ctx, span->end, span->x, span->y,
731 (const GLchan (*)[4]) rgbaTmp,
732 span->array->mask);
733 }
734 }
735 }
736 }
737
738 /* restore default dest buffer */
739 _swrast_use_draw_buffer(ctx);
740 }
741
742
743
744 /**
745 * This function may modify any of the array values in the span.
746 * span->interpMask and span->arrayMask may be changed but will be restored
747 * to their original values before returning.
748 */
749 void
750 _swrast_write_index_span( GLcontext *ctx, struct sw_span *span)
751 {
752 SWcontext *swrast = SWRAST_CONTEXT(ctx);
753 const GLuint origInterpMask = span->interpMask;
754 const GLuint origArrayMask = span->arrayMask;
755
756 ASSERT(span->end <= MAX_WIDTH);
757 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
758 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
759 ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
760 ASSERT((span->interpMask & span->arrayMask) == 0);
761
762 if (span->arrayMask & SPAN_MASK) {
763 /* mask was initialized by caller, probably glBitmap */
764 span->writeAll = GL_FALSE;
765 }
766 else {
767 MEMSET(span->array->mask, 1, span->end);
768 span->writeAll = GL_TRUE;
769 }
770
771 /* Clipping */
772 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
773 if (!clip_span(ctx, span)) {
774 return;
775 }
776 }
777
778 #ifdef DEBUG
779 if (span->arrayMask & SPAN_XY) {
780 GLuint i;
781 for (i = 0; i < span->end; i++) {
782 if (span->array->mask[i]) {
783 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
784 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
785 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
786 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
787 }
788 }
789 }
790 #endif
791
792 /* Polygon Stippling */
793 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
794 stipple_polygon_span(ctx, span);
795 }
796
797 /* Depth test and stencil */
798 if (ctx->Depth.Test || ctx->Stencil.Enabled) {
799 if (span->interpMask & SPAN_Z)
800 _swrast_span_interpolate_z(ctx, span);
801
802 if (ctx->Stencil.Enabled) {
803 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
804 span->arrayMask = origArrayMask;
805 return;
806 }
807 }
808 else {
809 ASSERT(ctx->Depth.Test);
810 if (!_swrast_depth_test_span(ctx, span)) {
811 span->arrayMask = origArrayMask;
812 return;
813 }
814 }
815 }
816
817 /* if we get here, something passed the depth test */
818 ctx->OcclusionResult = GL_TRUE;
819
820 /* we have to wait until after occlusion to do this test */
821 if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
822 /* write no pixels */
823 span->arrayMask = origArrayMask;
824 return;
825 }
826
827 /* Interpolate the color indexes if needed */
828 if (span->interpMask & SPAN_INDEX) {
829 interpolate_indexes(ctx, span);
830 /* clear the bit - this allows the WriteMonoCISpan optimization below */
831 span->interpMask &= ~SPAN_INDEX;
832 }
833
834 /* Fog */
835 if (ctx->Fog.Enabled) {
836 _swrast_fog_ci_span(ctx, span);
837 }
838
839 /* Antialias coverage application */
840 if (span->arrayMask & SPAN_COVERAGE) {
841 GLuint i;
842 GLuint *index = span->array->index;
843 GLfloat *coverage = span->array->coverage;
844 for (i = 0; i < span->end; i++) {
845 ASSERT(coverage[i] < 16);
846 index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
847 }
848 }
849
850 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
851 /* draw to zero or two or more buffers */
852 multi_write_index_span(ctx, span);
853 }
854 else {
855 /* normal situation: draw to exactly one buffer */
856 if (ctx->Color.IndexLogicOpEnabled) {
857 _swrast_logicop_ci_span(ctx, span, span->array->index);
858 }
859
860 if (ctx->Color.IndexMask != 0xffffffff) {
861 _swrast_mask_index_span(ctx, span, span->array->index);
862 }
863
864 /* write pixels */
865 if (span->arrayMask & SPAN_XY) {
866 /* array of pixel coords */
867 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
868 /* all pixels have same color index */
869 (*swrast->Driver.WriteMonoCIPixels)(ctx, span->end,
870 span->array->x, span->array->y,
871 FixedToInt(span->index),
872 span->array->mask);
873 }
874 else {
875 (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, span->array->x,
876 span->array->y, span->array->index,
877 span->array->mask );
878 }
879 }
880 else {
881 /* horizontal run of pixels */
882 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
883 /* all pixels have same color index */
884 (*swrast->Driver.WriteMonoCISpan)(ctx, span->end, span->x, span->y,
885 FixedToInt(span->index),
886 span->array->mask);
887 }
888 else {
889 (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
890 span->array->index,
891 span->array->mask);
892 }
893 }
894 }
895
896 span->interpMask = origInterpMask;
897 span->arrayMask = origArrayMask;
898 }
899
900
901 /**
902 * This function may modify any of the array values in the span.
903 * span->interpMask and span->arrayMask may be changed but will be restored
904 * to their original values before returning.
905 */
906 void
907 _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
908 {
909 SWcontext *swrast = SWRAST_CONTEXT(ctx);
910 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
911 const GLuint origInterpMask = span->interpMask;
912 const GLuint origArrayMask = span->arrayMask;
913 GLboolean monoColor;
914
915 ASSERT(span->end <= MAX_WIDTH);
916 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
917 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
918 ASSERT((span->interpMask & span->arrayMask) == 0);
919 ASSERT((span->interpMask | span->arrayMask) & SPAN_RGBA);
920 #ifdef DEBUG
921 if (ctx->Fog.Enabled)
922 ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG);
923 if (ctx->Depth.Test)
924 ASSERT((span->interpMask | span->arrayMask) & SPAN_Z);
925 #endif
926
927 if (span->arrayMask & SPAN_MASK) {
928 /* mask was initialized by caller, probably glBitmap */
929 span->writeAll = GL_FALSE;
930 }
931 else {
932 MEMSET(span->array->mask, 1, span->end);
933 span->writeAll = GL_TRUE;
934 }
935
936 /* Determine if we have mono-chromatic colors */
937 monoColor = (span->interpMask & SPAN_RGBA) &&
938 span->redStep == 0 && span->greenStep == 0 &&
939 span->blueStep == 0 && span->alphaStep == 0;
940
941 /* Clipping */
942 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
943 if (!clip_span(ctx, span)) {
944 return;
945 }
946 }
947
948 #ifdef DEBUG
949 if (span->arrayMask & SPAN_XY) {
950 GLuint i;
951 for (i = 0; i < span->end; i++) {
952 if (span->array->mask[i]) {
953 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
954 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
955 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
956 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
957 }
958 }
959 }
960 #endif
961
962 /* Polygon Stippling */
963 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
964 stipple_polygon_span(ctx, span);
965 }
966
967 /* Fragment program */
968 if (ctx->FragmentProgram.Enabled) {
969 /* Now we may need to interpolate the colors */
970 if ((span->interpMask & SPAN_RGBA) &&
971 (span->arrayMask & SPAN_RGBA) == 0) {
972 interpolate_colors(ctx, span);
973 span->interpMask &= ~SPAN_RGBA;
974 }
975 _swrast_exec_nv_fragment_program(ctx, span);
976 monoColor = GL_FALSE;
977 }
978
979 /* Do the alpha test */
980 if (ctx->Color.AlphaEnabled) {
981 if (!_swrast_alpha_test(ctx, span)) {
982 span->interpMask = origInterpMask;
983 span->arrayMask = origArrayMask;
984 return;
985 }
986 }
987
988 /* Stencil and Z testing */
989 if (ctx->Stencil.Enabled || ctx->Depth.Test) {
990 if (span->interpMask & SPAN_Z)
991 _swrast_span_interpolate_z(ctx, span);
992
993 if (ctx->Stencil.Enabled) {
994 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
995 span->interpMask = origInterpMask;
996 span->arrayMask = origArrayMask;
997 return;
998 }
999 }
1000 else {
1001 ASSERT(ctx->Depth.Test);
1002 ASSERT(span->arrayMask & SPAN_Z);
1003 /* regular depth testing */
1004 if (!_swrast_depth_test_span(ctx, span)) {
1005 span->interpMask = origInterpMask;
1006 span->arrayMask = origArrayMask;
1007 return;
1008 }
1009 }
1010 }
1011
1012 /* if we get here, something passed the depth test */
1013 ctx->OcclusionResult = GL_TRUE;
1014
1015 /* can't abort span-writing until after occlusion testing */
1016 if (colorMask == 0x0) {
1017 span->interpMask = origInterpMask;
1018 span->arrayMask = origArrayMask;
1019 return;
1020 }
1021
1022 /* Now we may need to interpolate the colors */
1023 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) {
1024 interpolate_colors(ctx, span);
1025 /* clear the bit - this allows the WriteMonoCISpan optimization below */
1026 span->interpMask &= ~SPAN_RGBA;
1027 }
1028
1029 /* Fog */
1030 if (ctx->Fog.Enabled) {
1031 _swrast_fog_rgba_span(ctx, span);
1032 monoColor = GL_FALSE;
1033 }
1034
1035 /* Antialias coverage application */
1036 if (span->arrayMask & SPAN_COVERAGE) {
1037 GLchan (*rgba)[4] = span->array->rgba;
1038 GLfloat *coverage = span->array->coverage;
1039 GLuint i;
1040 for (i = 0; i < span->end; i++) {
1041 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
1042 }
1043 monoColor = GL_FALSE;
1044 }
1045
1046 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1047 multi_write_rgba_span(ctx, span);
1048 }
1049 else {
1050 /* normal: write to exactly one buffer */
1051 if (ctx->Color.ColorLogicOpEnabled) {
1052 _swrast_logicop_rgba_span(ctx, span, span->array->rgba);
1053 monoColor = GL_FALSE;
1054 }
1055 else if (ctx->Color.BlendEnabled) {
1056 _swrast_blend_span(ctx, span, span->array->rgba);
1057 monoColor = GL_FALSE;
1058 }
1059
1060 /* Color component masking */
1061 if (colorMask != 0xffffffff) {
1062 _swrast_mask_rgba_span(ctx, span, span->array->rgba);
1063 monoColor = GL_FALSE;
1064 }
1065
1066 /* write pixels */
1067 if (span->arrayMask & SPAN_XY) {
1068 /* array of pixel coords */
1069 /* XXX test for mono color */
1070 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
1071 span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask);
1072 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1073 _swrast_write_alpha_pixels(ctx, span->end,
1074 span->array->x, span->array->y,
1075 (const GLchan (*)[4]) span->array->rgba,
1076 span->array->mask);
1077 }
1078 }
1079 else {
1080 /* horizontal run of pixels */
1081 if (monoColor) {
1082 /* all pixels have same color */
1083 GLchan color[4];
1084 color[RCOMP] = FixedToChan(span->red);
1085 color[GCOMP] = FixedToChan(span->green);
1086 color[BCOMP] = FixedToChan(span->blue);
1087 color[ACOMP] = FixedToChan(span->alpha);
1088 (*swrast->Driver.WriteMonoRGBASpan)(ctx, span->end, span->x,
1089 span->y, color, span->array->mask);
1090 if (swrast->_RasterMask & ALPHABUF_BIT) {
1091 _swrast_write_mono_alpha_span(ctx, span->end, span->x, span->y,
1092 color[ACOMP],
1093 span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
1094 }
1095 }
1096 else {
1097 /* each pixel is a different color */
1098 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
1099 (const GLchan (*)[4]) span->array->rgba,
1100 span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
1101 if (swrast->_RasterMask & ALPHABUF_BIT) {
1102 _swrast_write_alpha_span(ctx, span->end, span->x, span->y,
1103 (const GLchan (*)[4]) span->array->rgba,
1104 span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
1105 }
1106 }
1107 }
1108 }
1109
1110 span->interpMask = origInterpMask;
1111 span->arrayMask = origArrayMask;
1112 }
1113
1114
1115 /**
1116 * Add specular color to base color. This is used only when
1117 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1118 */
1119 static void
1120 add_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] )
1121 {
1122 GLuint i;
1123 for (i = 0; i < n; i++) {
1124 #if CHAN_TYPE == GL_FLOAT
1125 /* no clamping */
1126 rgba[i][RCOMP] += specular[i][RCOMP];
1127 rgba[i][GCOMP] += specular[i][GCOMP];
1128 rgba[i][BCOMP] += specular[i][BCOMP];
1129 #else
1130 GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
1131 GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
1132 GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
1133 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1134 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1135 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1136 #endif
1137 }
1138 }
1139
1140
1141 /**
1142 * This function may modify any of the array values in the span.
1143 * span->interpMask and span->arrayMask may be changed but will be restored
1144 * to their original values before returning.
1145 */
1146 void
1147 _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span)
1148 {
1149 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1150 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1151 const GLuint origArrayMask = span->arrayMask;
1152
1153 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
1154 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
1155 ASSERT(span->end <= MAX_WIDTH);
1156 ASSERT((span->interpMask & span->arrayMask) == 0);
1157 ASSERT(ctx->Texture._EnabledUnits);
1158
1159 /*
1160 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1161 */
1162
1163 if (span->arrayMask & SPAN_MASK) {
1164 /* mask was initialized by caller, probably glBitmap */
1165 span->writeAll = GL_FALSE;
1166 }
1167 else {
1168 MEMSET(span->array->mask, 1, span->end);
1169 span->writeAll = GL_TRUE;
1170 }
1171
1172 /* Clipping */
1173 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1174 if (!clip_span(ctx, span)) {
1175 return;
1176 }
1177 }
1178
1179 #ifdef DEBUG
1180 if (span->arrayMask & SPAN_XY) {
1181 GLuint i;
1182 for (i = 0; i < span->end; i++) {
1183 if (span->array->mask[i]) {
1184 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
1185 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
1186 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
1187 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1188 }
1189 }
1190 }
1191 #endif
1192
1193 /* Polygon Stippling */
1194 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1195 stipple_polygon_span(ctx, span);
1196 }
1197
1198 /* Need texture coordinates now */
1199 if ((span->interpMask & SPAN_TEXTURE)
1200 && (span->arrayMask & SPAN_TEXTURE) == 0)
1201 interpolate_texcoords(ctx, span);
1202
1203 /* Texture with alpha test */
1204 if (ctx->Color.AlphaEnabled) {
1205
1206 /* Now we need the rgba array, fill it in if needed */
1207 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1208 interpolate_colors(ctx, span);
1209
1210 /* Texturing without alpha is done after depth-testing which
1211 * gives a potential speed-up.
1212 */
1213 if (ctx->FragmentProgram.Enabled)
1214 _swrast_exec_nv_fragment_program( ctx, span );
1215 else
1216 _swrast_texture_span( ctx, span );
1217
1218 /* Do the alpha test */
1219 if (!_swrast_alpha_test(ctx, span)) {
1220 span->arrayMask = origArrayMask;
1221 return;
1222 }
1223 }
1224
1225 /* Stencil and Z testing */
1226 if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1227 if (span->interpMask & SPAN_Z)
1228 _swrast_span_interpolate_z(ctx, span);
1229
1230 if (ctx->Stencil.Enabled) {
1231 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1232 span->arrayMask = origArrayMask;
1233 return;
1234 }
1235 }
1236 else {
1237 ASSERT(ctx->Depth.Test);
1238 ASSERT(span->arrayMask & SPAN_Z);
1239 /* regular depth testing */
1240 if (!_swrast_depth_test_span(ctx, span)) {
1241 span->arrayMask = origArrayMask;
1242 return;
1243 }
1244 }
1245 }
1246
1247 /* if we get here, some fragments passed the depth test */
1248 ctx->OcclusionResult = GL_TRUE;
1249
1250 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1251 * the occlusion test.
1252 */
1253 if (colorMask == 0x0) {
1254 span->arrayMask = origArrayMask;
1255 return;
1256 }
1257
1258 /* Texture without alpha test */
1259 if (!ctx->Color.AlphaEnabled) {
1260
1261 /* Now we need the rgba array, fill it in if needed */
1262 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1263 interpolate_colors(ctx, span);
1264
1265 if (ctx->FragmentProgram.Enabled)
1266 _swrast_exec_nv_fragment_program( ctx, span );
1267 else
1268 _swrast_texture_span( ctx, span );
1269 }
1270
1271 ASSERT(span->arrayMask & SPAN_RGBA);
1272
1273 /* Add base and specular colors */
1274 if (ctx->Fog.ColorSumEnabled ||
1275 (ctx->Light.Enabled &&
1276 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1277 if (span->interpMask & SPAN_SPEC) {
1278 interpolate_specular(ctx, span);
1279 }
1280 ASSERT(span->arrayMask & SPAN_SPEC);
1281 add_colors( span->end, span->array->rgba, span->array->spec );
1282 }
1283
1284 /* Fog */
1285 if (ctx->Fog.Enabled) {
1286 _swrast_fog_rgba_span(ctx, span);
1287 }
1288
1289 /* Antialias coverage application */
1290 if (span->arrayMask & SPAN_COVERAGE) {
1291 GLchan (*rgba)[4] = span->array->rgba;
1292 GLfloat *coverage = span->array->coverage;
1293 GLuint i;
1294 for (i = 0; i < span->end; i++) {
1295 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
1296 }
1297 }
1298
1299 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1300 multi_write_rgba_span(ctx, span);
1301 }
1302 else {
1303 /* normal: write to exactly one buffer */
1304 if (ctx->Color.ColorLogicOpEnabled) {
1305 _swrast_logicop_rgba_span(ctx, span, span->array->rgba);
1306 }
1307 else if (ctx->Color.BlendEnabled) {
1308 _swrast_blend_span(ctx, span, span->array->rgba);
1309 }
1310
1311 if (colorMask != 0xffffffff) {
1312 _swrast_mask_rgba_span(ctx, span, span->array->rgba);
1313 }
1314
1315
1316 if (span->arrayMask & SPAN_XY) {
1317 /* array of pixel coords */
1318 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
1319 span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask);
1320 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1321 _swrast_write_alpha_pixels(ctx, span->end,
1322 span->array->x, span->array->y,
1323 (const GLchan (*)[4]) span->array->rgba,
1324 span->array->mask);
1325 }
1326 }
1327 else {
1328 /* horizontal run of pixels */
1329 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
1330 (const GLchan (*)[4]) span->array->rgba,
1331 span->writeAll ? NULL : span->array->mask);
1332 if (swrast->_RasterMask & ALPHABUF_BIT) {
1333 _swrast_write_alpha_span(ctx, span->end, span->x, span->y,
1334 (const GLchan (*)[4]) span->array->rgba,
1335 span->writeAll ? NULL : span->array->mask);
1336 }
1337 }
1338 }
1339
1340 span->arrayMask = origArrayMask;
1341 }
1342
1343
1344
1345 /**
1346 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1347 * reading ouside the buffer's boundaries.
1348 */
1349 void
1350 _swrast_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
1351 GLuint n, GLint x, GLint y, GLchan rgba[][4] )
1352 {
1353 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1354 const GLint bufWidth = (GLint) buffer->Width;
1355 const GLint bufHeight = (GLint) buffer->Height;
1356
1357 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1358 /* completely above, below, or right */
1359 /* XXX maybe leave undefined? */
1360 _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1361 }
1362 else {
1363 GLint skip, length;
1364 if (x < 0) {
1365 /* left edge clippping */
1366 skip = -x;
1367 length = (GLint) n - skip;
1368 if (length < 0) {
1369 /* completely left of window */
1370 return;
1371 }
1372 if (length > bufWidth) {
1373 length = bufWidth;
1374 }
1375 }
1376 else if ((GLint) (x + n) > bufWidth) {
1377 /* right edge clipping */
1378 skip = 0;
1379 length = bufWidth - x;
1380 if (length < 0) {
1381 /* completely to right of window */
1382 return;
1383 }
1384 }
1385 else {
1386 /* no clipping */
1387 skip = 0;
1388 length = (GLint) n;
1389 }
1390
1391 (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
1392 if (buffer->UseSoftwareAlphaBuffers) {
1393 _swrast_read_alpha_span(ctx, length, x + skip, y, rgba + skip);
1394 }
1395 }
1396 }
1397
1398
1399 /**
1400 * Read CI pixels from frame buffer. Clipping will be done to prevent
1401 * reading ouside the buffer's boundaries.
1402 */
1403 void
1404 _swrast_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
1405 GLuint n, GLint x, GLint y, GLuint indx[] )
1406 {
1407 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1408 const GLint bufWidth = (GLint) buffer->Width;
1409 const GLint bufHeight = (GLint) buffer->Height;
1410
1411 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1412 /* completely above, below, or right */
1413 _mesa_bzero(indx, n * sizeof(GLuint));
1414 }
1415 else {
1416 GLint skip, length;
1417 if (x < 0) {
1418 /* left edge clippping */
1419 skip = -x;
1420 length = (GLint) n - skip;
1421 if (length < 0) {
1422 /* completely left of window */
1423 return;
1424 }
1425 if (length > bufWidth) {
1426 length = bufWidth;
1427 }
1428 }
1429 else if ((GLint) (x + n) > bufWidth) {
1430 /* right edge clipping */
1431 skip = 0;
1432 length = bufWidth - x;
1433 if (length < 0) {
1434 /* completely to right of window */
1435 return;
1436 }
1437 }
1438 else {
1439 /* no clipping */
1440 skip = 0;
1441 length = (GLint) n;
1442 }
1443
1444 (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
1445 }
1446 }