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