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