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