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