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