mesa: make sure the gotten value isn't greater than the
[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 "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 * 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 #if 0
446 static GLfloat
447 compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
448 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
449 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
450 {
451 GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
452 GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
453 GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
454 GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
455 GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
456 GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
457 GLfloat rho = MAX2(x, y);
458 GLfloat lambda = LOG2(rho);
459 return lambda;
460 }
461 #endif
462
463
464 /**
465 * Compute mipmap LOD from partial derivatives.
466 * This is a faster approximation than above function.
467 */
468 GLfloat
469 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
470 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
471 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
472 {
473 GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
474 GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
475 GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
476 GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
477 GLfloat maxU, maxV, rho, lambda;
478 dsdx2 = FABSF(dsdx2);
479 dsdy2 = FABSF(dsdy2);
480 dtdx2 = FABSF(dtdx2);
481 dtdy2 = FABSF(dtdy2);
482 maxU = MAX2(dsdx2, dsdy2) * texW;
483 maxV = MAX2(dtdx2, dtdy2) * texH;
484 rho = MAX2(maxU, maxV);
485 lambda = LOG2(rho);
486 return lambda;
487 }
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
796 ASSERT(span->end <= MAX_WIDTH);
797 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
798 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
799 ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
800 /*
801 ASSERT((span->interpMask & span->arrayMask) == 0);
802 */
803
804 if (span->arrayMask & SPAN_MASK) {
805 /* mask was initialized by caller, probably glBitmap */
806 span->writeAll = GL_FALSE;
807 }
808 else {
809 _mesa_memset(span->array->mask, 1, span->end);
810 span->writeAll = GL_TRUE;
811 }
812
813 /* Clipping */
814 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
815 if (!clip_span(ctx, span)) {
816 return;
817 }
818 }
819
820 /* Depth bounds test */
821 if (ctx->Depth.BoundsTest && ctx->DrawBuffer->Visual.depthBits > 0) {
822 if (!_swrast_depth_bounds_test(ctx, span)) {
823 return;
824 }
825 }
826
827 #ifdef DEBUG
828 /* Make sure all fragments are within window bounds */
829 if (span->arrayMask & SPAN_XY) {
830 GLuint i;
831 for (i = 0; i < span->end; i++) {
832 if (span->array->mask[i]) {
833 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
834 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
835 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
836 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
837 }
838 }
839 }
840 #endif
841
842 /* Polygon Stippling */
843 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
844 stipple_polygon_span(ctx, span);
845 }
846
847 /* Stencil and Z testing */
848 if (ctx->Depth.Test || ctx->Stencil.Enabled) {
849 if (!(span->arrayMask & SPAN_Z))
850 _swrast_span_interpolate_z(ctx, span);
851
852 if (ctx->Stencil.Enabled) {
853 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
854 span->arrayMask = origArrayMask;
855 return;
856 }
857 }
858 else {
859 ASSERT(ctx->Depth.Test);
860 if (!_swrast_depth_test_span(ctx, span)) {
861 span->interpMask = origInterpMask;
862 span->arrayMask = origArrayMask;
863 return;
864 }
865 }
866 }
867
868 #if FEATURE_ARB_occlusion_query
869 if (ctx->Query.CurrentOcclusionObject) {
870 /* update count of 'passed' fragments */
871 struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
872 GLuint i;
873 for (i = 0; i < span->end; i++)
874 q->Result += span->array->mask[i];
875 }
876 #endif
877
878 /* we have to wait until after occlusion to do this test */
879 if (ctx->Color.IndexMask == 0) {
880 /* write no pixels */
881 span->arrayMask = origArrayMask;
882 return;
883 }
884
885 /* Interpolate the color indexes if needed */
886 if (swrast->_FogEnabled ||
887 ctx->Color.IndexLogicOpEnabled ||
888 ctx->Color.IndexMask != 0xffffffff ||
889 (span->arrayMask & SPAN_COVERAGE)) {
890 if (!(span->arrayMask & SPAN_INDEX) /*span->interpMask & SPAN_INDEX*/) {
891 interpolate_indexes(ctx, span);
892 }
893 }
894
895 /* Fog */
896 if (swrast->_FogEnabled) {
897 _swrast_fog_ci_span(ctx, span);
898 }
899
900 /* Antialias coverage application */
901 if (span->arrayMask & SPAN_COVERAGE) {
902 const GLfloat *coverage = span->array->coverage;
903 GLuint *index = span->array->index;
904 GLuint i;
905 for (i = 0; i < span->end; i++) {
906 ASSERT(coverage[i] < 16);
907 index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
908 }
909 }
910
911 /*
912 * Write to renderbuffers
913 */
914 {
915 struct gl_framebuffer *fb = ctx->DrawBuffer;
916 const GLuint output = 0; /* only frag progs can write to other outputs */
917 const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
918 GLuint indexSave[MAX_WIDTH];
919 GLuint buf;
920
921 if (numDrawBuffers > 1) {
922 /* save indexes for second, third renderbuffer writes */
923 _mesa_memcpy(indexSave, span->array->index,
924 span->end * sizeof(indexSave[0]));
925 }
926
927 for (buf = 0; buf < fb->_NumColorDrawBuffers[output]; buf++) {
928 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
929 ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
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 < numDrawBuffers) {
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
1036 if (span->array->ChanType == GL_FLOAT) {
1037 if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
1038 interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
1039 }
1040 }
1041 else {
1042 /* need float colors */
1043 if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
1044 interpolate_float_colors(span);
1045 }
1046 }
1047
1048 if ((span->arrayAttribs & FRAG_BIT_COL1) == 0) {
1049 /* XXX could avoid this and interpolate COL1 in the loop below */
1050 interpolate_active_attribs(ctx, span, FRAG_BIT_COL1);
1051 }
1052
1053 ASSERT(span->arrayAttribs & FRAG_BIT_COL0);
1054 ASSERT(span->arrayAttribs & FRAG_BIT_COL1);
1055
1056 for (i = 0; i < span->end; i++) {
1057 if (mask[i]) {
1058 col0[i][0] += col1[i][0];
1059 col0[i][1] += col1[i][1];
1060 col0[i][2] += col1[i][2];
1061 }
1062 }
1063
1064 span->array->ChanType = GL_FLOAT;
1065 }
1066
1067
1068 /**
1069 * Apply antialiasing coverage value to alpha values.
1070 */
1071 static INLINE void
1072 apply_aa_coverage(SWspan *span)
1073 {
1074 const GLfloat *coverage = span->array->coverage;
1075 GLuint i;
1076 if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1077 GLubyte (*rgba)[4] = span->array->rgba8;
1078 for (i = 0; i < span->end; i++) {
1079 const GLfloat a = rgba[i][ACOMP] * coverage[i];
1080 rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0);
1081 ASSERT(coverage[i] >= 0.0);
1082 ASSERT(coverage[i] <= 1.0);
1083 }
1084 }
1085 else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
1086 GLushort (*rgba)[4] = span->array->rgba16;
1087 for (i = 0; i < span->end; i++) {
1088 const GLfloat a = rgba[i][ACOMP] * coverage[i];
1089 rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0);
1090 }
1091 }
1092 else {
1093 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
1094 for (i = 0; i < span->end; i++) {
1095 rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
1096 /* clamp later */
1097 }
1098 }
1099 }
1100
1101
1102 /**
1103 * Clamp span's float colors to [0,1]
1104 */
1105 static INLINE void
1106 clamp_colors(SWspan *span)
1107 {
1108 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
1109 GLuint i;
1110 ASSERT(span->array->ChanType == GL_FLOAT);
1111 for (i = 0; i < span->end; i++) {
1112 rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
1113 rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
1114 rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
1115 rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
1116 }
1117 }
1118
1119
1120 /**
1121 * Convert the span's color arrays to the given type.
1122 * The only way 'output' can be greater than one is when we have a fragment
1123 * program that writes to gl_FragData[1] or higher.
1124 * \param output which fragment program color output is being processed
1125 */
1126 static INLINE void
1127 convert_color_type(SWspan *span, GLenum newType, GLuint output)
1128 {
1129 GLvoid *src, *dst;
1130
1131 if (output > 0 || span->array->ChanType == GL_FLOAT) {
1132 src = span->array->attribs[FRAG_ATTRIB_COL0 + output];
1133 span->array->ChanType = GL_FLOAT;
1134 }
1135 else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1136 src = span->array->rgba8;
1137 }
1138 else {
1139 ASSERT(span->array->ChanType == GL_UNSIGNED_SHORT);
1140 src = span->array->rgba16;
1141 }
1142
1143 if (newType == GL_UNSIGNED_BYTE) {
1144 dst = span->array->rgba8;
1145 }
1146 else if (newType == GL_UNSIGNED_SHORT) {
1147 dst = span->array->rgba16;
1148 }
1149 else {
1150 dst = span->array->attribs[FRAG_ATTRIB_COL0];
1151 }
1152
1153 _mesa_convert_colors(span->array->ChanType, src,
1154 newType, dst,
1155 span->end, span->array->mask);
1156
1157 span->array->ChanType = newType;
1158 span->array->rgba = dst;
1159 }
1160
1161
1162
1163 /**
1164 * Apply fragment shader, fragment program or normal texturing to span.
1165 */
1166 static INLINE void
1167 shade_texture_span(GLcontext *ctx, SWspan *span)
1168 {
1169 GLbitfield inputsRead;
1170
1171 /* Determine which fragment attributes are actually needed */
1172 if (ctx->FragmentProgram._Current) {
1173 inputsRead = ctx->FragmentProgram._Current->Base.InputsRead;
1174 }
1175 else {
1176 /* XXX we could be a bit smarter about this */
1177 inputsRead = ~0;
1178 }
1179
1180 if (ctx->FragmentProgram._Current ||
1181 ctx->ATIFragmentShader._Enabled) {
1182 /* programmable shading */
1183 if (span->primitive == GL_BITMAP && span->array->ChanType != GL_FLOAT) {
1184 convert_color_type(span, GL_FLOAT, 0);
1185 }
1186 if (span->primitive != GL_POINT) {
1187 /* for points, we populated the arrays already */
1188 interpolate_active_attribs(ctx, span, ~0);
1189 }
1190 span->array->ChanType = GL_FLOAT;
1191
1192 if (!(span->arrayMask & SPAN_Z))
1193 _swrast_span_interpolate_z (ctx, span);
1194
1195 #if 0
1196 if (inputsRead & FRAG_BIT_WPOS)
1197 #else
1198 /* XXX always interpolate wpos so that DDX/DDY work */
1199 #endif
1200 interpolate_wpos(ctx, span);
1201
1202 /* Run fragment program/shader now */
1203 if (ctx->FragmentProgram._Current) {
1204 _swrast_exec_fragment_program(ctx, span);
1205 }
1206 else {
1207 ASSERT(ctx->ATIFragmentShader._Enabled);
1208 _swrast_exec_fragment_shader(ctx, span);
1209 }
1210 }
1211 else if (ctx->Texture._EnabledUnits) {
1212 /* conventional texturing */
1213
1214 #if CHAN_BITS == 32
1215 if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
1216 interpolate_int_colors(ctx, span);
1217 }
1218 #else
1219 if (!(span->arrayMask & SPAN_RGBA))
1220 interpolate_int_colors(ctx, span);
1221 #endif
1222 if ((span->arrayAttribs & FRAG_BITS_TEX_ANY) == 0x0)
1223 interpolate_texcoords(ctx, span);
1224
1225 _swrast_texture_span(ctx, span);
1226 }
1227 }
1228
1229
1230
1231 /**
1232 * Apply all the per-fragment operations to a span.
1233 * This now includes texturing (_swrast_write_texture_span() is history).
1234 * This function may modify any of the array values in the span.
1235 * span->interpMask and span->arrayMask may be changed but will be restored
1236 * to their original values before returning.
1237 */
1238 void
1239 _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
1240 {
1241 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1242 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1243 const GLbitfield origInterpMask = span->interpMask;
1244 const GLbitfield origArrayMask = span->arrayMask;
1245 const GLbitfield origArrayAttribs = span->arrayAttribs;
1246 const GLenum origChanType = span->array->ChanType;
1247 void * const origRgba = span->array->rgba;
1248 const GLboolean shader = (ctx->FragmentProgram._Current
1249 || ctx->ATIFragmentShader._Enabled);
1250 const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledUnits;
1251 struct gl_framebuffer *fb = ctx->DrawBuffer;
1252 GLuint output;
1253
1254 /*
1255 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__,
1256 span->interpMask, span->arrayMask);
1257 */
1258
1259 ASSERT(span->primitive == GL_POINT ||
1260 span->primitive == GL_LINE ||
1261 span->primitive == GL_POLYGON ||
1262 span->primitive == GL_BITMAP);
1263 ASSERT(span->end <= MAX_WIDTH);
1264
1265 /* Fragment write masks */
1266 if (span->arrayMask & SPAN_MASK) {
1267 /* mask was initialized by caller, probably glBitmap */
1268 span->writeAll = GL_FALSE;
1269 }
1270 else {
1271 _mesa_memset(span->array->mask, 1, span->end);
1272 span->writeAll = GL_TRUE;
1273 }
1274
1275 /* Clip to window/scissor box */
1276 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1277 if (!clip_span(ctx, span)) {
1278 return;
1279 }
1280 }
1281
1282 #ifdef DEBUG
1283 /* Make sure all fragments are within window bounds */
1284 if (span->arrayMask & SPAN_XY) {
1285 GLuint i;
1286 for (i = 0; i < span->end; i++) {
1287 if (span->array->mask[i]) {
1288 assert(span->array->x[i] >= fb->_Xmin);
1289 assert(span->array->x[i] < fb->_Xmax);
1290 assert(span->array->y[i] >= fb->_Ymin);
1291 assert(span->array->y[i] < fb->_Ymax);
1292 }
1293 }
1294 }
1295 #endif
1296
1297 /* Polygon Stippling */
1298 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1299 stipple_polygon_span(ctx, span);
1300 }
1301
1302 /* This is the normal place to compute the fragment color/Z
1303 * from texturing or shading.
1304 */
1305 if (shaderOrTexture && !swrast->_DeferredTexture) {
1306 shade_texture_span(ctx, span);
1307 }
1308
1309 /* Do the alpha test */
1310 if (ctx->Color.AlphaEnabled) {
1311 if (!_swrast_alpha_test(ctx, span)) {
1312 goto end;
1313 }
1314 }
1315
1316 /* Stencil and Z testing */
1317 if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1318 if (!(span->arrayMask & SPAN_Z))
1319 _swrast_span_interpolate_z(ctx, span);
1320
1321 if (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0) {
1322 /* Combined Z/stencil tests */
1323 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1324 goto end;
1325 }
1326 }
1327 else if (fb->Visual.depthBits > 0) {
1328 /* Just regular depth testing */
1329 ASSERT(ctx->Depth.Test);
1330 ASSERT(span->arrayMask & SPAN_Z);
1331 if (!_swrast_depth_test_span(ctx, span)) {
1332 goto end;
1333 }
1334 }
1335 }
1336
1337 #if FEATURE_ARB_occlusion_query
1338 if (ctx->Query.CurrentOcclusionObject) {
1339 /* update count of 'passed' fragments */
1340 struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1341 GLuint i;
1342 for (i = 0; i < span->end; i++)
1343 q->Result += span->array->mask[i];
1344 }
1345 #endif
1346
1347 /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1348 * the occlusion test.
1349 */
1350 if (colorMask == 0x0) {
1351 goto end;
1352 }
1353
1354 /* If we were able to defer fragment color computation to now, there's
1355 * a good chance that many fragments will have already been killed by
1356 * Z/stencil testing.
1357 */
1358 if (shaderOrTexture && swrast->_DeferredTexture) {
1359 shade_texture_span(ctx, span);
1360 }
1361
1362 #if CHAN_BITS == 32
1363 if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
1364 interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
1365 }
1366 #else
1367 if ((span->arrayMask & SPAN_RGBA) == 0) {
1368 interpolate_int_colors(ctx, span);
1369 }
1370 #endif
1371
1372 ASSERT(span->arrayMask & SPAN_RGBA);
1373
1374 if (!shader) {
1375 /* Add base and specular colors */
1376 if (ctx->Fog.ColorSumEnabled ||
1377 (ctx->Light.Enabled &&
1378 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1379 add_specular(ctx, span);
1380 }
1381 }
1382
1383 /* Fog */
1384 if (swrast->_FogEnabled) {
1385 _swrast_fog_rgba_span(ctx, span);
1386 }
1387
1388 /* Antialias coverage application */
1389 if (span->arrayMask & SPAN_COVERAGE) {
1390 apply_aa_coverage(span);
1391 }
1392
1393 /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
1394 if (ctx->Color.ClampFragmentColor == GL_TRUE &&
1395 span->array->ChanType == GL_FLOAT) {
1396 clamp_colors(span);
1397 }
1398
1399 /*
1400 * Write to renderbuffers
1401 */
1402 /* Loop over color outputs (GL_ARB_draw_buffers) written by frag prog */
1403 for (output = 0; output < swrast->_NumColorOutputs; output++) {
1404 if (swrast->_ColorOutputsMask & (1 << output)) {
1405 const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
1406 GLchan rgbaSave[MAX_WIDTH][4];
1407 GLuint buf;
1408
1409 ASSERT(numDrawBuffers > 0);
1410
1411 if (fb->_ColorDrawBuffers[output][0]->DataType
1412 != span->array->ChanType || output > 0) {
1413 convert_color_type(span,
1414 fb->_ColorDrawBuffers[output][0]->DataType,
1415 output);
1416 }
1417
1418 if (numDrawBuffers > 1) {
1419 /* save colors for second, third renderbuffer writes */
1420 _mesa_memcpy(rgbaSave, span->array->rgba,
1421 4 * span->end * sizeof(GLchan));
1422 }
1423
1424 /* Loop over renderbuffers (i.e. GL_FRONT_AND_BACK) */
1425 for (buf = 0; buf < numDrawBuffers; buf++) {
1426 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1427 ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
1428
1429 if (ctx->Color._LogicOpEnabled) {
1430 _swrast_logicop_rgba_span(ctx, rb, span);
1431 }
1432 else if (ctx->Color.BlendEnabled) {
1433 _swrast_blend_span(ctx, rb, span);
1434 }
1435
1436 if (colorMask != 0xffffffff) {
1437 _swrast_mask_rgba_span(ctx, rb, span);
1438 }
1439
1440 if (span->arrayMask & SPAN_XY) {
1441 /* array of pixel coords */
1442 ASSERT(rb->PutValues);
1443 rb->PutValues(ctx, rb, span->end,
1444 span->array->x, span->array->y,
1445 span->array->rgba, span->array->mask);
1446 }
1447 else {
1448 /* horizontal run of pixels */
1449 ASSERT(rb->PutRow);
1450 rb->PutRow(ctx, rb, span->end, span->x, span->y,
1451 span->array->rgba,
1452 span->writeAll ? NULL: span->array->mask);
1453 }
1454
1455 if (buf + 1 < numDrawBuffers) {
1456 /* restore original span values */
1457 _mesa_memcpy(span->array->rgba, rgbaSave,
1458 4 * span->end * sizeof(GLchan));
1459 }
1460 } /* for buf */
1461 } /* if output is written to */
1462 } /* for output */
1463
1464 end:
1465 /* restore these values before returning */
1466 span->interpMask = origInterpMask;
1467 span->arrayMask = origArrayMask;
1468 span->arrayAttribs = origArrayAttribs;
1469 span->array->ChanType = origChanType;
1470 span->array->rgba = origRgba;
1471 }
1472
1473
1474 /**
1475 * Read RGBA pixels from a renderbuffer. Clipping will be done to prevent
1476 * reading ouside the buffer's boundaries.
1477 * \param dstType datatype for returned colors
1478 * \param rgba the returned colors
1479 */
1480 void
1481 _swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1482 GLuint n, GLint x, GLint y, GLenum dstType,
1483 GLvoid *rgba)
1484 {
1485 const GLint bufWidth = (GLint) rb->Width;
1486 const GLint bufHeight = (GLint) rb->Height;
1487
1488 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1489 /* completely above, below, or right */
1490 /* XXX maybe leave rgba values undefined? */
1491 _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1492 }
1493 else {
1494 GLint skip, length;
1495 if (x < 0) {
1496 /* left edge clipping */
1497 skip = -x;
1498 length = (GLint) n - skip;
1499 if (length < 0) {
1500 /* completely left of window */
1501 return;
1502 }
1503 if (length > bufWidth) {
1504 length = bufWidth;
1505 }
1506 }
1507 else if ((GLint) (x + n) > bufWidth) {
1508 /* right edge clipping */
1509 skip = 0;
1510 length = bufWidth - x;
1511 if (length < 0) {
1512 /* completely to right of window */
1513 return;
1514 }
1515 }
1516 else {
1517 /* no clipping */
1518 skip = 0;
1519 length = (GLint) n;
1520 }
1521
1522 ASSERT(rb);
1523 ASSERT(rb->GetRow);
1524 ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
1525
1526 if (rb->DataType == dstType) {
1527 rb->GetRow(ctx, rb, length, x + skip, y,
1528 (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
1529 }
1530 else {
1531 GLuint temp[MAX_WIDTH * 4];
1532 rb->GetRow(ctx, rb, length, x + skip, y, temp);
1533 _mesa_convert_colors(rb->DataType, temp,
1534 dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
1535 length, NULL);
1536 }
1537 }
1538 }
1539
1540
1541 /**
1542 * Read CI pixels from a renderbuffer. Clipping will be done to prevent
1543 * reading ouside the buffer's boundaries.
1544 */
1545 void
1546 _swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1547 GLuint n, GLint x, GLint y, GLuint index[] )
1548 {
1549 const GLint bufWidth = (GLint) rb->Width;
1550 const GLint bufHeight = (GLint) rb->Height;
1551
1552 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1553 /* completely above, below, or right */
1554 _mesa_bzero(index, n * sizeof(GLuint));
1555 }
1556 else {
1557 GLint skip, length;
1558 if (x < 0) {
1559 /* left edge clipping */
1560 skip = -x;
1561 length = (GLint) n - skip;
1562 if (length < 0) {
1563 /* completely left of window */
1564 return;
1565 }
1566 if (length > bufWidth) {
1567 length = bufWidth;
1568 }
1569 }
1570 else if ((GLint) (x + n) > bufWidth) {
1571 /* right edge clipping */
1572 skip = 0;
1573 length = bufWidth - x;
1574 if (length < 0) {
1575 /* completely to right of window */
1576 return;
1577 }
1578 }
1579 else {
1580 /* no clipping */
1581 skip = 0;
1582 length = (GLint) n;
1583 }
1584
1585 ASSERT(rb->GetRow);
1586 ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1587
1588 if (rb->DataType == GL_UNSIGNED_BYTE) {
1589 GLubyte index8[MAX_WIDTH];
1590 GLint i;
1591 rb->GetRow(ctx, rb, length, x + skip, y, index8);
1592 for (i = 0; i < length; i++)
1593 index[skip + i] = index8[i];
1594 }
1595 else if (rb->DataType == GL_UNSIGNED_SHORT) {
1596 GLushort index16[MAX_WIDTH];
1597 GLint i;
1598 rb->GetRow(ctx, rb, length, x + skip, y, index16);
1599 for (i = 0; i < length; i++)
1600 index[skip + i] = index16[i];
1601 }
1602 else if (rb->DataType == GL_UNSIGNED_INT) {
1603 rb->GetRow(ctx, rb, length, x + skip, y, index + skip);
1604 }
1605 }
1606 }
1607
1608
1609 /**
1610 * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
1611 * reading values outside the buffer bounds.
1612 * We can use this for reading any format/type of renderbuffer.
1613 * \param valueSize is the size in bytes of each value (pixel) put into the
1614 * values array.
1615 */
1616 void
1617 _swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
1618 GLuint count, const GLint x[], const GLint y[],
1619 void *values, GLuint valueSize)
1620 {
1621 GLuint i, inCount = 0, inStart = 0;
1622
1623 for (i = 0; i < count; i++) {
1624 if (x[i] >= 0 && y[i] >= 0 &&
1625 x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
1626 /* inside */
1627 if (inCount == 0)
1628 inStart = i;
1629 inCount++;
1630 }
1631 else {
1632 if (inCount > 0) {
1633 /* read [inStart, inStart + inCount) */
1634 rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
1635 (GLubyte *) values + inStart * valueSize);
1636 inCount = 0;
1637 }
1638 }
1639 }
1640 if (inCount > 0) {
1641 /* read last values */
1642 rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
1643 (GLubyte *) values + inStart * valueSize);
1644 }
1645 }
1646
1647
1648 /**
1649 * Wrapper for gl_renderbuffer::PutRow() which does clipping.
1650 * \param valueSize size of each value (pixel) in bytes
1651 */
1652 void
1653 _swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1654 GLuint count, GLint x, GLint y,
1655 const GLvoid *values, GLuint valueSize)
1656 {
1657 GLint skip = 0;
1658
1659 if (y < 0 || y >= (GLint) rb->Height)
1660 return; /* above or below */
1661
1662 if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
1663 return; /* entirely left or right */
1664
1665 if ((GLint) (x + count) > (GLint) rb->Width) {
1666 /* right clip */
1667 GLint clip = x + count - rb->Width;
1668 count -= clip;
1669 }
1670
1671 if (x < 0) {
1672 /* left clip */
1673 skip = -x;
1674 x = 0;
1675 count -= skip;
1676 }
1677
1678 rb->PutRow(ctx, rb, count, x, y,
1679 (const GLubyte *) values + skip * valueSize, NULL);
1680 }
1681
1682
1683 /**
1684 * Wrapper for gl_renderbuffer::GetRow() which does clipping.
1685 * \param valueSize size of each value (pixel) in bytes
1686 */
1687 void
1688 _swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1689 GLuint count, GLint x, GLint y,
1690 GLvoid *values, GLuint valueSize)
1691 {
1692 GLint skip = 0;
1693
1694 if (y < 0 || y >= (GLint) rb->Height)
1695 return; /* above or below */
1696
1697 if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
1698 return; /* entirely left or right */
1699
1700 if (x + count > rb->Width) {
1701 /* right clip */
1702 GLint clip = x + count - rb->Width;
1703 count -= clip;
1704 }
1705
1706 if (x < 0) {
1707 /* left clip */
1708 skip = -x;
1709 x = 0;
1710 count -= skip;
1711 }
1712
1713 rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
1714 }
1715
1716
1717 /**
1718 * Get RGBA pixels from the given renderbuffer. Put the pixel colors into
1719 * the span's specular color arrays. The specular color arrays should no
1720 * longer be needed by time this function is called.
1721 * Used by blending, logicop and masking functions.
1722 * \return pointer to the colors we read.
1723 */
1724 void *
1725 _swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
1726 SWspan *span)
1727 {
1728 const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
1729 void *rbPixels;
1730
1731 /*
1732 * Point rbPixels to a temporary space (use specular color arrays).
1733 */
1734 rbPixels = span->array->attribs[FRAG_ATTRIB_COL1];
1735
1736 /* Get destination values from renderbuffer */
1737 if (span->arrayMask & SPAN_XY) {
1738 _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
1739 rbPixels, pixelSize);
1740 }
1741 else {
1742 _swrast_get_row(ctx, rb, span->end, span->x, span->y,
1743 rbPixels, pixelSize);
1744 }
1745
1746 return rbPixels;
1747 }