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