Header file clean-up:
[mesa.git] / src / mesa / swrast / s_span.c
1 /* $Id: s_span.c,v 1.50 2002/10/24 23:57:24 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 /**
29 * \file swrast/s_span.c
30 * \brief Span processing functions used by all rasterization functions.
31 * This is where all the per-fragment tests are performed
32 * \author Brian Paul
33 */
34
35 #include "glheader.h"
36 #include "colormac.h"
37 #include "context.h"
38 #include "macros.h"
39 #include "mmath.h"
40 #include "imports.h"
41
42 #include "s_alpha.h"
43 #include "s_alphabuf.h"
44 #include "s_blend.h"
45 #include "s_context.h"
46 #include "s_depth.h"
47 #include "s_fog.h"
48 #include "s_logic.h"
49 #include "s_masking.h"
50 #include "s_span.h"
51 #include "s_stencil.h"
52 #include "s_texture.h"
53
54
55 /**
56 * Init span's Z interpolation values to the RasterPos Z.
57 * Used during setup for glDraw/CopyPixels.
58 */
59 void
60 _mesa_span_default_z( GLcontext *ctx, struct sw_span *span )
61 {
62 if (ctx->Visual.depthBits <= 16)
63 span->z = FloatToFixed(ctx->Current.RasterPos[2] * ctx->DepthMax);
64 else
65 span->z = (GLint) (ctx->Current.RasterPos[2] * ctx->DepthMax);
66 span->zStep = 0;
67 span->interpMask |= SPAN_Z;
68 }
69
70
71 /**
72 * Init span's fog interpolation values to the RasterPos fog.
73 * Used during setup for glDraw/CopyPixels.
74 */
75 void
76 _mesa_span_default_fog( GLcontext *ctx, struct sw_span *span )
77 {
78 span->fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
79 span->fogStep = 0;
80 span->interpMask |= SPAN_FOG;
81 }
82
83
84 /**
85 * Init span's color or index interpolation values to the RasterPos color.
86 * Used during setup for glDraw/CopyPixels.
87 */
88 void
89 _mesa_span_default_color( GLcontext *ctx, struct sw_span *span )
90 {
91 if (ctx->Visual.rgbMode) {
92 GLchan r, g, b, a;
93 UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
94 UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
95 UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
96 UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
97 #if CHAN_TYPE == GL_FLOAT
98 span->red = r;
99 span->green = g;
100 span->blue = b;
101 span->alpha = a;
102 #else
103 span->red = IntToFixed(r);
104 span->green = IntToFixed(g);
105 span->blue = IntToFixed(b);
106 span->alpha = IntToFixed(a);
107 #endif
108 span->redStep = 0;
109 span->greenStep = 0;
110 span->blueStep = 0;
111 span->alphaStep = 0;
112 span->interpMask |= SPAN_RGBA;
113 }
114 else {
115 span->index = IntToFixed(ctx->Current.RasterIndex);
116 span->indexStep = 0;
117 span->interpMask |= SPAN_INDEX;
118 }
119 }
120
121
122 /**
123 * Init span's texcoord interpolation values to the RasterPos texcoords.
124 * Used during setup for glDraw/CopyPixels.
125 */
126 void
127 _mesa_span_default_texcoords( GLcontext *ctx, struct sw_span *span )
128 {
129 GLuint i;
130 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
131 COPY_4V(span->tex[i], ctx->Current.RasterTexCoords[i]);
132 ASSIGN_4V(span->texStepX[i], 0.0F, 0.0F, 0.0F, 0.0F);
133 ASSIGN_4V(span->texStepY[i], 0.0F, 0.0F, 0.0F, 0.0F);
134 }
135 span->interpMask |= SPAN_TEXTURE;
136 }
137
138
139 /* Fill in the span.color.rgba array from the interpolation values */
140 static void
141 interpolate_colors(GLcontext *ctx, struct sw_span *span)
142 {
143 GLfixed r = span->red;
144 GLfixed g = span->green;
145 GLfixed b = span->blue;
146 GLfixed a = span->alpha;
147 const GLint dr = span->redStep;
148 const GLint dg = span->greenStep;
149 const GLint db = span->blueStep;
150 const GLint da = span->alphaStep;
151 const GLuint n = span->end;
152 GLchan (*rgba)[4] = span->array->rgba;
153 GLuint i;
154
155 ASSERT((span->interpMask & SPAN_RGBA) &&
156 !(span->arrayMask & SPAN_RGBA));
157
158 if (span->interpMask & SPAN_FLAT) {
159 /* constant color */
160 GLchan color[4];
161 color[RCOMP] = FixedToChan(r);
162 color[GCOMP] = FixedToChan(g);
163 color[BCOMP] = FixedToChan(b);
164 color[ACOMP] = FixedToChan(a);
165 for (i = 0; i < n; i++) {
166 COPY_CHAN4(span->array->rgba[i], color);
167 }
168 }
169 else {
170 /* interpolate */
171 for (i = 0; i < n; i++) {
172 rgba[i][RCOMP] = FixedToChan(r);
173 rgba[i][GCOMP] = FixedToChan(g);
174 rgba[i][BCOMP] = FixedToChan(b);
175 rgba[i][ACOMP] = FixedToChan(a);
176 r += dr;
177 g += dg;
178 b += db;
179 a += da;
180 }
181 }
182 span->arrayMask |= SPAN_RGBA;
183 }
184
185
186 /* Fill in the span.color.index array from the interpolation values */
187 static void
188 interpolate_indexes(GLcontext *ctx, struct sw_span *span)
189 {
190 GLfixed index = span->index;
191 const GLint indexStep = span->indexStep;
192 const GLuint n = span->end;
193 GLuint *indexes = span->array->index;
194 GLuint i;
195 ASSERT((span->interpMask & SPAN_INDEX) &&
196 !(span->arrayMask & SPAN_INDEX));
197
198 if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
199 /* constant color */
200 index = FixedToInt(index);
201 for (i = 0; i < n; i++) {
202 indexes[i] = index;
203 }
204 }
205 else {
206 /* interpolate */
207 for (i = 0; i < n; i++) {
208 indexes[i] = FixedToInt(index);
209 index += indexStep;
210 }
211 }
212 span->arrayMask |= SPAN_INDEX;
213 }
214
215
216 /* Fill in the span.->array->spec array from the interpolation values */
217 static void
218 interpolate_specular(GLcontext *ctx, struct sw_span *span)
219 {
220 if (span->interpMask & SPAN_FLAT) {
221 /* constant color */
222 const GLchan r = FixedToChan(span->specRed);
223 const GLchan g = FixedToChan(span->specGreen);
224 const GLchan b = FixedToChan(span->specBlue);
225 GLuint i;
226 for (i = 0; i < span->end; i++) {
227 span->array->spec[i][RCOMP] = r;
228 span->array->spec[i][GCOMP] = g;
229 span->array->spec[i][BCOMP] = b;
230 }
231 }
232 else {
233 /* interpolate */
234 #if CHAN_TYPE == GL_FLOAT
235 GLfloat r = span->specRed;
236 GLfloat g = span->specGreen;
237 GLfloat b = span->specBlue;
238 #else
239 GLfixed r = span->specRed;
240 GLfixed g = span->specGreen;
241 GLfixed b = span->specBlue;
242 #endif
243 GLuint i;
244 for (i = 0; i < span->end; i++) {
245 span->array->spec[i][RCOMP] = FixedToChan(r);
246 span->array->spec[i][GCOMP] = FixedToChan(g);
247 span->array->spec[i][BCOMP] = FixedToChan(b);
248 r += span->specRedStep;
249 g += span->specGreenStep;
250 b += span->specBlueStep;
251 }
252 }
253 span->arrayMask |= SPAN_SPEC;
254 }
255
256
257 /* Fill in the span.zArray array from the interpolation values */
258 void
259 _mesa_span_interpolate_z( const GLcontext *ctx, struct sw_span *span )
260 {
261 const GLuint n = span->end;
262 GLuint i;
263
264 ASSERT((span->interpMask & SPAN_Z) &&
265 !(span->arrayMask & SPAN_Z));
266
267 if (ctx->Visual.depthBits <= 16) {
268 GLfixed zval = span->z;
269 GLdepth *z = span->array->z;
270 for (i = 0; i < n; i++) {
271 z[i] = FixedToInt(zval);
272 zval += span->zStep;
273 }
274 }
275 else {
276 /* Deep Z buffer, no fixed->int shift */
277 GLfixed zval = span->z;
278 GLdepth *z = span->array->z;
279 for (i = 0; i < n; i++) {
280 z[i] = zval;
281 zval += span->zStep;
282 }
283 }
284 span->arrayMask |= SPAN_Z;
285 }
286
287
288 /*
289 * This the ideal solution, as given in the OpenGL spec.
290 */
291 #if 0
292 static GLfloat
293 compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
294 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
295 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
296 {
297 GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
298 GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
299 GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
300 GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
301 GLfloat x = sqrt(dudx * dudx + dvdx * dvdx);
302 GLfloat y = sqrt(dudy * dudy + dvdy * dvdy);
303 GLfloat rho = MAX2(x, y);
304 GLfloat lambda = LOG2(rho);
305 return lambda;
306 }
307 #endif
308
309
310 /*
311 * This is a faster approximation
312 */
313 static GLfloat
314 compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
315 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
316 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
317 {
318 GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
319 GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
320 GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
321 GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
322 GLfloat maxU, maxV, rho, lambda;
323 dsdx2 = FABSF(dsdx2);
324 dsdy2 = FABSF(dsdy2);
325 dtdx2 = FABSF(dtdx2);
326 dtdy2 = FABSF(dtdy2);
327 maxU = MAX2(dsdx2, dsdy2) * texW;
328 maxV = MAX2(dtdx2, dtdy2) * texH;
329 rho = MAX2(maxU, maxV);
330 lambda = LOG2(rho);
331 return lambda;
332 }
333
334 /*
335 * Fill in the span.texcoords array from the interpolation values.
336 * XXX We could optimize here for the case when dq = 0. That would
337 * usually be the case when using an orthographic projection.
338 */
339 static void
340 interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
341 {
342 ASSERT(span->interpMask & SPAN_TEXTURE);
343 ASSERT(!(span->arrayMask & SPAN_TEXTURE));
344
345 if (ctx->Texture._EnabledUnits > 1) {
346 /* multitexture */
347 GLuint u;
348 span->arrayMask |= SPAN_TEXTURE;
349 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
350 if (ctx->Texture.Unit[u]._ReallyEnabled) {
351 const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
352 const struct gl_texture_image *img = obj->Image[obj->BaseLevel];
353 GLboolean needLambda = (obj->MinFilter != obj->MagFilter);
354 if (needLambda) {
355 GLfloat (*texcoord)[4] = span->array->texcoords[u];
356 GLfloat *lambda = span->array->lambda[u];
357 const GLfloat texW = (GLfloat) img->WidthScale;
358 const GLfloat texH = (GLfloat) img->HeightScale;
359 const GLfloat dsdx = span->texStepX[u][0];
360 const GLfloat dsdy = span->texStepY[u][0];
361 const GLfloat dtdx = span->texStepX[u][1];
362 const GLfloat dtdy = span->texStepY[u][1];
363 const GLfloat drdx = span->texStepX[u][2];
364 const GLfloat dqdx = span->texStepX[u][3];
365 const GLfloat dqdy = span->texStepY[u][3];
366 GLfloat s = span->tex[u][0];
367 GLfloat t = span->tex[u][1];
368 GLfloat r = span->tex[u][2];
369 GLfloat q = span->tex[u][3];
370 GLuint i;
371 for (i = 0; i < span->end; i++) {
372 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
373 texcoord[i][0] = s * invQ;
374 texcoord[i][1] = t * invQ;
375 texcoord[i][2] = r * invQ;
376 lambda[i] = compute_lambda(dsdx, dsdy, dtdx, dtdy,
377 dqdx, dqdy, texW, texH,
378 s, t, q, invQ);
379 s += dsdx;
380 t += dtdx;
381 r += drdx;
382 q += dqdx;
383 }
384 span->arrayMask |= SPAN_LAMBDA;
385 }
386 else {
387 GLfloat (*texcoord)[4] = span->array->texcoords[u];
388 GLfloat *lambda = span->array->lambda[u];
389 const GLfloat dsdx = span->texStepX[u][0];
390 const GLfloat dtdx = span->texStepX[u][1];
391 const GLfloat drdx = span->texStepX[u][2];
392 const GLfloat dqdx = span->texStepX[u][3];
393 GLfloat s = span->tex[u][0];
394 GLfloat t = span->tex[u][1];
395 GLfloat r = span->tex[u][2];
396 GLfloat q = span->tex[u][3];
397 GLuint i;
398 if (dqdx == 0.0) {
399 /* Ortho projection or polygon's parallel to window X axis */
400 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
401 for (i = 0; i < span->end; i++) {
402 texcoord[i][0] = s * invQ;
403 texcoord[i][1] = t * invQ;
404 texcoord[i][2] = r * invQ;
405 lambda[i] = 0.0;
406 s += dsdx;
407 t += dtdx;
408 r += drdx;
409 }
410 }
411 else {
412 for (i = 0; i < span->end; i++) {
413 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
414 texcoord[i][0] = s * invQ;
415 texcoord[i][1] = t * invQ;
416 texcoord[i][2] = r * invQ;
417 lambda[i] = 0.0;
418 s += dsdx;
419 t += dtdx;
420 r += drdx;
421 q += dqdx;
422 }
423 }
424 } /* lambda */
425 } /* if */
426 } /* for */
427 }
428 else {
429 /* single texture */
430 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
431 const struct gl_texture_image *img = obj->Image[obj->BaseLevel];
432 GLboolean needLambda = (obj->MinFilter != obj->MagFilter);
433 span->arrayMask |= SPAN_TEXTURE;
434 if (needLambda) {
435 /* just texture unit 0, with lambda */
436 GLfloat (*texcoord)[4] = span->array->texcoords[0];
437 GLfloat *lambda = span->array->lambda[0];
438 const GLfloat texW = (GLfloat) img->WidthScale;
439 const GLfloat texH = (GLfloat) img->HeightScale;
440 const GLfloat dsdx = span->texStepX[0][0];
441 const GLfloat dsdy = span->texStepY[0][0];
442 const GLfloat dtdx = span->texStepX[0][1];
443 const GLfloat dtdy = span->texStepY[0][1];
444 const GLfloat drdx = span->texStepX[0][2];
445 const GLfloat dqdx = span->texStepX[0][3];
446 const GLfloat dqdy = span->texStepY[0][3];
447 GLfloat s = span->tex[0][0];
448 GLfloat t = span->tex[0][1];
449 GLfloat r = span->tex[0][2];
450 GLfloat q = span->tex[0][3];
451 GLuint i;
452 for (i = 0; i < span->end; i++) {
453 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
454 lambda[i] = compute_lambda(dsdx, dsdy, dtdx, dtdy,
455 dqdx, dqdy, texW, texH,
456 s, t, q, invQ);
457 texcoord[i][0] = s * invQ;
458 texcoord[i][1] = t * invQ;
459 texcoord[i][2] = r * invQ;
460 s += dsdx;
461 t += dtdx;
462 r += drdx;
463 q += dqdx;
464 }
465 span->arrayMask |= SPAN_LAMBDA;
466 }
467 else {
468 /* just texture 0, without lambda */
469 GLfloat (*texcoord)[4] = span->array->texcoords[0];
470 const GLfloat dsdx = span->texStepX[0][0];
471 const GLfloat dtdx = span->texStepX[0][1];
472 const GLfloat drdx = span->texStepX[0][2];
473 const GLfloat dqdx = span->texStepX[0][3];
474 GLfloat s = span->tex[0][0];
475 GLfloat t = span->tex[0][1];
476 GLfloat r = span->tex[0][2];
477 GLfloat q = span->tex[0][3];
478 GLuint i;
479 if (dqdx == 0.0) {
480 /* Ortho projection or polygon's parallel to window X axis */
481 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
482 for (i = 0; i < span->end; i++) {
483 texcoord[i][0] = s * invQ;
484 texcoord[i][1] = t * invQ;
485 texcoord[i][2] = r * invQ;
486 s += dsdx;
487 t += dtdx;
488 r += drdx;
489 }
490 }
491 else {
492 for (i = 0; i < span->end; i++) {
493 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
494 texcoord[i][0] = s * invQ;
495 texcoord[i][1] = t * invQ;
496 texcoord[i][2] = r * invQ;
497 s += dsdx;
498 t += dtdx;
499 r += drdx;
500 q += dqdx;
501 }
502 }
503 }
504 }
505 }
506
507
508 /**
509 * Apply the current polygon stipple pattern to a span of pixels.
510 */
511 static void
512 stipple_polygon_span( GLcontext *ctx, struct sw_span *span )
513 {
514 const GLuint highbit = 0x80000000;
515 const GLuint stipple = ctx->PolygonStipple[span->y % 32];
516 GLubyte *mask = span->array->mask;
517 GLuint i, m;
518
519 ASSERT(ctx->Polygon.StippleFlag);
520 ASSERT((span->arrayMask & SPAN_XY) == 0);
521
522 m = highbit >> (GLuint) (span->x % 32);
523
524 for (i = 0; i < span->end; i++) {
525 if ((m & stipple) == 0) {
526 mask[i] = 0;
527 }
528 m = m >> 1;
529 if (m == 0) {
530 m = highbit;
531 }
532 }
533 span->writeAll = GL_FALSE;
534 }
535
536
537 /**
538 * Clip a pixel span to the current buffer/window boundaries:
539 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
540 * window clipping and scissoring.
541 * Return: GL_TRUE some pixels still visible
542 * GL_FALSE nothing visible
543 */
544 static GLuint
545 clip_span( GLcontext *ctx, struct sw_span *span )
546 {
547 const GLint xmin = ctx->DrawBuffer->_Xmin;
548 const GLint xmax = ctx->DrawBuffer->_Xmax;
549 const GLint ymin = ctx->DrawBuffer->_Ymin;
550 const GLint ymax = ctx->DrawBuffer->_Ymax;
551
552 if (span->arrayMask & SPAN_XY) {
553 /* arrays of x/y pixel coords */
554 const GLint *x = span->array->x;
555 const GLint *y = span->array->y;
556 const GLint n = span->end;
557 GLubyte *mask = span->array->mask;
558 GLint i;
559 if (span->arrayMask & SPAN_MASK) {
560 /* note: using & intead of && to reduce branches */
561 for (i = 0; i < n; i++) {
562 mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
563 & (y[i] >= ymin) & (y[i] < ymax);
564 }
565 }
566 else {
567 /* note: using & intead of && to reduce branches */
568 for (i = 0; i < n; i++) {
569 mask[i] = (x[i] >= xmin) & (x[i] < xmax)
570 & (y[i] >= ymin) & (y[i] < ymax);
571 }
572 }
573 return GL_TRUE; /* some pixels visible */
574 }
575 else {
576 /* horizontal span of pixels */
577 const GLint x = span->x;
578 const GLint y = span->y;
579 const GLint n = span->end;
580
581 /* Trivial rejection tests */
582 if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
583 span->end = 0;
584 return GL_FALSE; /* all pixels clipped */
585 }
586
587 /* Clip to the left */
588 if (x < xmin) {
589 ASSERT(x + n > xmin);
590 span->writeAll = GL_FALSE;
591 BZERO(span->array->mask, (xmin - x) * sizeof(GLubyte));
592 }
593
594 /* Clip to right */
595 if (x + n > xmax) {
596 ASSERT(x < xmax);
597 span->end = xmax - x;
598 }
599
600 return GL_TRUE; /* some pixels visible */
601 }
602 }
603
604
605
606 /**
607 * Draw to more than one color buffer (or none).
608 */
609 static void
610 multi_write_index_span( GLcontext *ctx, struct sw_span *span )
611 {
612 SWcontext *swrast = SWRAST_CONTEXT(ctx);
613 GLuint bufferBit;
614
615 /* loop over four possible dest color buffers */
616 for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) {
617 if (bufferBit & ctx->Color._DrawDestMask) {
618 GLuint indexTmp[MAX_WIDTH];
619 ASSERT(span->end < MAX_WIDTH);
620
621 /* Set the current read/draw buffer */
622 swrast->CurrentBuffer = bufferBit;
623 (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
624
625 /* make copy of incoming indexes */
626 MEMCPY( indexTmp, span->array->index, span->end * sizeof(GLuint) );
627
628 if (ctx->Color.IndexLogicOpEnabled) {
629 _mesa_logicop_ci_span(ctx, span, indexTmp);
630 }
631
632 if (ctx->Color.IndexMask != 0xffffffff) {
633 _mesa_mask_index_span(ctx, span, indexTmp);
634 }
635
636 if (span->arrayMask & SPAN_XY) {
637 /* array of pixel coords */
638 (*swrast->Driver.WriteCI32Pixels)(ctx, span->end,
639 span->array->x, span->array->y,
640 indexTmp, span->array->mask);
641 }
642 else {
643 /* horizontal run of pixels */
644 (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
645 indexTmp, span->array->mask);
646 }
647 }
648 }
649
650 /* restore default dest buffer */
651 _swrast_use_draw_buffer(ctx);
652 }
653
654
655 /**
656 * Draw to more than one RGBA color buffer (or none).
657 * All fragment operations, up to (but not) blending/logicop should
658 * have been done first.
659 */
660 static void
661 multi_write_rgba_span( GLcontext *ctx, struct sw_span *span )
662 {
663 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
664 GLuint bufferBit;
665 SWcontext *swrast = SWRAST_CONTEXT(ctx);
666
667 ASSERT(colorMask != 0x0);
668
669 if (ctx->Color.DrawBuffer == GL_NONE)
670 return;
671
672 /* loop over four possible dest color buffers */
673 for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) {
674 if (bufferBit & ctx->Color._DrawDestMask) {
675 GLchan rgbaTmp[MAX_WIDTH][4];
676 ASSERT(span->end < MAX_WIDTH);
677
678 /* Set the current read/draw buffer */
679 swrast->CurrentBuffer = bufferBit;
680 (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
681
682 /* make copy of incoming colors */
683 MEMCPY( rgbaTmp, span->array->rgba, 4 * span->end * sizeof(GLchan) );
684
685 if (ctx->Color.ColorLogicOpEnabled) {
686 _mesa_logicop_rgba_span(ctx, span, rgbaTmp);
687 }
688 else if (ctx->Color.BlendEnabled) {
689 _mesa_blend_span(ctx, span, rgbaTmp);
690 }
691
692 if (colorMask != 0xffffffff) {
693 _mesa_mask_rgba_span(ctx, span, rgbaTmp);
694 }
695
696 if (span->arrayMask & SPAN_XY) {
697 /* array of pixel coords */
698 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end,
699 span->array->x, span->array->y,
700 (const GLchan (*)[4]) rgbaTmp,
701 span->array->mask);
702 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
703 _mesa_write_alpha_pixels(ctx, span->end,
704 span->array->x, span->array->y,
705 (const GLchan (*)[4]) rgbaTmp,
706 span->array->mask);
707 }
708 }
709 else {
710 /* horizontal run of pixels */
711 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
712 (const GLchan (*)[4]) rgbaTmp,
713 span->array->mask);
714 if (swrast->_RasterMask & ALPHABUF_BIT) {
715 _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
716 (const GLchan (*)[4]) rgbaTmp,
717 span->array->mask);
718 }
719 }
720 }
721 }
722
723 /* restore default dest buffer */
724 _swrast_use_draw_buffer(ctx);
725 }
726
727
728
729 /**
730 * This function may modify any of the array values in the span.
731 * span->interpMask and span->arrayMask may be changed but will be restored
732 * to their original values before returning.
733 */
734 void
735 _mesa_write_index_span( GLcontext *ctx, struct sw_span *span)
736 {
737 SWcontext *swrast = SWRAST_CONTEXT(ctx);
738 const GLuint origInterpMask = span->interpMask;
739 const GLuint origArrayMask = span->arrayMask;
740
741 ASSERT(span->end <= MAX_WIDTH);
742 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
743 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
744 ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
745 ASSERT((span->interpMask & span->arrayMask) == 0);
746
747 if (span->arrayMask & SPAN_MASK) {
748 /* mask was initialized by caller, probably glBitmap */
749 span->writeAll = GL_FALSE;
750 }
751 else {
752 MEMSET(span->array->mask, 1, span->end);
753 span->writeAll = GL_TRUE;
754 }
755
756 /* Clipping */
757 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
758 if (!clip_span(ctx, span)) {
759 return;
760 }
761 }
762
763 #ifdef DEBUG
764 if (span->arrayMask & SPAN_XY) {
765 GLuint i;
766 for (i = 0; i < span->end; i++) {
767 if (span->array->mask[i]) {
768 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
769 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
770 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
771 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
772 }
773 }
774 }
775 #endif
776
777 /* Polygon Stippling */
778 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
779 stipple_polygon_span(ctx, span);
780 }
781
782 /* Depth test and stencil */
783 if (ctx->Depth.Test || ctx->Stencil.Enabled) {
784 if (span->interpMask & SPAN_Z)
785 _mesa_span_interpolate_z(ctx, span);
786
787 if (ctx->Stencil.Enabled) {
788 if (!_mesa_stencil_and_ztest_span(ctx, span)) {
789 span->arrayMask = origArrayMask;
790 return;
791 }
792 }
793 else {
794 ASSERT(ctx->Depth.Test);
795 if (!_mesa_depth_test_span(ctx, span)) {
796 span->arrayMask = origArrayMask;
797 return;
798 }
799 }
800 }
801
802 /* if we get here, something passed the depth test */
803 ctx->OcclusionResult = GL_TRUE;
804
805 /* we have to wait until after occlusion to do this test */
806 if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
807 /* write no pixels */
808 span->arrayMask = origArrayMask;
809 return;
810 }
811
812 /* Interpolate the color indexes if needed */
813 if (span->interpMask & SPAN_INDEX) {
814 interpolate_indexes(ctx, span);
815 /* clear the bit - this allows the WriteMonoCISpan optimization below */
816 span->interpMask &= ~SPAN_INDEX;
817 }
818
819 /* Fog */
820 if (ctx->Fog.Enabled) {
821 _mesa_fog_ci_span(ctx, span);
822 }
823
824 /* Antialias coverage application */
825 if (span->arrayMask & SPAN_COVERAGE) {
826 GLuint i;
827 GLuint *index = span->array->index;
828 GLfloat *coverage = span->array->coverage;
829 for (i = 0; i < span->end; i++) {
830 ASSERT(coverage[i] < 16);
831 index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
832 }
833 }
834
835 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
836 /* draw to zero or two or more buffers */
837 multi_write_index_span(ctx, span);
838 }
839 else {
840 /* normal situation: draw to exactly one buffer */
841 if (ctx->Color.IndexLogicOpEnabled) {
842 _mesa_logicop_ci_span(ctx, span, span->array->index);
843 }
844
845 if (ctx->Color.IndexMask != 0xffffffff) {
846 _mesa_mask_index_span(ctx, span, span->array->index);
847 }
848
849 /* write pixels */
850 if (span->arrayMask & SPAN_XY) {
851 /* array of pixel coords */
852 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
853 /* all pixels have same color index */
854 (*swrast->Driver.WriteMonoCIPixels)(ctx, span->end,
855 span->array->x, span->array->y,
856 FixedToInt(span->index),
857 span->array->mask);
858 }
859 else {
860 (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, span->array->x,
861 span->array->y, span->array->index,
862 span->array->mask );
863 }
864 }
865 else {
866 /* horizontal run of pixels */
867 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
868 /* all pixels have same color index */
869 (*swrast->Driver.WriteMonoCISpan)(ctx, span->end, span->x, span->y,
870 FixedToInt(span->index),
871 span->array->mask);
872 }
873 else {
874 (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
875 span->array->index,
876 span->array->mask);
877 }
878 }
879 }
880
881 span->interpMask = origInterpMask;
882 span->arrayMask = origArrayMask;
883 }
884
885
886 /**
887 * This function may modify any of the array values in the span.
888 * span->interpMask and span->arrayMask may be changed but will be restored
889 * to their original values before returning.
890 */
891 void
892 _mesa_write_rgba_span( GLcontext *ctx, struct sw_span *span)
893 {
894 SWcontext *swrast = SWRAST_CONTEXT(ctx);
895 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
896 const GLuint origInterpMask = span->interpMask;
897 const GLuint origArrayMask = span->arrayMask;
898 GLboolean monoColor;
899
900 ASSERT(span->end <= MAX_WIDTH);
901 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
902 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
903 ASSERT((span->interpMask & span->arrayMask) == 0);
904 ASSERT((span->interpMask | span->arrayMask) & SPAN_RGBA);
905 #ifdef DEBUG
906 if (ctx->Fog.Enabled)
907 ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG);
908 if (ctx->Depth.Test)
909 ASSERT((span->interpMask | span->arrayMask) & SPAN_Z);
910 #endif
911
912 if (span->arrayMask & SPAN_MASK) {
913 /* mask was initialized by caller, probably glBitmap */
914 span->writeAll = GL_FALSE;
915 }
916 else {
917 MEMSET(span->array->mask, 1, span->end);
918 span->writeAll = GL_TRUE;
919 }
920
921 /* Determine if we have mono-chromatic colors */
922 monoColor = (span->interpMask & SPAN_RGBA) &&
923 span->redStep == 0 && span->greenStep == 0 &&
924 span->blueStep == 0 && span->alphaStep == 0;
925
926 /* Clipping */
927 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
928 if (!clip_span(ctx, span)) {
929 return;
930 }
931 }
932
933 #ifdef DEBUG
934 if (span->arrayMask & SPAN_XY) {
935 GLuint i;
936 for (i = 0; i < span->end; i++) {
937 if (span->array->mask[i]) {
938 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
939 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
940 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
941 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
942 }
943 }
944 }
945 #endif
946
947 /* Polygon Stippling */
948 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
949 stipple_polygon_span(ctx, span);
950 }
951
952 /* Do the alpha test */
953 if (ctx->Color.AlphaEnabled) {
954 if (!_mesa_alpha_test(ctx, span)) {
955 span->interpMask = origInterpMask;
956 span->arrayMask = origArrayMask;
957 return;
958 }
959 }
960
961 /* Stencil and Z testing */
962 if (ctx->Stencil.Enabled || ctx->Depth.Test) {
963 if (span->interpMask & SPAN_Z)
964 _mesa_span_interpolate_z(ctx, span);
965
966 if (ctx->Stencil.Enabled) {
967 if (!_mesa_stencil_and_ztest_span(ctx, span)) {
968 span->interpMask = origInterpMask;
969 span->arrayMask = origArrayMask;
970 return;
971 }
972 }
973 else {
974 ASSERT(ctx->Depth.Test);
975 ASSERT(span->arrayMask & SPAN_Z);
976 /* regular depth testing */
977 if (!_mesa_depth_test_span(ctx, span)) {
978 span->interpMask = origInterpMask;
979 span->arrayMask = origArrayMask;
980 return;
981 }
982 }
983 }
984
985 /* if we get here, something passed the depth test */
986 ctx->OcclusionResult = GL_TRUE;
987
988 /* can't abort span-writing until after occlusion testing */
989 if (colorMask == 0x0) {
990 span->interpMask = origInterpMask;
991 span->arrayMask = origArrayMask;
992 return;
993 }
994
995 /* Now we may need to interpolate the colors */
996 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) {
997 interpolate_colors(ctx, span);
998 /* clear the bit - this allows the WriteMonoCISpan optimization below */
999 span->interpMask &= ~SPAN_RGBA;
1000 }
1001
1002 /* Fog */
1003 if (ctx->Fog.Enabled) {
1004 _mesa_fog_rgba_span(ctx, span);
1005 monoColor = GL_FALSE;
1006 }
1007
1008 /* Antialias coverage application */
1009 if (span->arrayMask & SPAN_COVERAGE) {
1010 GLchan (*rgba)[4] = span->array->rgba;
1011 GLfloat *coverage = span->array->coverage;
1012 GLuint i;
1013 for (i = 0; i < span->end; i++) {
1014 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
1015 }
1016 monoColor = GL_FALSE;
1017 }
1018
1019 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1020 multi_write_rgba_span(ctx, span);
1021 }
1022 else {
1023 /* normal: write to exactly one buffer */
1024 if (ctx->Color.ColorLogicOpEnabled) {
1025 _mesa_logicop_rgba_span(ctx, span, span->array->rgba);
1026 monoColor = GL_FALSE;
1027 }
1028 else if (ctx->Color.BlendEnabled) {
1029 _mesa_blend_span(ctx, span, span->array->rgba);
1030 monoColor = GL_FALSE;
1031 }
1032
1033 /* Color component masking */
1034 if (colorMask != 0xffffffff) {
1035 _mesa_mask_rgba_span(ctx, span, span->array->rgba);
1036 monoColor = GL_FALSE;
1037 }
1038
1039 /* write pixels */
1040 if (span->arrayMask & SPAN_XY) {
1041 /* array of pixel coords */
1042 /* XXX test for mono color */
1043 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
1044 span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask);
1045 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1046 _mesa_write_alpha_pixels(ctx, span->end,
1047 span->array->x, span->array->y,
1048 (const GLchan (*)[4]) span->array->rgba,
1049 span->array->mask);
1050 }
1051 }
1052 else {
1053 /* horizontal run of pixels */
1054 if (monoColor) {
1055 /* all pixels have same color */
1056 GLchan color[4];
1057 color[RCOMP] = FixedToChan(span->red);
1058 color[GCOMP] = FixedToChan(span->green);
1059 color[BCOMP] = FixedToChan(span->blue);
1060 color[ACOMP] = FixedToChan(span->alpha);
1061 (*swrast->Driver.WriteMonoRGBASpan)(ctx, span->end, span->x,
1062 span->y, color, span->array->mask);
1063 /* XXX software alpha buffer writes! */
1064 }
1065 else {
1066 /* each pixel is a different color */
1067 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
1068 (const GLchan (*)[4]) span->array->rgba,
1069 span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
1070 if (swrast->_RasterMask & ALPHABUF_BIT) {
1071 _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
1072 (const GLchan (*)[4]) span->array->rgba,
1073 span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
1074 }
1075 }
1076 }
1077 }
1078
1079 span->interpMask = origInterpMask;
1080 span->arrayMask = origArrayMask;
1081 }
1082
1083
1084 /**
1085 * Add specular color to base color. This is used only when
1086 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1087 */
1088 static void
1089 add_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] )
1090 {
1091 GLuint i;
1092 for (i = 0; i < n; i++) {
1093 #if CHAN_TYPE == GL_FLOAT
1094 /* no clamping */
1095 rgba[i][RCOMP] += specular[i][RCOMP];
1096 rgba[i][GCOMP] += specular[i][GCOMP];
1097 rgba[i][BCOMP] += specular[i][BCOMP];
1098 #else
1099 GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
1100 GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
1101 GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
1102 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1103 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1104 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1105 #endif
1106 }
1107 }
1108
1109
1110 /**
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 _mesa_write_texture_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 origArrayMask = span->arrayMask;
1121
1122 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
1123 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
1124 ASSERT(span->end <= MAX_WIDTH);
1125 ASSERT((span->interpMask & span->arrayMask) == 0);
1126 ASSERT(ctx->Texture._EnabledUnits);
1127
1128 /*
1129 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1130 */
1131
1132 if (span->arrayMask & SPAN_MASK) {
1133 /* mask was initialized by caller, probably glBitmap */
1134 span->writeAll = GL_FALSE;
1135 }
1136 else {
1137 MEMSET(span->array->mask, 1, span->end);
1138 span->writeAll = GL_TRUE;
1139 }
1140
1141 /* Clipping */
1142 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1143 if (!clip_span(ctx, span)) {
1144 return;
1145 }
1146 }
1147
1148 #ifdef DEBUG
1149 if (span->arrayMask & SPAN_XY) {
1150 GLuint i;
1151 for (i = 0; i < span->end; i++) {
1152 if (span->array->mask[i]) {
1153 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
1154 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
1155 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
1156 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1157 }
1158 }
1159 }
1160 #endif
1161
1162 /* Polygon Stippling */
1163 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1164 stipple_polygon_span(ctx, span);
1165 }
1166
1167 /* Need texture coordinates now */
1168 if ((span->interpMask & SPAN_TEXTURE)
1169 && (span->arrayMask & SPAN_TEXTURE) == 0)
1170 interpolate_texcoords(ctx, span);
1171
1172 /* Texture with alpha test */
1173 if (ctx->Color.AlphaEnabled) {
1174
1175 /* Now we need the rgba array, fill it in if needed */
1176 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1177 interpolate_colors(ctx, span);
1178
1179 /* Texturing without alpha is done after depth-testing which
1180 * gives a potential speed-up.
1181 */
1182 _swrast_texture_span( ctx, span );
1183
1184 /* Do the alpha test */
1185 if (!_mesa_alpha_test(ctx, span)) {
1186 span->arrayMask = origArrayMask;
1187 return;
1188 }
1189 }
1190
1191 /* Stencil and Z testing */
1192 if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1193 if (span->interpMask & SPAN_Z)
1194 _mesa_span_interpolate_z(ctx, span);
1195
1196 if (ctx->Stencil.Enabled) {
1197 if (!_mesa_stencil_and_ztest_span(ctx, span)) {
1198 span->arrayMask = origArrayMask;
1199 return;
1200 }
1201 }
1202 else {
1203 ASSERT(ctx->Depth.Test);
1204 ASSERT(span->arrayMask & SPAN_Z);
1205 /* regular depth testing */
1206 if (!_mesa_depth_test_span(ctx, span)) {
1207 span->arrayMask = origArrayMask;
1208 return;
1209 }
1210 }
1211 }
1212
1213 /* if we get here, some fragments passed the depth test */
1214 ctx->OcclusionResult = GL_TRUE;
1215
1216 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1217 * the occlusion test.
1218 */
1219 if (colorMask == 0x0) {
1220 span->arrayMask = origArrayMask;
1221 return;
1222 }
1223
1224 /* Texture without alpha test */
1225 if (!ctx->Color.AlphaEnabled) {
1226
1227 /* Now we need the rgba array, fill it in if needed */
1228 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1229 interpolate_colors(ctx, span);
1230
1231 _swrast_texture_span( ctx, span );
1232 }
1233
1234 ASSERT(span->arrayMask & SPAN_RGBA);
1235
1236 /* Add base and specular colors */
1237 if (ctx->Fog.ColorSumEnabled ||
1238 (ctx->Light.Enabled &&
1239 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1240 if (span->interpMask & SPAN_SPEC) {
1241 interpolate_specular(ctx, span);
1242 }
1243 ASSERT(span->arrayMask & SPAN_SPEC);
1244 add_colors( span->end, span->array->rgba, span->array->spec );
1245 }
1246
1247 /* Fog */
1248 if (ctx->Fog.Enabled) {
1249 _mesa_fog_rgba_span(ctx, span);
1250 }
1251
1252 /* Antialias coverage application */
1253 if (span->arrayMask & SPAN_COVERAGE) {
1254 GLchan (*rgba)[4] = span->array->rgba;
1255 GLfloat *coverage = span->array->coverage;
1256 GLuint i;
1257 for (i = 0; i < span->end; i++) {
1258 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
1259 }
1260 }
1261
1262 if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1263 multi_write_rgba_span(ctx, span);
1264 }
1265 else {
1266 /* normal: write to exactly one buffer */
1267 if (ctx->Color.ColorLogicOpEnabled) {
1268 _mesa_logicop_rgba_span(ctx, span, span->array->rgba);
1269 }
1270 else if (ctx->Color.BlendEnabled) {
1271 _mesa_blend_span(ctx, span, span->array->rgba);
1272 }
1273
1274 if (colorMask != 0xffffffff) {
1275 _mesa_mask_rgba_span(ctx, span, span->array->rgba);
1276 }
1277
1278
1279 if (span->arrayMask & SPAN_XY) {
1280 /* array of pixel coords */
1281 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
1282 span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask);
1283 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1284 _mesa_write_alpha_pixels(ctx, span->end,
1285 span->array->x, span->array->y,
1286 (const GLchan (*)[4]) span->array->rgba,
1287 span->array->mask);
1288 }
1289 }
1290 else {
1291 /* horizontal run of pixels */
1292 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
1293 (const GLchan (*)[4]) span->array->rgba,
1294 span->writeAll ? NULL : span->array->mask);
1295 if (swrast->_RasterMask & ALPHABUF_BIT) {
1296 _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
1297 (const GLchan (*)[4]) span->array->rgba,
1298 span->writeAll ? NULL : span->array->mask);
1299 }
1300 }
1301 }
1302
1303 span->arrayMask = origArrayMask;
1304 }
1305
1306
1307
1308 /**
1309 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1310 * reading ouside the buffer's boundaries.
1311 */
1312 void
1313 _mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
1314 GLuint n, GLint x, GLint y, GLchan rgba[][4] )
1315 {
1316 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1317 const GLint bufWidth = (GLint) buffer->Width;
1318 const GLint bufHeight = (GLint) buffer->Height;
1319
1320 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1321 /* completely above, below, or right */
1322 /* XXX maybe leave undefined? */
1323 BZERO(rgba, 4 * n * sizeof(GLchan));
1324 }
1325 else {
1326 GLint skip, length;
1327 if (x < 0) {
1328 /* left edge clippping */
1329 skip = -x;
1330 length = (GLint) n - skip;
1331 if (length < 0) {
1332 /* completely left of window */
1333 return;
1334 }
1335 if (length > bufWidth) {
1336 length = bufWidth;
1337 }
1338 }
1339 else if ((GLint) (x + n) > bufWidth) {
1340 /* right edge clipping */
1341 skip = 0;
1342 length = bufWidth - x;
1343 if (length < 0) {
1344 /* completely to right of window */
1345 return;
1346 }
1347 }
1348 else {
1349 /* no clipping */
1350 skip = 0;
1351 length = (GLint) n;
1352 }
1353
1354 (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
1355 if (buffer->UseSoftwareAlphaBuffers) {
1356 _mesa_read_alpha_span(ctx, length, x + skip, y, rgba + skip);
1357 }
1358 }
1359 }
1360
1361
1362 /**
1363 * Read CI pixels from frame buffer. Clipping will be done to prevent
1364 * reading ouside the buffer's boundaries.
1365 */
1366 void
1367 _mesa_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
1368 GLuint n, GLint x, GLint y, GLuint indx[] )
1369 {
1370 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1371 const GLint bufWidth = (GLint) buffer->Width;
1372 const GLint bufHeight = (GLint) buffer->Height;
1373
1374 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1375 /* completely above, below, or right */
1376 BZERO(indx, n * sizeof(GLuint));
1377 }
1378 else {
1379 GLint skip, length;
1380 if (x < 0) {
1381 /* left edge clippping */
1382 skip = -x;
1383 length = (GLint) n - skip;
1384 if (length < 0) {
1385 /* completely left of window */
1386 return;
1387 }
1388 if (length > bufWidth) {
1389 length = bufWidth;
1390 }
1391 }
1392 else if ((GLint) (x + n) > bufWidth) {
1393 /* right edge clipping */
1394 skip = 0;
1395 length = bufWidth - x;
1396 if (length < 0) {
1397 /* completely to right of window */
1398 return;
1399 }
1400 }
1401 else {
1402 /* no clipping */
1403 skip = 0;
1404 length = (GLint) n;
1405 }
1406
1407 (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
1408 }
1409 }