fix some bugs in interpolate_specular()
[mesa.git] / src / mesa / swrast / s_span.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2006 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 #include "image.h"
39
40 #include "s_atifragshader.h"
41 #include "s_alpha.h"
42 #include "s_arbshader.h"
43 #include "s_blend.h"
44 #include "s_context.h"
45 #include "s_depth.h"
46 #include "s_fog.h"
47 #include "s_logic.h"
48 #include "s_masking.h"
49 #include "s_nvfragprog.h"
50 #include "s_span.h"
51 #include "s_stencil.h"
52 #include "s_texcombine.h"
53
54
55 /**
56 * Init span's Z interpolation values to the RasterPos Z.
57 * Used during setup for glDraw/CopyPixels.
58 */
59 void
60 _swrast_span_default_z( GLcontext *ctx, SWspan *span )
61 {
62 const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
63 if (ctx->DrawBuffer->Visual.depthBits <= 16)
64 span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
65 else
66 span->z = (GLint) (ctx->Current.RasterPos[2] * depthMax + 0.5F);
67 span->zStep = 0;
68 span->interpMask |= SPAN_Z;
69 }
70
71
72 /**
73 * Init span's fog interpolation values to the RasterPos fog.
74 * Used during setup for glDraw/CopyPixels.
75 */
76 void
77 _swrast_span_default_fog( GLcontext *ctx, SWspan *span )
78 {
79 span->fog = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
80 span->fogStep = span->dfogdx = span->dfogdy = 0.0F;
81 span->interpMask |= SPAN_FOG;
82 }
83
84
85 /**
86 * Init span's rgba or index interpolation values to the RasterPos color.
87 * Used during setup for glDraw/CopyPixels.
88 */
89 void
90 _swrast_span_default_color( GLcontext *ctx, SWspan *span )
91 {
92 if (ctx->Visual.rgbMode) {
93 GLchan r, g, b, a;
94 UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
95 UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
96 UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
97 UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
98 #if CHAN_TYPE == GL_FLOAT
99 span->red = r;
100 span->green = g;
101 span->blue = b;
102 span->alpha = a;
103 #else
104 span->red = IntToFixed(r);
105 span->green = IntToFixed(g);
106 span->blue = IntToFixed(b);
107 span->alpha = IntToFixed(a);
108 #endif
109 span->redStep = 0;
110 span->greenStep = 0;
111 span->blueStep = 0;
112 span->alphaStep = 0;
113 span->interpMask |= SPAN_RGBA;
114 }
115 else {
116 span->index = FloatToFixed(ctx->Current.RasterIndex);
117 span->indexStep = 0;
118 span->interpMask |= SPAN_INDEX;
119 }
120 }
121
122
123 /**
124 * Init span's texcoord interpolation values to the RasterPos texcoords.
125 * Used during setup for glDraw/CopyPixels.
126 */
127 void
128 _swrast_span_default_texcoords( GLcontext *ctx, SWspan *span )
129 {
130 GLuint i;
131 for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
132 const GLfloat *tc = ctx->Current.RasterTexCoords[i];
133 if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled) {
134 COPY_4V(span->tex[i], tc);
135 }
136 else if (tc[3] > 0.0F) {
137 /* use (s/q, t/q, r/q, 1) */
138 span->tex[i][0] = tc[0] / tc[3];
139 span->tex[i][1] = tc[1] / tc[3];
140 span->tex[i][2] = tc[2] / tc[3];
141 span->tex[i][3] = 1.0;
142 }
143 else {
144 ASSIGN_4V(span->tex[i], 0.0F, 0.0F, 0.0F, 1.0F);
145 }
146 ASSIGN_4V(span->texStepX[i], 0.0F, 0.0F, 0.0F, 0.0F);
147 ASSIGN_4V(span->texStepY[i], 0.0F, 0.0F, 0.0F, 0.0F);
148 }
149 span->interpMask |= SPAN_TEXTURE;
150 }
151
152
153 /**
154 * Interpolate primary colors to fill in the span->array->color array.
155 */
156 static INLINE void
157 interpolate_colors(SWspan *span)
158 {
159 const GLuint n = span->end;
160 GLuint i;
161
162 ASSERT((span->interpMask & SPAN_RGBA) &&
163 !(span->arrayMask & SPAN_RGBA));
164
165 switch (span->array->ChanType) {
166 #if CHAN_BITS != 32
167 case GL_UNSIGNED_BYTE:
168 {
169 GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
170 if (span->interpMask & SPAN_FLAT) {
171 GLubyte color[4];
172 color[RCOMP] = FixedToInt(span->red);
173 color[GCOMP] = FixedToInt(span->green);
174 color[BCOMP] = FixedToInt(span->blue);
175 color[ACOMP] = FixedToInt(span->alpha);
176 for (i = 0; i < n; i++) {
177 COPY_4UBV(rgba[i], color);
178 }
179 }
180 else {
181 GLfixed r = span->red;
182 GLfixed g = span->green;
183 GLfixed b = span->blue;
184 GLfixed a = span->alpha;
185 GLint dr = span->redStep;
186 GLint dg = span->greenStep;
187 GLint db = span->blueStep;
188 GLint da = span->alphaStep;
189 for (i = 0; i < n; i++) {
190 rgba[i][RCOMP] = FixedToChan(r);
191 rgba[i][GCOMP] = FixedToChan(g);
192 rgba[i][BCOMP] = FixedToChan(b);
193 rgba[i][ACOMP] = FixedToChan(a);
194 r += dr;
195 g += dg;
196 b += db;
197 a += da;
198 }
199 }
200 }
201 break;
202 case GL_UNSIGNED_SHORT:
203 {
204 GLushort (*rgba)[4] = span->array->color.sz2.rgba;
205 if (span->interpMask & SPAN_FLAT) {
206 GLushort color[4];
207 color[RCOMP] = FixedToInt(span->red);
208 color[GCOMP] = FixedToInt(span->green);
209 color[BCOMP] = FixedToInt(span->blue);
210 color[ACOMP] = FixedToInt(span->alpha);
211 for (i = 0; i < n; i++) {
212 COPY_4V(rgba[i], color);
213 }
214 }
215 else {
216 GLushort (*rgba)[4] = span->array->color.sz2.rgba;
217 GLfixed r, g, b, a;
218 GLint dr, dg, db, da;
219 r = span->red;
220 g = span->green;
221 b = span->blue;
222 a = span->alpha;
223 dr = span->redStep;
224 dg = span->greenStep;
225 db = span->blueStep;
226 da = span->alphaStep;
227 for (i = 0; i < n; i++) {
228 rgba[i][RCOMP] = FixedToChan(r);
229 rgba[i][GCOMP] = FixedToChan(g);
230 rgba[i][BCOMP] = FixedToChan(b);
231 rgba[i][ACOMP] = FixedToChan(a);
232 r += dr;
233 g += dg;
234 b += db;
235 a += da;
236 }
237 }
238 }
239 break;
240 #endif
241 case GL_FLOAT:
242 {
243 GLfloat (*rgba)[4] = span->array->color.sz4.rgba;
244 GLfloat r, g, b, a, dr, dg, db, da;
245 r = span->red;
246 g = span->green;
247 b = span->blue;
248 a = span->alpha;
249 if (span->interpMask & SPAN_FLAT) {
250 dr = dg = db = da = 0.0;
251 }
252 else {
253 dr = span->redStep;
254 dg = span->greenStep;
255 db = span->blueStep;
256 da = span->alphaStep;
257 }
258 for (i = 0; i < n; i++) {
259 rgba[i][RCOMP] = r;
260 rgba[i][GCOMP] = g;
261 rgba[i][BCOMP] = b;
262 rgba[i][ACOMP] = a;
263 r += dr;
264 g += dg;
265 b += db;
266 a += da;
267 }
268 }
269 break;
270 default:
271 _mesa_problem(NULL, "bad datatype in interpolate_colors");
272 }
273 span->arrayMask |= SPAN_RGBA;
274 }
275
276
277 /**
278 * Interpolate specular/secondary colors.
279 */
280 static INLINE void
281 interpolate_specular(SWspan *span)
282 {
283 const GLuint n = span->end;
284 GLuint i;
285
286 switch (span->array->ChanType) {
287 #if CHAN_BITS != 32
288 case GL_UNSIGNED_BYTE:
289 {
290 GLubyte (*spec)[4] = span->array->color.sz1.spec;
291 if (span->interpMask & SPAN_FLAT) {
292 GLubyte color[4];
293 color[RCOMP] = FixedToInt(span->specRed);
294 color[GCOMP] = FixedToInt(span->specGreen);
295 color[BCOMP] = FixedToInt(span->specBlue);
296 color[ACOMP] = 0;
297 for (i = 0; i < n; i++) {
298 COPY_4UBV(spec[i], color);
299 }
300 }
301 else {
302 GLfixed r = span->specRed;
303 GLfixed g = span->specGreen;
304 GLfixed b = span->specBlue;
305 GLint dr = span->specRedStep;
306 GLint dg = span->specGreenStep;
307 GLint db = span->specBlueStep;
308 for (i = 0; i < n; i++) {
309 spec[i][RCOMP] = CLAMP(FixedToChan(r), 0, 255);
310 spec[i][GCOMP] = CLAMP(FixedToChan(g), 0, 255);
311 spec[i][BCOMP] = CLAMP(FixedToChan(b), 0, 255);
312 spec[i][ACOMP] = 0;
313 r += dr;
314 g += dg;
315 b += db;
316 }
317 }
318 }
319 break;
320 case GL_UNSIGNED_SHORT:
321 {
322 GLushort (*spec)[4] = span->array->color.sz2.spec;
323 if (span->interpMask & SPAN_FLAT) {
324 GLushort color[4];
325 color[RCOMP] = FixedToInt(span->specRed);
326 color[GCOMP] = FixedToInt(span->specGreen);
327 color[BCOMP] = FixedToInt(span->specBlue);
328 color[ACOMP] = 0;
329 for (i = 0; i < n; i++) {
330 COPY_4V(spec[i], color);
331 }
332 }
333 else {
334 GLfixed r = FloatToFixed(span->specRed);
335 GLfixed g = FloatToFixed(span->specGreen);
336 GLfixed b = FloatToFixed(span->specBlue);
337 GLint dr = FloatToFixed(span->specRedStep);
338 GLint dg = FloatToFixed(span->specGreenStep);
339 GLint db = FloatToFixed(span->specBlueStep);
340 for (i = 0; i < n; i++) {
341 spec[i][RCOMP] = FixedToInt(r);
342 spec[i][GCOMP] = FixedToInt(g);
343 spec[i][BCOMP] = FixedToInt(b);
344 spec[i][ACOMP] = 0;
345 r += dr;
346 g += dg;
347 b += db;
348 }
349 }
350 }
351 break;
352 #endif
353 case GL_FLOAT:
354 {
355 GLfloat (*spec)[4] = span->array->color.sz4.spec;
356 #if CHAN_BITS <= 16
357 GLfloat r = CHAN_TO_FLOAT(FixedToChan(span->specRed));
358 GLfloat g = CHAN_TO_FLOAT(FixedToChan(span->specGreen));
359 GLfloat b = CHAN_TO_FLOAT(FixedToChan(span->specBlue));
360 #else
361 GLfloat r = span->specRed;
362 GLfloat g = span->specGreen;
363 GLfloat b = span->specBlue;
364 #endif
365 GLfloat dr, dg, db;
366 if (span->interpMask & SPAN_FLAT) {
367 dr = dg = db = 0.0;
368 }
369 else {
370 #if CHAN_BITS <= 16
371 dr = CHAN_TO_FLOAT(FixedToChan(span->specRedStep));
372 dg = CHAN_TO_FLOAT(FixedToChan(span->specGreenStep));
373 db = CHAN_TO_FLOAT(FixedToChan(span->specBlueStep));
374 #else
375 dr = span->specRedStep;
376 dg = span->specGreenStep;
377 db = span->specBlueStep;
378 #endif
379 }
380 for (i = 0; i < n; i++) {
381 spec[i][RCOMP] = r;
382 spec[i][GCOMP] = g;
383 spec[i][BCOMP] = b;
384 spec[i][ACOMP] = 0.0F;
385 r += dr;
386 g += dg;
387 b += db;
388 }
389 }
390 break;
391 default:
392 _mesa_problem(NULL, "bad datatype in interpolate_specular");
393 }
394 span->arrayMask |= SPAN_SPEC;
395 }
396
397
398 /* Fill in the span.color.index array from the interpolation values */
399 static INLINE void
400 interpolate_indexes(GLcontext *ctx, SWspan *span)
401 {
402 GLfixed index = span->index;
403 const GLint indexStep = span->indexStep;
404 const GLuint n = span->end;
405 GLuint *indexes = span->array->index;
406 GLuint i;
407 (void) ctx;
408 ASSERT((span->interpMask & SPAN_INDEX) &&
409 !(span->arrayMask & SPAN_INDEX));
410
411 if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
412 /* constant color */
413 index = FixedToInt(index);
414 for (i = 0; i < n; i++) {
415 indexes[i] = index;
416 }
417 }
418 else {
419 /* interpolate */
420 for (i = 0; i < n; i++) {
421 indexes[i] = FixedToInt(index);
422 index += indexStep;
423 }
424 }
425 span->arrayMask |= SPAN_INDEX;
426 span->interpMask &= ~SPAN_INDEX;
427 }
428
429
430 /* Fill in the span.array.fog values from the interpolation values */
431 static INLINE void
432 interpolate_fog(const GLcontext *ctx, SWspan *span)
433 {
434 GLfloat *fog = span->array->fog;
435 const GLfloat fogStep = span->fogStep;
436 GLfloat fogCoord = span->fog;
437 const GLuint haveW = (span->interpMask & SPAN_W);
438 const GLfloat wStep = haveW ? span->dwdx : 0.0F;
439 GLfloat w = haveW ? span->w : 1.0F;
440 GLuint i;
441 for (i = 0; i < span->end; i++) {
442 fog[i] = fogCoord / w;
443 fogCoord += fogStep;
444 w += wStep;
445 }
446 span->arrayMask |= SPAN_FOG;
447 }
448
449
450 /* Fill in the span.zArray array from the interpolation values */
451 void
452 _swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span )
453 {
454 const GLuint n = span->end;
455 GLuint i;
456
457 ASSERT((span->interpMask & SPAN_Z) &&
458 !(span->arrayMask & SPAN_Z));
459
460 if (ctx->DrawBuffer->Visual.depthBits <= 16) {
461 GLfixed zval = span->z;
462 GLuint *z = span->array->z;
463 for (i = 0; i < n; i++) {
464 z[i] = FixedToInt(zval);
465 zval += span->zStep;
466 }
467 }
468 else {
469 /* Deep Z buffer, no fixed->int shift */
470 GLuint zval = span->z;
471 GLuint *z = span->array->z;
472 for (i = 0; i < n; i++) {
473 z[i] = zval;
474 zval += span->zStep;
475 }
476 }
477 span->interpMask &= ~SPAN_Z;
478 span->arrayMask |= SPAN_Z;
479 }
480
481
482 /*
483 * This the ideal solution, as given in the OpenGL spec.
484 */
485 #if 0
486 static GLfloat
487 compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
488 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
489 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
490 {
491 GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
492 GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
493 GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
494 GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
495 GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
496 GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
497 GLfloat rho = MAX2(x, y);
498 GLfloat lambda = LOG2(rho);
499 return lambda;
500 }
501 #endif
502
503
504 /*
505 * This is a faster approximation
506 */
507 GLfloat
508 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
509 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
510 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
511 {
512 GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
513 GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
514 GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
515 GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
516 GLfloat maxU, maxV, rho, lambda;
517 dsdx2 = FABSF(dsdx2);
518 dsdy2 = FABSF(dsdy2);
519 dtdx2 = FABSF(dtdx2);
520 dtdy2 = FABSF(dtdy2);
521 maxU = MAX2(dsdx2, dsdy2) * texW;
522 maxV = MAX2(dtdx2, dtdy2) * texH;
523 rho = MAX2(maxU, maxV);
524 lambda = LOG2(rho);
525 return lambda;
526 }
527
528
529 /**
530 * Fill in the span.texcoords array from the interpolation values.
531 * Note: in the places where we divide by Q (or mult by invQ) we're
532 * really doing two things: perspective correction and texcoord
533 * projection. Remember, for texcoord (s,t,r,q) we need to index
534 * texels with (s/q, t/q, r/q).
535 * If we're using a fragment program, we never do the division
536 * for texcoord projection. That's done by the TXP instruction
537 * or user-written code.
538 */
539 static void
540 interpolate_texcoords(GLcontext *ctx, SWspan *span)
541 {
542 ASSERT(span->interpMask & SPAN_TEXTURE);
543 ASSERT(!(span->arrayMask & SPAN_TEXTURE));
544
545 if (ctx->Texture._EnabledCoordUnits > 1) {
546 /* multitexture */
547 GLuint u;
548 span->arrayMask |= SPAN_TEXTURE;
549 /* XXX CoordUnits vs. ImageUnits */
550 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
551 if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
552 const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
553 GLfloat texW, texH;
554 GLboolean needLambda;
555 if (obj) {
556 const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
557 needLambda = (obj->MinFilter != obj->MagFilter)
558 || ctx->FragmentProgram._Enabled;
559 texW = img->WidthScale;
560 texH = img->HeightScale;
561 }
562 else {
563 /* using a fragment program */
564 texW = 1.0;
565 texH = 1.0;
566 needLambda = GL_FALSE;
567 }
568 if (needLambda) {
569 GLfloat (*texcoord)[4] = span->array->texcoords[u];
570 GLfloat *lambda = span->array->lambda[u];
571 const GLfloat dsdx = span->texStepX[u][0];
572 const GLfloat dsdy = span->texStepY[u][0];
573 const GLfloat dtdx = span->texStepX[u][1];
574 const GLfloat dtdy = span->texStepY[u][1];
575 const GLfloat drdx = span->texStepX[u][2];
576 const GLfloat dqdx = span->texStepX[u][3];
577 const GLfloat dqdy = span->texStepY[u][3];
578 GLfloat s = span->tex[u][0];
579 GLfloat t = span->tex[u][1];
580 GLfloat r = span->tex[u][2];
581 GLfloat q = span->tex[u][3];
582 GLuint i;
583 if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
584 ctx->ShaderObjects._FragmentShaderPresent) {
585 /* do perspective correction but don't divide s, t, r by q */
586 const GLfloat dwdx = span->dwdx;
587 GLfloat w = span->w;
588 for (i = 0; i < span->end; i++) {
589 const GLfloat invW = 1.0F / w;
590 texcoord[i][0] = s * invW;
591 texcoord[i][1] = t * invW;
592 texcoord[i][2] = r * invW;
593 texcoord[i][3] = q * invW;
594 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
595 dqdx, dqdy, texW, texH,
596 s, t, q, invW);
597 s += dsdx;
598 t += dtdx;
599 r += drdx;
600 q += dqdx;
601 w += dwdx;
602 }
603
604 }
605 else {
606 for (i = 0; i < span->end; i++) {
607 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
608 texcoord[i][0] = s * invQ;
609 texcoord[i][1] = t * invQ;
610 texcoord[i][2] = r * invQ;
611 texcoord[i][3] = q;
612 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
613 dqdx, dqdy, texW, texH,
614 s, t, q, invQ);
615 s += dsdx;
616 t += dtdx;
617 r += drdx;
618 q += dqdx;
619 }
620 }
621 span->arrayMask |= SPAN_LAMBDA;
622 }
623 else {
624 GLfloat (*texcoord)[4] = span->array->texcoords[u];
625 GLfloat *lambda = span->array->lambda[u];
626 const GLfloat dsdx = span->texStepX[u][0];
627 const GLfloat dtdx = span->texStepX[u][1];
628 const GLfloat drdx = span->texStepX[u][2];
629 const GLfloat dqdx = span->texStepX[u][3];
630 GLfloat s = span->tex[u][0];
631 GLfloat t = span->tex[u][1];
632 GLfloat r = span->tex[u][2];
633 GLfloat q = span->tex[u][3];
634 GLuint i;
635 if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
636 ctx->ShaderObjects._FragmentShaderPresent) {
637 /* do perspective correction but don't divide s, t, r by q */
638 const GLfloat dwdx = span->dwdx;
639 GLfloat w = span->w;
640 for (i = 0; i < span->end; i++) {
641 const GLfloat invW = 1.0F / w;
642 texcoord[i][0] = s * invW;
643 texcoord[i][1] = t * invW;
644 texcoord[i][2] = r * invW;
645 texcoord[i][3] = q * invW;
646 lambda[i] = 0.0;
647 s += dsdx;
648 t += dtdx;
649 r += drdx;
650 q += dqdx;
651 w += dwdx;
652 }
653 }
654 else if (dqdx == 0.0F) {
655 /* Ortho projection or polygon's parallel to window X axis */
656 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
657 for (i = 0; i < span->end; i++) {
658 texcoord[i][0] = s * invQ;
659 texcoord[i][1] = t * invQ;
660 texcoord[i][2] = r * invQ;
661 texcoord[i][3] = q;
662 lambda[i] = 0.0;
663 s += dsdx;
664 t += dtdx;
665 r += drdx;
666 }
667 }
668 else {
669 for (i = 0; i < span->end; i++) {
670 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
671 texcoord[i][0] = s * invQ;
672 texcoord[i][1] = t * invQ;
673 texcoord[i][2] = r * invQ;
674 texcoord[i][3] = q;
675 lambda[i] = 0.0;
676 s += dsdx;
677 t += dtdx;
678 r += drdx;
679 q += dqdx;
680 }
681 }
682 } /* lambda */
683 } /* if */
684 } /* for */
685 }
686 else {
687 /* single texture */
688 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
689 GLfloat texW, texH;
690 GLboolean needLambda;
691 if (obj) {
692 const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
693 needLambda = (obj->MinFilter != obj->MagFilter)
694 || ctx->FragmentProgram._Enabled;
695 texW = (GLfloat) img->WidthScale;
696 texH = (GLfloat) img->HeightScale;
697 }
698 else {
699 needLambda = GL_FALSE;
700 texW = texH = 1.0;
701 }
702 span->arrayMask |= SPAN_TEXTURE;
703 if (needLambda) {
704 /* just texture unit 0, with lambda */
705 GLfloat (*texcoord)[4] = span->array->texcoords[0];
706 GLfloat *lambda = span->array->lambda[0];
707 const GLfloat dsdx = span->texStepX[0][0];
708 const GLfloat dsdy = span->texStepY[0][0];
709 const GLfloat dtdx = span->texStepX[0][1];
710 const GLfloat dtdy = span->texStepY[0][1];
711 const GLfloat drdx = span->texStepX[0][2];
712 const GLfloat dqdx = span->texStepX[0][3];
713 const GLfloat dqdy = span->texStepY[0][3];
714 GLfloat s = span->tex[0][0];
715 GLfloat t = span->tex[0][1];
716 GLfloat r = span->tex[0][2];
717 GLfloat q = span->tex[0][3];
718 GLuint i;
719 if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
720 ctx->ShaderObjects._FragmentShaderPresent) {
721 /* do perspective correction but don't divide s, t, r by q */
722 const GLfloat dwdx = span->dwdx;
723 GLfloat w = span->w;
724 for (i = 0; i < span->end; i++) {
725 const GLfloat invW = 1.0F / w;
726 texcoord[i][0] = s * invW;
727 texcoord[i][1] = t * invW;
728 texcoord[i][2] = r * invW;
729 texcoord[i][3] = q * invW;
730 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
731 dqdx, dqdy, texW, texH,
732 s, t, q, invW);
733 s += dsdx;
734 t += dtdx;
735 r += drdx;
736 q += dqdx;
737 w += dwdx;
738 }
739 }
740 else {
741 /* tex.c */
742 for (i = 0; i < span->end; i++) {
743 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
744 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
745 dqdx, dqdy, texW, texH,
746 s, t, q, invQ);
747 texcoord[i][0] = s * invQ;
748 texcoord[i][1] = t * invQ;
749 texcoord[i][2] = r * invQ;
750 texcoord[i][3] = q;
751 s += dsdx;
752 t += dtdx;
753 r += drdx;
754 q += dqdx;
755 }
756 }
757 span->arrayMask |= SPAN_LAMBDA;
758 }
759 else {
760 /* just texture 0, without lambda */
761 GLfloat (*texcoord)[4] = span->array->texcoords[0];
762 const GLfloat dsdx = span->texStepX[0][0];
763 const GLfloat dtdx = span->texStepX[0][1];
764 const GLfloat drdx = span->texStepX[0][2];
765 const GLfloat dqdx = span->texStepX[0][3];
766 GLfloat s = span->tex[0][0];
767 GLfloat t = span->tex[0][1];
768 GLfloat r = span->tex[0][2];
769 GLfloat q = span->tex[0][3];
770 GLuint i;
771 if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
772 ctx->ShaderObjects._FragmentShaderPresent) {
773 /* do perspective correction but don't divide s, t, r by q */
774 const GLfloat dwdx = span->dwdx;
775 GLfloat w = span->w;
776 for (i = 0; i < span->end; i++) {
777 const GLfloat invW = 1.0F / w;
778 texcoord[i][0] = s * invW;
779 texcoord[i][1] = t * invW;
780 texcoord[i][2] = r * invW;
781 texcoord[i][3] = q * invW;
782 s += dsdx;
783 t += dtdx;
784 r += drdx;
785 q += dqdx;
786 w += dwdx;
787 }
788 }
789 else if (dqdx == 0.0F) {
790 /* Ortho projection or polygon's parallel to window X axis */
791 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
792 for (i = 0; i < span->end; i++) {
793 texcoord[i][0] = s * invQ;
794 texcoord[i][1] = t * invQ;
795 texcoord[i][2] = r * invQ;
796 texcoord[i][3] = q;
797 s += dsdx;
798 t += dtdx;
799 r += drdx;
800 }
801 }
802 else {
803 for (i = 0; i < span->end; i++) {
804 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
805 texcoord[i][0] = s * invQ;
806 texcoord[i][1] = t * invQ;
807 texcoord[i][2] = r * invQ;
808 texcoord[i][3] = q;
809 s += dsdx;
810 t += dtdx;
811 r += drdx;
812 q += dqdx;
813 }
814 }
815 }
816 }
817 }
818
819
820 /**
821 * Fill in the span.varying array from the interpolation values.
822 */
823 static INLINE void
824 interpolate_varying(GLcontext *ctx, SWspan *span)
825 {
826 GLuint i, j;
827
828 ASSERT(span->interpMask & SPAN_VARYING);
829 ASSERT(!(span->arrayMask & SPAN_VARYING));
830
831 span->arrayMask |= SPAN_VARYING;
832
833 for (i = 0; i < MAX_VARYING_VECTORS; i++) {
834 for (j = 0; j < VARYINGS_PER_VECTOR; j++) {
835 const GLfloat dvdx = span->varStepX[i][j];
836 GLfloat v = span->var[i][j];
837 const GLfloat dwdx = span->dwdx;
838 GLfloat w = span->w;
839 GLuint k;
840
841 for (k = 0; k < span->end; k++) {
842 GLfloat invW = 1.0f / w;
843 span->array->varying[k][i][j] = v * invW;
844 v += dvdx;
845 w += dwdx;
846 }
847 }
848 }
849 }
850
851
852 /**
853 * Apply the current polygon stipple pattern to a span of pixels.
854 */
855 static INLINE void
856 stipple_polygon_span( GLcontext *ctx, SWspan *span )
857 {
858 const GLuint highbit = 0x80000000;
859 const GLuint stipple = ctx->PolygonStipple[span->y % 32];
860 GLubyte *mask = span->array->mask;
861 GLuint i, m;
862
863 ASSERT(ctx->Polygon.StippleFlag);
864 ASSERT((span->arrayMask & SPAN_XY) == 0);
865
866 m = highbit >> (GLuint) (span->x % 32);
867
868 for (i = 0; i < span->end; i++) {
869 if ((m & stipple) == 0) {
870 mask[i] = 0;
871 }
872 m = m >> 1;
873 if (m == 0) {
874 m = highbit;
875 }
876 }
877 span->writeAll = GL_FALSE;
878 }
879
880
881 /**
882 * Clip a pixel span to the current buffer/window boundaries:
883 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
884 * window clipping and scissoring.
885 * Return: GL_TRUE some pixels still visible
886 * GL_FALSE nothing visible
887 */
888 static INLINE GLuint
889 clip_span( GLcontext *ctx, SWspan *span )
890 {
891 const GLint xmin = ctx->DrawBuffer->_Xmin;
892 const GLint xmax = ctx->DrawBuffer->_Xmax;
893 const GLint ymin = ctx->DrawBuffer->_Ymin;
894 const GLint ymax = ctx->DrawBuffer->_Ymax;
895
896 if (span->arrayMask & SPAN_XY) {
897 /* arrays of x/y pixel coords */
898 const GLint *x = span->array->x;
899 const GLint *y = span->array->y;
900 const GLint n = span->end;
901 GLubyte *mask = span->array->mask;
902 GLint i;
903 if (span->arrayMask & SPAN_MASK) {
904 /* note: using & intead of && to reduce branches */
905 for (i = 0; i < n; i++) {
906 mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
907 & (y[i] >= ymin) & (y[i] < ymax);
908 }
909 }
910 else {
911 /* note: using & intead of && to reduce branches */
912 for (i = 0; i < n; i++) {
913 mask[i] = (x[i] >= xmin) & (x[i] < xmax)
914 & (y[i] >= ymin) & (y[i] < ymax);
915 }
916 }
917 return GL_TRUE; /* some pixels visible */
918 }
919 else {
920 /* horizontal span of pixels */
921 const GLint x = span->x;
922 const GLint y = span->y;
923 const GLint n = span->end;
924
925 /* Trivial rejection tests */
926 if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
927 span->end = 0;
928 return GL_FALSE; /* all pixels clipped */
929 }
930
931 /* Clip to the left */
932 if (x < xmin) {
933 ASSERT(x + n > xmin);
934 span->writeAll = GL_FALSE;
935 _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
936 }
937
938 /* Clip to right */
939 if (x + n > xmax) {
940 ASSERT(x < xmax);
941 span->end = xmax - x;
942 }
943
944 return GL_TRUE; /* some pixels visible */
945 }
946 }
947
948
949 /**
950 * Apply all the per-fragment opertions to a span of color index fragments
951 * and write them to the enabled color drawbuffers.
952 * The 'span' parameter can be considered to be const. Note that
953 * span->interpMask and span->arrayMask may be changed but will be restored
954 * to their original values before returning.
955 */
956 void
957 _swrast_write_index_span( GLcontext *ctx, SWspan *span)
958 {
959 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
960 const GLbitfield origInterpMask = span->interpMask;
961 const GLbitfield origArrayMask = span->arrayMask;
962
963 ASSERT(span->end <= MAX_WIDTH);
964 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
965 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
966 ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
967 ASSERT((span->interpMask & span->arrayMask) == 0);
968
969 if (span->arrayMask & SPAN_MASK) {
970 /* mask was initialized by caller, probably glBitmap */
971 span->writeAll = GL_FALSE;
972 }
973 else {
974 _mesa_memset(span->array->mask, 1, span->end);
975 span->writeAll = GL_TRUE;
976 }
977
978 /* Clipping */
979 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
980 if (!clip_span(ctx, span)) {
981 return;
982 }
983 }
984
985 /* Depth bounds test */
986 if (ctx->Depth.BoundsTest && ctx->DrawBuffer->Visual.depthBits > 0) {
987 if (!_swrast_depth_bounds_test(ctx, span)) {
988 return;
989 }
990 }
991
992 #ifdef DEBUG
993 /* Make sure all fragments are within window bounds */
994 if (span->arrayMask & SPAN_XY) {
995 GLuint i;
996 for (i = 0; i < span->end; i++) {
997 if (span->array->mask[i]) {
998 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
999 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
1000 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
1001 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1002 }
1003 }
1004 }
1005 #endif
1006
1007 /* Polygon Stippling */
1008 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1009 stipple_polygon_span(ctx, span);
1010 }
1011
1012 /* Stencil and Z testing */
1013 if (ctx->Depth.Test || ctx->Stencil.Enabled) {
1014 if (span->interpMask & SPAN_Z)
1015 _swrast_span_interpolate_z(ctx, span);
1016
1017 if (ctx->Stencil.Enabled) {
1018 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1019 span->arrayMask = origArrayMask;
1020 return;
1021 }
1022 }
1023 else {
1024 ASSERT(ctx->Depth.Test);
1025 if (!_swrast_depth_test_span(ctx, span)) {
1026 span->interpMask = origInterpMask;
1027 span->arrayMask = origArrayMask;
1028 return;
1029 }
1030 }
1031 }
1032
1033 #if FEATURE_ARB_occlusion_query
1034 if (ctx->Query.CurrentOcclusionObject) {
1035 /* update count of 'passed' fragments */
1036 struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1037 GLuint i;
1038 for (i = 0; i < span->end; i++)
1039 q->Result += span->array->mask[i];
1040 }
1041 #endif
1042
1043 /* we have to wait until after occlusion to do this test */
1044 if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
1045 /* write no pixels */
1046 span->arrayMask = origArrayMask;
1047 return;
1048 }
1049
1050 /* Interpolate the color indexes if needed */
1051 if (swrast->_FogEnabled ||
1052 ctx->Color.IndexLogicOpEnabled ||
1053 ctx->Color.IndexMask != 0xffffffff ||
1054 (span->arrayMask & SPAN_COVERAGE)) {
1055 if (span->interpMask & SPAN_INDEX) {
1056 interpolate_indexes(ctx, span);
1057 }
1058 }
1059
1060 /* Fog */
1061 if (swrast->_FogEnabled) {
1062 _swrast_fog_ci_span(ctx, span);
1063 }
1064
1065 /* Antialias coverage application */
1066 if (span->arrayMask & SPAN_COVERAGE) {
1067 const GLfloat *coverage = span->array->coverage;
1068 GLuint *index = span->array->index;
1069 GLuint i;
1070 for (i = 0; i < span->end; i++) {
1071 ASSERT(coverage[i] < 16);
1072 index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
1073 }
1074 }
1075
1076 /*
1077 * Write to renderbuffers
1078 */
1079 {
1080 struct gl_framebuffer *fb = ctx->DrawBuffer;
1081 const GLuint output = 0; /* only frag progs can write to other outputs */
1082 const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
1083 GLuint indexSave[MAX_WIDTH];
1084 GLuint buf;
1085
1086 if (numDrawBuffers > 1) {
1087 /* save indexes for second, third renderbuffer writes */
1088 _mesa_memcpy(indexSave, span->array->index,
1089 span->end * sizeof(indexSave[0]));
1090 }
1091
1092 for (buf = 0; buf < fb->_NumColorDrawBuffers[output]; buf++) {
1093 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1094 ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1095
1096 if (ctx->Color.IndexLogicOpEnabled) {
1097 _swrast_logicop_ci_span(ctx, rb, span);
1098 }
1099
1100 if (ctx->Color.IndexMask != 0xffffffff) {
1101 _swrast_mask_ci_span(ctx, rb, span);
1102 }
1103
1104 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
1105 /* all fragments have same color index */
1106 GLubyte index8;
1107 GLushort index16;
1108 GLuint index32;
1109 void *value;
1110
1111 if (rb->DataType == GL_UNSIGNED_BYTE) {
1112 index8 = FixedToInt(span->index);
1113 value = &index8;
1114 }
1115 else if (rb->DataType == GL_UNSIGNED_SHORT) {
1116 index16 = FixedToInt(span->index);
1117 value = &index16;
1118 }
1119 else {
1120 ASSERT(rb->DataType == GL_UNSIGNED_INT);
1121 index32 = FixedToInt(span->index);
1122 value = &index32;
1123 }
1124
1125 if (span->arrayMask & SPAN_XY) {
1126 rb->PutMonoValues(ctx, rb, span->end, span->array->x,
1127 span->array->y, value, span->array->mask);
1128 }
1129 else {
1130 rb->PutMonoRow(ctx, rb, span->end, span->x, span->y,
1131 value, span->array->mask);
1132 }
1133 }
1134 else {
1135 /* each fragment is a different color */
1136 GLubyte index8[MAX_WIDTH];
1137 GLushort index16[MAX_WIDTH];
1138 void *values;
1139
1140 if (rb->DataType == GL_UNSIGNED_BYTE) {
1141 GLuint k;
1142 for (k = 0; k < span->end; k++) {
1143 index8[k] = (GLubyte) span->array->index[k];
1144 }
1145 values = index8;
1146 }
1147 else if (rb->DataType == GL_UNSIGNED_SHORT) {
1148 GLuint k;
1149 for (k = 0; k < span->end; k++) {
1150 index16[k] = (GLushort) span->array->index[k];
1151 }
1152 values = index16;
1153 }
1154 else {
1155 ASSERT(rb->DataType == GL_UNSIGNED_INT);
1156 values = span->array->index;
1157 }
1158
1159 if (span->arrayMask & SPAN_XY) {
1160 rb->PutValues(ctx, rb, span->end,
1161 span->array->x, span->array->y,
1162 values, span->array->mask);
1163 }
1164 else {
1165 rb->PutRow(ctx, rb, span->end, span->x, span->y,
1166 values, span->array->mask);
1167 }
1168 }
1169
1170 if (buf + 1 < numDrawBuffers) {
1171 /* restore original span values */
1172 _mesa_memcpy(span->array->index, indexSave,
1173 span->end * sizeof(indexSave[0]));
1174 }
1175 } /* for buf */
1176 }
1177
1178 span->interpMask = origInterpMask;
1179 span->arrayMask = origArrayMask;
1180 }
1181
1182
1183 /**
1184 * Add specular color to base color. This is used only when
1185 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1186 */
1187 static INLINE void
1188 add_specular(GLcontext *ctx, SWspan *span)
1189 {
1190 switch (span->array->ChanType) {
1191 case GL_UNSIGNED_BYTE:
1192 {
1193 GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
1194 GLubyte (*spec)[4] = span->array->color.sz1.spec;
1195 GLuint i;
1196 for (i = 0; i < span->end; i++) {
1197 GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
1198 GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
1199 GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
1200 GLint a = rgba[i][ACOMP] + spec[i][ACOMP];
1201 rgba[i][RCOMP] = MIN2(r, 255);
1202 rgba[i][GCOMP] = MIN2(g, 255);
1203 rgba[i][BCOMP] = MIN2(b, 255);
1204 rgba[i][ACOMP] = MIN2(a, 255);
1205 }
1206 }
1207 break;
1208 case GL_UNSIGNED_SHORT:
1209 {
1210 GLushort (*rgba)[4] = span->array->color.sz2.rgba;
1211 GLushort (*spec)[4] = span->array->color.sz2.spec;
1212 GLuint i;
1213 for (i = 0; i < span->end; i++) {
1214 GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
1215 GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
1216 GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
1217 GLint a = rgba[i][ACOMP] + spec[i][ACOMP];
1218 rgba[i][RCOMP] = MIN2(r, 65535);
1219 rgba[i][GCOMP] = MIN2(g, 65535);
1220 rgba[i][BCOMP] = MIN2(b, 65535);
1221 rgba[i][ACOMP] = MIN2(a, 65535);
1222 }
1223 }
1224 break;
1225 case GL_FLOAT:
1226 {
1227 GLfloat (*rgba)[4] = span->array->color.sz4.rgba;
1228 GLfloat (*spec)[4] = span->array->color.sz4.spec;
1229 GLuint i;
1230 for (i = 0; i < span->end; i++) {
1231 rgba[i][RCOMP] += spec[i][RCOMP];
1232 rgba[i][GCOMP] += spec[i][GCOMP];
1233 rgba[i][BCOMP] += spec[i][BCOMP];
1234 rgba[i][ACOMP] += spec[i][ACOMP];
1235 }
1236 }
1237 break;
1238 default:
1239 _mesa_problem(ctx, "Invalid datatype in add_specular");
1240 }
1241 }
1242
1243
1244 /**
1245 * Apply antialiasing coverage value to alpha values.
1246 */
1247 static INLINE void
1248 apply_aa_coverage(SWspan *span)
1249 {
1250 const GLfloat *coverage = span->array->coverage;
1251 GLuint i;
1252 if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1253 GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
1254 for (i = 0; i < span->end; i++) {
1255 const GLfloat a = rgba[i][ACOMP] * coverage[i];
1256 rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0);
1257 ASSERT(coverage[i] >= 0.0);
1258 ASSERT(coverage[i] <= 1.0);
1259 }
1260 }
1261 else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
1262 GLushort (*rgba)[4] = span->array->color.sz2.rgba;
1263 for (i = 0; i < span->end; i++) {
1264 const GLfloat a = rgba[i][ACOMP] * coverage[i];
1265 rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0);
1266 }
1267 }
1268 else {
1269 GLfloat (*rgba)[4] = span->array->color.sz4.rgba;
1270 for (i = 0; i < span->end; i++) {
1271 rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
1272 }
1273 }
1274 }
1275
1276
1277 /**
1278 * Clamp span's float colors to [0,1]
1279 */
1280 static INLINE void
1281 clamp_colors(SWspan *span)
1282 {
1283 GLfloat (*rgba)[4] = span->array->color.sz4.rgba;
1284 GLuint i;
1285 ASSERT(span->array->ChanType == GL_FLOAT);
1286 for (i = 0; i < span->end; i++) {
1287 rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
1288 rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
1289 rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
1290 rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
1291 }
1292 }
1293
1294
1295 /**
1296 * Convert the span's color arrays to the given type.
1297 */
1298 static INLINE void
1299 convert_color_type(GLcontext *ctx, SWspan *span, GLenum newType)
1300 {
1301 GLvoid *src, *dst;
1302 if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1303 src = span->array->color.sz1.rgba;
1304 }
1305 else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1306 src = span->array->color.sz2.rgba;
1307 }
1308 else {
1309 src = span->array->color.sz4.rgba;
1310 }
1311 if (newType == GL_UNSIGNED_BYTE) {
1312 dst = span->array->color.sz1.rgba;
1313 }
1314 else if (newType == GL_UNSIGNED_BYTE) {
1315 dst = span->array->color.sz2.rgba;
1316 }
1317 else {
1318 dst = span->array->color.sz4.rgba;
1319 }
1320
1321 _mesa_convert_colors(span->array->ChanType, src,
1322 newType, dst,
1323 span->end, span->array->mask);
1324
1325 span->array->ChanType = newType;
1326 }
1327
1328
1329
1330 /**
1331 * Apply fragment shader, fragment program or normal texturing to span.
1332 */
1333 static INLINE void
1334 shade_texture_span(GLcontext *ctx, SWspan *span)
1335 {
1336 /* Now we need the rgba array, fill it in if needed */
1337 if (span->interpMask & SPAN_RGBA)
1338 interpolate_colors(span);
1339
1340 if (ctx->Texture._EnabledCoordUnits && (span->interpMask & SPAN_TEXTURE))
1341 interpolate_texcoords(ctx, span);
1342
1343 if (ctx->ShaderObjects._FragmentShaderPresent ||
1344 ctx->FragmentProgram._Enabled ||
1345 ctx->ATIFragmentShader._Enabled) {
1346
1347 /* use float colors if running a fragment program or shader */
1348 const GLenum oldType = span->array->ChanType;
1349 const GLenum newType = GL_FLOAT;
1350 if (oldType != newType) {
1351 GLvoid *src = (oldType == GL_UNSIGNED_BYTE)
1352 ? (GLvoid *) span->array->color.sz1.rgba
1353 : (GLvoid *) span->array->color.sz2.rgba;
1354 _mesa_convert_colors(oldType, src,
1355 newType, span->array->color.sz4.rgba,
1356 span->end, span->array->mask);
1357 span->array->ChanType = newType;
1358 }
1359
1360 /* fragment programs/shaders may need specular, fog and Z coords */
1361 if (span->interpMask & SPAN_SPEC)
1362 interpolate_specular(span);
1363
1364 if (span->interpMask & SPAN_FOG)
1365 interpolate_fog(ctx, span);
1366
1367 if (span->interpMask & SPAN_Z)
1368 _swrast_span_interpolate_z (ctx, span);
1369
1370 /* Run fragment program/shader now */
1371 if (ctx->ShaderObjects._FragmentShaderPresent) {
1372 interpolate_varying(ctx, span);
1373 _swrast_exec_arbshader(ctx, span);
1374 }
1375 else if (ctx->FragmentProgram._Enabled) {
1376 _swrast_exec_fragment_program(ctx, span);
1377 }
1378 else {
1379 ASSERT(ctx->ATIFragmentShader._Enabled);
1380 _swrast_exec_fragment_shader(ctx, span);
1381 }
1382 }
1383 else if (ctx->Texture._EnabledUnits && (span->arrayMask & SPAN_TEXTURE)) {
1384 /* conventional texturing */
1385 _swrast_texture_span(ctx, span);
1386 }
1387 }
1388
1389
1390
1391 /**
1392 * Apply all the per-fragment operations to a span.
1393 * This now includes texturing (_swrast_write_texture_span() is history).
1394 * This function may modify any of the array values in the span.
1395 * span->interpMask and span->arrayMask may be changed but will be restored
1396 * to their original values before returning.
1397 */
1398 void
1399 _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
1400 {
1401 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1402 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1403 const GLbitfield origInterpMask = span->interpMask;
1404 const GLbitfield origArrayMask = span->arrayMask;
1405 const GLenum chanType = span->array->ChanType;
1406 const GLboolean shader
1407 = ctx->FragmentProgram._Enabled
1408 || ctx->ShaderObjects._FragmentShaderPresent
1409 || ctx->ATIFragmentShader._Enabled;
1410 const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledUnits;
1411 GLboolean deferredTexture;
1412
1413 /*
1414 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__,
1415 span->interpMask, span->arrayMask);
1416 */
1417
1418 ASSERT(span->primitive == GL_POINT ||
1419 span->primitive == GL_LINE ||
1420 span->primitive == GL_POLYGON ||
1421 span->primitive == GL_BITMAP);
1422 ASSERT(span->end <= MAX_WIDTH);
1423 ASSERT((span->interpMask & span->arrayMask) == 0);
1424 ASSERT((span->interpMask & SPAN_RGBA) ^ (span->arrayMask & SPAN_RGBA));
1425
1426 /* check for conditions that prevent deferred shading */
1427 if (ctx->Color.AlphaEnabled) {
1428 /* alpha test depends on post-texture/shader colors */
1429 deferredTexture = GL_FALSE;
1430 }
1431 else if (shaderOrTexture) {
1432 if (ctx->FragmentProgram._Enabled) {
1433 if (ctx->FragmentProgram.Current->Base.OutputsWritten
1434 & (1 << FRAG_RESULT_DEPR)) {
1435 /* Z comes from fragment program */
1436 deferredTexture = GL_FALSE;
1437 }
1438 else {
1439 deferredTexture = GL_TRUE;
1440 }
1441 }
1442 else if (ctx->ShaderObjects._FragmentShaderPresent) {
1443 /* XXX how do we test if Z is written by shader? */
1444 deferredTexture = GL_FALSE; /* never defer to be safe */
1445 }
1446 else {
1447 /* ATI frag shader or conventional texturing */
1448 deferredTexture = GL_TRUE;
1449 }
1450 }
1451 else {
1452 /* no texturing or shadering */
1453 deferredTexture = GL_FALSE;
1454 }
1455
1456 /* Fragment write masks */
1457 if (span->arrayMask & SPAN_MASK) {
1458 /* mask was initialized by caller, probably glBitmap */
1459 span->writeAll = GL_FALSE;
1460 }
1461 else {
1462 _mesa_memset(span->array->mask, 1, span->end);
1463 span->writeAll = GL_TRUE;
1464 }
1465
1466 /* Clip to window/scissor box */
1467 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1468 if (!clip_span(ctx, span)) {
1469 return;
1470 }
1471 }
1472
1473 #ifdef DEBUG
1474 /* Make sure all fragments are within window bounds */
1475 if (span->arrayMask & SPAN_XY) {
1476 GLuint i;
1477 for (i = 0; i < span->end; i++) {
1478 if (span->array->mask[i]) {
1479 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
1480 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
1481 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
1482 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1483 }
1484 }
1485 }
1486 #endif
1487
1488 /* Polygon Stippling */
1489 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1490 stipple_polygon_span(ctx, span);
1491 }
1492
1493 /* This is the normal place to compute the resulting fragment color/Z.
1494 * As an optimization, we try to defer this until after Z/stencil
1495 * testing in order to try to avoid computing colors that we won't
1496 * actually need.
1497 */
1498 if (shaderOrTexture && !deferredTexture) {
1499 shade_texture_span(ctx, span);
1500 }
1501
1502 /* Do the alpha test */
1503 if (ctx->Color.AlphaEnabled) {
1504 if (!_swrast_alpha_test(ctx, span)) {
1505 goto end;
1506 }
1507 }
1508
1509 /* Stencil and Z testing */
1510 if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1511 if (span->interpMask & SPAN_Z)
1512 _swrast_span_interpolate_z(ctx, span);
1513
1514 if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) {
1515 /* Combined Z/stencil tests */
1516 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1517 goto end;
1518 }
1519 }
1520 else if (ctx->DrawBuffer->Visual.depthBits > 0) {
1521 /* Just regular depth testing */
1522 ASSERT(ctx->Depth.Test);
1523 ASSERT(span->arrayMask & SPAN_Z);
1524 if (!_swrast_depth_test_span(ctx, span)) {
1525 goto end;
1526 }
1527 }
1528 }
1529
1530 #if FEATURE_ARB_occlusion_query
1531 if (ctx->Query.CurrentOcclusionObject) {
1532 /* update count of 'passed' fragments */
1533 struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1534 GLuint i;
1535 for (i = 0; i < span->end; i++)
1536 q->Result += span->array->mask[i];
1537 }
1538 #endif
1539
1540 /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1541 * the occlusion test.
1542 */
1543 if (colorMask == 0x0) {
1544 goto end;
1545 }
1546
1547 /* If we were able to defer fragment color computation to now, there's
1548 * a good chance that many fragments will have already been killed by
1549 * Z/stencil testing.
1550 */
1551 if (deferredTexture) {
1552 ASSERT(shaderOrTexture);
1553 shade_texture_span(ctx, span);
1554 }
1555
1556 if ((span->arrayMask & SPAN_RGBA) == 0) {
1557 interpolate_colors(span);
1558 }
1559
1560 ASSERT(span->arrayMask & SPAN_RGBA);
1561
1562 if (!shader) {
1563 /* Add base and specular colors */
1564 if (ctx->Fog.ColorSumEnabled ||
1565 (ctx->Light.Enabled &&
1566 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1567 if (span->interpMask & SPAN_SPEC) {
1568 interpolate_specular(span);
1569 }
1570 if (span->arrayMask & SPAN_SPEC) {
1571 add_specular(ctx, span);
1572 }
1573 else {
1574 /* We probably added the base/specular colors during the
1575 * vertex stage!
1576 */
1577 }
1578 }
1579 }
1580
1581 /* Fog */
1582 if (swrast->_FogEnabled) {
1583 _swrast_fog_rgba_span(ctx, span);
1584 }
1585
1586 /* Antialias coverage application */
1587 if (span->arrayMask & SPAN_COVERAGE) {
1588 apply_aa_coverage(span);
1589 }
1590
1591 /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
1592 if (ctx->Color.ClampFragmentColor == GL_TRUE &&
1593 span->array->ChanType == GL_FLOAT) {
1594 clamp_colors(span);
1595 }
1596
1597 /*
1598 * Write to renderbuffers
1599 */
1600 {
1601 struct gl_framebuffer *fb = ctx->DrawBuffer;
1602 const GLuint output = 0; /* only frag progs can write to other outputs */
1603 const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
1604 GLchan rgbaSave[MAX_WIDTH][4];
1605 GLuint buf;
1606
1607 if (numDrawBuffers > 0) {
1608 if (fb->_ColorDrawBuffers[output][0]->DataType
1609 != span->array->ChanType) {
1610 convert_color_type(ctx, span,
1611 fb->_ColorDrawBuffers[output][0]->DataType);
1612 }
1613 }
1614
1615 if (numDrawBuffers > 1) {
1616 /* save colors for second, third renderbuffer writes */
1617 _mesa_memcpy(rgbaSave, span->array->rgba,
1618 4 * span->end * sizeof(GLchan));
1619 }
1620
1621 for (buf = 0; buf < numDrawBuffers; buf++) {
1622 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1623 ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
1624
1625 if (ctx->Color._LogicOpEnabled) {
1626 _swrast_logicop_rgba_span(ctx, rb, span);
1627 }
1628 else if (ctx->Color.BlendEnabled) {
1629 _swrast_blend_span(ctx, rb, span);
1630 }
1631
1632 if (colorMask != 0xffffffff) {
1633 _swrast_mask_rgba_span(ctx, rb, span);
1634 }
1635
1636 if (span->arrayMask & SPAN_XY) {
1637 /* array of pixel coords */
1638 ASSERT(rb->PutValues);
1639 rb->PutValues(ctx, rb, span->end,
1640 span->array->x, span->array->y,
1641 span->array->rgba, span->array->mask);
1642 }
1643 else {
1644 /* horizontal run of pixels */
1645 ASSERT(rb->PutRow);
1646 rb->PutRow(ctx, rb, span->end, span->x, span->y, span->array->rgba,
1647 span->writeAll ? NULL: span->array->mask);
1648 }
1649
1650 if (buf + 1 < numDrawBuffers) {
1651 /* restore original span values */
1652 _mesa_memcpy(span->array->rgba, rgbaSave,
1653 4 * span->end * sizeof(GLchan));
1654 }
1655 } /* for buf */
1656
1657 }
1658
1659 end:
1660 /* restore these values before returning */
1661 span->interpMask = origInterpMask;
1662 span->arrayMask = origArrayMask;
1663 span->array->ChanType = chanType;
1664 }
1665
1666
1667 /**
1668 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1669 * reading ouside the buffer's boundaries.
1670 * \param type datatype for returned colors
1671 * \param rgba the returned colors
1672 */
1673 void
1674 _swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1675 GLuint n, GLint x, GLint y, GLenum dstType,
1676 GLvoid *rgba)
1677 {
1678 const GLint bufWidth = (GLint) rb->Width;
1679 const GLint bufHeight = (GLint) rb->Height;
1680
1681 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1682 /* completely above, below, or right */
1683 /* XXX maybe leave rgba values undefined? */
1684 _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1685 }
1686 else {
1687 GLint skip, length;
1688 if (x < 0) {
1689 /* left edge clipping */
1690 skip = -x;
1691 length = (GLint) n - skip;
1692 if (length < 0) {
1693 /* completely left of window */
1694 return;
1695 }
1696 if (length > bufWidth) {
1697 length = bufWidth;
1698 }
1699 }
1700 else if ((GLint) (x + n) > bufWidth) {
1701 /* right edge clipping */
1702 skip = 0;
1703 length = bufWidth - x;
1704 if (length < 0) {
1705 /* completely to right of window */
1706 return;
1707 }
1708 }
1709 else {
1710 /* no clipping */
1711 skip = 0;
1712 length = (GLint) n;
1713 }
1714
1715 ASSERT(rb);
1716 ASSERT(rb->GetRow);
1717 ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
1718
1719 if (rb->DataType == dstType) {
1720 rb->GetRow(ctx, rb, length, x + skip, y,
1721 (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
1722 }
1723 else {
1724 GLuint temp[MAX_WIDTH * 4];
1725 rb->GetRow(ctx, rb, length, x + skip, y, temp);
1726 _mesa_convert_colors(rb->DataType, temp,
1727 dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
1728 length, NULL);
1729 }
1730 }
1731 }
1732
1733
1734 /**
1735 * Read CI pixels from frame buffer. Clipping will be done to prevent
1736 * reading ouside the buffer's boundaries.
1737 */
1738 void
1739 _swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1740 GLuint n, GLint x, GLint y, GLuint index[] )
1741 {
1742 const GLint bufWidth = (GLint) rb->Width;
1743 const GLint bufHeight = (GLint) rb->Height;
1744
1745 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1746 /* completely above, below, or right */
1747 _mesa_bzero(index, n * sizeof(GLuint));
1748 }
1749 else {
1750 GLint skip, length;
1751 if (x < 0) {
1752 /* left edge clipping */
1753 skip = -x;
1754 length = (GLint) n - skip;
1755 if (length < 0) {
1756 /* completely left of window */
1757 return;
1758 }
1759 if (length > bufWidth) {
1760 length = bufWidth;
1761 }
1762 }
1763 else if ((GLint) (x + n) > bufWidth) {
1764 /* right edge clipping */
1765 skip = 0;
1766 length = bufWidth - x;
1767 if (length < 0) {
1768 /* completely to right of window */
1769 return;
1770 }
1771 }
1772 else {
1773 /* no clipping */
1774 skip = 0;
1775 length = (GLint) n;
1776 }
1777
1778 ASSERT(rb->GetRow);
1779 ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1780
1781 if (rb->DataType == GL_UNSIGNED_BYTE) {
1782 GLubyte index8[MAX_WIDTH];
1783 GLint i;
1784 rb->GetRow(ctx, rb, length, x + skip, y, index8);
1785 for (i = 0; i < length; i++)
1786 index[skip + i] = index8[i];
1787 }
1788 else if (rb->DataType == GL_UNSIGNED_SHORT) {
1789 GLushort index16[MAX_WIDTH];
1790 GLint i;
1791 rb->GetRow(ctx, rb, length, x + skip, y, index16);
1792 for (i = 0; i < length; i++)
1793 index[skip + i] = index16[i];
1794 }
1795 else if (rb->DataType == GL_UNSIGNED_INT) {
1796 rb->GetRow(ctx, rb, length, x + skip, y, index + skip);
1797 }
1798 }
1799 }
1800
1801
1802 /**
1803 * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
1804 * reading values outside the buffer bounds.
1805 * We can use this for reading any format/type of renderbuffer.
1806 * \param valueSize is the size in bytes of each value (pixel) put into the
1807 * values array.
1808 */
1809 void
1810 _swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
1811 GLuint count, const GLint x[], const GLint y[],
1812 void *values, GLuint valueSize)
1813 {
1814 GLuint i, inCount = 0, inStart = 0;
1815
1816 for (i = 0; i < count; i++) {
1817 if (x[i] >= 0 && y[i] >= 0 && x[i] < rb->Width && y[i] < rb->Height) {
1818 /* inside */
1819 if (inCount == 0)
1820 inStart = i;
1821 inCount++;
1822 }
1823 else {
1824 if (inCount > 0) {
1825 /* read [inStart, inStart + inCount) */
1826 rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
1827 (GLubyte *) values + inStart * valueSize);
1828 inCount = 0;
1829 }
1830 }
1831 }
1832 if (inCount > 0) {
1833 /* read last values */
1834 rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
1835 (GLubyte *) values + inStart * valueSize);
1836 }
1837 }
1838
1839
1840 /**
1841 * Wrapper for gl_renderbuffer::PutRow() which does clipping.
1842 * \param valueSize size of each value (pixel) in bytes
1843 */
1844 void
1845 _swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1846 GLuint count, GLint x, GLint y,
1847 const GLvoid *values, GLuint valueSize)
1848 {
1849 GLint skip = 0;
1850
1851 if (y < 0 || y >= rb->Height)
1852 return; /* above or below */
1853
1854 if (x + (GLint) count <= 0 || x >= rb->Width)
1855 return; /* entirely left or right */
1856
1857 if (x + count > rb->Width) {
1858 /* right clip */
1859 GLint clip = x + count - rb->Width;
1860 count -= clip;
1861 }
1862
1863 if (x < 0) {
1864 /* left clip */
1865 skip = -x;
1866 x = 0;
1867 count -= skip;
1868 }
1869
1870 rb->PutRow(ctx, rb, count, x, y,
1871 (const GLubyte *) values + skip * valueSize, NULL);
1872 }
1873
1874
1875 /**
1876 * Wrapper for gl_renderbuffer::GetRow() which does clipping.
1877 * \param valueSize size of each value (pixel) in bytes
1878 */
1879 void
1880 _swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1881 GLuint count, GLint x, GLint y,
1882 GLvoid *values, GLuint valueSize)
1883 {
1884 GLint skip = 0;
1885
1886 if (y < 0 || y >= rb->Height)
1887 return; /* above or below */
1888
1889 if (x + (GLint) count <= 0 || x >= rb->Width)
1890 return; /* entirely left or right */
1891
1892 if (x + count > rb->Width) {
1893 /* right clip */
1894 GLint clip = x + count - rb->Width;
1895 count -= clip;
1896 }
1897
1898 if (x < 0) {
1899 /* left clip */
1900 skip = -x;
1901 x = 0;
1902 count -= skip;
1903 }
1904
1905 rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
1906 }
1907
1908
1909 /**
1910 * Get RGBA pixels from the given renderbuffer. Put the pixel colors into
1911 * the span's specular color arrays. The specular color arrays should no
1912 * longer be needed by time this function is called.
1913 * Used by blending, logicop and masking functions.
1914 * \return pointer to the colors we read.
1915 */
1916 void *
1917 _swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
1918 SWspan *span)
1919 {
1920 const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
1921 void *rbPixels;
1922
1923 /*
1924 * Determine pixel size (in bytes).
1925 * Point rbPixels to a temporary space (use specular color arrays).
1926 */
1927 if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1928 rbPixels = span->array->color.sz1.spec;
1929 }
1930 else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
1931 rbPixels = span->array->color.sz2.spec;
1932 }
1933 else {
1934 rbPixels = span->array->color.sz4.spec;
1935 }
1936
1937 /* Get destination values from renderbuffer */
1938 if (span->arrayMask & SPAN_XY) {
1939 _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
1940 rbPixels, pixelSize);
1941 }
1942 else {
1943 _swrast_get_row(ctx, rb, span->end, span->x, span->y,
1944 rbPixels, pixelSize);
1945 }
1946
1947 return rbPixels;
1948 }