Added ctx->Texture._EnabledCoordUnits bitfield.
[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 s += dsdx;
519 t += dtdx;
520 r += drdx;
521 }
522 }
523 else {
524 for (i = 0; i < span->end; i++) {
525 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
526 texcoord[i][0] = s * invQ;
527 texcoord[i][1] = t * invQ;
528 texcoord[i][2] = r * invQ;
529 s += dsdx;
530 t += dtdx;
531 r += drdx;
532 q += dqdx;
533 }
534 }
535 }
536 }
537 }
538
539
540 /**
541 * Apply the current polygon stipple pattern to a span of pixels.
542 */
543 static void
544 stipple_polygon_span( GLcontext *ctx, struct sw_span *span )
545 {
546 const GLuint highbit = 0x80000000;
547 const GLuint stipple = ctx->PolygonStipple[span->y % 32];
548 GLubyte *mask = span->array->mask;
549 GLuint i, m;
550
551 ASSERT(ctx->Polygon.StippleFlag);
552 ASSERT((span->arrayMask & SPAN_XY) == 0);
553
554 m = highbit >> (GLuint) (span->x % 32);
555
556 for (i = 0; i < span->end; i++) {
557 if ((m & stipple) == 0) {
558 mask[i] = 0;
559 }
560 m = m >> 1;
561 if (m == 0) {
562 m = highbit;
563 }
564 }
565 span->writeAll = GL_FALSE;
566 }
567
568
569 /**
570 * Clip a pixel span to the current buffer/window boundaries:
571 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
572 * window clipping and scissoring.
573 * Return: GL_TRUE some pixels still visible
574 * GL_FALSE nothing visible
575 */
576 static GLuint
577 clip_span( GLcontext *ctx, struct sw_span *span )
578 {
579 const GLint xmin = ctx->DrawBuffer->_Xmin;
580 const GLint xmax = ctx->DrawBuffer->_Xmax;
581 const GLint ymin = ctx->DrawBuffer->_Ymin;
582 const GLint ymax = ctx->DrawBuffer->_Ymax;
583
584 if (span->arrayMask & SPAN_XY) {
585 /* arrays of x/y pixel coords */
586 const GLint *x = span->array->x;
587 const GLint *y = span->array->y;
588 const GLint n = span->end;
589 GLubyte *mask = span->array->mask;
590 GLint i;
591 if (span->arrayMask & SPAN_MASK) {
592 /* note: using & intead of && to reduce branches */
593 for (i = 0; i < n; i++) {
594 mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
595 & (y[i] >= ymin) & (y[i] < ymax);
596 }
597 }
598 else {
599 /* note: using & intead of && to reduce branches */
600 for (i = 0; i < n; i++) {
601 mask[i] = (x[i] >= xmin) & (x[i] < xmax)
602 & (y[i] >= ymin) & (y[i] < ymax);
603 }
604 }
605 return GL_TRUE; /* some pixels visible */
606 }
607 else {
608 /* horizontal span of pixels */
609 const GLint x = span->x;
610 const GLint y = span->y;
611 const GLint n = span->end;
612
613 /* Trivial rejection tests */
614 if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
615 span->end = 0;
616 return GL_FALSE; /* all pixels clipped */
617 }
618
619 /* Clip to the left */
620 if (x < xmin) {
621 ASSERT(x + n > xmin);
622 span->writeAll = GL_FALSE;
623 _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
624 }
625
626 /* Clip to right */
627 if (x + n > xmax) {
628 ASSERT(x < xmax);
629 span->end = xmax - x;
630 }
631
632 return GL_TRUE; /* some pixels visible */
633 }
634 }
635
636
637
638 /**
639 * Draw to more than one color buffer (or none).
640 */
641 static void
642 multi_write_index_span( GLcontext *ctx, struct sw_span *span )
643 {
644 SWcontext *swrast = SWRAST_CONTEXT(ctx);
645 GLuint bufferBit;
646
647 /* loop over four possible dest color buffers */
648 for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) {
649 if (bufferBit & ctx->Color._DrawDestMask) {
650 GLuint indexTmp[MAX_WIDTH];
651 ASSERT(span->end < MAX_WIDTH);
652
653 /* Set the current read/draw buffer */
654 swrast->CurrentBuffer = bufferBit;
655 (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
656
657 /* make copy of incoming indexes */
658 MEMCPY( indexTmp, span->array->index, span->end * sizeof(GLuint) );
659
660 if (ctx->Color.IndexLogicOpEnabled) {
661 _swrast_logicop_ci_span(ctx, span, indexTmp);
662 }
663
664 if (ctx->Color.IndexMask != 0xffffffff) {
665 _swrast_mask_index_span(ctx, span, indexTmp);
666 }
667
668 if (span->arrayMask & SPAN_XY) {
669 /* array of pixel coords */
670 (*swrast->Driver.WriteCI32Pixels)(ctx, span->end,
671 span->array->x, span->array->y,
672 indexTmp, span->array->mask);
673 }
674 else {
675 /* horizontal run of pixels */
676 (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
677 indexTmp, span->array->mask);
678 }
679 }
680 }
681
682 /* restore default dest buffer */
683 _swrast_use_draw_buffer(ctx);
684 }
685
686
687 /**
688 * Draw to more than one RGBA color buffer (or none).
689 * All fragment operations, up to (but not) blending/logicop should
690 * have been done first.
691 */
692 static void
693 multi_write_rgba_span( GLcontext *ctx, struct sw_span *span )
694 {
695 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
696 GLuint bufferBit;
697 SWcontext *swrast = SWRAST_CONTEXT(ctx);
698
699 ASSERT(colorMask != 0x0);
700
701 if (ctx->Color.DrawBuffer == GL_NONE)
702 return;
703
704 /* loop over four possible dest color buffers */
705 for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) {
706 if (bufferBit & ctx->Color._DrawDestMask) {
707 GLchan rgbaTmp[MAX_WIDTH][4];
708 ASSERT(span->end < MAX_WIDTH);
709
710 /* Set the current read/draw buffer */
711 swrast->CurrentBuffer = bufferBit;
712 (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
713
714 /* make copy of incoming colors */
715 MEMCPY( rgbaTmp, span->array->rgba, 4 * span->end * sizeof(GLchan) );
716
717 if (ctx->Color.ColorLogicOpEnabled) {
718 _swrast_logicop_rgba_span(ctx, span, rgbaTmp);
719 }
720 else if (ctx->Color.BlendEnabled) {
721 _swrast_blend_span(ctx, span, rgbaTmp);
722 }
723
724 if (colorMask != 0xffffffff) {
725 _swrast_mask_rgba_span(ctx, span, rgbaTmp);
726 }
727
728 if (span->arrayMask & SPAN_XY) {
729 /* array of pixel coords */
730 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end,
731 span->array->x, span->array->y,
732 (const GLchan (*)[4]) rgbaTmp,
733 span->array->mask);
734 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
735 _swrast_write_alpha_pixels(ctx, span->end,
736 span->array->x, span->array->y,
737 (const GLchan (*)[4]) rgbaTmp,
738 span->array->mask);
739 }
740 }
741 else {
742 /* horizontal run of pixels */
743 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
744 (const GLchan (*)[4]) rgbaTmp,
745 span->array->mask);
746 if (swrast->_RasterMask & ALPHABUF_BIT) {
747 _swrast_write_alpha_span(ctx, span->end, span->x, span->y,
748 (const GLchan (*)[4]) rgbaTmp,
749 span->array->mask);
750 }
751 }
752 }
753 }
754
755 /* restore default dest buffer */
756 _swrast_use_draw_buffer(ctx);
757 }
758
759
760
761 /**
762 * This function may modify any of the array values in the span.
763 * span->interpMask and span->arrayMask may be changed but will be restored
764 * to their original values before returning.
765 */
766 void
767 _swrast_write_index_span( GLcontext *ctx, struct sw_span *span)
768 {
769 SWcontext *swrast = SWRAST_CONTEXT(ctx);
770 const GLuint origInterpMask = span->interpMask;
771 const GLuint origArrayMask = span->arrayMask;
772
773 ASSERT(span->end <= MAX_WIDTH);
774 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
775 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
776 ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
777 ASSERT((span->interpMask & span->arrayMask) == 0);
778
779 if (span->arrayMask & SPAN_MASK) {
780 /* mask was initialized by caller, probably glBitmap */
781 span->writeAll = GL_FALSE;
782 }
783 else {
784 MEMSET(span->array->mask, 1, span->end);
785 span->writeAll = GL_TRUE;
786 }
787
788 /* Clipping */
789 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
790 if (!clip_span(ctx, span)) {
791 return;
792 }
793 }
794
795 #ifdef DEBUG
796 if (span->arrayMask & SPAN_XY) {
797 GLuint i;
798 for (i = 0; i < span->end; i++) {
799 if (span->array->mask[i]) {
800 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
801 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
802 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
803 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
804 }
805 }
806 }
807 #endif
808
809 /* Polygon Stippling */
810 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
811 stipple_polygon_span(ctx, span);
812 }
813
814 /* Depth test and stencil */
815 if (ctx->Depth.Test || ctx->Stencil.Enabled) {
816 if (span->interpMask & SPAN_Z)
817 _swrast_span_interpolate_z(ctx, span);
818
819 if (ctx->Stencil.Enabled) {
820 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
821 span->arrayMask = origArrayMask;
822 return;
823 }
824 }
825 else {
826 ASSERT(ctx->Depth.Test);
827 if (!_swrast_depth_test_span(ctx, span)) {
828 span->arrayMask = origArrayMask;
829 return;
830 }
831 }
832 }
833
834 /* if we get here, something passed the depth test */
835 ctx->OcclusionResult = GL_TRUE;
836
837 /* we have to wait until after occlusion to do this test */
838 if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
839 /* write no pixels */
840 span->arrayMask = origArrayMask;
841 return;
842 }
843
844 /* Interpolate the color indexes if needed */
845 if (span->interpMask & SPAN_INDEX) {
846 interpolate_indexes(ctx, span);
847 /* clear the bit - this allows the WriteMonoCISpan optimization below */
848 span->interpMask &= ~SPAN_INDEX;
849 }
850
851 /* Fog */
852 if (ctx->Fog.Enabled) {
853 _swrast_fog_ci_span(ctx, span);
854 }
855
856 /* Antialias coverage application */
857 if (span->arrayMask & SPAN_COVERAGE) {
858 GLuint i;
859 GLuint *index = span->array->index;
860 GLfloat *coverage = span->array->coverage;
861 for (i = 0; i < span->end; i++) {
862 ASSERT(coverage[i] < 16);
863 index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
864 }
865 }
866
867 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
868 /* draw to zero or two or more buffers */
869 multi_write_index_span(ctx, span);
870 }
871 else {
872 /* normal situation: draw to exactly one buffer */
873 if (ctx->Color.IndexLogicOpEnabled) {
874 _swrast_logicop_ci_span(ctx, span, span->array->index);
875 }
876
877 if (ctx->Color.IndexMask != 0xffffffff) {
878 _swrast_mask_index_span(ctx, span, span->array->index);
879 }
880
881 /* write pixels */
882 if (span->arrayMask & SPAN_XY) {
883 /* array of pixel coords */
884 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
885 /* all pixels have same color index */
886 (*swrast->Driver.WriteMonoCIPixels)(ctx, span->end,
887 span->array->x, span->array->y,
888 FixedToInt(span->index),
889 span->array->mask);
890 }
891 else {
892 (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, span->array->x,
893 span->array->y, span->array->index,
894 span->array->mask );
895 }
896 }
897 else {
898 /* horizontal run of pixels */
899 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
900 /* all pixels have same color index */
901 (*swrast->Driver.WriteMonoCISpan)(ctx, span->end, span->x, span->y,
902 FixedToInt(span->index),
903 span->array->mask);
904 }
905 else {
906 (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
907 span->array->index,
908 span->array->mask);
909 }
910 }
911 }
912
913 span->interpMask = origInterpMask;
914 span->arrayMask = origArrayMask;
915 }
916
917
918 /**
919 * This function may modify any of the array values in the span.
920 * span->interpMask and span->arrayMask may be changed but will be restored
921 * to their original values before returning.
922 */
923 void
924 _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
925 {
926 SWcontext *swrast = SWRAST_CONTEXT(ctx);
927 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
928 const GLuint origInterpMask = span->interpMask;
929 const GLuint origArrayMask = span->arrayMask;
930 GLboolean monoColor;
931
932 ASSERT(span->end <= MAX_WIDTH);
933 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
934 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
935 ASSERT((span->interpMask & span->arrayMask) == 0);
936 ASSERT((span->interpMask | span->arrayMask) & SPAN_RGBA);
937 #ifdef DEBUG
938 if (ctx->Fog.Enabled)
939 ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG);
940 if (ctx->Depth.Test)
941 ASSERT((span->interpMask | span->arrayMask) & SPAN_Z);
942 #endif
943
944 if (span->arrayMask & SPAN_MASK) {
945 /* mask was initialized by caller, probably glBitmap */
946 span->writeAll = GL_FALSE;
947 }
948 else {
949 MEMSET(span->array->mask, 1, span->end);
950 span->writeAll = GL_TRUE;
951 }
952
953 /* Determine if we have mono-chromatic colors */
954 monoColor = (span->interpMask & SPAN_RGBA) &&
955 span->redStep == 0 && span->greenStep == 0 &&
956 span->blueStep == 0 && span->alphaStep == 0;
957
958 /* Clipping */
959 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
960 if (!clip_span(ctx, span)) {
961 return;
962 }
963 }
964
965 #ifdef DEBUG
966 if (span->arrayMask & SPAN_XY) {
967 GLuint i;
968 for (i = 0; i < span->end; i++) {
969 if (span->array->mask[i]) {
970 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
971 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
972 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
973 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
974 }
975 }
976 }
977 #endif
978
979 /* Polygon Stippling */
980 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
981 stipple_polygon_span(ctx, span);
982 }
983
984 /* Fragment program */
985 if (ctx->FragmentProgram.Enabled) {
986 /* Now we may need to interpolate the colors */
987 if ((span->interpMask & SPAN_RGBA) &&
988 (span->arrayMask & SPAN_RGBA) == 0) {
989 interpolate_colors(ctx, span);
990 span->interpMask &= ~SPAN_RGBA;
991 }
992 if (span->interpMask & SPAN_SPEC) {
993 interpolate_specular(ctx, span);
994 }
995 _swrast_exec_nv_fragment_program(ctx, span);
996 monoColor = GL_FALSE;
997 }
998
999 /* Do the alpha test */
1000 if (ctx->Color.AlphaEnabled) {
1001 if (!_swrast_alpha_test(ctx, span)) {
1002 span->interpMask = origInterpMask;
1003 span->arrayMask = origArrayMask;
1004 return;
1005 }
1006 }
1007
1008 /* Stencil and Z testing */
1009 if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1010 if (span->interpMask & SPAN_Z)
1011 _swrast_span_interpolate_z(ctx, span);
1012
1013 if (ctx->Stencil.Enabled) {
1014 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1015 span->interpMask = origInterpMask;
1016 span->arrayMask = origArrayMask;
1017 return;
1018 }
1019 }
1020 else {
1021 ASSERT(ctx->Depth.Test);
1022 ASSERT(span->arrayMask & SPAN_Z);
1023 /* regular depth testing */
1024 if (!_swrast_depth_test_span(ctx, span)) {
1025 span->interpMask = origInterpMask;
1026 span->arrayMask = origArrayMask;
1027 return;
1028 }
1029 }
1030 }
1031
1032 /* if we get here, something passed the depth test */
1033 ctx->OcclusionResult = GL_TRUE;
1034
1035 /* can't abort span-writing until after occlusion testing */
1036 if (colorMask == 0x0) {
1037 span->interpMask = origInterpMask;
1038 span->arrayMask = origArrayMask;
1039 return;
1040 }
1041
1042 /* Now we may need to interpolate the colors */
1043 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) {
1044 interpolate_colors(ctx, span);
1045 /* clear the bit - this allows the WriteMonoCISpan optimization below */
1046 span->interpMask &= ~SPAN_RGBA;
1047 }
1048
1049 /* Fog */
1050 if (ctx->Fog.Enabled) {
1051 _swrast_fog_rgba_span(ctx, span);
1052 monoColor = GL_FALSE;
1053 }
1054
1055 /* Antialias coverage application */
1056 if (span->arrayMask & SPAN_COVERAGE) {
1057 GLchan (*rgba)[4] = span->array->rgba;
1058 GLfloat *coverage = span->array->coverage;
1059 GLuint i;
1060 for (i = 0; i < span->end; i++) {
1061 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
1062 }
1063 monoColor = GL_FALSE;
1064 }
1065
1066 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1067 multi_write_rgba_span(ctx, span);
1068 }
1069 else {
1070 /* normal: write to exactly one buffer */
1071 if (ctx->Color.ColorLogicOpEnabled) {
1072 _swrast_logicop_rgba_span(ctx, span, span->array->rgba);
1073 monoColor = GL_FALSE;
1074 }
1075 else if (ctx->Color.BlendEnabled) {
1076 _swrast_blend_span(ctx, span, span->array->rgba);
1077 monoColor = GL_FALSE;
1078 }
1079
1080 /* Color component masking */
1081 if (colorMask != 0xffffffff) {
1082 _swrast_mask_rgba_span(ctx, span, span->array->rgba);
1083 monoColor = GL_FALSE;
1084 }
1085
1086 /* write pixels */
1087 if (span->arrayMask & SPAN_XY) {
1088 /* array of pixel coords */
1089 /* XXX test for mono color */
1090 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
1091 span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask);
1092 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1093 _swrast_write_alpha_pixels(ctx, span->end,
1094 span->array->x, span->array->y,
1095 (const GLchan (*)[4]) span->array->rgba,
1096 span->array->mask);
1097 }
1098 }
1099 else {
1100 /* horizontal run of pixels */
1101 if (monoColor) {
1102 /* all pixels have same color */
1103 GLchan color[4];
1104 color[RCOMP] = FixedToChan(span->red);
1105 color[GCOMP] = FixedToChan(span->green);
1106 color[BCOMP] = FixedToChan(span->blue);
1107 color[ACOMP] = FixedToChan(span->alpha);
1108 (*swrast->Driver.WriteMonoRGBASpan)(ctx, span->end, span->x,
1109 span->y, color, span->array->mask);
1110 if (swrast->_RasterMask & ALPHABUF_BIT) {
1111 _swrast_write_mono_alpha_span(ctx, span->end, span->x, span->y,
1112 color[ACOMP],
1113 span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
1114 }
1115 }
1116 else {
1117 /* each pixel is a different color */
1118 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
1119 (const GLchan (*)[4]) span->array->rgba,
1120 span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
1121 if (swrast->_RasterMask & ALPHABUF_BIT) {
1122 _swrast_write_alpha_span(ctx, span->end, span->x, span->y,
1123 (const GLchan (*)[4]) span->array->rgba,
1124 span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
1125 }
1126 }
1127 }
1128 }
1129
1130 span->interpMask = origInterpMask;
1131 span->arrayMask = origArrayMask;
1132 }
1133
1134
1135 /**
1136 * Add specular color to base color. This is used only when
1137 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1138 */
1139 static void
1140 add_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] )
1141 {
1142 GLuint i;
1143 for (i = 0; i < n; i++) {
1144 #if CHAN_TYPE == GL_FLOAT
1145 /* no clamping */
1146 rgba[i][RCOMP] += specular[i][RCOMP];
1147 rgba[i][GCOMP] += specular[i][GCOMP];
1148 rgba[i][BCOMP] += specular[i][BCOMP];
1149 #else
1150 GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
1151 GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
1152 GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
1153 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1154 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1155 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1156 #endif
1157 }
1158 }
1159
1160
1161 /**
1162 * This function may modify any of the array values in the span.
1163 * span->interpMask and span->arrayMask may be changed but will be restored
1164 * to their original values before returning.
1165 */
1166 void
1167 _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span)
1168 {
1169 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1170 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1171 const GLuint origArrayMask = span->arrayMask;
1172
1173 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
1174 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
1175 ASSERT(span->end <= MAX_WIDTH);
1176 ASSERT((span->interpMask & span->arrayMask) == 0);
1177 ASSERT(ctx->Texture._EnabledCoordUnits);
1178
1179 /*
1180 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1181 */
1182
1183 if (span->arrayMask & SPAN_MASK) {
1184 /* mask was initialized by caller, probably glBitmap */
1185 span->writeAll = GL_FALSE;
1186 }
1187 else {
1188 MEMSET(span->array->mask, 1, span->end);
1189 span->writeAll = GL_TRUE;
1190 }
1191
1192 /* Clipping */
1193 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1194 if (!clip_span(ctx, span)) {
1195 return;
1196 }
1197 }
1198
1199 #ifdef DEBUG
1200 if (span->arrayMask & SPAN_XY) {
1201 GLuint i;
1202 for (i = 0; i < span->end; i++) {
1203 if (span->array->mask[i]) {
1204 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
1205 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
1206 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
1207 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1208 }
1209 }
1210 }
1211 #endif
1212
1213 /* Polygon Stippling */
1214 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1215 stipple_polygon_span(ctx, span);
1216 }
1217
1218 /* Need texture coordinates now */
1219 if ((span->interpMask & SPAN_TEXTURE)
1220 && (span->arrayMask & SPAN_TEXTURE) == 0)
1221 interpolate_texcoords(ctx, span);
1222
1223 /* Texture with alpha test */
1224 if (ctx->Color.AlphaEnabled) {
1225
1226 /* Now we need the rgba array, fill it in if needed */
1227 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1228 interpolate_colors(ctx, span);
1229
1230 if (span->interpMask & SPAN_SPEC) {
1231 interpolate_specular(ctx, span);
1232 }
1233
1234 /* Texturing without alpha is done after depth-testing which
1235 * gives a potential speed-up.
1236 */
1237 if (ctx->FragmentProgram.Enabled)
1238 _swrast_exec_nv_fragment_program( ctx, span );
1239 else
1240 _swrast_texture_span( ctx, span );
1241
1242 /* Do the alpha test */
1243 if (!_swrast_alpha_test(ctx, span)) {
1244 span->arrayMask = origArrayMask;
1245 return;
1246 }
1247 }
1248
1249 /* Stencil and Z testing */
1250 if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1251 if (span->interpMask & SPAN_Z)
1252 _swrast_span_interpolate_z(ctx, span);
1253
1254 if (ctx->Stencil.Enabled) {
1255 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1256 span->arrayMask = origArrayMask;
1257 return;
1258 }
1259 }
1260 else {
1261 ASSERT(ctx->Depth.Test);
1262 ASSERT(span->arrayMask & SPAN_Z);
1263 /* regular depth testing */
1264 if (!_swrast_depth_test_span(ctx, span)) {
1265 span->arrayMask = origArrayMask;
1266 return;
1267 }
1268 }
1269 }
1270
1271 /* if we get here, some fragments passed the depth test */
1272 ctx->OcclusionResult = GL_TRUE;
1273
1274 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1275 * the occlusion test.
1276 */
1277 if (colorMask == 0x0) {
1278 span->arrayMask = origArrayMask;
1279 return;
1280 }
1281
1282 /* Texture without alpha test */
1283 if (!ctx->Color.AlphaEnabled) {
1284
1285 /* Now we need the rgba array, fill it in if needed */
1286 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1287 interpolate_colors(ctx, span);
1288
1289 if (span->interpMask & SPAN_SPEC) {
1290 interpolate_specular(ctx, span);
1291 }
1292
1293 if (ctx->FragmentProgram.Enabled)
1294 _swrast_exec_nv_fragment_program( ctx, span );
1295 else
1296 _swrast_texture_span( ctx, span );
1297 }
1298
1299 ASSERT(span->arrayMask & SPAN_RGBA);
1300
1301 /* Add base and specular colors */
1302 if (ctx->Fog.ColorSumEnabled ||
1303 (ctx->Light.Enabled &&
1304 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1305 if (span->interpMask & SPAN_SPEC) {
1306 interpolate_specular(ctx, span);
1307 }
1308 ASSERT(span->arrayMask & SPAN_SPEC);
1309 add_colors( span->end, span->array->rgba, span->array->spec );
1310 }
1311
1312 /* Fog */
1313 if (ctx->Fog.Enabled) {
1314 _swrast_fog_rgba_span(ctx, span);
1315 }
1316
1317 /* Antialias coverage application */
1318 if (span->arrayMask & SPAN_COVERAGE) {
1319 GLchan (*rgba)[4] = span->array->rgba;
1320 GLfloat *coverage = span->array->coverage;
1321 GLuint i;
1322 for (i = 0; i < span->end; i++) {
1323 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
1324 }
1325 }
1326
1327 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1328 multi_write_rgba_span(ctx, span);
1329 }
1330 else {
1331 /* normal: write to exactly one buffer */
1332 if (ctx->Color.ColorLogicOpEnabled) {
1333 _swrast_logicop_rgba_span(ctx, span, span->array->rgba);
1334 }
1335 else if (ctx->Color.BlendEnabled) {
1336 _swrast_blend_span(ctx, span, span->array->rgba);
1337 }
1338
1339 if (colorMask != 0xffffffff) {
1340 _swrast_mask_rgba_span(ctx, span, span->array->rgba);
1341 }
1342
1343
1344 if (span->arrayMask & SPAN_XY) {
1345 /* array of pixel coords */
1346 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
1347 span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask);
1348 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1349 _swrast_write_alpha_pixels(ctx, span->end,
1350 span->array->x, span->array->y,
1351 (const GLchan (*)[4]) span->array->rgba,
1352 span->array->mask);
1353 }
1354 }
1355 else {
1356 /* horizontal run of pixels */
1357 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
1358 (const GLchan (*)[4]) span->array->rgba,
1359 span->writeAll ? NULL : span->array->mask);
1360 if (swrast->_RasterMask & ALPHABUF_BIT) {
1361 _swrast_write_alpha_span(ctx, span->end, span->x, span->y,
1362 (const GLchan (*)[4]) span->array->rgba,
1363 span->writeAll ? NULL : span->array->mask);
1364 }
1365 }
1366 }
1367
1368 span->arrayMask = origArrayMask;
1369 }
1370
1371
1372
1373 /**
1374 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1375 * reading ouside the buffer's boundaries.
1376 */
1377 void
1378 _swrast_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
1379 GLuint n, GLint x, GLint y, GLchan rgba[][4] )
1380 {
1381 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1382 const GLint bufWidth = (GLint) buffer->Width;
1383 const GLint bufHeight = (GLint) buffer->Height;
1384
1385 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1386 /* completely above, below, or right */
1387 /* XXX maybe leave undefined? */
1388 _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1389 }
1390 else {
1391 GLint skip, length;
1392 if (x < 0) {
1393 /* left edge clippping */
1394 skip = -x;
1395 length = (GLint) n - skip;
1396 if (length < 0) {
1397 /* completely left of window */
1398 return;
1399 }
1400 if (length > bufWidth) {
1401 length = bufWidth;
1402 }
1403 }
1404 else if ((GLint) (x + n) > bufWidth) {
1405 /* right edge clipping */
1406 skip = 0;
1407 length = bufWidth - x;
1408 if (length < 0) {
1409 /* completely to right of window */
1410 return;
1411 }
1412 }
1413 else {
1414 /* no clipping */
1415 skip = 0;
1416 length = (GLint) n;
1417 }
1418
1419 (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
1420 if (buffer->UseSoftwareAlphaBuffers) {
1421 _swrast_read_alpha_span(ctx, length, x + skip, y, rgba + skip);
1422 }
1423 }
1424 }
1425
1426
1427 /**
1428 * Read CI pixels from frame buffer. Clipping will be done to prevent
1429 * reading ouside the buffer's boundaries.
1430 */
1431 void
1432 _swrast_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
1433 GLuint n, GLint x, GLint y, GLuint indx[] )
1434 {
1435 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1436 const GLint bufWidth = (GLint) buffer->Width;
1437 const GLint bufHeight = (GLint) buffer->Height;
1438
1439 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1440 /* completely above, below, or right */
1441 _mesa_bzero(indx, n * sizeof(GLuint));
1442 }
1443 else {
1444 GLint skip, length;
1445 if (x < 0) {
1446 /* left edge clippping */
1447 skip = -x;
1448 length = (GLint) n - skip;
1449 if (length < 0) {
1450 /* completely left of window */
1451 return;
1452 }
1453 if (length > bufWidth) {
1454 length = bufWidth;
1455 }
1456 }
1457 else if ((GLint) (x + n) > bufWidth) {
1458 /* right edge clipping */
1459 skip = 0;
1460 length = bufWidth - x;
1461 if (length < 0) {
1462 /* completely to right of window */
1463 return;
1464 }
1465 }
1466 else {
1467 /* no clipping */
1468 skip = 0;
1469 length = (GLint) n;
1470 }
1471
1472 (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
1473 }
1474 }