Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

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