s_span.c revision e4f976b8b9d74a74b5816146cb11880c3a493929
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5
4 *
5 * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26/**
27 * \file swrast/s_span.c
28 * \brief Span processing functions used by all rasterization functions.
29 * This is where all the per-fragment tests are performed
30 * \author Brian Paul
31 */
32
33#include "glheader.h"
34#include "colormac.h"
35#include "context.h"
36#include "macros.h"
37#include "imports.h"
38#include "image.h"
39
40#include "s_atifragshader.h"
41#include "s_alpha.h"
42#include "s_blend.h"
43#include "s_context.h"
44#include "s_depth.h"
45#include "s_fog.h"
46#include "s_logic.h"
47#include "s_masking.h"
48#include "s_fragprog.h"
49#include "s_span.h"
50#include "s_stencil.h"
51#include "s_texcombine.h"
52
53
54/**
55 * Init span's Z interpolation values to the RasterPos Z.
56 * Used during setup for glDraw/CopyPixels.
57 */
58void
59_swrast_span_default_z( GLcontext *ctx, SWspan *span )
60{
61   const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
62   if (ctx->DrawBuffer->Visual.depthBits <= 16)
63      span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
64   else
65      span->z = (GLint) (ctx->Current.RasterPos[2] * 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 */
75void
76_swrast_span_default_fog( GLcontext *ctx, SWspan *span )
77{
78   span->attrStart[FRAG_ATTRIB_FOGC][0]
79      = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
80   span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0;
81   span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0;
82   span->interpMask |= SPAN_FOG;
83}
84
85
86/**
87 * Init span's rgba or index interpolation values to the RasterPos color.
88 * Used during setup for glDraw/CopyPixels.
89 */
90void
91_swrast_span_default_color( GLcontext *ctx, SWspan *span )
92{
93   if (ctx->Visual.rgbMode) {
94      GLchan r, g, b, a;
95      UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
96      UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
97      UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
98      UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
99#if CHAN_TYPE == GL_FLOAT
100      span->red = r;
101      span->green = g;
102      span->blue = b;
103      span->alpha = a;
104#else
105      span->red   = IntToFixed(r);
106      span->green = IntToFixed(g);
107      span->blue  = IntToFixed(b);
108      span->alpha = IntToFixed(a);
109#endif
110      span->redStep = 0;
111      span->greenStep = 0;
112      span->blueStep = 0;
113      span->alphaStep = 0;
114      span->interpMask |= SPAN_RGBA;
115   }
116   else {
117      span->index = FloatToFixed(ctx->Current.RasterIndex);
118      span->indexStep = 0;
119      span->interpMask |= SPAN_INDEX;
120   }
121}
122
123
124/**
125 * Init span's texcoord interpolation values to the RasterPos texcoords.
126 * Used during setup for glDraw/CopyPixels.
127 */
128void
129_swrast_span_default_texcoords( GLcontext *ctx, SWspan *span )
130{
131   GLuint i;
132   for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
133      const GLuint attr = FRAG_ATTRIB_TEX0 + i;
134      const GLfloat *tc = ctx->Current.RasterTexCoords[i];
135      if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) {
136         COPY_4V(span->attrStart[attr], tc);
137      }
138      else if (tc[3] > 0.0F) {
139         /* use (s/q, t/q, r/q, 1) */
140         span->attrStart[attr][0] = tc[0] / tc[3];
141         span->attrStart[attr][1] = tc[1] / tc[3];
142         span->attrStart[attr][2] = tc[2] / tc[3];
143         span->attrStart[attr][3] = 1.0;
144      }
145      else {
146         ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F);
147      }
148      ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F);
149      ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F);
150   }
151   span->interpMask |= SPAN_TEXTURE;
152}
153
154
155/**
156 * Interpolate primary colors to fill in the span->array->color array.
157 */
158static INLINE void
159interpolate_colors(SWspan *span)
160{
161   const GLuint n = span->end;
162   GLuint i;
163
164   ASSERT((span->interpMask & SPAN_RGBA)  &&
165          !(span->arrayMask & SPAN_RGBA));
166
167   switch (span->array->ChanType) {
168#if CHAN_BITS != 32
169   case GL_UNSIGNED_BYTE:
170      {
171         GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
172         if (span->interpMask & SPAN_FLAT) {
173            GLubyte color[4];
174            color[RCOMP] = FixedToInt(span->red);
175            color[GCOMP] = FixedToInt(span->green);
176            color[BCOMP] = FixedToInt(span->blue);
177            color[ACOMP] = FixedToInt(span->alpha);
178            for (i = 0; i < n; i++) {
179               COPY_4UBV(rgba[i], color);
180            }
181         }
182         else {
183            GLfixed r = span->red;
184            GLfixed g = span->green;
185            GLfixed b = span->blue;
186            GLfixed a = span->alpha;
187            GLint dr = span->redStep;
188            GLint dg = span->greenStep;
189            GLint db = span->blueStep;
190            GLint da = span->alphaStep;
191            for (i = 0; i < n; i++) {
192               rgba[i][RCOMP] = FixedToChan(r);
193               rgba[i][GCOMP] = FixedToChan(g);
194               rgba[i][BCOMP] = FixedToChan(b);
195               rgba[i][ACOMP] = FixedToChan(a);
196               r += dr;
197               g += dg;
198               b += db;
199               a += da;
200            }
201         }
202      }
203      break;
204   case GL_UNSIGNED_SHORT:
205      {
206         GLushort (*rgba)[4] = span->array->color.sz2.rgba;
207         if (span->interpMask & SPAN_FLAT) {
208            GLushort color[4];
209            color[RCOMP] = FixedToInt(span->red);
210            color[GCOMP] = FixedToInt(span->green);
211            color[BCOMP] = FixedToInt(span->blue);
212            color[ACOMP] = FixedToInt(span->alpha);
213            for (i = 0; i < n; i++) {
214               COPY_4V(rgba[i], color);
215            }
216         }
217         else {
218            GLushort (*rgba)[4] = span->array->color.sz2.rgba;
219            GLfixed r, g, b, a;
220            GLint dr, dg, db, da;
221            r = span->red;
222            g = span->green;
223            b = span->blue;
224            a = span->alpha;
225            dr = span->redStep;
226            dg = span->greenStep;
227            db = span->blueStep;
228            da = span->alphaStep;
229            for (i = 0; i < n; i++) {
230               rgba[i][RCOMP] = FixedToChan(r);
231               rgba[i][GCOMP] = FixedToChan(g);
232               rgba[i][BCOMP] = FixedToChan(b);
233               rgba[i][ACOMP] = FixedToChan(a);
234               r += dr;
235               g += dg;
236               b += db;
237               a += da;
238            }
239         }
240      }
241      break;
242#endif
243   case GL_FLOAT:
244      {
245         GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
246         GLfloat r, g, b, a, dr, dg, db, da;
247         r = span->red;
248         g = span->green;
249         b = span->blue;
250         a = span->alpha;
251         if (span->interpMask & SPAN_FLAT) {
252            dr = dg = db = da = 0.0;
253         }
254         else {
255            dr = span->redStep;
256            dg = span->greenStep;
257            db = span->blueStep;
258            da = span->alphaStep;
259         }
260         for (i = 0; i < n; i++) {
261            rgba[i][RCOMP] = r;
262            rgba[i][GCOMP] = g;
263            rgba[i][BCOMP] = b;
264            rgba[i][ACOMP] = a;
265            r += dr;
266            g += dg;
267            b += db;
268            a += da;
269         }
270      }
271      break;
272   default:
273      _mesa_problem(NULL, "bad datatype in interpolate_colors");
274   }
275   span->arrayMask |= SPAN_RGBA;
276}
277
278
279/**
280 * Interpolate specular/secondary colors.
281 */
282static INLINE void
283interpolate_specular(SWspan *span)
284{
285   const GLuint n = span->end;
286   GLuint i;
287
288   switch (span->array->ChanType) {
289#if CHAN_BITS != 32
290   case GL_UNSIGNED_BYTE:
291      {
292         GLubyte (*spec)[4] = span->array->color.sz1.spec;
293         if (span->interpMask & SPAN_FLAT) {
294            GLubyte color[4];
295            color[RCOMP] = FixedToInt(span->specRed);
296            color[GCOMP] = FixedToInt(span->specGreen);
297            color[BCOMP] = FixedToInt(span->specBlue);
298            color[ACOMP] = 0;
299            for (i = 0; i < n; i++) {
300               COPY_4UBV(spec[i], color);
301            }
302         }
303         else {
304            GLfixed r = span->specRed;
305            GLfixed g = span->specGreen;
306            GLfixed b = span->specBlue;
307            GLint dr = span->specRedStep;
308            GLint dg = span->specGreenStep;
309            GLint db = span->specBlueStep;
310            for (i = 0; i < n; i++) {
311               spec[i][RCOMP] = CLAMP(FixedToChan(r), 0, 255);
312               spec[i][GCOMP] = CLAMP(FixedToChan(g), 0, 255);
313               spec[i][BCOMP] = CLAMP(FixedToChan(b), 0, 255);
314               spec[i][ACOMP] = 0;
315               r += dr;
316               g += dg;
317               b += db;
318            }
319         }
320      }
321      break;
322   case GL_UNSIGNED_SHORT:
323      {
324         GLushort (*spec)[4] = span->array->color.sz2.spec;
325         if (span->interpMask & SPAN_FLAT) {
326            GLushort color[4];
327            color[RCOMP] = FixedToInt(span->specRed);
328            color[GCOMP] = FixedToInt(span->specGreen);
329            color[BCOMP] = FixedToInt(span->specBlue);
330            color[ACOMP] = 0;
331            for (i = 0; i < n; i++) {
332               COPY_4V(spec[i], color);
333            }
334         }
335         else {
336            GLfixed r = FloatToFixed(span->specRed);
337            GLfixed g = FloatToFixed(span->specGreen);
338            GLfixed b = FloatToFixed(span->specBlue);
339            GLint dr = FloatToFixed(span->specRedStep);
340            GLint dg = FloatToFixed(span->specGreenStep);
341            GLint db = FloatToFixed(span->specBlueStep);
342            for (i = 0; i < n; i++) {
343               spec[i][RCOMP] = FixedToInt(r);
344               spec[i][GCOMP] = FixedToInt(g);
345               spec[i][BCOMP] = FixedToInt(b);
346               spec[i][ACOMP] = 0;
347               r += dr;
348               g += dg;
349               b += db;
350            }
351         }
352      }
353      break;
354#endif
355   case GL_FLOAT:
356      {
357         GLfloat (*spec)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
358#if CHAN_BITS <= 16
359         GLfloat r = CHAN_TO_FLOAT(FixedToChan(span->specRed));
360         GLfloat g = CHAN_TO_FLOAT(FixedToChan(span->specGreen));
361         GLfloat b = CHAN_TO_FLOAT(FixedToChan(span->specBlue));
362#else
363         GLfloat r = span->specRed;
364         GLfloat g = span->specGreen;
365         GLfloat b = span->specBlue;
366#endif
367         GLfloat dr, dg, db;
368         if (span->interpMask & SPAN_FLAT) {
369            dr = dg = db = 0.0;
370         }
371         else {
372#if CHAN_BITS <= 16
373            dr = CHAN_TO_FLOAT(FixedToChan(span->specRedStep));
374            dg = CHAN_TO_FLOAT(FixedToChan(span->specGreenStep));
375            db = CHAN_TO_FLOAT(FixedToChan(span->specBlueStep));
376#else
377            dr = span->specRedStep;
378            dg = span->specGreenStep;
379            db = span->specBlueStep;
380#endif
381         }
382         for (i = 0; i < n; i++) {
383            spec[i][RCOMP] = r;
384            spec[i][GCOMP] = g;
385            spec[i][BCOMP] = b;
386            spec[i][ACOMP] = 0.0F;
387            r += dr;
388            g += dg;
389            b += db;
390         }
391      }
392      break;
393   default:
394      _mesa_problem(NULL, "bad datatype in interpolate_specular");
395   }
396   span->arrayMask |= SPAN_SPEC;
397}
398
399
400/* Fill in the span.color.index array from the interpolation values */
401static INLINE void
402interpolate_indexes(GLcontext *ctx, SWspan *span)
403{
404   GLfixed index = span->index;
405   const GLint indexStep = span->indexStep;
406   const GLuint n = span->end;
407   GLuint *indexes = span->array->index;
408   GLuint i;
409   (void) ctx;
410   ASSERT((span->interpMask & SPAN_INDEX)  &&
411	  !(span->arrayMask & SPAN_INDEX));
412
413   if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
414      /* constant color */
415      index = FixedToInt(index);
416      for (i = 0; i < n; i++) {
417         indexes[i] = index;
418      }
419   }
420   else {
421      /* interpolate */
422      for (i = 0; i < n; i++) {
423         indexes[i] = FixedToInt(index);
424         index += indexStep;
425      }
426   }
427   span->arrayMask |= SPAN_INDEX;
428   span->interpMask &= ~SPAN_INDEX;
429}
430
431
432/* Fill in the span.array.fog values from the interpolation values */
433static INLINE void
434interpolate_fog(const GLcontext *ctx, SWspan *span)
435{
436   GLfloat (*fog)[4] = span->array->attribs[FRAG_ATTRIB_FOGC];
437   const GLfloat fogStep = span->attrStepX[FRAG_ATTRIB_FOGC][0];
438   GLfloat fogCoord = span->attrStart[FRAG_ATTRIB_FOGC][0];
439   const GLuint haveW = (span->interpMask & SPAN_W);
440   const GLfloat wStep = haveW ? span->attrStepX[FRAG_ATTRIB_WPOS][3] : 0.0F;
441   GLfloat w = haveW ? span->attrStart[FRAG_ATTRIB_WPOS][3] : 1.0F;
442   GLuint i;
443   for (i = 0; i < span->end; i++) {
444      fog[i][0] = fogCoord / w;
445      fogCoord += fogStep;
446      w += wStep;
447   }
448   span->arrayMask |= SPAN_FOG;
449}
450
451
452/* Fill in the span.zArray array from the interpolation values */
453void
454_swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span )
455{
456   const GLuint n = span->end;
457   GLuint i;
458
459   ASSERT((span->interpMask & SPAN_Z)  &&
460	  !(span->arrayMask & SPAN_Z));
461
462   if (ctx->DrawBuffer->Visual.depthBits <= 16) {
463      GLfixed zval = span->z;
464      GLuint *z = span->array->z;
465      for (i = 0; i < n; i++) {
466         z[i] = FixedToInt(zval);
467         zval += span->zStep;
468      }
469   }
470   else {
471      /* Deep Z buffer, no fixed->int shift */
472      GLuint zval = span->z;
473      GLuint *z = span->array->z;
474      for (i = 0; i < n; i++) {
475         z[i] = zval;
476         zval += span->zStep;
477      }
478   }
479   span->interpMask &= ~SPAN_Z;
480   span->arrayMask |= SPAN_Z;
481}
482
483
484/*
485 * This the ideal solution, as given in the OpenGL spec.
486 */
487#if 0
488static GLfloat
489compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
490               GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
491               GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
492{
493   GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
494   GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
495   GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
496   GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
497   GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
498   GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
499   GLfloat rho = MAX2(x, y);
500   GLfloat lambda = LOG2(rho);
501   return lambda;
502}
503#endif
504
505
506/*
507 * This is a faster approximation
508 */
509GLfloat
510_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
511                     GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
512                     GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
513{
514   GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
515   GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
516   GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
517   GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
518   GLfloat maxU, maxV, rho, lambda;
519   dsdx2 = FABSF(dsdx2);
520   dsdy2 = FABSF(dsdy2);
521   dtdx2 = FABSF(dtdx2);
522   dtdy2 = FABSF(dtdy2);
523   maxU = MAX2(dsdx2, dsdy2) * texW;
524   maxV = MAX2(dtdx2, dtdy2) * texH;
525   rho = MAX2(maxU, maxV);
526   lambda = LOG2(rho);
527   return lambda;
528}
529
530
531/**
532 * Fill in the span.texcoords array from the interpolation values.
533 * Note: in the places where we divide by Q (or mult by invQ) we're
534 * really doing two things: perspective correction and texcoord
535 * projection.  Remember, for texcoord (s,t,r,q) we need to index
536 * texels with (s/q, t/q, r/q).
537 * If we're using a fragment program, we never do the division
538 * for texcoord projection.  That's done by the TXP instruction
539 * or user-written code.
540 */
541static void
542interpolate_texcoords(GLcontext *ctx, SWspan *span)
543{
544   const GLuint maxUnit
545      = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1;
546   GLuint u;
547
548   ASSERT(span->interpMask & SPAN_TEXTURE);
549   ASSERT(!(span->arrayMask & SPAN_TEXTURE));
550
551   span->arrayMask |= SPAN_TEXTURE;
552
553   /* XXX CoordUnits vs. ImageUnits */
554   for (u = 0; u < maxUnit; u++) {
555      if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
556         const GLuint attr = FRAG_ATTRIB_TEX0 + u;
557         const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
558         GLfloat texW, texH;
559         GLboolean needLambda;
560         GLfloat (*texcoord)[4] = span->array->attribs[attr];
561         GLfloat *lambda = span->array->lambda[u];
562         const GLfloat dsdx = span->attrStepX[attr][0];
563         const GLfloat dsdy = span->attrStepY[attr][0];
564         const GLfloat dtdx = span->attrStepX[attr][1];
565         const GLfloat dtdy = span->attrStepY[attr][1];
566         const GLfloat drdx = span->attrStepX[attr][2];
567         const GLfloat dqdx = span->attrStepX[attr][3];
568         const GLfloat dqdy = span->attrStepY[attr][3];
569         GLfloat s = span->attrStart[attr][0];
570         GLfloat t = span->attrStart[attr][1];
571         GLfloat r = span->attrStart[attr][2];
572         GLfloat q = span->attrStart[attr][3];
573
574         if (obj) {
575            const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
576            needLambda = (obj->MinFilter != obj->MagFilter)
577               || ctx->FragmentProgram._Current;
578            texW = img->WidthScale;
579            texH = img->HeightScale;
580         }
581         else {
582            /* using a fragment program */
583            texW = 1.0;
584            texH = 1.0;
585            needLambda = GL_FALSE;
586         }
587
588         if (needLambda) {
589            GLuint i;
590            if (ctx->FragmentProgram._Current
591                || ctx->ATIFragmentShader._Enabled) {
592               /* do perspective correction but don't divide s, t, r by q */
593               const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
594               GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
595               for (i = 0; i < span->end; i++) {
596                  const GLfloat invW = 1.0F / w;
597                  texcoord[i][0] = s * invW;
598                  texcoord[i][1] = t * invW;
599                  texcoord[i][2] = r * invW;
600                  texcoord[i][3] = q * invW;
601                  lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
602                                                     dqdx, dqdy, texW, texH,
603                                                     s, t, q, invW);
604                  s += dsdx;
605                  t += dtdx;
606                  r += drdx;
607                  q += dqdx;
608                  w += dwdx;
609               }
610            }
611            else {
612               for (i = 0; i < span->end; i++) {
613                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
614                  texcoord[i][0] = s * invQ;
615                  texcoord[i][1] = t * invQ;
616                  texcoord[i][2] = r * invQ;
617                  texcoord[i][3] = q;
618                  lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
619                                                     dqdx, dqdy, texW, texH,
620                                                     s, t, q, invQ);
621                  s += dsdx;
622                  t += dtdx;
623                  r += drdx;
624                  q += dqdx;
625               }
626            }
627            span->arrayMask |= SPAN_LAMBDA;
628         }
629         else {
630            GLuint i;
631            if (ctx->FragmentProgram._Current ||
632                ctx->ATIFragmentShader._Enabled) {
633               /* do perspective correction but don't divide s, t, r by q */
634               const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
635               GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
636               for (i = 0; i < span->end; i++) {
637                  const GLfloat invW = 1.0F / w;
638                  texcoord[i][0] = s * invW;
639                  texcoord[i][1] = t * invW;
640                  texcoord[i][2] = r * invW;
641                  texcoord[i][3] = q * invW;
642                  lambda[i] = 0.0;
643                  s += dsdx;
644                  t += dtdx;
645                  r += drdx;
646                  q += dqdx;
647                  w += dwdx;
648               }
649            }
650            else if (dqdx == 0.0F) {
651               /* Ortho projection or polygon's parallel to window X axis */
652               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
653               for (i = 0; i < span->end; i++) {
654                  texcoord[i][0] = s * invQ;
655                  texcoord[i][1] = t * invQ;
656                  texcoord[i][2] = r * invQ;
657                  texcoord[i][3] = q;
658                  lambda[i] = 0.0;
659                  s += dsdx;
660                  t += dtdx;
661                  r += drdx;
662               }
663            }
664            else {
665               for (i = 0; i < span->end; i++) {
666                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
667                  texcoord[i][0] = s * invQ;
668                  texcoord[i][1] = t * invQ;
669                  texcoord[i][2] = r * invQ;
670                  texcoord[i][3] = q;
671                  lambda[i] = 0.0;
672                  s += dsdx;
673                  t += dtdx;
674                  r += drdx;
675                  q += dqdx;
676               }
677            }
678         } /* lambda */
679      } /* if */
680   } /* for */
681}
682
683
684
685/**
686 * Fill in the arrays->attribs[FRAG_ATTRIB_VARx] arrays from the
687 * interpolation values.
688 * XXX since interpolants/arrays are getting uniformed, we might merge
689 * this with interpolate_texcoords(), interpolate_Fog(), etc. someday.
690 */
691static INLINE void
692interpolate_varying(GLcontext *ctx, SWspan *span)
693{
694   GLuint var;
695   const GLbitfield inputsUsed = ctx->FragmentProgram._Current->Base.InputsRead;
696
697   ASSERT(span->interpMask & SPAN_VARYING);
698   ASSERT(!(span->arrayMask & SPAN_VARYING));
699
700   span->arrayMask |= SPAN_VARYING;
701
702   for (var = 0; var < MAX_VARYING; var++) {
703      if (inputsUsed & FRAG_BIT_VAR(var)) {
704         const GLuint attr = FRAG_ATTRIB_VAR0 + var;
705         GLuint j;
706         for (j = 0; j < 4; j++) {
707            const GLfloat dvdx = span->attrStepX[attr][j];
708            GLfloat v = span->attrStart[attr][j];
709            const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
710            GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
711            GLuint k;
712            for (k = 0; k < span->end; k++) {
713               GLfloat invW = 1.0f / w;
714               span->array->attribs[attr][k][j] = v * invW;
715               v += dvdx;
716               w += dwdx;
717            }
718         }
719      }
720   }
721}
722
723
724/**
725 * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array.
726 */
727static INLINE void
728interpolate_wpos(GLcontext *ctx, SWspan *span)
729{
730   GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS];
731   GLuint i;
732   if (span->arrayMask & SPAN_XY) {
733      for (i = 0; i < span->end; i++) {
734         wpos[i][0] = (GLfloat) span->array->x[i];
735         wpos[i][1] = (GLfloat) span->array->y[i];
736      }
737   }
738   else {
739      for (i = 0; i < span->end; i++) {
740         wpos[i][0] = (GLfloat) span->x + i;
741         wpos[i][1] = (GLfloat) span->y;
742      }
743   }
744   for (i = 0; i < span->end; i++) {
745      wpos[i][2] = (GLfloat) span->array->z[i] / ctx->DrawBuffer->_DepthMaxF;
746      wpos[i][3] = span->attrStart[FRAG_ATTRIB_WPOS][3]
747                 + i * span->attrStepX[FRAG_ATTRIB_WPOS][3];
748   }
749}
750
751
752/**
753 * Apply the current polygon stipple pattern to a span of pixels.
754 */
755static INLINE void
756stipple_polygon_span(GLcontext *ctx, SWspan *span)
757{
758   GLubyte *mask = span->array->mask;
759
760   ASSERT(ctx->Polygon.StippleFlag);
761
762   if (span->arrayMask & SPAN_XY) {
763      /* arrays of x/y pixel coords */
764      GLuint i;
765      for (i = 0; i < span->end; i++) {
766         const GLint col = span->array->x[i] % 32;
767         const GLint row = span->array->y[i] % 32;
768         const GLuint stipple = ctx->PolygonStipple[row];
769         if (((1 << col) & stipple) == 0) {
770            mask[i] = 0;
771         }
772      }
773   }
774   else {
775      /* horizontal span of pixels */
776      const GLuint highBit = 1 << 31;
777      const GLuint stipple = ctx->PolygonStipple[span->y % 32];
778      GLuint i, m = highBit >> (GLuint) (span->x % 32);
779      for (i = 0; i < span->end; i++) {
780         if ((m & stipple) == 0) {
781            mask[i] = 0;
782         }
783         m = m >> 1;
784         if (m == 0) {
785            m = highBit;
786         }
787      }
788   }
789   span->writeAll = GL_FALSE;
790}
791
792
793/**
794 * Clip a pixel span to the current buffer/window boundaries:
795 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
796 * window clipping and scissoring.
797 * Return:   GL_TRUE   some pixels still visible
798 *           GL_FALSE  nothing visible
799 */
800static INLINE GLuint
801clip_span( GLcontext *ctx, SWspan *span )
802{
803   const GLint xmin = ctx->DrawBuffer->_Xmin;
804   const GLint xmax = ctx->DrawBuffer->_Xmax;
805   const GLint ymin = ctx->DrawBuffer->_Ymin;
806   const GLint ymax = ctx->DrawBuffer->_Ymax;
807
808   if (span->arrayMask & SPAN_XY) {
809      /* arrays of x/y pixel coords */
810      const GLint *x = span->array->x;
811      const GLint *y = span->array->y;
812      const GLint n = span->end;
813      GLubyte *mask = span->array->mask;
814      GLint i;
815      if (span->arrayMask & SPAN_MASK) {
816         /* note: using & intead of && to reduce branches */
817         for (i = 0; i < n; i++) {
818            mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
819                     & (y[i] >= ymin) & (y[i] < ymax);
820         }
821      }
822      else {
823         /* note: using & intead of && to reduce branches */
824         for (i = 0; i < n; i++) {
825            mask[i] = (x[i] >= xmin) & (x[i] < xmax)
826                    & (y[i] >= ymin) & (y[i] < ymax);
827         }
828      }
829      return GL_TRUE;  /* some pixels visible */
830   }
831   else {
832      /* horizontal span of pixels */
833      const GLint x = span->x;
834      const GLint y = span->y;
835      const GLint n = span->end;
836
837      /* Trivial rejection tests */
838      if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
839         span->end = 0;
840         return GL_FALSE;  /* all pixels clipped */
841      }
842
843      /* Clip to the left */
844      if (x < xmin) {
845         ASSERT(x + n > xmin);
846         span->writeAll = GL_FALSE;
847         _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
848      }
849
850      /* Clip to right */
851      if (x + n > xmax) {
852         ASSERT(x < xmax);
853         span->end = xmax - x;
854      }
855
856      return GL_TRUE;  /* some pixels visible */
857   }
858}
859
860
861/**
862 * Apply all the per-fragment opertions to a span of color index fragments
863 * and write them to the enabled color drawbuffers.
864 * The 'span' parameter can be considered to be const.  Note that
865 * span->interpMask and span->arrayMask may be changed but will be restored
866 * to their original values before returning.
867 */
868void
869_swrast_write_index_span( GLcontext *ctx, SWspan *span)
870{
871   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
872   const GLbitfield origInterpMask = span->interpMask;
873   const GLbitfield origArrayMask = span->arrayMask;
874
875   ASSERT(span->end <= MAX_WIDTH);
876   ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
877	  span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
878   ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
879   ASSERT((span->interpMask & span->arrayMask) == 0);
880
881   if (span->arrayMask & SPAN_MASK) {
882      /* mask was initialized by caller, probably glBitmap */
883      span->writeAll = GL_FALSE;
884   }
885   else {
886      _mesa_memset(span->array->mask, 1, span->end);
887      span->writeAll = GL_TRUE;
888   }
889
890   /* Clipping */
891   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
892      if (!clip_span(ctx, span)) {
893         return;
894      }
895   }
896
897   /* Depth bounds test */
898   if (ctx->Depth.BoundsTest && ctx->DrawBuffer->Visual.depthBits > 0) {
899      if (!_swrast_depth_bounds_test(ctx, span)) {
900         return;
901      }
902   }
903
904#ifdef DEBUG
905   /* Make sure all fragments are within window bounds */
906   if (span->arrayMask & SPAN_XY) {
907      GLuint i;
908      for (i = 0; i < span->end; i++) {
909         if (span->array->mask[i]) {
910            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
911            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
912            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
913            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
914         }
915      }
916   }
917#endif
918
919   /* Polygon Stippling */
920   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
921      stipple_polygon_span(ctx, span);
922   }
923
924   /* Stencil and Z testing */
925   if (ctx->Depth.Test || ctx->Stencil.Enabled) {
926      if (span->interpMask & SPAN_Z)
927         _swrast_span_interpolate_z(ctx, span);
928
929      if (ctx->Stencil.Enabled) {
930         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
931            span->arrayMask = origArrayMask;
932            return;
933         }
934      }
935      else {
936         ASSERT(ctx->Depth.Test);
937         if (!_swrast_depth_test_span(ctx, span)) {
938            span->interpMask = origInterpMask;
939            span->arrayMask = origArrayMask;
940            return;
941         }
942      }
943   }
944
945#if FEATURE_ARB_occlusion_query
946   if (ctx->Query.CurrentOcclusionObject) {
947      /* update count of 'passed' fragments */
948      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
949      GLuint i;
950      for (i = 0; i < span->end; i++)
951         q->Result += span->array->mask[i];
952   }
953#endif
954
955   /* we have to wait until after occlusion to do this test */
956   if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
957      /* write no pixels */
958      span->arrayMask = origArrayMask;
959      return;
960   }
961
962   /* Interpolate the color indexes if needed */
963   if (swrast->_FogEnabled ||
964       ctx->Color.IndexLogicOpEnabled ||
965       ctx->Color.IndexMask != 0xffffffff ||
966       (span->arrayMask & SPAN_COVERAGE)) {
967      if (span->interpMask & SPAN_INDEX) {
968         interpolate_indexes(ctx, span);
969      }
970   }
971
972   /* Fog */
973   if (swrast->_FogEnabled) {
974      _swrast_fog_ci_span(ctx, span);
975   }
976
977   /* Antialias coverage application */
978   if (span->arrayMask & SPAN_COVERAGE) {
979      const GLfloat *coverage = span->array->coverage;
980      GLuint *index = span->array->index;
981      GLuint i;
982      for (i = 0; i < span->end; i++) {
983         ASSERT(coverage[i] < 16);
984         index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
985      }
986   }
987
988   /*
989    * Write to renderbuffers
990    */
991   {
992      struct gl_framebuffer *fb = ctx->DrawBuffer;
993      const GLuint output = 0; /* only frag progs can write to other outputs */
994      const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
995      GLuint indexSave[MAX_WIDTH];
996      GLuint buf;
997
998      if (numDrawBuffers > 1) {
999         /* save indexes for second, third renderbuffer writes */
1000         _mesa_memcpy(indexSave, span->array->index,
1001                      span->end * sizeof(indexSave[0]));
1002      }
1003
1004      for (buf = 0; buf < fb->_NumColorDrawBuffers[output]; buf++) {
1005         struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1006         ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1007
1008         if (ctx->Color.IndexLogicOpEnabled) {
1009            _swrast_logicop_ci_span(ctx, rb, span);
1010         }
1011
1012         if (ctx->Color.IndexMask != 0xffffffff) {
1013            _swrast_mask_ci_span(ctx, rb, span);
1014         }
1015
1016         if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
1017            /* all fragments have same color index */
1018            GLubyte index8;
1019            GLushort index16;
1020            GLuint index32;
1021            void *value;
1022
1023            if (rb->DataType == GL_UNSIGNED_BYTE) {
1024               index8 = FixedToInt(span->index);
1025               value = &index8;
1026            }
1027            else if (rb->DataType == GL_UNSIGNED_SHORT) {
1028               index16 = FixedToInt(span->index);
1029               value = &index16;
1030            }
1031            else {
1032               ASSERT(rb->DataType == GL_UNSIGNED_INT);
1033               index32 = FixedToInt(span->index);
1034               value = &index32;
1035            }
1036
1037            if (span->arrayMask & SPAN_XY) {
1038               rb->PutMonoValues(ctx, rb, span->end, span->array->x,
1039                                 span->array->y, value, span->array->mask);
1040            }
1041            else {
1042               rb->PutMonoRow(ctx, rb, span->end, span->x, span->y,
1043                              value, span->array->mask);
1044            }
1045         }
1046         else {
1047            /* each fragment is a different color */
1048            GLubyte index8[MAX_WIDTH];
1049            GLushort index16[MAX_WIDTH];
1050            void *values;
1051
1052            if (rb->DataType == GL_UNSIGNED_BYTE) {
1053               GLuint k;
1054               for (k = 0; k < span->end; k++) {
1055                  index8[k] = (GLubyte) span->array->index[k];
1056               }
1057               values = index8;
1058            }
1059            else if (rb->DataType == GL_UNSIGNED_SHORT) {
1060               GLuint k;
1061               for (k = 0; k < span->end; k++) {
1062                  index16[k] = (GLushort) span->array->index[k];
1063               }
1064               values = index16;
1065            }
1066            else {
1067               ASSERT(rb->DataType == GL_UNSIGNED_INT);
1068               values = span->array->index;
1069            }
1070
1071            if (span->arrayMask & SPAN_XY) {
1072               rb->PutValues(ctx, rb, span->end,
1073                             span->array->x, span->array->y,
1074                             values, span->array->mask);
1075            }
1076            else {
1077               rb->PutRow(ctx, rb, span->end, span->x, span->y,
1078                          values, span->array->mask);
1079            }
1080         }
1081
1082         if (buf + 1 < numDrawBuffers) {
1083            /* restore original span values */
1084            _mesa_memcpy(span->array->index, indexSave,
1085                         span->end * sizeof(indexSave[0]));
1086         }
1087      } /* for buf */
1088   }
1089
1090   span->interpMask = origInterpMask;
1091   span->arrayMask = origArrayMask;
1092}
1093
1094
1095/**
1096 * Add specular color to base color.  This is used only when
1097 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1098 */
1099static INLINE void
1100add_specular(GLcontext *ctx, SWspan *span)
1101{
1102   switch (span->array->ChanType) {
1103   case GL_UNSIGNED_BYTE:
1104      {
1105         GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
1106         GLubyte (*spec)[4] = span->array->color.sz1.spec;
1107         GLuint i;
1108         for (i = 0; i < span->end; i++) {
1109            GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
1110            GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
1111            GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
1112            GLint a = rgba[i][ACOMP] + spec[i][ACOMP];
1113            rgba[i][RCOMP] = MIN2(r, 255);
1114            rgba[i][GCOMP] = MIN2(g, 255);
1115            rgba[i][BCOMP] = MIN2(b, 255);
1116            rgba[i][ACOMP] = MIN2(a, 255);
1117         }
1118      }
1119      break;
1120   case GL_UNSIGNED_SHORT:
1121      {
1122         GLushort (*rgba)[4] = span->array->color.sz2.rgba;
1123         GLushort (*spec)[4] = span->array->color.sz2.spec;
1124         GLuint i;
1125         for (i = 0; i < span->end; i++) {
1126            GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
1127            GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
1128            GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
1129            GLint a = rgba[i][ACOMP] + spec[i][ACOMP];
1130            rgba[i][RCOMP] = MIN2(r, 65535);
1131            rgba[i][GCOMP] = MIN2(g, 65535);
1132            rgba[i][BCOMP] = MIN2(b, 65535);
1133            rgba[i][ACOMP] = MIN2(a, 65535);
1134         }
1135      }
1136      break;
1137   case GL_FLOAT:
1138      {
1139         GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
1140         GLfloat (*spec)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
1141         GLuint i;
1142         for (i = 0; i < span->end; i++) {
1143            rgba[i][RCOMP] += spec[i][RCOMP];
1144            rgba[i][GCOMP] += spec[i][GCOMP];
1145            rgba[i][BCOMP] += spec[i][BCOMP];
1146            rgba[i][ACOMP] += spec[i][ACOMP];
1147         }
1148      }
1149      break;
1150   default:
1151      _mesa_problem(ctx, "Invalid datatype in add_specular");
1152   }
1153}
1154
1155
1156/**
1157 * Apply antialiasing coverage value to alpha values.
1158 */
1159static INLINE void
1160apply_aa_coverage(SWspan *span)
1161{
1162   const GLfloat *coverage = span->array->coverage;
1163   GLuint i;
1164   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1165      GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
1166      for (i = 0; i < span->end; i++) {
1167         const GLfloat a = rgba[i][ACOMP] * coverage[i];
1168         rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0);
1169         ASSERT(coverage[i] >= 0.0);
1170         ASSERT(coverage[i] <= 1.0);
1171      }
1172   }
1173   else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
1174      GLushort (*rgba)[4] = span->array->color.sz2.rgba;
1175      for (i = 0; i < span->end; i++) {
1176         const GLfloat a = rgba[i][ACOMP] * coverage[i];
1177         rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0);
1178      }
1179   }
1180   else {
1181      GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
1182      for (i = 0; i < span->end; i++) {
1183         rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
1184      }
1185   }
1186}
1187
1188
1189/**
1190 * Clamp span's float colors to [0,1]
1191 */
1192static INLINE void
1193clamp_colors(SWspan *span)
1194{
1195   GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
1196   GLuint i;
1197   ASSERT(span->array->ChanType == GL_FLOAT);
1198   for (i = 0; i < span->end; i++) {
1199      rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
1200      rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
1201      rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
1202      rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
1203   }
1204}
1205
1206
1207/**
1208 * Convert the span's color arrays to the given type.
1209 */
1210static INLINE void
1211convert_color_type(SWspan *span, GLenum newType)
1212{
1213   GLvoid *src, *dst;
1214   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1215      src = span->array->color.sz1.rgba;
1216   }
1217   else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1218      src = span->array->color.sz2.rgba;
1219   }
1220   else {
1221      src = span->array->attribs[FRAG_ATTRIB_COL0];
1222   }
1223   if (newType == GL_UNSIGNED_BYTE) {
1224      dst = span->array->color.sz1.rgba;
1225   }
1226   else if (newType == GL_UNSIGNED_BYTE) {
1227      dst = span->array->color.sz2.rgba;
1228   }
1229   else {
1230      dst = span->array->attribs[FRAG_ATTRIB_COL0];
1231   }
1232
1233   _mesa_convert_colors(span->array->ChanType, src,
1234                        newType, dst,
1235                        span->end, span->array->mask);
1236
1237   span->array->ChanType = newType;
1238}
1239
1240
1241
1242/**
1243 * Apply fragment shader, fragment program or normal texturing to span.
1244 */
1245static INLINE void
1246shade_texture_span(GLcontext *ctx, SWspan *span)
1247{
1248   /* Now we need the rgba array, fill it in if needed */
1249   if (span->interpMask & SPAN_RGBA)
1250      interpolate_colors(span);
1251
1252   if (ctx->Texture._EnabledCoordUnits && (span->interpMask & SPAN_TEXTURE))
1253      interpolate_texcoords(ctx, span);
1254
1255   if (ctx->FragmentProgram._Current ||
1256       ctx->ATIFragmentShader._Enabled) {
1257
1258      /* use float colors if running a fragment program or shader */
1259      const GLenum oldType = span->array->ChanType;
1260      const GLenum newType = GL_FLOAT;
1261      if (oldType != newType) {
1262         GLvoid *src = (oldType == GL_UNSIGNED_BYTE)
1263            ? (GLvoid *) span->array->color.sz1.rgba
1264            : (GLvoid *) span->array->color.sz2.rgba;
1265         _mesa_convert_colors(oldType, src,
1266                              newType, span->array->attribs[FRAG_ATTRIB_COL0],
1267                              span->end, span->array->mask);
1268         span->array->ChanType = newType;
1269      }
1270
1271      /* fragment programs/shaders may need specular, fog and Z coords */
1272      if (span->interpMask & SPAN_SPEC)
1273         interpolate_specular(span);
1274
1275      if (span->interpMask & SPAN_FOG)
1276         interpolate_fog(ctx, span);
1277
1278      if (span->interpMask & SPAN_Z)
1279         _swrast_span_interpolate_z (ctx, span);
1280
1281      if (ctx->Shader.CurrentProgram && span->interpMask & SPAN_VARYING)
1282         interpolate_varying(ctx, span);
1283
1284      if (ctx->FragmentProgram._Current &&
1285          (ctx->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_WPOS))
1286         interpolate_wpos(ctx, span);
1287
1288      /* Run fragment program/shader now */
1289      if (ctx->FragmentProgram._Current) {
1290         _swrast_exec_fragment_program(ctx, span);
1291      }
1292      else {
1293         ASSERT(ctx->ATIFragmentShader._Enabled);
1294         _swrast_exec_fragment_shader(ctx, span);
1295      }
1296   }
1297   else if (ctx->Texture._EnabledUnits && (span->arrayMask & SPAN_TEXTURE)) {
1298      /* conventional texturing */
1299      _swrast_texture_span(ctx, span);
1300   }
1301}
1302
1303
1304
1305/**
1306 * Apply all the per-fragment operations to a span.
1307 * This now includes texturing (_swrast_write_texture_span() is history).
1308 * This function may modify any of the array values in the span.
1309 * span->interpMask and span->arrayMask may be changed but will be restored
1310 * to their original values before returning.
1311 */
1312void
1313_swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
1314{
1315   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1316   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1317   const GLbitfield origInterpMask = span->interpMask;
1318   const GLbitfield origArrayMask = span->arrayMask;
1319   const GLenum chanType = span->array->ChanType;
1320   const GLboolean shader = (ctx->FragmentProgram._Current
1321                             || ctx->ATIFragmentShader._Enabled);
1322   const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledUnits;
1323   GLboolean deferredTexture;
1324
1325   /*
1326   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__,
1327          span->interpMask, span->arrayMask);
1328   */
1329
1330   ASSERT(span->primitive == GL_POINT ||
1331          span->primitive == GL_LINE ||
1332	  span->primitive == GL_POLYGON ||
1333          span->primitive == GL_BITMAP);
1334   ASSERT(span->end <= MAX_WIDTH);
1335   ASSERT((span->interpMask & span->arrayMask) == 0);
1336   ASSERT((span->interpMask & SPAN_RGBA) ^ (span->arrayMask & SPAN_RGBA));
1337
1338   /* check for conditions that prevent deferred shading */
1339   if (ctx->Color.AlphaEnabled) {
1340      /* alpha test depends on post-texture/shader colors */
1341      deferredTexture = GL_FALSE;
1342   }
1343   else if (shaderOrTexture) {
1344      if (ctx->FragmentProgram._Current) {
1345         if (ctx->FragmentProgram.Current->Base.OutputsWritten
1346             & (1 << FRAG_RESULT_DEPR)) {
1347            /* Z comes from fragment program/shader */
1348            deferredTexture = GL_FALSE;
1349         }
1350         else {
1351            deferredTexture = GL_TRUE;
1352         }
1353      }
1354      else {
1355         /* ATI frag shader or conventional texturing */
1356         deferredTexture = GL_TRUE;
1357      }
1358   }
1359   else {
1360      /* no texturing or shadering */
1361      deferredTexture = GL_FALSE;
1362   }
1363
1364   /* Fragment write masks */
1365   if (span->arrayMask & SPAN_MASK) {
1366      /* mask was initialized by caller, probably glBitmap */
1367      span->writeAll = GL_FALSE;
1368   }
1369   else {
1370      _mesa_memset(span->array->mask, 1, span->end);
1371      span->writeAll = GL_TRUE;
1372   }
1373
1374   /* Clip to window/scissor box */
1375   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1376      if (!clip_span(ctx, span)) {
1377	 return;
1378      }
1379   }
1380
1381#ifdef DEBUG
1382   /* Make sure all fragments are within window bounds */
1383   if (span->arrayMask & SPAN_XY) {
1384      GLuint i;
1385      for (i = 0; i < span->end; i++) {
1386         if (span->array->mask[i]) {
1387            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
1388            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
1389            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
1390            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1391         }
1392      }
1393   }
1394#endif
1395
1396   /* Polygon Stippling */
1397   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1398      stipple_polygon_span(ctx, span);
1399   }
1400
1401   /* This is the normal place to compute the resulting fragment color/Z.
1402    * As an optimization, we try to defer this until after Z/stencil
1403    * testing in order to try to avoid computing colors that we won't
1404    * actually need.
1405    */
1406   if (shaderOrTexture && !deferredTexture) {
1407      shade_texture_span(ctx, span);
1408   }
1409
1410   /* Do the alpha test */
1411   if (ctx->Color.AlphaEnabled) {
1412      if (!_swrast_alpha_test(ctx, span)) {
1413         goto end;
1414      }
1415   }
1416
1417   /* Stencil and Z testing */
1418   if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1419      if (span->interpMask & SPAN_Z)
1420         _swrast_span_interpolate_z(ctx, span);
1421
1422      if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) {
1423         /* Combined Z/stencil tests */
1424         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1425            goto end;
1426         }
1427      }
1428      else if (ctx->DrawBuffer->Visual.depthBits > 0) {
1429         /* Just regular depth testing */
1430         ASSERT(ctx->Depth.Test);
1431         ASSERT(span->arrayMask & SPAN_Z);
1432         if (!_swrast_depth_test_span(ctx, span)) {
1433            goto end;
1434         }
1435      }
1436   }
1437
1438#if FEATURE_ARB_occlusion_query
1439   if (ctx->Query.CurrentOcclusionObject) {
1440      /* update count of 'passed' fragments */
1441      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1442      GLuint i;
1443      for (i = 0; i < span->end; i++)
1444         q->Result += span->array->mask[i];
1445   }
1446#endif
1447
1448   /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1449    * the occlusion test.
1450    */
1451   if (colorMask == 0x0) {
1452      goto end;
1453   }
1454
1455   /* If we were able to defer fragment color computation to now, there's
1456    * a good chance that many fragments will have already been killed by
1457    * Z/stencil testing.
1458    */
1459   if (deferredTexture) {
1460      ASSERT(shaderOrTexture);
1461      shade_texture_span(ctx, span);
1462   }
1463
1464   if ((span->arrayMask & SPAN_RGBA) == 0) {
1465      interpolate_colors(span);
1466   }
1467
1468   ASSERT(span->arrayMask & SPAN_RGBA);
1469
1470   if (!shader) {
1471      /* Add base and specular colors */
1472      if (ctx->Fog.ColorSumEnabled ||
1473          (ctx->Light.Enabled &&
1474           ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1475         if (span->interpMask & SPAN_SPEC) {
1476            interpolate_specular(span);
1477         }
1478         if (span->arrayMask & SPAN_SPEC) {
1479            add_specular(ctx, span);
1480         }
1481         else {
1482            /* We probably added the base/specular colors during the
1483             * vertex stage!
1484             */
1485         }
1486      }
1487   }
1488
1489   /* Fog */
1490   if (swrast->_FogEnabled) {
1491      _swrast_fog_rgba_span(ctx, span);
1492   }
1493
1494   /* Antialias coverage application */
1495   if (span->arrayMask & SPAN_COVERAGE) {
1496      apply_aa_coverage(span);
1497   }
1498
1499   /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
1500   if (ctx->Color.ClampFragmentColor == GL_TRUE &&
1501       span->array->ChanType == GL_FLOAT) {
1502      clamp_colors(span);
1503   }
1504
1505   /*
1506    * Write to renderbuffers
1507    */
1508   {
1509      struct gl_framebuffer *fb = ctx->DrawBuffer;
1510      const GLuint output = 0; /* only frag progs can write to other outputs */
1511      const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
1512      GLchan rgbaSave[MAX_WIDTH][4];
1513      GLuint buf;
1514
1515      if (numDrawBuffers > 0) {
1516         if (fb->_ColorDrawBuffers[output][0]->DataType
1517             != span->array->ChanType) {
1518            convert_color_type(span,
1519                               fb->_ColorDrawBuffers[output][0]->DataType);
1520         }
1521      }
1522
1523      if (numDrawBuffers > 1) {
1524         /* save colors for second, third renderbuffer writes */
1525         _mesa_memcpy(rgbaSave, span->array->rgba,
1526                      4 * span->end * sizeof(GLchan));
1527      }
1528
1529      for (buf = 0; buf < numDrawBuffers; buf++) {
1530         struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1531         ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
1532
1533         if (ctx->Color._LogicOpEnabled) {
1534            _swrast_logicop_rgba_span(ctx, rb, span);
1535         }
1536         else if (ctx->Color.BlendEnabled) {
1537            _swrast_blend_span(ctx, rb, span);
1538         }
1539
1540         if (colorMask != 0xffffffff) {
1541            _swrast_mask_rgba_span(ctx, rb, span);
1542         }
1543
1544         if (span->arrayMask & SPAN_XY) {
1545            /* array of pixel coords */
1546            ASSERT(rb->PutValues);
1547            rb->PutValues(ctx, rb, span->end,
1548                          span->array->x, span->array->y,
1549                          span->array->rgba, span->array->mask);
1550         }
1551         else {
1552            /* horizontal run of pixels */
1553            ASSERT(rb->PutRow);
1554            rb->PutRow(ctx, rb, span->end, span->x, span->y, span->array->rgba,
1555                       span->writeAll ? NULL: span->array->mask);
1556         }
1557
1558         if (buf + 1 < numDrawBuffers) {
1559            /* restore original span values */
1560            _mesa_memcpy(span->array->rgba, rgbaSave,
1561                         4 * span->end * sizeof(GLchan));
1562         }
1563      } /* for buf */
1564
1565   }
1566
1567end:
1568   /* restore these values before returning */
1569   span->interpMask = origInterpMask;
1570   span->arrayMask = origArrayMask;
1571   span->array->ChanType = chanType;
1572}
1573
1574
1575/**
1576 * Read RGBA pixels from a renderbuffer.  Clipping will be done to prevent
1577 * reading ouside the buffer's boundaries.
1578 * \param dstType  datatype for returned colors
1579 * \param rgba  the returned colors
1580 */
1581void
1582_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1583                        GLuint n, GLint x, GLint y, GLenum dstType,
1584                        GLvoid *rgba)
1585{
1586   const GLint bufWidth = (GLint) rb->Width;
1587   const GLint bufHeight = (GLint) rb->Height;
1588
1589   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1590      /* completely above, below, or right */
1591      /* XXX maybe leave rgba values undefined? */
1592      _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1593   }
1594   else {
1595      GLint skip, length;
1596      if (x < 0) {
1597         /* left edge clipping */
1598         skip = -x;
1599         length = (GLint) n - skip;
1600         if (length < 0) {
1601            /* completely left of window */
1602            return;
1603         }
1604         if (length > bufWidth) {
1605            length = bufWidth;
1606         }
1607      }
1608      else if ((GLint) (x + n) > bufWidth) {
1609         /* right edge clipping */
1610         skip = 0;
1611         length = bufWidth - x;
1612         if (length < 0) {
1613            /* completely to right of window */
1614            return;
1615         }
1616      }
1617      else {
1618         /* no clipping */
1619         skip = 0;
1620         length = (GLint) n;
1621      }
1622
1623      ASSERT(rb);
1624      ASSERT(rb->GetRow);
1625      ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
1626
1627      if (rb->DataType == dstType) {
1628         rb->GetRow(ctx, rb, length, x + skip, y,
1629                    (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
1630      }
1631      else {
1632         GLuint temp[MAX_WIDTH * 4];
1633         rb->GetRow(ctx, rb, length, x + skip, y, temp);
1634         _mesa_convert_colors(rb->DataType, temp,
1635                   dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
1636                   length, NULL);
1637      }
1638   }
1639}
1640
1641
1642/**
1643 * Read CI pixels from a renderbuffer.  Clipping will be done to prevent
1644 * reading ouside the buffer's boundaries.
1645 */
1646void
1647_swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1648                         GLuint n, GLint x, GLint y, GLuint index[] )
1649{
1650   const GLint bufWidth = (GLint) rb->Width;
1651   const GLint bufHeight = (GLint) rb->Height;
1652
1653   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1654      /* completely above, below, or right */
1655      _mesa_bzero(index, n * sizeof(GLuint));
1656   }
1657   else {
1658      GLint skip, length;
1659      if (x < 0) {
1660         /* left edge clipping */
1661         skip = -x;
1662         length = (GLint) n - skip;
1663         if (length < 0) {
1664            /* completely left of window */
1665            return;
1666         }
1667         if (length > bufWidth) {
1668            length = bufWidth;
1669         }
1670      }
1671      else if ((GLint) (x + n) > bufWidth) {
1672         /* right edge clipping */
1673         skip = 0;
1674         length = bufWidth - x;
1675         if (length < 0) {
1676            /* completely to right of window */
1677            return;
1678         }
1679      }
1680      else {
1681         /* no clipping */
1682         skip = 0;
1683         length = (GLint) n;
1684      }
1685
1686      ASSERT(rb->GetRow);
1687      ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1688
1689      if (rb->DataType == GL_UNSIGNED_BYTE) {
1690         GLubyte index8[MAX_WIDTH];
1691         GLint i;
1692         rb->GetRow(ctx, rb, length, x + skip, y, index8);
1693         for (i = 0; i < length; i++)
1694            index[skip + i] = index8[i];
1695      }
1696      else if (rb->DataType == GL_UNSIGNED_SHORT) {
1697         GLushort index16[MAX_WIDTH];
1698         GLint i;
1699         rb->GetRow(ctx, rb, length, x + skip, y, index16);
1700         for (i = 0; i < length; i++)
1701            index[skip + i] = index16[i];
1702      }
1703      else if (rb->DataType == GL_UNSIGNED_INT) {
1704         rb->GetRow(ctx, rb, length, x + skip, y, index + skip);
1705      }
1706   }
1707}
1708
1709
1710/**
1711 * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
1712 * reading values outside the buffer bounds.
1713 * We can use this for reading any format/type of renderbuffer.
1714 * \param valueSize is the size in bytes of each value (pixel) put into the
1715 *                  values array.
1716 */
1717void
1718_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
1719                   GLuint count, const GLint x[], const GLint y[],
1720                   void *values, GLuint valueSize)
1721{
1722   GLuint i, inCount = 0, inStart = 0;
1723
1724   for (i = 0; i < count; i++) {
1725      if (x[i] >= 0 && y[i] >= 0 &&
1726	  x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
1727         /* inside */
1728         if (inCount == 0)
1729            inStart = i;
1730         inCount++;
1731      }
1732      else {
1733         if (inCount > 0) {
1734            /* read [inStart, inStart + inCount) */
1735            rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
1736                          (GLubyte *) values + inStart * valueSize);
1737            inCount = 0;
1738         }
1739      }
1740   }
1741   if (inCount > 0) {
1742      /* read last values */
1743      rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
1744                    (GLubyte *) values + inStart * valueSize);
1745   }
1746}
1747
1748
1749/**
1750 * Wrapper for gl_renderbuffer::PutRow() which does clipping.
1751 * \param valueSize  size of each value (pixel) in bytes
1752 */
1753void
1754_swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1755                GLuint count, GLint x, GLint y,
1756                const GLvoid *values, GLuint valueSize)
1757{
1758   GLint skip = 0;
1759
1760   if (y < 0 || y >= (GLint) rb->Height)
1761      return; /* above or below */
1762
1763   if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
1764      return; /* entirely left or right */
1765
1766   if ((GLint) (x + count) > (GLint) rb->Width) {
1767      /* right clip */
1768      GLint clip = x + count - rb->Width;
1769      count -= clip;
1770   }
1771
1772   if (x < 0) {
1773      /* left clip */
1774      skip = -x;
1775      x = 0;
1776      count -= skip;
1777   }
1778
1779   rb->PutRow(ctx, rb, count, x, y,
1780              (const GLubyte *) values + skip * valueSize, NULL);
1781}
1782
1783
1784/**
1785 * Wrapper for gl_renderbuffer::GetRow() which does clipping.
1786 * \param valueSize  size of each value (pixel) in bytes
1787 */
1788void
1789_swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1790                GLuint count, GLint x, GLint y,
1791                GLvoid *values, GLuint valueSize)
1792{
1793   GLint skip = 0;
1794
1795   if (y < 0 || y >= (GLint) rb->Height)
1796      return; /* above or below */
1797
1798   if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
1799      return; /* entirely left or right */
1800
1801   if (x + count > rb->Width) {
1802      /* right clip */
1803      GLint clip = x + count - rb->Width;
1804      count -= clip;
1805   }
1806
1807   if (x < 0) {
1808      /* left clip */
1809      skip = -x;
1810      x = 0;
1811      count -= skip;
1812   }
1813
1814   rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
1815}
1816
1817
1818/**
1819 * Get RGBA pixels from the given renderbuffer.  Put the pixel colors into
1820 * the span's specular color arrays.  The specular color arrays should no
1821 * longer be needed by time this function is called.
1822 * Used by blending, logicop and masking functions.
1823 * \return pointer to the colors we read.
1824 */
1825void *
1826_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
1827                      SWspan *span)
1828{
1829   const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
1830   void *rbPixels;
1831
1832   /*
1833    * Determine pixel size (in bytes).
1834    * Point rbPixels to a temporary space (use specular color arrays).
1835    */
1836   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1837      rbPixels = span->array->color.sz1.spec;
1838   }
1839   else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
1840      rbPixels = span->array->color.sz2.spec;
1841   }
1842   else {
1843      rbPixels = span->array->attribs[FRAG_ATTRIB_COL1];
1844   }
1845
1846   /* Get destination values from renderbuffer */
1847   if (span->arrayMask & SPAN_XY) {
1848      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
1849                         rbPixels, pixelSize);
1850   }
1851   else {
1852      _swrast_get_row(ctx, rb, span->end, span->x, span->y,
1853                      rbPixels, pixelSize);
1854   }
1855
1856   return rbPixels;
1857}
1858