3d3ec57d3977310d66b5fd1179f085109a55cf6e
[profile/ivi/mesa.git] / src / mesa / swrast / s_span.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  7.5
4  *
5  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26
27 /**
28  * \file swrast/s_span.c
29  * \brief Span processing functions used by all rasterization functions.
30  * This is where all the per-fragment tests are performed
31  * \author Brian Paul
32  */
33
34 #include "main/glheader.h"
35 #include "main/colormac.h"
36 #include "main/macros.h"
37 #include "main/imports.h"
38 #include "main/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 #include <stdbool.h>
54
55 /**
56  * Set default fragment attributes for the span using the
57  * current raster values.  Used prior to glDraw/CopyPixels
58  * and glBitmap.
59  */
60 void
61 _swrast_span_default_attribs(struct gl_context *ctx, SWspan *span)
62 {
63    GLchan r, g, b, a;
64    /* Z*/
65    {
66       const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
67       if (ctx->DrawBuffer->Visual.depthBits <= 16)
68          span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
69       else {
70          GLfloat tmpf = ctx->Current.RasterPos[2] * depthMax; 
71          tmpf = MIN2(tmpf, depthMax);
72          span->z = (GLint)tmpf;
73       }
74       span->zStep = 0;
75       span->interpMask |= SPAN_Z;
76    }
77
78    /* W (for perspective correction) */
79    span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0;
80    span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0;
81    span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;
82
83    /* primary color, or color index */
84    UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
85    UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
86    UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
87    UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
88 #if CHAN_TYPE == GL_FLOAT
89    span->red = r;
90    span->green = g;
91    span->blue = b;
92    span->alpha = a;
93 #else
94    span->red   = IntToFixed(r);
95    span->green = IntToFixed(g);
96    span->blue  = IntToFixed(b);
97    span->alpha = IntToFixed(a);
98 #endif
99    span->redStep = 0;
100    span->greenStep = 0;
101    span->blueStep = 0;
102    span->alphaStep = 0;
103    span->interpMask |= SPAN_RGBA;
104
105    COPY_4V(span->attrStart[FRAG_ATTRIB_COL0], ctx->Current.RasterColor);
106    ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
107    ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
108
109    /* Secondary color */
110    if (ctx->Light.Enabled || ctx->Fog.ColorSumEnabled)
111    {
112       COPY_4V(span->attrStart[FRAG_ATTRIB_COL1], ctx->Current.RasterSecondaryColor);
113       ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
114       ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
115    }
116
117    /* fog */
118    {
119       const SWcontext *swrast = SWRAST_CONTEXT(ctx);
120       GLfloat fogVal; /* a coord or a blend factor */
121       if (swrast->_PreferPixelFog) {
122          /* fog blend factors will be computed from fog coordinates per pixel */
123          fogVal = ctx->Current.RasterDistance;
124       }
125       else {
126          /* fog blend factor should be computed from fogcoord now */
127          fogVal = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
128       }
129       span->attrStart[FRAG_ATTRIB_FOGC][0] = fogVal;
130       span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0;
131       span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0;
132    }
133
134    /* texcoords */
135    {
136       GLuint i;
137       for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
138          const GLuint attr = FRAG_ATTRIB_TEX0 + i;
139          const GLfloat *tc = ctx->Current.RasterTexCoords[i];
140          if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) {
141             COPY_4V(span->attrStart[attr], tc);
142          }
143          else if (tc[3] > 0.0F) {
144             /* use (s/q, t/q, r/q, 1) */
145             span->attrStart[attr][0] = tc[0] / tc[3];
146             span->attrStart[attr][1] = tc[1] / tc[3];
147             span->attrStart[attr][2] = tc[2] / tc[3];
148             span->attrStart[attr][3] = 1.0;
149          }
150          else {
151             ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F);
152          }
153          ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F);
154          ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F);
155       }
156    }
157 }
158
159
160 /**
161  * Interpolate the active attributes (and'd with attrMask) to
162  * fill in span->array->attribs[].
163  * Perspective correction will be done.  The point/line/triangle function
164  * should have computed attrStart/Step values for FRAG_ATTRIB_WPOS[3]!
165  */
166 static inline void
167 interpolate_active_attribs(struct gl_context *ctx, SWspan *span,
168                            GLbitfield64 attrMask)
169 {
170    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
171
172    /*
173     * Don't overwrite existing array values, such as colors that may have
174     * been produced by glDraw/CopyPixels.
175     */
176    attrMask &= ~span->arrayAttribs;
177
178    ATTRIB_LOOP_BEGIN
179       if (attrMask & BITFIELD64_BIT(attr)) {
180          const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
181          GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
182          const GLfloat dv0dx = span->attrStepX[attr][0];
183          const GLfloat dv1dx = span->attrStepX[attr][1];
184          const GLfloat dv2dx = span->attrStepX[attr][2];
185          const GLfloat dv3dx = span->attrStepX[attr][3];
186          GLfloat v0 = span->attrStart[attr][0] + span->leftClip * dv0dx;
187          GLfloat v1 = span->attrStart[attr][1] + span->leftClip * dv1dx;
188          GLfloat v2 = span->attrStart[attr][2] + span->leftClip * dv2dx;
189          GLfloat v3 = span->attrStart[attr][3] + span->leftClip * dv3dx;
190          GLuint k;
191          for (k = 0; k < span->end; k++) {
192             const GLfloat invW = 1.0f / w;
193             span->array->attribs[attr][k][0] = v0 * invW;
194             span->array->attribs[attr][k][1] = v1 * invW;
195             span->array->attribs[attr][k][2] = v2 * invW;
196             span->array->attribs[attr][k][3] = v3 * invW;
197             v0 += dv0dx;
198             v1 += dv1dx;
199             v2 += dv2dx;
200             v3 += dv3dx;
201             w += dwdx;
202          }
203          ASSERT((span->arrayAttribs & BITFIELD64_BIT(attr)) == 0);
204          span->arrayAttribs |= BITFIELD64_BIT(attr);
205       }
206    ATTRIB_LOOP_END
207 }
208
209
210 /**
211  * Interpolate primary colors to fill in the span->array->rgba8 (or rgb16)
212  * color array.
213  */
214 static inline void
215 interpolate_int_colors(struct gl_context *ctx, SWspan *span)
216 {
217 #if CHAN_BITS != 32
218    const GLuint n = span->end;
219    GLuint i;
220
221    ASSERT(!(span->arrayMask & SPAN_RGBA));
222 #endif
223
224    switch (span->array->ChanType) {
225 #if CHAN_BITS != 32
226    case GL_UNSIGNED_BYTE:
227       {
228          GLubyte (*rgba)[4] = span->array->rgba8;
229          if (span->interpMask & SPAN_FLAT) {
230             GLubyte color[4];
231             color[RCOMP] = FixedToInt(span->red);
232             color[GCOMP] = FixedToInt(span->green);
233             color[BCOMP] = FixedToInt(span->blue);
234             color[ACOMP] = FixedToInt(span->alpha);
235             for (i = 0; i < n; i++) {
236                COPY_4UBV(rgba[i], color);
237             }
238          }
239          else {
240             GLfixed r = span->red;
241             GLfixed g = span->green;
242             GLfixed b = span->blue;
243             GLfixed a = span->alpha;
244             GLint dr = span->redStep;
245             GLint dg = span->greenStep;
246             GLint db = span->blueStep;
247             GLint da = span->alphaStep;
248             for (i = 0; i < n; i++) {
249                rgba[i][RCOMP] = FixedToChan(r);
250                rgba[i][GCOMP] = FixedToChan(g);
251                rgba[i][BCOMP] = FixedToChan(b);
252                rgba[i][ACOMP] = FixedToChan(a);
253                r += dr;
254                g += dg;
255                b += db;
256                a += da;
257             }
258          }
259       }
260       break;
261    case GL_UNSIGNED_SHORT:
262       {
263          GLushort (*rgba)[4] = span->array->rgba16;
264          if (span->interpMask & SPAN_FLAT) {
265             GLushort color[4];
266             color[RCOMP] = FixedToInt(span->red);
267             color[GCOMP] = FixedToInt(span->green);
268             color[BCOMP] = FixedToInt(span->blue);
269             color[ACOMP] = FixedToInt(span->alpha);
270             for (i = 0; i < n; i++) {
271                COPY_4V(rgba[i], color);
272             }
273          }
274          else {
275             GLushort (*rgba)[4] = span->array->rgba16;
276             GLfixed r, g, b, a;
277             GLint dr, dg, db, da;
278             r = span->red;
279             g = span->green;
280             b = span->blue;
281             a = span->alpha;
282             dr = span->redStep;
283             dg = span->greenStep;
284             db = span->blueStep;
285             da = span->alphaStep;
286             for (i = 0; i < n; i++) {
287                rgba[i][RCOMP] = FixedToChan(r);
288                rgba[i][GCOMP] = FixedToChan(g);
289                rgba[i][BCOMP] = FixedToChan(b);
290                rgba[i][ACOMP] = FixedToChan(a);
291                r += dr;
292                g += dg;
293                b += db;
294                a += da;
295             }
296          }
297       }
298       break;
299 #endif
300    case GL_FLOAT:
301       interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
302       break;
303    default:
304       _mesa_problem(ctx, "bad datatype 0x%x in interpolate_int_colors",
305                     span->array->ChanType);
306    }
307    span->arrayMask |= SPAN_RGBA;
308 }
309
310
311 /**
312  * Populate the FRAG_ATTRIB_COL0 array.
313  */
314 static inline void
315 interpolate_float_colors(SWspan *span)
316 {
317    GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
318    const GLuint n = span->end;
319    GLuint i;
320
321    assert(!(span->arrayAttribs & FRAG_BIT_COL0));
322
323    if (span->arrayMask & SPAN_RGBA) {
324       /* convert array of int colors */
325       for (i = 0; i < n; i++) {
326          col0[i][0] = UBYTE_TO_FLOAT(span->array->rgba8[i][0]);
327          col0[i][1] = UBYTE_TO_FLOAT(span->array->rgba8[i][1]);
328          col0[i][2] = UBYTE_TO_FLOAT(span->array->rgba8[i][2]);
329          col0[i][3] = UBYTE_TO_FLOAT(span->array->rgba8[i][3]);
330       }
331    }
332    else {
333       /* interpolate red/green/blue/alpha to get float colors */
334       ASSERT(span->interpMask & SPAN_RGBA);
335       if (span->interpMask & SPAN_FLAT) {
336          GLfloat r = FixedToFloat(span->red);
337          GLfloat g = FixedToFloat(span->green);
338          GLfloat b = FixedToFloat(span->blue);
339          GLfloat a = FixedToFloat(span->alpha);
340          for (i = 0; i < n; i++) {
341             ASSIGN_4V(col0[i], r, g, b, a);
342          }
343       }
344       else {
345          GLfloat r = FixedToFloat(span->red);
346          GLfloat g = FixedToFloat(span->green);
347          GLfloat b = FixedToFloat(span->blue);
348          GLfloat a = FixedToFloat(span->alpha);
349          GLfloat dr = FixedToFloat(span->redStep);
350          GLfloat dg = FixedToFloat(span->greenStep);
351          GLfloat db = FixedToFloat(span->blueStep);
352          GLfloat da = FixedToFloat(span->alphaStep);
353          for (i = 0; i < n; i++) {
354             col0[i][0] = r;
355             col0[i][1] = g;
356             col0[i][2] = b;
357             col0[i][3] = a;
358             r += dr;
359             g += dg;
360             b += db;
361             a += da;
362          }
363       }
364    }
365
366    span->arrayAttribs |= FRAG_BIT_COL0;
367    span->array->ChanType = GL_FLOAT;
368 }
369
370
371
372 /**
373  * Fill in the span.zArray array from the span->z, zStep values.
374  */
375 void
376 _swrast_span_interpolate_z( const struct gl_context *ctx, SWspan *span )
377 {
378    const GLuint n = span->end;
379    GLuint i;
380
381    ASSERT(!(span->arrayMask & SPAN_Z));
382
383    if (ctx->DrawBuffer->Visual.depthBits <= 16) {
384       GLfixed zval = span->z;
385       GLuint *z = span->array->z; 
386       for (i = 0; i < n; i++) {
387          z[i] = FixedToInt(zval);
388          zval += span->zStep;
389       }
390    }
391    else {
392       /* Deep Z buffer, no fixed->int shift */
393       GLuint zval = span->z;
394       GLuint *z = span->array->z;
395       for (i = 0; i < n; i++) {
396          z[i] = zval;
397          zval += span->zStep;
398       }
399    }
400    span->interpMask &= ~SPAN_Z;
401    span->arrayMask |= SPAN_Z;
402 }
403
404
405 /**
406  * Compute mipmap LOD from partial derivatives.
407  * This the ideal solution, as given in the OpenGL spec.
408  */
409 GLfloat
410 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
411                        GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
412                        GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
413 {
414    GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
415    GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
416    GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
417    GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
418    GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
419    GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
420    GLfloat rho = MAX2(x, y);
421    GLfloat lambda = LOG2(rho);
422    return lambda;
423 }
424
425
426 /**
427  * Compute mipmap LOD from partial derivatives.
428  * This is a faster approximation than above function.
429  */
430 #if 0
431 GLfloat
432 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
433                      GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
434                      GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
435 {
436    GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
437    GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
438    GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
439    GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
440    GLfloat maxU, maxV, rho, lambda;
441    dsdx2 = FABSF(dsdx2);
442    dsdy2 = FABSF(dsdy2);
443    dtdx2 = FABSF(dtdx2);
444    dtdy2 = FABSF(dtdy2);
445    maxU = MAX2(dsdx2, dsdy2) * texW;
446    maxV = MAX2(dtdx2, dtdy2) * texH;
447    rho = MAX2(maxU, maxV);
448    lambda = LOG2(rho);
449    return lambda;
450 }
451 #endif
452
453
454 /**
455  * Fill in the span.array->attrib[FRAG_ATTRIB_TEXn] arrays from the
456  * using the attrStart/Step values.
457  *
458  * This function only used during fixed-function fragment processing.
459  *
460  * Note: in the places where we divide by Q (or mult by invQ) we're
461  * really doing two things: perspective correction and texcoord
462  * projection.  Remember, for texcoord (s,t,r,q) we need to index
463  * texels with (s/q, t/q, r/q).
464  */
465 static void
466 interpolate_texcoords(struct gl_context *ctx, SWspan *span)
467 {
468    const GLuint maxUnit
469       = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1;
470    GLuint u;
471
472    /* XXX CoordUnits vs. ImageUnits */
473    for (u = 0; u < maxUnit; u++) {
474       if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
475          const GLuint attr = FRAG_ATTRIB_TEX0 + u;
476          const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
477          GLfloat texW, texH;
478          GLboolean needLambda;
479          GLfloat (*texcoord)[4] = span->array->attribs[attr];
480          GLfloat *lambda = span->array->lambda[u];
481          const GLfloat dsdx = span->attrStepX[attr][0];
482          const GLfloat dsdy = span->attrStepY[attr][0];
483          const GLfloat dtdx = span->attrStepX[attr][1];
484          const GLfloat dtdy = span->attrStepY[attr][1];
485          const GLfloat drdx = span->attrStepX[attr][2];
486          const GLfloat dqdx = span->attrStepX[attr][3];
487          const GLfloat dqdy = span->attrStepY[attr][3];
488          GLfloat s = span->attrStart[attr][0] + span->leftClip * dsdx;
489          GLfloat t = span->attrStart[attr][1] + span->leftClip * dtdx;
490          GLfloat r = span->attrStart[attr][2] + span->leftClip * drdx;
491          GLfloat q = span->attrStart[attr][3] + span->leftClip * dqdx;
492
493          if (obj) {
494             const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
495             const struct swrast_texture_image *swImg =
496                swrast_texture_image_const(img);
497
498             needLambda = (obj->Sampler.MinFilter != obj->Sampler.MagFilter)
499                || ctx->FragmentProgram._Current;
500             /* LOD is calculated directly in the ansiotropic filter, we can
501              * skip the normal lambda function as the result is ignored.
502              */
503             if (obj->Sampler.MaxAnisotropy > 1.0 &&
504                 obj->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
505                needLambda = GL_FALSE;
506             }
507             texW = swImg->WidthScale;
508             texH = swImg->HeightScale;
509          }
510          else {
511             /* using a fragment program */
512             texW = 1.0;
513             texH = 1.0;
514             needLambda = GL_FALSE;
515          }
516
517          if (needLambda) {
518             GLuint i;
519             if (ctx->FragmentProgram._Current
520                 || ctx->ATIFragmentShader._Enabled) {
521                /* do perspective correction but don't divide s, t, r by q */
522                const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
523                GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dwdx;
524                for (i = 0; i < span->end; i++) {
525                   const GLfloat invW = 1.0F / w;
526                   texcoord[i][0] = s * invW;
527                   texcoord[i][1] = t * invW;
528                   texcoord[i][2] = r * invW;
529                   texcoord[i][3] = q * invW;
530                   lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
531                                                      dqdx, dqdy, texW, texH,
532                                                      s, t, q, invW);
533                   s += dsdx;
534                   t += dtdx;
535                   r += drdx;
536                   q += dqdx;
537                   w += dwdx;
538                }
539             }
540             else {
541                for (i = 0; i < span->end; i++) {
542                   const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
543                   texcoord[i][0] = s * invQ;
544                   texcoord[i][1] = t * invQ;
545                   texcoord[i][2] = r * invQ;
546                   texcoord[i][3] = q;
547                   lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
548                                                      dqdx, dqdy, texW, texH,
549                                                      s, t, q, invQ);
550                   s += dsdx;
551                   t += dtdx;
552                   r += drdx;
553                   q += dqdx;
554                }
555             }
556             span->arrayMask |= SPAN_LAMBDA;
557          }
558          else {
559             GLuint i;
560             if (ctx->FragmentProgram._Current ||
561                 ctx->ATIFragmentShader._Enabled) {
562                /* do perspective correction but don't divide s, t, r by q */
563                const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
564                GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dwdx;
565                for (i = 0; i < span->end; i++) {
566                   const GLfloat invW = 1.0F / w;
567                   texcoord[i][0] = s * invW;
568                   texcoord[i][1] = t * invW;
569                   texcoord[i][2] = r * invW;
570                   texcoord[i][3] = q * invW;
571                   lambda[i] = 0.0;
572                   s += dsdx;
573                   t += dtdx;
574                   r += drdx;
575                   q += dqdx;
576                   w += dwdx;
577                }
578             }
579             else if (dqdx == 0.0F) {
580                /* Ortho projection or polygon's parallel to window X axis */
581                const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
582                for (i = 0; i < span->end; i++) {
583                   texcoord[i][0] = s * invQ;
584                   texcoord[i][1] = t * invQ;
585                   texcoord[i][2] = r * invQ;
586                   texcoord[i][3] = q;
587                   lambda[i] = 0.0;
588                   s += dsdx;
589                   t += dtdx;
590                   r += drdx;
591                }
592             }
593             else {
594                for (i = 0; i < span->end; i++) {
595                   const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
596                   texcoord[i][0] = s * invQ;
597                   texcoord[i][1] = t * invQ;
598                   texcoord[i][2] = r * invQ;
599                   texcoord[i][3] = q;
600                   lambda[i] = 0.0;
601                   s += dsdx;
602                   t += dtdx;
603                   r += drdx;
604                   q += dqdx;
605                }
606             }
607          } /* lambda */
608       } /* if */
609    } /* for */
610 }
611
612
613 /**
614  * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array.
615  */
616 static inline void
617 interpolate_wpos(struct gl_context *ctx, SWspan *span)
618 {
619    GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS];
620    GLuint i;
621    const GLfloat zScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
622    GLfloat w, dw;
623
624    if (span->arrayMask & SPAN_XY) {
625       for (i = 0; i < span->end; i++) {
626          wpos[i][0] = (GLfloat) span->array->x[i];
627          wpos[i][1] = (GLfloat) span->array->y[i];
628       }
629    }
630    else {
631       for (i = 0; i < span->end; i++) {
632          wpos[i][0] = (GLfloat) span->x + i;
633          wpos[i][1] = (GLfloat) span->y;
634       }
635    }
636
637    dw = span->attrStepX[FRAG_ATTRIB_WPOS][3];
638    w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dw;
639    for (i = 0; i < span->end; i++) {
640       wpos[i][2] = (GLfloat) span->array->z[i] * zScale;
641       wpos[i][3] = w;
642       w += dw;
643    }
644 }
645
646
647 /**
648  * Apply the current polygon stipple pattern to a span of pixels.
649  */
650 static inline void
651 stipple_polygon_span(struct gl_context *ctx, SWspan *span)
652 {
653    GLubyte *mask = span->array->mask;
654
655    ASSERT(ctx->Polygon.StippleFlag);
656
657    if (span->arrayMask & SPAN_XY) {
658       /* arrays of x/y pixel coords */
659       GLuint i;
660       for (i = 0; i < span->end; i++) {
661          const GLint col = span->array->x[i] % 32;
662          const GLint row = span->array->y[i] % 32;
663          const GLuint stipple = ctx->PolygonStipple[row];
664          if (((1 << col) & stipple) == 0) {
665             mask[i] = 0;
666          }
667       }
668    }
669    else {
670       /* horizontal span of pixels */
671       const GLuint highBit = 1 << 31;
672       const GLuint stipple = ctx->PolygonStipple[span->y % 32];
673       GLuint i, m = highBit >> (GLuint) (span->x % 32);
674       for (i = 0; i < span->end; i++) {
675          if ((m & stipple) == 0) {
676             mask[i] = 0;
677          }
678          m = m >> 1;
679          if (m == 0) {
680             m = highBit;
681          }
682       }
683    }
684    span->writeAll = GL_FALSE;
685 }
686
687
688 /**
689  * Clip a pixel span to the current buffer/window boundaries:
690  * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
691  * window clipping and scissoring.
692  * Return:   GL_TRUE   some pixels still visible
693  *           GL_FALSE  nothing visible
694  */
695 static inline GLuint
696 clip_span( struct gl_context *ctx, SWspan *span )
697 {
698    const GLint xmin = ctx->DrawBuffer->_Xmin;
699    const GLint xmax = ctx->DrawBuffer->_Xmax;
700    const GLint ymin = ctx->DrawBuffer->_Ymin;
701    const GLint ymax = ctx->DrawBuffer->_Ymax;
702
703    span->leftClip = 0;
704
705    if (span->arrayMask & SPAN_XY) {
706       /* arrays of x/y pixel coords */
707       const GLint *x = span->array->x;
708       const GLint *y = span->array->y;
709       const GLint n = span->end;
710       GLubyte *mask = span->array->mask;
711       GLint i;
712       GLuint passed = 0;
713       if (span->arrayMask & SPAN_MASK) {
714          /* note: using & intead of && to reduce branches */
715          for (i = 0; i < n; i++) {
716             mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
717                      & (y[i] >= ymin) & (y[i] < ymax);
718             passed += mask[i];
719          }
720       }
721       else {
722          /* note: using & intead of && to reduce branches */
723          for (i = 0; i < n; i++) {
724             mask[i] = (x[i] >= xmin) & (x[i] < xmax)
725                     & (y[i] >= ymin) & (y[i] < ymax);
726             passed += mask[i];
727          }
728       }
729       return passed > 0;
730    }
731    else {
732       /* horizontal span of pixels */
733       const GLint x = span->x;
734       const GLint y = span->y;
735       GLint n = span->end;
736
737       /* Trivial rejection tests */
738       if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
739          span->end = 0;
740          return GL_FALSE;  /* all pixels clipped */
741       }
742
743       /* Clip to right */
744       if (x + n > xmax) {
745          ASSERT(x < xmax);
746          n = span->end = xmax - x;
747       }
748
749       /* Clip to the left */
750       if (x < xmin) {
751          const GLint leftClip = xmin - x;
752          GLuint i;
753
754          ASSERT(leftClip > 0);
755          ASSERT(x + n > xmin);
756
757          /* Clip 'leftClip' pixels from the left side.
758           * The span->leftClip field will be applied when we interpolate
759           * fragment attributes.
760           * For arrays of values, shift them left.
761           */
762          for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
763             if (span->interpMask & (1 << i)) {
764                GLuint j;
765                for (j = 0; j < 4; j++) {
766                   span->attrStart[i][j] += leftClip * span->attrStepX[i][j];
767                }
768             }
769          }
770
771          span->red += leftClip * span->redStep;
772          span->green += leftClip * span->greenStep;
773          span->blue += leftClip * span->blueStep;
774          span->alpha += leftClip * span->alphaStep;
775          span->index += leftClip * span->indexStep;
776          span->z += leftClip * span->zStep;
777          span->intTex[0] += leftClip * span->intTexStep[0];
778          span->intTex[1] += leftClip * span->intTexStep[1];
779
780 #define SHIFT_ARRAY(ARRAY, SHIFT, LEN) \
781          memmove(ARRAY, ARRAY + (SHIFT), (LEN) * sizeof(ARRAY[0]))
782
783          for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
784             if (span->arrayAttribs & (1 << i)) {
785                /* shift array elements left by 'leftClip' */
786                SHIFT_ARRAY(span->array->attribs[i], leftClip, n - leftClip);
787             }
788          }
789
790          SHIFT_ARRAY(span->array->mask, leftClip, n - leftClip);
791          SHIFT_ARRAY(span->array->rgba8, leftClip, n - leftClip);
792          SHIFT_ARRAY(span->array->rgba16, leftClip, n - leftClip);
793          SHIFT_ARRAY(span->array->x, leftClip, n - leftClip);
794          SHIFT_ARRAY(span->array->y, leftClip, n - leftClip);
795          SHIFT_ARRAY(span->array->z, leftClip, n - leftClip);
796          SHIFT_ARRAY(span->array->index, leftClip, n - leftClip);
797          for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
798             SHIFT_ARRAY(span->array->lambda[i], leftClip, n - leftClip);
799          }
800          SHIFT_ARRAY(span->array->coverage, leftClip, n - leftClip);
801
802 #undef SHIFT_ARRAY
803
804          span->leftClip = leftClip;
805          span->x = xmin;
806          span->end -= leftClip;
807          span->writeAll = GL_FALSE;
808       }
809
810       ASSERT(span->x >= xmin);
811       ASSERT(span->x + span->end <= xmax);
812       ASSERT(span->y >= ymin);
813       ASSERT(span->y < ymax);
814
815       return GL_TRUE;  /* some pixels visible */
816    }
817 }
818
819
820 /**
821  * Add specular colors to primary colors.
822  * Only called during fixed-function operation.
823  * Result is float color array (FRAG_ATTRIB_COL0).
824  */
825 static inline void
826 add_specular(struct gl_context *ctx, SWspan *span)
827 {
828    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
829    const GLubyte *mask = span->array->mask;
830    GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
831    GLfloat (*col1)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
832    GLuint i;
833
834    ASSERT(!ctx->FragmentProgram._Current);
835    ASSERT(span->arrayMask & SPAN_RGBA);
836    ASSERT(swrast->_ActiveAttribMask & FRAG_BIT_COL1);
837    (void) swrast; /* silence warning */
838
839    if (span->array->ChanType == GL_FLOAT) {
840       if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
841          interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
842       }
843    }
844    else {
845       /* need float colors */
846       if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
847          interpolate_float_colors(span);
848       }
849    }
850
851    if ((span->arrayAttribs & FRAG_BIT_COL1) == 0) {
852       /* XXX could avoid this and interpolate COL1 in the loop below */
853       interpolate_active_attribs(ctx, span, FRAG_BIT_COL1);
854    }
855
856    ASSERT(span->arrayAttribs & FRAG_BIT_COL0);
857    ASSERT(span->arrayAttribs & FRAG_BIT_COL1);
858
859    for (i = 0; i < span->end; i++) {
860       if (mask[i]) {
861          col0[i][0] += col1[i][0];
862          col0[i][1] += col1[i][1];
863          col0[i][2] += col1[i][2];
864       }
865    }
866
867    span->array->ChanType = GL_FLOAT;
868 }
869
870
871 /**
872  * Apply antialiasing coverage value to alpha values.
873  */
874 static inline void
875 apply_aa_coverage(SWspan *span)
876 {
877    const GLfloat *coverage = span->array->coverage;
878    GLuint i;
879    if (span->array->ChanType == GL_UNSIGNED_BYTE) {
880       GLubyte (*rgba)[4] = span->array->rgba8;
881       for (i = 0; i < span->end; i++) {
882          const GLfloat a = rgba[i][ACOMP] * coverage[i];
883          rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0);
884          ASSERT(coverage[i] >= 0.0);
885          ASSERT(coverage[i] <= 1.0);
886       }
887    }
888    else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
889       GLushort (*rgba)[4] = span->array->rgba16;
890       for (i = 0; i < span->end; i++) {
891          const GLfloat a = rgba[i][ACOMP] * coverage[i];
892          rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0);
893       }
894    }
895    else {
896       GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
897       for (i = 0; i < span->end; i++) {
898          rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
899          /* clamp later */
900       }
901    }
902 }
903
904
905 /**
906  * Clamp span's float colors to [0,1]
907  */
908 static inline void
909 clamp_colors(SWspan *span)
910 {
911    GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
912    GLuint i;
913    ASSERT(span->array->ChanType == GL_FLOAT);
914    for (i = 0; i < span->end; i++) {
915       rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
916       rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
917       rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
918       rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
919    }
920 }
921
922
923 /**
924  * Convert the span's color arrays to the given type.
925  * The only way 'output' can be greater than zero is when we have a fragment
926  * program that writes to gl_FragData[1] or higher.
927  * \param output  which fragment program color output is being processed
928  */
929 static inline void
930 convert_color_type(SWspan *span, GLenum newType, GLuint output)
931 {
932    GLvoid *src, *dst;
933
934    if (output > 0 || span->array->ChanType == GL_FLOAT) {
935       src = span->array->attribs[FRAG_ATTRIB_COL0 + output];
936       span->array->ChanType = GL_FLOAT;
937    }
938    else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
939       src = span->array->rgba8;
940    }
941    else {
942       ASSERT(span->array->ChanType == GL_UNSIGNED_SHORT);
943       src = span->array->rgba16;
944    }
945
946    if (newType == GL_UNSIGNED_BYTE) {
947       dst = span->array->rgba8;
948    }
949    else if (newType == GL_UNSIGNED_SHORT) {
950       dst = span->array->rgba16;
951    }
952    else {
953       dst = span->array->attribs[FRAG_ATTRIB_COL0];
954    }
955
956    _mesa_convert_colors(span->array->ChanType, src,
957                         newType, dst,
958                         span->end, span->array->mask);
959
960    span->array->ChanType = newType;
961    span->array->rgba = dst;
962 }
963
964
965
966 /**
967  * Apply fragment shader, fragment program or normal texturing to span.
968  */
969 static inline void
970 shade_texture_span(struct gl_context *ctx, SWspan *span)
971 {
972    /* This is a hack to work around drivers such as i965 that:
973     *
974     *     - Set _MaintainTexEnvProgram to generate GLSL IR for
975     *       fixed-function fragment processing.
976     *     - Don't call _mesa_ir_link_shader to generate Mesa IR from
977     *       the GLSL IR.
978     *     - May use swrast to handle glDrawPixels.
979     *
980     * Since _mesa_ir_link_shader is never called, there is no Mesa IR
981     * to execute.  Instead do regular fixed-function processing.
982     *
983     * It is also worth noting that the software fixed-function path is
984     * much faster than the software shader path.
985     */
986    const bool use_fragment_program =
987       ctx->FragmentProgram._Current
988       && ctx->FragmentProgram._Current != ctx->FragmentProgram._TexEnvProgram;
989
990    if (use_fragment_program ||
991        ctx->ATIFragmentShader._Enabled) {
992       /* programmable shading */
993       if (span->primitive == GL_BITMAP && span->array->ChanType != GL_FLOAT) {
994          convert_color_type(span, GL_FLOAT, 0);
995       }
996       else {
997          span->array->rgba = (void *) span->array->attribs[FRAG_ATTRIB_COL0];
998       }
999
1000       if (span->primitive != GL_POINT ||
1001           (span->interpMask & SPAN_RGBA) ||
1002           ctx->Point.PointSprite) {
1003          /* for single-pixel points, we populated the arrays already */
1004          interpolate_active_attribs(ctx, span, ~0);
1005       }
1006       span->array->ChanType = GL_FLOAT;
1007
1008       if (!(span->arrayMask & SPAN_Z))
1009          _swrast_span_interpolate_z (ctx, span);
1010
1011 #if 0
1012       if (inputsRead & FRAG_BIT_WPOS)
1013 #else
1014       /* XXX always interpolate wpos so that DDX/DDY work */
1015 #endif
1016          interpolate_wpos(ctx, span);
1017
1018       /* Run fragment program/shader now */
1019       if (use_fragment_program) {
1020          _swrast_exec_fragment_program(ctx, span);
1021       }
1022       else {
1023          ASSERT(ctx->ATIFragmentShader._Enabled);
1024          _swrast_exec_fragment_shader(ctx, span);
1025       }
1026    }
1027    else if (ctx->Texture._EnabledCoordUnits) {
1028       /* conventional texturing */
1029
1030 #if CHAN_BITS == 32
1031       if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
1032          interpolate_int_colors(ctx, span);
1033       }
1034 #else
1035       if (!(span->arrayMask & SPAN_RGBA))
1036          interpolate_int_colors(ctx, span);
1037 #endif
1038       if ((span->arrayAttribs & FRAG_BITS_TEX_ANY) == 0x0)
1039          interpolate_texcoords(ctx, span);
1040
1041       _swrast_texture_span(ctx, span);
1042    }
1043 }
1044
1045
1046
1047 /**
1048  * Apply all the per-fragment operations to a span.
1049  * This now includes texturing (_swrast_write_texture_span() is history).
1050  * This function may modify any of the array values in the span.
1051  * span->interpMask and span->arrayMask may be changed but will be restored
1052  * to their original values before returning.
1053  */
1054 void
1055 _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
1056 {
1057    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1058    const GLuint *colorMask = (GLuint *) ctx->Color.ColorMask;
1059    const GLbitfield origInterpMask = span->interpMask;
1060    const GLbitfield origArrayMask = span->arrayMask;
1061    const GLbitfield64 origArrayAttribs = span->arrayAttribs;
1062    const GLenum origChanType = span->array->ChanType;
1063    void * const origRgba = span->array->rgba;
1064    const GLboolean shader = (ctx->FragmentProgram._Current
1065                              || ctx->ATIFragmentShader._Enabled);
1066    const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledCoordUnits;
1067    struct gl_framebuffer *fb = ctx->DrawBuffer;
1068
1069    /*
1070    printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__,
1071           span->interpMask, span->arrayMask);
1072    */
1073
1074    ASSERT(span->primitive == GL_POINT ||
1075           span->primitive == GL_LINE ||
1076           span->primitive == GL_POLYGON ||
1077           span->primitive == GL_BITMAP);
1078
1079    /* Fragment write masks */
1080    if (span->arrayMask & SPAN_MASK) {
1081       /* mask was initialized by caller, probably glBitmap */
1082       span->writeAll = GL_FALSE;
1083    }
1084    else {
1085       memset(span->array->mask, 1, span->end);
1086       span->writeAll = GL_TRUE;
1087    }
1088
1089    /* Clip to window/scissor box */
1090    if (!clip_span(ctx, span)) {
1091       return;
1092    }
1093
1094    ASSERT(span->end <= MAX_WIDTH);
1095
1096    /* Depth bounds test */
1097    if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) {
1098       if (!_swrast_depth_bounds_test(ctx, span)) {
1099          return;
1100       }
1101    }
1102
1103 #ifdef DEBUG
1104    /* Make sure all fragments are within window bounds */
1105    if (span->arrayMask & SPAN_XY) {
1106       /* array of pixel locations */
1107       GLuint i;
1108       for (i = 0; i < span->end; i++) {
1109          if (span->array->mask[i]) {
1110             assert(span->array->x[i] >= fb->_Xmin);
1111             assert(span->array->x[i] < fb->_Xmax);
1112             assert(span->array->y[i] >= fb->_Ymin);
1113             assert(span->array->y[i] < fb->_Ymax);
1114          }
1115       }
1116    }
1117 #endif
1118
1119    /* Polygon Stippling */
1120    if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1121       stipple_polygon_span(ctx, span);
1122    }
1123
1124    /* This is the normal place to compute the fragment color/Z
1125     * from texturing or shading.
1126     */
1127    if (shaderOrTexture && !swrast->_DeferredTexture) {
1128       shade_texture_span(ctx, span);
1129    }
1130
1131    /* Do the alpha test */
1132    if (ctx->Color.AlphaEnabled) {
1133       if (!_swrast_alpha_test(ctx, span)) {
1134          /* all fragments failed test */
1135          goto end;
1136       }
1137    }
1138
1139    /* Stencil and Z testing */
1140    if (ctx->Stencil._Enabled || ctx->Depth.Test) {
1141       if (!(span->arrayMask & SPAN_Z))
1142          _swrast_span_interpolate_z(ctx, span);
1143
1144       if (ctx->Transform.DepthClamp)
1145          _swrast_depth_clamp_span(ctx, span);
1146
1147       if (ctx->Stencil._Enabled) {
1148          /* Combined Z/stencil tests */
1149          if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1150             /* all fragments failed test */
1151             goto end;
1152          }
1153       }
1154       else if (fb->Visual.depthBits > 0) {
1155          /* Just regular depth testing */
1156          ASSERT(ctx->Depth.Test);
1157          ASSERT(span->arrayMask & SPAN_Z);
1158          if (!_swrast_depth_test_span(ctx, span)) {
1159             /* all fragments failed test */
1160             goto end;
1161          }
1162       }
1163    }
1164
1165    if (ctx->Query.CurrentOcclusionObject) {
1166       /* update count of 'passed' fragments */
1167       struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1168       GLuint i;
1169       for (i = 0; i < span->end; i++)
1170          q->Result += span->array->mask[i];
1171    }
1172
1173    /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1174     * the occlusion test.
1175     */
1176    if (fb->_NumColorDrawBuffers == 1 && colorMask[0] == 0x0) {
1177       /* no colors to write */
1178       goto end;
1179    }
1180
1181    /* If we were able to defer fragment color computation to now, there's
1182     * a good chance that many fragments will have already been killed by
1183     * Z/stencil testing.
1184     */
1185    if (shaderOrTexture && swrast->_DeferredTexture) {
1186       shade_texture_span(ctx, span);
1187    }
1188
1189 #if CHAN_BITS == 32
1190    if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
1191       interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
1192    }
1193 #else
1194    if ((span->arrayMask & SPAN_RGBA) == 0) {
1195       interpolate_int_colors(ctx, span);
1196    }
1197 #endif
1198
1199    ASSERT(span->arrayMask & SPAN_RGBA);
1200
1201    if (span->primitive == GL_BITMAP || !swrast->SpecularVertexAdd) {
1202       /* Add primary and specular (diffuse + specular) colors */
1203       if (!shader) {
1204          if (ctx->Fog.ColorSumEnabled ||
1205              (ctx->Light.Enabled &&
1206               ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1207             add_specular(ctx, span);
1208          }
1209       }
1210    }
1211
1212    /* Fog */
1213    if (swrast->_FogEnabled) {
1214       _swrast_fog_rgba_span(ctx, span);
1215    }
1216
1217    /* Antialias coverage application */
1218    if (span->arrayMask & SPAN_COVERAGE) {
1219       apply_aa_coverage(span);
1220    }
1221
1222    /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
1223    if (ctx->Color.ClampFragmentColor == GL_TRUE &&
1224        span->array->ChanType == GL_FLOAT) {
1225       clamp_colors(span);
1226    }
1227
1228    /*
1229     * Write to renderbuffers.
1230     * Depending on glDrawBuffer() state and the which color outputs are
1231     * written by the fragment shader, we may either replicate one color to
1232     * all renderbuffers or write a different color to each renderbuffer.
1233     * multiFragOutputs=TRUE for the later case.
1234     */
1235    {
1236       const GLuint numBuffers = fb->_NumColorDrawBuffers;
1237       const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
1238       const GLboolean multiFragOutputs = 
1239          (fp && fp->Base.OutputsWritten >= (1 << FRAG_RESULT_DATA0));
1240       GLuint buf;
1241
1242       for (buf = 0; buf < numBuffers; buf++) {
1243          struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf];
1244
1245          /* color[fragOutput] will be written to buffer[buf] */
1246
1247          if (rb) {
1248             GLchan rgbaSave[MAX_WIDTH][4];
1249             const GLuint fragOutput = multiFragOutputs ? buf : 0;
1250
1251             /* set span->array->rgba to colors for render buffer's datatype */
1252             if (rb->DataType != span->array->ChanType || fragOutput > 0) {
1253                convert_color_type(span, rb->DataType, fragOutput);
1254             }
1255             else {
1256                if (rb->DataType == GL_UNSIGNED_BYTE) {
1257                   span->array->rgba = span->array->rgba8;
1258                }
1259                else if (rb->DataType == GL_UNSIGNED_SHORT) {
1260                   span->array->rgba = (void *) span->array->rgba16;
1261                }
1262                else {
1263                   span->array->rgba = (void *)
1264                      span->array->attribs[FRAG_ATTRIB_COL0];
1265                }
1266             }
1267
1268             if (!multiFragOutputs && numBuffers > 1) {
1269                /* save colors for second, third renderbuffer writes */
1270                memcpy(rgbaSave, span->array->rgba,
1271                       4 * span->end * sizeof(GLchan));
1272             }
1273
1274             ASSERT(rb->_BaseFormat == GL_RGBA ||
1275                    rb->_BaseFormat == GL_RGB ||
1276                    rb->_BaseFormat == GL_RED ||
1277                    rb->_BaseFormat == GL_RG ||
1278                    rb->_BaseFormat == GL_ALPHA);
1279
1280             if (ctx->Color.ColorLogicOpEnabled) {
1281                _swrast_logicop_rgba_span(ctx, rb, span);
1282             }
1283             else if ((ctx->Color.BlendEnabled >> buf) & 1) {
1284                _swrast_blend_span(ctx, rb, span);
1285             }
1286
1287             if (colorMask[buf] != 0xffffffff) {
1288                _swrast_mask_rgba_span(ctx, rb, span, buf);
1289             }
1290
1291             if (span->arrayMask & SPAN_XY) {
1292                /* array of pixel coords */
1293                ASSERT(rb->PutValues);
1294                rb->PutValues(ctx, rb, span->end,
1295                              span->array->x, span->array->y,
1296                              span->array->rgba, span->array->mask);
1297             }
1298             else {
1299                /* horizontal run of pixels */
1300                ASSERT(rb->PutRow);
1301                rb->PutRow(ctx, rb, span->end, span->x, span->y,
1302                           span->array->rgba,
1303                           span->writeAll ? NULL: span->array->mask);
1304             }
1305
1306             if (!multiFragOutputs && numBuffers > 1) {
1307                /* restore original span values */
1308                memcpy(span->array->rgba, rgbaSave,
1309                       4 * span->end * sizeof(GLchan));
1310             }
1311
1312          } /* if rb */
1313       } /* for buf */
1314    }
1315
1316 end:
1317    /* restore these values before returning */
1318    span->interpMask = origInterpMask;
1319    span->arrayMask = origArrayMask;
1320    span->arrayAttribs = origArrayAttribs;
1321    span->array->ChanType = origChanType;
1322    span->array->rgba = origRgba;
1323 }
1324
1325
1326 /**
1327  * Read float RGBA pixels from a renderbuffer.  Clipping will be done to
1328  * prevent reading ouside the buffer's boundaries.
1329  * \param rgba  the returned colors
1330  */
1331 void
1332 _swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb,
1333                         GLuint n, GLint x, GLint y,
1334                         GLvoid *rgba)
1335 {
1336    GLenum dstType = GL_FLOAT;
1337    const GLint bufWidth = (GLint) rb->Width;
1338    const GLint bufHeight = (GLint) rb->Height;
1339
1340    if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1341       /* completely above, below, or right */
1342       /* XXX maybe leave rgba values undefined? */
1343       memset(rgba, 0, 4 * n * sizeof(GLchan));
1344    }
1345    else {
1346       GLint skip, length;
1347       if (x < 0) {
1348          /* left edge clipping */
1349          skip = -x;
1350          length = (GLint) n - skip;
1351          if (length < 0) {
1352             /* completely left of window */
1353             return;
1354          }
1355          if (length > bufWidth) {
1356             length = bufWidth;
1357          }
1358       }
1359       else if ((GLint) (x + n) > bufWidth) {
1360          /* right edge clipping */
1361          skip = 0;
1362          length = bufWidth - x;
1363          if (length < 0) {
1364             /* completely to right of window */
1365             return;
1366          }
1367       }
1368       else {
1369          /* no clipping */
1370          skip = 0;
1371          length = (GLint) n;
1372       }
1373
1374       ASSERT(rb);
1375       ASSERT(rb->GetRow);
1376       ASSERT(rb->_BaseFormat == GL_RGBA ||
1377              rb->_BaseFormat == GL_RGB ||
1378              rb->_BaseFormat == GL_RG ||
1379              rb->_BaseFormat == GL_RED ||
1380              rb->_BaseFormat == GL_LUMINANCE ||
1381              rb->_BaseFormat == GL_INTENSITY ||
1382              rb->_BaseFormat == GL_LUMINANCE_ALPHA ||
1383              rb->_BaseFormat == GL_ALPHA);
1384
1385       if (rb->DataType == dstType) {
1386          rb->GetRow(ctx, rb, length, x + skip, y,
1387                     (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
1388       }
1389       else {
1390          GLuint temp[MAX_WIDTH * 4];
1391          rb->GetRow(ctx, rb, length, x + skip, y, temp);
1392          _mesa_convert_colors(rb->DataType, temp,
1393                    dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
1394                    length, NULL);
1395       }
1396    }
1397 }
1398
1399
1400 /**
1401  * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
1402  * reading values outside the buffer bounds.
1403  * We can use this for reading any format/type of renderbuffer.
1404  * \param valueSize is the size in bytes of each value (pixel) put into the
1405  *                  values array.
1406  */
1407 void
1408 _swrast_get_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
1409                    GLuint count, const GLint x[], const GLint y[],
1410                    void *values, GLuint valueSize)
1411 {
1412    GLuint i, inCount = 0, inStart = 0;
1413
1414    for (i = 0; i < count; i++) {
1415       if (x[i] >= 0 && y[i] >= 0 &&
1416           x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
1417          /* inside */
1418          if (inCount == 0)
1419             inStart = i;
1420          inCount++;
1421       }
1422       else {
1423          if (inCount > 0) {
1424             /* read [inStart, inStart + inCount) */
1425             rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
1426                           (GLubyte *) values + inStart * valueSize);
1427             inCount = 0;
1428          }
1429       }
1430    }
1431    if (inCount > 0) {
1432       /* read last values */
1433       rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
1434                     (GLubyte *) values + inStart * valueSize);
1435    }
1436 }
1437
1438
1439 /**
1440  * Wrapper for gl_renderbuffer::GetRow() which does clipping.
1441  * \param valueSize  size of each value (pixel) in bytes
1442  */
1443 void
1444 _swrast_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
1445                 GLuint count, GLint x, GLint y,
1446                 GLvoid *values, GLuint valueSize)
1447 {
1448    GLint skip = 0;
1449
1450    if (y < 0 || y >= (GLint) rb->Height)
1451       return; /* above or below */
1452
1453    if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
1454       return; /* entirely left or right */
1455
1456    if (x + count > rb->Width) {
1457       /* right clip */
1458       GLint clip = x + count - rb->Width;
1459       count -= clip;
1460    }
1461
1462    if (x < 0) {
1463       /* left clip */
1464       skip = -x;
1465       x = 0;
1466       count -= skip;
1467    }
1468
1469    rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
1470 }
1471
1472
1473 /**
1474  * Get RGBA pixels from the given renderbuffer.
1475  * Used by blending, logicop and masking functions.
1476  * \return pointer to the colors we read.
1477  */
1478 void *
1479 _swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb,
1480                       SWspan *span)
1481 {
1482    const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
1483    void *rbPixels;
1484
1485    /* Point rbPixels to a temporary space */
1486    rbPixels = span->array->attribs[FRAG_ATTRIB_MAX - 1];
1487
1488    /* Get destination values from renderbuffer */
1489    if (span->arrayMask & SPAN_XY) {
1490       _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
1491                          rbPixels, pixelSize);
1492    }
1493    else {
1494       _swrast_get_row(ctx, rb, span->end, span->x, span->y,
1495                       rbPixels, pixelSize);
1496    }
1497
1498    return rbPixels;
1499 }