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