Major check-in of changes for GL_EXT_framebuffer_object extension.
[mesa.git] / src / mesa / swrast / s_span.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.3
4 *
5 * Copyright (C) 1999-2005 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
39 #include "s_atifragshader.h"
40 #include "s_alpha.h"
41 #include "s_blend.h"
42 #include "s_context.h"
43 #include "s_depth.h"
44 #include "s_fog.h"
45 #include "s_logic.h"
46 #include "s_masking.h"
47 #include "s_nvfragprog.h"
48 #include "s_span.h"
49 #include "s_stencil.h"
50 #include "s_texture.h"
51
52
53 /**
54 * Init span's Z interpolation values to the RasterPos Z.
55 * Used during setup for glDraw/CopyPixels.
56 */
57 void
58 _swrast_span_default_z( GLcontext *ctx, struct sw_span *span )
59 {
60 const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
61 if (ctx->Visual.depthBits <= 16)
62 span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
63 else
64 span->z = (GLint) (ctx->Current.RasterPos[2] * depthMax + 0.5F);
65 span->zStep = 0;
66 span->interpMask |= SPAN_Z;
67 }
68
69
70 /**
71 * Init span's fog interpolation values to the RasterPos fog.
72 * Used during setup for glDraw/CopyPixels.
73 */
74 void
75 _swrast_span_default_fog( GLcontext *ctx, struct sw_span *span )
76 {
77 span->fog = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
78 span->fogStep = span->dfogdx = span->dfogdy = 0.0F;
79 span->interpMask |= SPAN_FOG;
80 }
81
82
83 /**
84 * Init span's rgba or index interpolation values to the RasterPos color.
85 * Used during setup for glDraw/CopyPixels.
86 */
87 void
88 _swrast_span_default_color( GLcontext *ctx, struct sw_span *span )
89 {
90 if (ctx->Visual.rgbMode) {
91 GLchan r, g, b, a;
92 UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
93 UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
94 UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
95 UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
96 #if CHAN_TYPE == GL_FLOAT
97 span->red = r;
98 span->green = g;
99 span->blue = b;
100 span->alpha = a;
101 #else
102 span->red = IntToFixed(r);
103 span->green = IntToFixed(g);
104 span->blue = IntToFixed(b);
105 span->alpha = IntToFixed(a);
106 #endif
107 span->redStep = 0;
108 span->greenStep = 0;
109 span->blueStep = 0;
110 span->alphaStep = 0;
111 span->interpMask |= SPAN_RGBA;
112 }
113 else {
114 span->index = FloatToFixed(ctx->Current.RasterIndex);
115 span->indexStep = 0;
116 span->interpMask |= SPAN_INDEX;
117 }
118 }
119
120
121 /**
122 * Init span's texcoord interpolation values to the RasterPos texcoords.
123 * Used during setup for glDraw/CopyPixels.
124 */
125 void
126 _swrast_span_default_texcoords( GLcontext *ctx, struct sw_span *span )
127 {
128 GLuint i;
129 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
130 const GLfloat *tc = ctx->Current.RasterTexCoords[i];
131 if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled) {
132 COPY_4V(span->tex[i], tc);
133 }
134 else if (tc[3] > 0.0F) {
135 /* use (s/q, t/q, r/q, 1) */
136 span->tex[i][0] = tc[0] / tc[3];
137 span->tex[i][1] = tc[1] / tc[3];
138 span->tex[i][2] = tc[2] / tc[3];
139 span->tex[i][3] = 1.0;
140 }
141 else {
142 ASSIGN_4V(span->tex[i], 0.0F, 0.0F, 0.0F, 1.0F);
143 }
144 ASSIGN_4V(span->texStepX[i], 0.0F, 0.0F, 0.0F, 0.0F);
145 ASSIGN_4V(span->texStepY[i], 0.0F, 0.0F, 0.0F, 0.0F);
146 }
147 span->interpMask |= SPAN_TEXTURE;
148 }
149
150
151 /* Fill in the span.color.rgba array from the interpolation values */
152 static void
153 interpolate_colors(GLcontext *ctx, struct sw_span *span)
154 {
155 const GLuint n = span->end;
156 GLchan (*rgba)[4] = span->array->rgba;
157 GLuint i;
158 (void) ctx;
159
160 ASSERT((span->interpMask & SPAN_RGBA) &&
161 !(span->arrayMask & SPAN_RGBA));
162
163 if (span->interpMask & SPAN_FLAT) {
164 /* constant color */
165 GLchan color[4];
166 color[RCOMP] = FixedToChan(span->red);
167 color[GCOMP] = FixedToChan(span->green);
168 color[BCOMP] = FixedToChan(span->blue);
169 color[ACOMP] = FixedToChan(span->alpha);
170 for (i = 0; i < n; i++) {
171 COPY_CHAN4(span->array->rgba[i], color);
172 }
173 }
174 else {
175 /* interpolate */
176 #if CHAN_TYPE == GL_FLOAT
177 GLfloat r = span->red;
178 GLfloat g = span->green;
179 GLfloat b = span->blue;
180 GLfloat a = span->alpha;
181 const GLfloat dr = span->redStep;
182 const GLfloat dg = span->greenStep;
183 const GLfloat db = span->blueStep;
184 const GLfloat da = span->alphaStep;
185 #else
186 GLfixed r = span->red;
187 GLfixed g = span->green;
188 GLfixed b = span->blue;
189 GLfixed a = span->alpha;
190 const GLint dr = span->redStep;
191 const GLint dg = span->greenStep;
192 const GLint db = span->blueStep;
193 const GLint da = span->alphaStep;
194 #endif
195 for (i = 0; i < n; i++) {
196 rgba[i][RCOMP] = FixedToChan(r);
197 rgba[i][GCOMP] = FixedToChan(g);
198 rgba[i][BCOMP] = FixedToChan(b);
199 rgba[i][ACOMP] = FixedToChan(a);
200 r += dr;
201 g += dg;
202 b += db;
203 a += da;
204 }
205 }
206 span->arrayMask |= SPAN_RGBA;
207 }
208
209
210 /* Fill in the span.color.index array from the interpolation values */
211 static void
212 interpolate_indexes(GLcontext *ctx, struct sw_span *span)
213 {
214 GLfixed index = span->index;
215 const GLint indexStep = span->indexStep;
216 const GLuint n = span->end;
217 GLuint *indexes = span->array->index;
218 GLuint i;
219 (void) ctx;
220 ASSERT((span->interpMask & SPAN_INDEX) &&
221 !(span->arrayMask & SPAN_INDEX));
222
223 if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
224 /* constant color */
225 index = FixedToInt(index);
226 for (i = 0; i < n; i++) {
227 indexes[i] = index;
228 }
229 }
230 else {
231 /* interpolate */
232 for (i = 0; i < n; i++) {
233 indexes[i] = FixedToInt(index);
234 index += indexStep;
235 }
236 }
237 span->arrayMask |= SPAN_INDEX;
238 span->interpMask &= ~SPAN_INDEX;
239 }
240
241
242 /* Fill in the span.->array->spec array from the interpolation values */
243 static void
244 interpolate_specular(GLcontext *ctx, struct sw_span *span)
245 {
246 (void) ctx;
247 if (span->interpMask & SPAN_FLAT) {
248 /* constant color */
249 const GLchan r = FixedToChan(span->specRed);
250 const GLchan g = FixedToChan(span->specGreen);
251 const GLchan b = FixedToChan(span->specBlue);
252 GLuint i;
253 for (i = 0; i < span->end; i++) {
254 span->array->spec[i][RCOMP] = r;
255 span->array->spec[i][GCOMP] = g;
256 span->array->spec[i][BCOMP] = b;
257 }
258 }
259 else {
260 /* interpolate */
261 #if CHAN_TYPE == GL_FLOAT
262 GLfloat r = span->specRed;
263 GLfloat g = span->specGreen;
264 GLfloat b = span->specBlue;
265 #else
266 GLfixed r = span->specRed;
267 GLfixed g = span->specGreen;
268 GLfixed b = span->specBlue;
269 #endif
270 GLuint i;
271 for (i = 0; i < span->end; i++) {
272 span->array->spec[i][RCOMP] = FixedToChan(r);
273 span->array->spec[i][GCOMP] = FixedToChan(g);
274 span->array->spec[i][BCOMP] = FixedToChan(b);
275 r += span->specRedStep;
276 g += span->specGreenStep;
277 b += span->specBlueStep;
278 }
279 }
280 span->arrayMask |= SPAN_SPEC;
281 }
282
283
284 /* Fill in the span.array.fog values from the interpolation values */
285 static void
286 interpolate_fog(const GLcontext *ctx, struct sw_span *span)
287 {
288 GLfloat *fog = span->array->fog;
289 const GLfloat fogStep = span->fogStep;
290 GLfloat fogCoord = span->fog;
291 const GLuint haveW = (span->interpMask & SPAN_W);
292 const GLfloat wStep = haveW ? span->dwdx : 0.0F;
293 GLfloat w = haveW ? span->w : 1.0F;
294 GLuint i;
295 for (i = 0; i < span->end; i++) {
296 fog[i] = fogCoord / w;
297 fogCoord += fogStep;
298 w += wStep;
299 }
300 span->arrayMask |= SPAN_FOG;
301 }
302
303
304 /* Fill in the span.zArray array from the interpolation values */
305 void
306 _swrast_span_interpolate_z( const GLcontext *ctx, struct sw_span *span )
307 {
308 const GLuint n = span->end;
309 GLuint i;
310
311 ASSERT((span->interpMask & SPAN_Z) &&
312 !(span->arrayMask & SPAN_Z));
313
314 if (ctx->Visual.depthBits <= 16) {
315 GLfixed zval = span->z;
316 GLdepth *z = span->array->z;
317 for (i = 0; i < n; i++) {
318 z[i] = FixedToInt(zval);
319 zval += span->zStep;
320 }
321 }
322 else {
323 /* Deep Z buffer, no fixed->int shift */
324 GLfixed zval = span->z;
325 GLdepth *z = span->array->z;
326 for (i = 0; i < n; i++) {
327 z[i] = zval;
328 zval += span->zStep;
329 }
330 }
331 span->arrayMask |= SPAN_Z;
332 }
333
334
335 /*
336 * This the ideal solution, as given in the OpenGL spec.
337 */
338 #if 0
339 static GLfloat
340 compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
341 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
342 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
343 {
344 GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
345 GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
346 GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
347 GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
348 GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
349 GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
350 GLfloat rho = MAX2(x, y);
351 GLfloat lambda = LOG2(rho);
352 return lambda;
353 }
354 #endif
355
356
357 /*
358 * This is a faster approximation
359 */
360 GLfloat
361 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
362 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
363 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
364 {
365 GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
366 GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
367 GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
368 GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
369 GLfloat maxU, maxV, rho, lambda;
370 dsdx2 = FABSF(dsdx2);
371 dsdy2 = FABSF(dsdy2);
372 dtdx2 = FABSF(dtdx2);
373 dtdy2 = FABSF(dtdy2);
374 maxU = MAX2(dsdx2, dsdy2) * texW;
375 maxV = MAX2(dtdx2, dtdy2) * texH;
376 rho = MAX2(maxU, maxV);
377 lambda = LOG2(rho);
378 return lambda;
379 }
380
381
382 /**
383 * Fill in the span.texcoords array from the interpolation values.
384 * Note: in the places where we divide by Q (or mult by invQ) we're
385 * really doing two things: perspective correction and texcoord
386 * projection. Remember, for texcoord (s,t,r,q) we need to index
387 * texels with (s/q, t/q, r/q).
388 * If we're using a fragment program, we never do the division
389 * for texcoord projection. That's done by the TXP instruction
390 * or user-written code.
391 */
392 static void
393 interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
394 {
395 ASSERT(span->interpMask & SPAN_TEXTURE);
396 ASSERT(!(span->arrayMask & SPAN_TEXTURE));
397
398 if (ctx->Texture._EnabledCoordUnits > 1) {
399 /* multitexture */
400 GLuint u;
401 span->arrayMask |= SPAN_TEXTURE;
402 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
403 if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
404 const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
405 GLfloat texW, texH;
406 GLboolean needLambda;
407 if (obj) {
408 const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
409 needLambda = (obj->MinFilter != obj->MagFilter)
410 || ctx->FragmentProgram._Active;
411 texW = img->WidthScale;
412 texH = img->HeightScale;
413 }
414 else {
415 /* using a fragment program */
416 texW = 1.0;
417 texH = 1.0;
418 needLambda = GL_FALSE;
419 }
420 if (needLambda) {
421 GLfloat (*texcoord)[4] = span->array->texcoords[u];
422 GLfloat *lambda = span->array->lambda[u];
423 const GLfloat dsdx = span->texStepX[u][0];
424 const GLfloat dsdy = span->texStepY[u][0];
425 const GLfloat dtdx = span->texStepX[u][1];
426 const GLfloat dtdy = span->texStepY[u][1];
427 const GLfloat drdx = span->texStepX[u][2];
428 const GLfloat dqdx = span->texStepX[u][3];
429 const GLfloat dqdy = span->texStepY[u][3];
430 GLfloat s = span->tex[u][0];
431 GLfloat t = span->tex[u][1];
432 GLfloat r = span->tex[u][2];
433 GLfloat q = span->tex[u][3];
434 GLuint i;
435 if (ctx->FragmentProgram._Active) {
436 /* do perspective correction but don't divide s, t, r by q */
437 const GLfloat dwdx = span->dwdx;
438 GLfloat w = span->w;
439 for (i = 0; i < span->end; i++) {
440 const GLfloat invW = 1.0F / w;
441 texcoord[i][0] = s * invW;
442 texcoord[i][1] = t * invW;
443 texcoord[i][2] = r * invW;
444 texcoord[i][3] = q * invW;
445 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
446 dqdx, dqdy, texW, texH,
447 s, t, q, invW);
448 s += dsdx;
449 t += dtdx;
450 r += drdx;
451 q += dqdx;
452 w += dwdx;
453 }
454
455 }
456 else {
457 for (i = 0; i < span->end; i++) {
458 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
459 texcoord[i][0] = s * invQ;
460 texcoord[i][1] = t * invQ;
461 texcoord[i][2] = r * invQ;
462 texcoord[i][3] = q;
463 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
464 dqdx, dqdy, texW, texH,
465 s, t, q, invQ);
466 s += dsdx;
467 t += dtdx;
468 r += drdx;
469 q += dqdx;
470 }
471 }
472 span->arrayMask |= SPAN_LAMBDA;
473 }
474 else {
475 GLfloat (*texcoord)[4] = span->array->texcoords[u];
476 GLfloat *lambda = span->array->lambda[u];
477 const GLfloat dsdx = span->texStepX[u][0];
478 const GLfloat dtdx = span->texStepX[u][1];
479 const GLfloat drdx = span->texStepX[u][2];
480 const GLfloat dqdx = span->texStepX[u][3];
481 GLfloat s = span->tex[u][0];
482 GLfloat t = span->tex[u][1];
483 GLfloat r = span->tex[u][2];
484 GLfloat q = span->tex[u][3];
485 GLuint i;
486 if (ctx->FragmentProgram._Active) {
487 /* do perspective correction but don't divide s, t, r by q */
488 const GLfloat dwdx = span->dwdx;
489 GLfloat w = span->w;
490 for (i = 0; i < span->end; i++) {
491 const GLfloat invW = 1.0F / w;
492 texcoord[i][0] = s * invW;
493 texcoord[i][1] = t * invW;
494 texcoord[i][2] = r * invW;
495 texcoord[i][3] = q * invW;
496 lambda[i] = 0.0;
497 s += dsdx;
498 t += dtdx;
499 r += drdx;
500 q += dqdx;
501 w += dwdx;
502 }
503 }
504 else if (dqdx == 0.0F) {
505 /* Ortho projection or polygon's parallel to window X axis */
506 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
507 for (i = 0; i < span->end; i++) {
508 texcoord[i][0] = s * invQ;
509 texcoord[i][1] = t * invQ;
510 texcoord[i][2] = r * invQ;
511 texcoord[i][3] = q;
512 lambda[i] = 0.0;
513 s += dsdx;
514 t += dtdx;
515 r += drdx;
516 }
517 }
518 else {
519 for (i = 0; i < span->end; i++) {
520 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
521 texcoord[i][0] = s * invQ;
522 texcoord[i][1] = t * invQ;
523 texcoord[i][2] = r * invQ;
524 texcoord[i][3] = q;
525 lambda[i] = 0.0;
526 s += dsdx;
527 t += dtdx;
528 r += drdx;
529 q += dqdx;
530 }
531 }
532 } /* lambda */
533 } /* if */
534 } /* for */
535 }
536 else {
537 /* single texture */
538 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
539 GLfloat texW, texH;
540 GLboolean needLambda;
541 if (obj) {
542 const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
543 needLambda = (obj->MinFilter != obj->MagFilter)
544 || ctx->FragmentProgram._Active;
545 texW = (GLfloat) img->WidthScale;
546 texH = (GLfloat) img->HeightScale;
547 }
548 else {
549 needLambda = GL_FALSE;
550 texW = texH = 1.0;
551 }
552 span->arrayMask |= SPAN_TEXTURE;
553 if (needLambda) {
554 /* just texture unit 0, with lambda */
555 GLfloat (*texcoord)[4] = span->array->texcoords[0];
556 GLfloat *lambda = span->array->lambda[0];
557 const GLfloat dsdx = span->texStepX[0][0];
558 const GLfloat dsdy = span->texStepY[0][0];
559 const GLfloat dtdx = span->texStepX[0][1];
560 const GLfloat dtdy = span->texStepY[0][1];
561 const GLfloat drdx = span->texStepX[0][2];
562 const GLfloat dqdx = span->texStepX[0][3];
563 const GLfloat dqdy = span->texStepY[0][3];
564 GLfloat s = span->tex[0][0];
565 GLfloat t = span->tex[0][1];
566 GLfloat r = span->tex[0][2];
567 GLfloat q = span->tex[0][3];
568 GLuint i;
569 if (ctx->FragmentProgram._Active) {
570 /* do perspective correction but don't divide s, t, r by q */
571 const GLfloat dwdx = span->dwdx;
572 GLfloat w = span->w;
573 for (i = 0; i < span->end; i++) {
574 const GLfloat invW = 1.0F / w;
575 texcoord[i][0] = s * invW;
576 texcoord[i][1] = t * invW;
577 texcoord[i][2] = r * invW;
578 texcoord[i][3] = q * invW;
579 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
580 dqdx, dqdy, texW, texH,
581 s, t, q, invW);
582 s += dsdx;
583 t += dtdx;
584 r += drdx;
585 q += dqdx;
586 w += dwdx;
587 }
588 }
589 else {
590 /* tex.c */
591 for (i = 0; i < span->end; i++) {
592 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
593 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
594 dqdx, dqdy, texW, texH,
595 s, t, q, invQ);
596 texcoord[i][0] = s * invQ;
597 texcoord[i][1] = t * invQ;
598 texcoord[i][2] = r * invQ;
599 texcoord[i][3] = q;
600 s += dsdx;
601 t += dtdx;
602 r += drdx;
603 q += dqdx;
604 }
605 }
606 span->arrayMask |= SPAN_LAMBDA;
607 }
608 else {
609 /* just texture 0, without lambda */
610 GLfloat (*texcoord)[4] = span->array->texcoords[0];
611 const GLfloat dsdx = span->texStepX[0][0];
612 const GLfloat dtdx = span->texStepX[0][1];
613 const GLfloat drdx = span->texStepX[0][2];
614 const GLfloat dqdx = span->texStepX[0][3];
615 GLfloat s = span->tex[0][0];
616 GLfloat t = span->tex[0][1];
617 GLfloat r = span->tex[0][2];
618 GLfloat q = span->tex[0][3];
619 GLuint i;
620 if (ctx->FragmentProgram._Active) {
621 /* do perspective correction but don't divide s, t, r by q */
622 const GLfloat dwdx = span->dwdx;
623 GLfloat w = span->w;
624 for (i = 0; i < span->end; i++) {
625 const GLfloat invW = 1.0F / w;
626 texcoord[i][0] = s * invW;
627 texcoord[i][1] = t * invW;
628 texcoord[i][2] = r * invW;
629 texcoord[i][3] = q * invW;
630 s += dsdx;
631 t += dtdx;
632 r += drdx;
633 q += dqdx;
634 w += dwdx;
635 }
636 }
637 else if (dqdx == 0.0F) {
638 /* Ortho projection or polygon's parallel to window X axis */
639 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
640 for (i = 0; i < span->end; i++) {
641 texcoord[i][0] = s * invQ;
642 texcoord[i][1] = t * invQ;
643 texcoord[i][2] = r * invQ;
644 texcoord[i][3] = q;
645 s += dsdx;
646 t += dtdx;
647 r += drdx;
648 }
649 }
650 else {
651 for (i = 0; i < span->end; i++) {
652 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
653 texcoord[i][0] = s * invQ;
654 texcoord[i][1] = t * invQ;
655 texcoord[i][2] = r * invQ;
656 texcoord[i][3] = q;
657 s += dsdx;
658 t += dtdx;
659 r += drdx;
660 q += dqdx;
661 }
662 }
663 }
664 }
665 }
666
667
668 /**
669 * Apply the current polygon stipple pattern to a span of pixels.
670 */
671 static void
672 stipple_polygon_span( GLcontext *ctx, struct sw_span *span )
673 {
674 const GLuint highbit = 0x80000000;
675 const GLuint stipple = ctx->PolygonStipple[span->y % 32];
676 GLubyte *mask = span->array->mask;
677 GLuint i, m;
678
679 ASSERT(ctx->Polygon.StippleFlag);
680 ASSERT((span->arrayMask & SPAN_XY) == 0);
681
682 m = highbit >> (GLuint) (span->x % 32);
683
684 for (i = 0; i < span->end; i++) {
685 if ((m & stipple) == 0) {
686 mask[i] = 0;
687 }
688 m = m >> 1;
689 if (m == 0) {
690 m = highbit;
691 }
692 }
693 span->writeAll = GL_FALSE;
694 }
695
696
697 /**
698 * Clip a pixel span to the current buffer/window boundaries:
699 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
700 * window clipping and scissoring.
701 * Return: GL_TRUE some pixels still visible
702 * GL_FALSE nothing visible
703 */
704 static GLuint
705 clip_span( GLcontext *ctx, struct sw_span *span )
706 {
707 const GLint xmin = ctx->DrawBuffer->_Xmin;
708 const GLint xmax = ctx->DrawBuffer->_Xmax;
709 const GLint ymin = ctx->DrawBuffer->_Ymin;
710 const GLint ymax = ctx->DrawBuffer->_Ymax;
711
712 if (span->arrayMask & SPAN_XY) {
713 /* arrays of x/y pixel coords */
714 const GLint *x = span->array->x;
715 const GLint *y = span->array->y;
716 const GLint n = span->end;
717 GLubyte *mask = span->array->mask;
718 GLint i;
719 if (span->arrayMask & SPAN_MASK) {
720 /* note: using & intead of && to reduce branches */
721 for (i = 0; i < n; i++) {
722 mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
723 & (y[i] >= ymin) & (y[i] < ymax);
724 }
725 }
726 else {
727 /* note: using & intead of && to reduce branches */
728 for (i = 0; i < n; i++) {
729 mask[i] = (x[i] >= xmin) & (x[i] < xmax)
730 & (y[i] >= ymin) & (y[i] < ymax);
731 }
732 }
733 return GL_TRUE; /* some pixels visible */
734 }
735 else {
736 /* horizontal span of pixels */
737 const GLint x = span->x;
738 const GLint y = span->y;
739 const GLint n = span->end;
740
741 /* Trivial rejection tests */
742 if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
743 span->end = 0;
744 return GL_FALSE; /* all pixels clipped */
745 }
746
747 /* Clip to the left */
748 if (x < xmin) {
749 ASSERT(x + n > xmin);
750 span->writeAll = GL_FALSE;
751 _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
752 }
753
754 /* Clip to right */
755 if (x + n > xmax) {
756 ASSERT(x < xmax);
757 span->end = xmax - x;
758 }
759
760 return GL_TRUE; /* some pixels visible */
761 }
762 }
763
764
765 /**
766 * Apply all the per-fragment opertions to a span of color index fragments
767 * and write them to the enabled color drawbuffers.
768 * The 'span' parameter can be considered to be const. Note that
769 * span->interpMask and span->arrayMask may be changed but will be restored
770 * to their original values before returning.
771 */
772 void
773 _swrast_write_index_span( GLcontext *ctx, struct sw_span *span)
774 {
775 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
776 const struct gl_framebuffer *fb = ctx->DrawBuffer;
777 const GLuint output = 0;
778 const GLuint origInterpMask = span->interpMask;
779 const GLuint origArrayMask = span->arrayMask;
780 GLuint buf;
781
782 ASSERT(span->end <= MAX_WIDTH);
783 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
784 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
785 ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
786 ASSERT((span->interpMask & span->arrayMask) == 0);
787
788 if (span->arrayMask & SPAN_MASK) {
789 /* mask was initialized by caller, probably glBitmap */
790 span->writeAll = GL_FALSE;
791 }
792 else {
793 _mesa_memset(span->array->mask, 1, span->end);
794 span->writeAll = GL_TRUE;
795 }
796
797 /* Clipping */
798 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
799 if (!clip_span(ctx, span)) {
800 return;
801 }
802 }
803
804 /* Depth bounds test */
805 if (ctx->Depth.BoundsTest && ctx->Visual.depthBits > 0) {
806 if (!_swrast_depth_bounds_test(ctx, span)) {
807 return;
808 }
809 }
810
811 #ifdef DEBUG
812 /* Make sure all fragments are within window bounds */
813 if (span->arrayMask & SPAN_XY) {
814 GLuint i;
815 for (i = 0; i < span->end; i++) {
816 if (span->array->mask[i]) {
817 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
818 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
819 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
820 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
821 }
822 }
823 }
824 #endif
825
826 /* Polygon Stippling */
827 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
828 stipple_polygon_span(ctx, span);
829 }
830
831 /* Stencil and Z testing */
832 if (ctx->Depth.Test || ctx->Stencil.Enabled) {
833 if (span->interpMask & SPAN_Z)
834 _swrast_span_interpolate_z(ctx, span);
835
836 if (ctx->Stencil.Enabled) {
837 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
838 span->arrayMask = origArrayMask;
839 return;
840 }
841 }
842 else {
843 ASSERT(ctx->Depth.Test);
844 if (!_swrast_depth_test_span(ctx, span)) {
845 span->interpMask = origInterpMask;
846 span->arrayMask = origArrayMask;
847 return;
848 }
849 }
850 }
851
852 /* if we get here, something passed the depth test */
853 if (ctx->Depth.OcclusionTest) {
854 ctx->OcclusionResult = GL_TRUE;
855 }
856
857 #if FEATURE_ARB_occlusion_query
858 if (ctx->Occlusion.Active) {
859 /* update count of 'passed' fragments */
860 GLuint i;
861 for (i = 0; i < span->end; i++)
862 ctx->Occlusion.PassedCounter += span->array->mask[i];
863 }
864 #endif
865
866 /* we have to wait until after occlusion to do this test */
867 if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
868 /* write no pixels */
869 span->arrayMask = origArrayMask;
870 return;
871 }
872
873 /* Interpolate the color indexes if needed */
874 if (ctx->Fog.Enabled ||
875 ctx->Color.IndexLogicOpEnabled ||
876 ctx->Color.IndexMask != 0xffffffff ||
877 (span->arrayMask & SPAN_COVERAGE)) {
878 if (span->interpMask & SPAN_INDEX) {
879 interpolate_indexes(ctx, span);
880 }
881 }
882
883 /* Fog */
884 if (ctx->Fog.Enabled) {
885 _swrast_fog_ci_span(ctx, span);
886 }
887
888 /* Antialias coverage application */
889 if (span->arrayMask & SPAN_COVERAGE) {
890 const GLfloat *coverage = span->array->coverage;
891 GLuint *index = span->array->index;
892 GLuint i;
893 for (i = 0; i < span->end; i++) {
894 ASSERT(coverage[i] < 16);
895 index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
896 }
897 }
898
899 /* Loop over drawing buffers */
900 for (buf = 0; buf < fb->_NumColorDrawBuffers[output]; buf++) {
901 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
902 GLuint indexTemp[MAX_WIDTH], *index32;
903
904 ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
905
906 if (ctx->Color.IndexLogicOpEnabled ||
907 ctx->Color.IndexMask != 0xffffffff) {
908 /* make copy of incoming indexes */
909 MEMCPY(indexTemp, span->array->index, span->end * sizeof(GLuint));
910
911 if (ctx->Color.IndexLogicOpEnabled) {
912 _swrast_logicop_ci_span(ctx, rb, span, indexTemp);
913 }
914
915 if (ctx->Color.IndexMask != 0xffffffff) {
916 _swrast_mask_ci_span(ctx, rb, span, indexTemp);
917 }
918 index32 = indexTemp;
919 }
920 else {
921 index32 = span->array->index;
922 }
923
924 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
925 /* all fragments have same color index */
926 GLubyte index8;
927 GLushort index16;
928 GLuint index32;
929 void *value;
930
931 if (rb->DataType == GL_UNSIGNED_BYTE) {
932 index8 = FixedToInt(span->index);
933 value = &index8;
934 }
935 else if (rb->DataType == GL_UNSIGNED_SHORT) {
936 index16 = FixedToInt(span->index);
937 value = &index16;
938 }
939 else {
940 ASSERT(rb->DataType == GL_UNSIGNED_INT);
941 index32 = FixedToInt(span->index);
942 value = &index32;
943 }
944
945 if (span->arrayMask & SPAN_XY) {
946 rb->PutMonoValues(ctx, rb, span->end, span->array->x,
947 span->array->y, value, span->array->mask);
948 }
949 else {
950 rb->PutMonoRow(ctx, rb, span->end, span->x, span->y,
951 value, span->array->mask);
952 }
953 }
954 else {
955 /* each fragment is a different color */
956 GLubyte index8[MAX_WIDTH];
957 GLushort index16[MAX_WIDTH];
958 void *values;
959
960 if (rb->DataType == GL_UNSIGNED_BYTE) {
961 GLuint k;
962 for (k = 0; k < span->end; k++) {
963 index8[k] = (GLubyte) index32[k];
964 }
965 values = index8;
966 }
967 else if (rb->DataType == GL_UNSIGNED_SHORT) {
968 GLuint k;
969 for (k = 0; k < span->end; k++) {
970 index16[k] = (GLushort) index32[k];
971 }
972 values = index16;
973 }
974 else {
975 ASSERT(rb->DataType == GL_UNSIGNED_INT);
976 values = index32;
977 }
978
979 if (span->arrayMask & SPAN_XY) {
980 rb->PutValues(ctx, rb, span->end, span->array->x, span->array->y,
981 values, span->array->mask);
982 }
983 else {
984 rb->PutRow(ctx, rb, span->end, span->x, span->y,
985 values, span->array->mask);
986 }
987 }
988 }
989
990 #if OLD_RENDERBUFFER
991 /* restore default dest buffer */
992 _swrast_use_draw_buffer(ctx);
993 #endif
994
995 span->interpMask = origInterpMask;
996 span->arrayMask = origArrayMask;
997 }
998
999
1000 /**
1001 * Add specular color to base color. This is used only when
1002 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1003 */
1004 static void
1005 add_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] )
1006 {
1007 GLuint i;
1008 for (i = 0; i < n; i++) {
1009 #if CHAN_TYPE == GL_FLOAT
1010 /* no clamping */
1011 rgba[i][RCOMP] += specular[i][RCOMP];
1012 rgba[i][GCOMP] += specular[i][GCOMP];
1013 rgba[i][BCOMP] += specular[i][BCOMP];
1014 #else
1015 GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
1016 GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
1017 GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
1018 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1019 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1020 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1021 #endif
1022 }
1023 }
1024
1025
1026 /**
1027 * XXX merge this code into the _swrast_write_rgba_span() routine!
1028 *
1029 * Draw to more than one RGBA color buffer (or none).
1030 * All fragment operations, up to (but not) blending/logicop should
1031 * have been done first.
1032 */
1033 static void
1034 multi_write_rgba_span( GLcontext *ctx, struct sw_span *span )
1035 {
1036 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1037 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1038 struct gl_framebuffer *fb = ctx->DrawBuffer;
1039 const GLuint output = 0;
1040 GLuint i;
1041
1042 ASSERT(span->end < MAX_WIDTH);
1043 ASSERT(colorMask != 0x0);
1044
1045 for (i = 0; i < fb->_NumColorDrawBuffers[output]; i++) {
1046 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][i];
1047 GLchan rgbaTmp[MAX_WIDTH][4];
1048
1049 #if OLD_RENDERBUFFER /* obsolete code */
1050 GLuint bufferBit = fb->_ColorDrawBit[output][i];
1051 /* Set the current read/draw buffer */
1052 swrast->CurrentBufferBit = bufferBit;
1053 (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
1054 #endif
1055
1056 /* make copy of incoming colors */
1057 MEMCPY( rgbaTmp, span->array->rgba, 4 * span->end * sizeof(GLchan) );
1058
1059 if (ctx->Color._LogicOpEnabled) {
1060 _swrast_logicop_rgba_span(ctx, rb, span, rgbaTmp);
1061 }
1062 else if (ctx->Color.BlendEnabled) {
1063 _swrast_blend_span(ctx, rb, span, rgbaTmp);
1064 }
1065
1066 if (colorMask != 0xffffffff) {
1067 _swrast_mask_rgba_span(ctx, rb, span, rgbaTmp);
1068 }
1069
1070 if (span->arrayMask & SPAN_XY) {
1071 /* array of pixel coords */
1072 if (rb->PutValues) {
1073 rb->PutValues(ctx, rb, span->end, span->array->x,
1074 span->array->y, rgbaTmp, span->array->mask);
1075 }
1076 #if OLD_RENDERBUFFER
1077 else {
1078 swrast->Driver.WriteRGBAPixels(ctx, rb, span->end,
1079 span->array->x, span->array->y,
1080 (const GLchan (*)[4]) rgbaTmp,
1081 span->array->mask);
1082 }
1083 #endif
1084 }
1085 else {
1086 /* horizontal run of pixels */
1087 if (rb->PutRow) {
1088 rb->PutRow(ctx, rb, span->end, span->x, span->y, rgbaTmp,
1089 span->array->mask);
1090 }
1091 #if OLD_RENDERBUFFER
1092 else {
1093 swrast->Driver.WriteRGBASpan(ctx, rb, span->end, span->x, span->y,
1094 (const GLchan (*)[4]) rgbaTmp,
1095 span->array->mask);
1096 }
1097 #endif
1098 }
1099 }
1100
1101 #if OLD_RENDERBUFFER
1102 /* restore default dest buffer */
1103 _swrast_use_draw_buffer(ctx);
1104 #endif
1105 }
1106
1107
1108 /**
1109 * Apply all the per-fragment operations to a span.
1110 * This now includes texturing (_swrast_write_texture_span() is history).
1111 * This function may modify any of the array values in the span.
1112 * span->interpMask and span->arrayMask may be changed but will be restored
1113 * to their original values before returning.
1114 */
1115 void
1116 _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
1117 {
1118 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1119 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1120 const GLuint origInterpMask = span->interpMask;
1121 const GLuint origArrayMask = span->arrayMask;
1122
1123 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
1124 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
1125 ASSERT(span->end <= MAX_WIDTH);
1126 ASSERT((span->interpMask & span->arrayMask) == 0);
1127
1128 /*
1129 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__,
1130 span->interpMask, span->arrayMask);
1131 */
1132
1133 if (span->arrayMask & SPAN_MASK) {
1134 /* mask was initialized by caller, probably glBitmap */
1135 span->writeAll = GL_FALSE;
1136 }
1137 else {
1138 _mesa_memset(span->array->mask, 1, span->end);
1139 span->writeAll = GL_TRUE;
1140 }
1141
1142 /* Clip to window/scissor box */
1143 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1144 if (!clip_span(ctx, span)) {
1145 return;
1146 }
1147 }
1148
1149 #ifdef DEBUG
1150 /* Make sure all fragments are within window bounds */
1151 if (span->arrayMask & SPAN_XY) {
1152 GLuint i;
1153 for (i = 0; i < span->end; i++) {
1154 if (span->array->mask[i]) {
1155 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
1156 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
1157 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
1158 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1159 }
1160 }
1161 }
1162 #endif
1163
1164 /* Polygon Stippling */
1165 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1166 stipple_polygon_span(ctx, span);
1167 }
1168
1169 /* Interpolate texcoords? */
1170 if (ctx->Texture._EnabledCoordUnits
1171 && (span->interpMask & SPAN_TEXTURE)
1172 && (span->arrayMask & SPAN_TEXTURE) == 0) {
1173 interpolate_texcoords(ctx, span);
1174 }
1175
1176 /* If the alpha test is enabled, we have to compute the fragment colors
1177 * at this point and do the alpha test.
1178 * Else, if alpha test is not enabled, we'll try to defer fragment
1179 * color computation (by interpolation, texture mapping, fragment program)
1180 * until after the Z/stencil tests in the hope that many fragments will
1181 * get culled, leaving less work to do.
1182 */
1183 if (ctx->Color.AlphaEnabled) {
1184 /* Now we need the rgba array, fill it in if needed */
1185 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1186 interpolate_colors(ctx, span);
1187
1188 if (span->interpMask & SPAN_SPEC)
1189 interpolate_specular(ctx, span);
1190
1191 if (span->interpMask & SPAN_FOG)
1192 interpolate_fog(ctx, span);
1193
1194 /* Compute fragment colors with fragment program or texture lookups */
1195 if (ctx->FragmentProgram._Active)
1196 /* XXX interpolate depth values here??? */
1197 _swrast_exec_fragment_program( ctx, span );
1198 else if (ctx->ATIFragmentShader._Enabled)
1199 _swrast_exec_fragment_shader( ctx, span );
1200 else if (ctx->Texture._EnabledUnits)
1201 _swrast_texture_span( ctx, span );
1202
1203 /* Do the alpha test */
1204 if (!_swrast_alpha_test(ctx, span)) {
1205 span->arrayMask = origArrayMask;
1206 return;
1207 }
1208 }
1209
1210 /* Stencil and Z testing */
1211 if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1212 if (span->interpMask & SPAN_Z)
1213 _swrast_span_interpolate_z(ctx, span);
1214
1215 if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) {
1216 /* Combined Z/stencil tests */
1217 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1218 span->interpMask = origInterpMask;
1219 span->arrayMask = origArrayMask;
1220 return;
1221 }
1222 }
1223 else if (ctx->DrawBuffer->Visual.depthBits > 0) {
1224 /* Just regular depth testing */
1225 ASSERT(ctx->Depth.Test);
1226 ASSERT(span->arrayMask & SPAN_Z);
1227 if (!_swrast_depth_test_span(ctx, span)) {
1228 span->interpMask = origInterpMask;
1229 span->arrayMask = origArrayMask;
1230 return;
1231 }
1232 }
1233 }
1234
1235 /* if we get here, some fragments passed the depth test */
1236 if (ctx->Depth.OcclusionTest) {
1237 ctx->OcclusionResult = GL_TRUE;
1238 }
1239
1240 #if FEATURE_ARB_occlusion_query
1241 if (ctx->Occlusion.Active) {
1242 /* update count of 'passed' fragments */
1243 GLuint i;
1244 for (i = 0; i < span->end; i++)
1245 ctx->Occlusion.PassedCounter += span->array->mask[i];
1246 }
1247 #endif
1248
1249 /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1250 * the occlusion test.
1251 */
1252 if (colorMask == 0x0) {
1253 span->interpMask = origInterpMask;
1254 span->arrayMask = origArrayMask;
1255 return;
1256 }
1257
1258 /* If the alpha test isn't enabled, we're able to defer computing fragment
1259 * colors (by interpolation, texturing, fragment program) until now.
1260 * Hopefully, Z/stencil tests culled many of the fragments!
1261 */
1262 if (!ctx->Color.AlphaEnabled) {
1263 /* Now we need the rgba array, fill it in if needed */
1264 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1265 interpolate_colors(ctx, span);
1266
1267 if (span->interpMask & SPAN_SPEC)
1268 interpolate_specular(ctx, span);
1269
1270 if (span->interpMask & SPAN_FOG)
1271 interpolate_fog(ctx, span);
1272
1273 if (ctx->FragmentProgram._Active)
1274 _swrast_exec_fragment_program( ctx, span );
1275 else if (ctx->ATIFragmentShader._Enabled)
1276 _swrast_exec_fragment_shader( ctx, span );
1277 else if (ctx->Texture._EnabledUnits)
1278 _swrast_texture_span( ctx, span );
1279 }
1280
1281 ASSERT(span->arrayMask & SPAN_RGBA);
1282
1283 if (!ctx->FragmentProgram._Active) {
1284 /* Add base and specular colors */
1285 if (ctx->Fog.ColorSumEnabled ||
1286 (ctx->Light.Enabled &&
1287 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1288 if (span->interpMask & SPAN_SPEC) {
1289 interpolate_specular(ctx, span);
1290 }
1291 if (span->arrayMask & SPAN_SPEC) {
1292 add_colors( span->end, span->array->rgba, span->array->spec );
1293 }
1294 else {
1295 /* We probably added the base/specular colors during the
1296 * vertex stage!
1297 */
1298 }
1299 }
1300 }
1301
1302 /* Fog */
1303 if (swrast->_FogEnabled) {
1304 _swrast_fog_rgba_span(ctx, span);
1305 }
1306
1307 /* Antialias coverage application */
1308 if (span->arrayMask & SPAN_COVERAGE) {
1309 GLchan (*rgba)[4] = span->array->rgba;
1310 GLfloat *coverage = span->array->coverage;
1311 GLuint i;
1312 for (i = 0; i < span->end; i++) {
1313 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
1314 }
1315 }
1316
1317 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1318 /* need to do blend/logicop separately for each color buffer */
1319 multi_write_rgba_span(ctx, span);
1320 }
1321 else {
1322 /* normal: write to exactly one buffer */
1323 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
1324
1325 if (ctx->Color._LogicOpEnabled) {
1326 _swrast_logicop_rgba_span(ctx, rb, span, span->array->rgba);
1327 }
1328 else if (ctx->Color.BlendEnabled) {
1329 _swrast_blend_span(ctx, rb, span, span->array->rgba);
1330 }
1331
1332 /* Color component masking */
1333 if (colorMask != 0xffffffff) {
1334 _swrast_mask_rgba_span(ctx, rb, span, span->array->rgba);
1335 }
1336
1337 /* Finally, write the pixels to a color buffer */
1338 if (span->arrayMask & SPAN_XY) {
1339 /* array of pixel coords */
1340 if (rb->PutValues) {
1341 ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
1342 /* XXX check datatype */
1343 rb->PutValues(ctx, rb, span->end, span->array->x, span->array->y,
1344 span->array->rgba, span->array->mask);
1345 }
1346 #ifdef OLD_RENDERBUFFER
1347 else
1348 {
1349 swrast->Driver.WriteRGBAPixels(ctx, rb, span->end, span->array->x,
1350 span->array->y, (const GLchan (*)[4]) span->array->rgba,
1351 span->array->mask);
1352 }
1353 #endif
1354 }
1355 else {
1356 /* horizontal run of pixels */
1357 if (rb->PutRow) {
1358 ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
1359 /* XXX check datatype */
1360 rb->PutRow(ctx, rb, span->end, span->x, span->y, span->array->rgba,
1361 span->writeAll ? NULL : span->array->mask);
1362 }
1363 #ifdef OLD_RENDERBUFFER
1364 else
1365 {
1366 swrast->Driver.WriteRGBASpan(ctx, rb, span->end, span->x, span->y,
1367 (const GLchan (*)[4]) span->array->rgba,
1368 span->writeAll ? NULL : span->array->mask);
1369 }
1370 #endif
1371 }
1372 }
1373
1374 span->interpMask = origInterpMask;
1375 span->arrayMask = origArrayMask;
1376 }
1377
1378
1379
1380 /**
1381 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1382 * reading ouside the buffer's boundaries.
1383 */
1384 void
1385 _swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1386 GLuint n, GLint x, GLint y, GLchan rgba[][4] )
1387 {
1388 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1389 const GLint bufWidth = (GLint) rb->Width;
1390 const GLint bufHeight = (GLint) rb->Height;
1391
1392 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1393 /* completely above, below, or right */
1394 /* XXX maybe leave rgba values undefined? */
1395 _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1396 }
1397 else {
1398 GLint skip, length;
1399 if (x < 0) {
1400 /* left edge clippping */
1401 skip = -x;
1402 length = (GLint) n - skip;
1403 if (length < 0) {
1404 /* completely left of window */
1405 return;
1406 }
1407 if (length > bufWidth) {
1408 length = bufWidth;
1409 }
1410 }
1411 else if ((GLint) (x + n) > bufWidth) {
1412 /* right edge clipping */
1413 skip = 0;
1414 length = bufWidth - x;
1415 if (length < 0) {
1416 /* completely to right of window */
1417 return;
1418 }
1419 }
1420 else {
1421 /* no clipping */
1422 skip = 0;
1423 length = (GLint) n;
1424 }
1425
1426 if (rb && rb->GetRow) {
1427 assert(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
1428 assert(rb->DataType == GL_UNSIGNED_BYTE);
1429 rb->GetRow(ctx, rb, length, x + skip, y, rgba + skip);
1430 }
1431 #if OLD_RENDERBUFFER
1432 else {
1433 swrast->Driver.ReadRGBASpan(ctx, rb, length, x + skip, y,
1434 rgba + skip);
1435 /*
1436 if (buffer->UseSoftwareAlphaBuffers) {
1437 _swrast_read_alpha_span(ctx, length, x + skip, y, rgba + skip);
1438 }
1439 */
1440 }
1441 #endif
1442 }
1443 }
1444
1445
1446 /**
1447 * Read CI pixels from frame buffer. Clipping will be done to prevent
1448 * reading ouside the buffer's boundaries.
1449 */
1450 void
1451 _swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1452 GLuint n, GLint x, GLint y, GLuint index[] )
1453 {
1454 const GLint bufWidth = (GLint) rb->Width;
1455 const GLint bufHeight = (GLint) rb->Height;
1456
1457 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1458 /* completely above, below, or right */
1459 _mesa_bzero(index, n * sizeof(GLuint));
1460 }
1461 else {
1462 GLint skip, length;
1463 if (x < 0) {
1464 /* left edge clippping */
1465 skip = -x;
1466 length = (GLint) n - skip;
1467 if (length < 0) {
1468 /* completely left of window */
1469 return;
1470 }
1471 if (length > bufWidth) {
1472 length = bufWidth;
1473 }
1474 }
1475 else if ((GLint) (x + n) > bufWidth) {
1476 /* right edge clipping */
1477 skip = 0;
1478 length = bufWidth - x;
1479 if (length < 0) {
1480 /* completely to right of window */
1481 return;
1482 }
1483 }
1484 else {
1485 /* no clipping */
1486 skip = 0;
1487 length = (GLint) n;
1488 }
1489
1490 ASSERT(rb->GetRow);
1491 ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1492
1493 if (rb->DataType == GL_UNSIGNED_BYTE) {
1494 GLubyte index8[MAX_WIDTH];
1495 GLint i;
1496 rb->GetRow(ctx, rb, length, x + skip, y, index8);
1497 for (i = 0; i < length; i++)
1498 index[skip + i] = index8[i];
1499 }
1500 else if (rb->DataType == GL_UNSIGNED_SHORT) {
1501 GLushort index16[MAX_WIDTH];
1502 GLint i;
1503 rb->GetRow(ctx, rb, length, x + skip, y, index16);
1504 for (i = 0; i < length; i++)
1505 index[skip + i] = index16[i];
1506 }
1507 else if (rb->DataType == GL_UNSIGNED_INT) {
1508 rb->GetRow(ctx, rb, length, x + skip, y, index + skip);
1509 }
1510 }
1511 }