1 /* $Id: s_span.c,v 1.36 2002/02/17 17:30:57 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
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
42 #include "s_alphabuf.h"
44 #include "s_context.h"
48 #include "s_masking.h"
50 #include "s_stencil.h"
51 #include "s_texture.h"
55 * Init span's Z interpolation values to the RasterPos Z.
56 * Used during setup for glDraw/CopyPixels.
59 _mesa_span_default_z( GLcontext
*ctx
, struct sw_span
*span
)
61 if (ctx
->Visual
.depthBits
<= 16)
62 span
->z
= FloatToFixed(ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
);
64 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
);
66 span
->interpMask
|= SPAN_Z
;
71 * Init span's fog interpolation values to the RasterPos fog.
72 * Used during setup for glDraw/CopyPixels.
75 _mesa_span_default_fog( GLcontext
*ctx
, struct sw_span
*span
)
77 span
->fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
79 span
->interpMask
|= SPAN_FOG
;
84 * Init span's color or index interpolation values to the RasterPos color.
85 * Used during setup for glDraw/CopyPixels.
88 _mesa_span_default_color( GLcontext
*ctx
, struct sw_span
*span
)
90 if (ctx
->Visual
.rgbMode
) {
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
102 span
->red
= IntToFixed(r
);
103 span
->green
= IntToFixed(g
);
104 span
->blue
= IntToFixed(b
);
105 span
->alpha
= IntToFixed(a
);
111 span
->interpMask
|= SPAN_RGBA
;
114 span
->index
= IntToFixed(ctx
->Current
.RasterIndex
);
116 span
->interpMask
|= SPAN_INDEX
;
121 /* Fill in the span.color.rgba array from the interpolation values */
123 interpolate_colors(GLcontext
*ctx
, struct sw_span
*span
)
125 GLfixed r
= span
->red
;
126 GLfixed g
= span
->green
;
127 GLfixed b
= span
->blue
;
128 GLfixed a
= span
->alpha
;
129 const GLint dr
= span
->redStep
;
130 const GLint dg
= span
->greenStep
;
131 const GLint db
= span
->blueStep
;
132 const GLint da
= span
->alphaStep
;
133 const GLuint n
= span
->end
;
134 GLchan (*rgba
)[4] = span
->color
.rgba
;
137 ASSERT(span
->interpMask
& SPAN_RGBA
);
139 if (span
->interpMask
& SPAN_FLAT
) {
142 color
[RCOMP
] = FixedToChan(r
);
143 color
[GCOMP
] = FixedToChan(g
);
144 color
[BCOMP
] = FixedToChan(b
);
145 color
[ACOMP
] = FixedToChan(a
);
146 for (i
= 0; i
< n
; i
++) {
147 COPY_CHAN4(span
->color
.rgba
[i
], color
);
152 for (i
= 0; i
< n
; i
++) {
153 rgba
[i
][RCOMP
] = FixedToChan(r
);
154 rgba
[i
][GCOMP
] = FixedToChan(g
);
155 rgba
[i
][BCOMP
] = FixedToChan(b
);
156 rgba
[i
][ACOMP
] = FixedToChan(a
);
163 span
->arrayMask
|= SPAN_RGBA
;
167 /* Fill in the span.color.index array from the interpolation values */
169 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
171 GLfixed index
= span
->index
;
172 const GLint indexStep
= span
->indexStep
;
173 const GLuint n
= span
->end
;
174 GLuint
*indexes
= span
->color
.index
;
176 ASSERT(span
->interpMask
& SPAN_INDEX
);
178 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
180 index
= FixedToInt(index
);
181 for (i
= 0; i
< n
; i
++) {
187 for (i
= 0; i
< n
; i
++) {
188 indexes
[i
] = FixedToInt(index
);
192 span
->arrayMask
|= SPAN_INDEX
;
196 /* Fill in the span.specArray array from the interpolation values */
198 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
200 if (span
->interpMask
& SPAN_FLAT
) {
202 const GLchan r
= FixedToChan(span
->specRed
);
203 const GLchan g
= FixedToChan(span
->specGreen
);
204 const GLchan b
= FixedToChan(span
->specBlue
);
206 for (i
= 0; i
< span
->end
; i
++) {
207 span
->specArray
[i
][RCOMP
] = r
;
208 span
->specArray
[i
][GCOMP
] = g
;
209 span
->specArray
[i
][BCOMP
] = b
;
214 #if CHAN_TYPE == GL_FLOAT
215 GLfloat r
= span
->specRed
;
216 GLfloat g
= span
->specGreen
;
217 GLfloat b
= span
->specBlue
;
219 GLfixed r
= span
->specRed
;
220 GLfixed g
= span
->specGreen
;
221 GLfixed b
= span
->specBlue
;
224 for (i
= 0; i
< span
->end
; i
++) {
225 span
->specArray
[i
][RCOMP
] = FixedToChan(r
);
226 span
->specArray
[i
][GCOMP
] = FixedToChan(g
);
227 span
->specArray
[i
][BCOMP
] = FixedToChan(b
);
228 r
+= span
->specRedStep
;
229 g
+= span
->specGreenStep
;
230 b
+= span
->specBlueStep
;
233 span
->arrayMask
|= SPAN_SPEC
;
237 /* Fill in the span.zArray array from the interpolation values */
239 _mesa_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
241 const GLuint n
= span
->end
;
244 ASSERT(span
->interpMask
& SPAN_Z
);
246 if (ctx
->Visual
.depthBits
<= 16) {
247 GLfixed zval
= span
->z
;
248 for (i
= 0; i
< n
; i
++) {
249 span
->zArray
[i
] = FixedToInt(zval
);
254 /* Deep Z buffer, no fixed->int shift */
255 GLfixed zval
= span
->z
;
256 for (i
= 0; i
< n
; i
++) {
257 span
->zArray
[i
] = zval
;
261 span
->arrayMask
|= SPAN_Z
;
266 * Return log_base_2(x) / 2.
267 * We divide by two here since we didn't square rho in the triangle function.
272 /* This is pretty fast, but not accurate enough (only 2 fractional bits).
273 * Based on code from http://www.stereopsis.com/log2.html
275 static INLINE GLfloat
HALF_LOG2(GLfloat x
)
277 const GLfloat y
= x
* x
* x
* x
;
278 const GLuint ix
= *((GLuint
*) &y
);
279 const GLuint exp
= (ix
>> 23) & 0xFF;
280 const GLint log2
= ((GLint
) exp
) - 127;
281 return (GLfloat
) log2
* (0.5 / 4.0); /* 4, because of x^4 above */
285 /* Pretty fast, and accurate.
286 * Based on code from http://www.flipcode.com/totd/
288 static INLINE GLfloat
HALF_LOG2(GLfloat val
)
290 GLint
*exp_ptr
= (GLint
*) &val
;
292 const GLint log_2
= ((x
>> 23) & 255) - 128;
296 val
= ((-1.0f
/3) * val
+ 2) * val
- 2.0f
/3;
297 return 0.5F
* (val
+ log_2
);
302 /* Slow, portable solution.
303 * NOTE: log_base_2(x) = log(x) / log(2)
304 * NOTE: 1.442695 = 1/log(2).
306 #define HALF_LOG2(x) ((GLfloat) (log(x) * (1.442695F * 0.5F)))
308 #endif /* USE_IEEE */
313 * Fill in the span.texcoords array from the interpolation values.
314 * XXX We could optimize here for the case when dq = 0. That would
315 * usually be the case when using an orthographic projection.
318 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
320 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
322 if (ctx
->Texture
._ReallyEnabled
& ~TEXTURE0_ANY
) {
323 if (span
->interpMask
& SPAN_LAMBDA
) {
324 /* multitexture, lambda */
326 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
327 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
328 const GLfloat rho
= span
->rho
[u
];
329 const GLfloat ds
= span
->texStep
[u
][0];
330 const GLfloat dt
= span
->texStep
[u
][1];
331 const GLfloat dr
= span
->texStep
[u
][2];
332 const GLfloat dq
= span
->texStep
[u
][3];
333 GLfloat s
= span
->tex
[u
][0];
334 GLfloat t
= span
->tex
[u
][1];
335 GLfloat r
= span
->tex
[u
][2];
336 GLfloat q
= span
->tex
[u
][3];
339 /* Ortho projection or polygon's parallel to window X axis */
340 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
341 const GLfloat lambda
= HALF_LOG2(rho
* invQ
* invQ
);
342 for (i
= 0; i
< span
->end
; i
++) {
343 span
->texcoords
[u
][i
][0] = s
* invQ
;
344 span
->texcoords
[u
][i
][1] = t
* invQ
;
345 span
->texcoords
[u
][i
][2] = r
* invQ
;
346 span
->lambda
[u
][i
] = lambda
;
353 for (i
= 0; i
< span
->end
; i
++) {
354 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
355 span
->texcoords
[u
][i
][0] = s
* invQ
;
356 span
->texcoords
[u
][i
][1] = t
* invQ
;
357 span
->texcoords
[u
][i
][2] = r
* invQ
;
358 span
->lambda
[u
][i
] = HALF_LOG2(rho
* invQ
* invQ
);
367 span
->arrayMask
|= SPAN_LAMBDA
;
370 /* multitexture, no lambda */
372 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
373 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
374 const GLfloat ds
= span
->texStep
[u
][0];
375 const GLfloat dt
= span
->texStep
[u
][1];
376 const GLfloat dr
= span
->texStep
[u
][2];
377 const GLfloat dq
= span
->texStep
[u
][3];
378 GLfloat s
= span
->tex
[u
][0];
379 GLfloat t
= span
->tex
[u
][1];
380 GLfloat r
= span
->tex
[u
][2];
381 GLfloat q
= span
->tex
[u
][3];
384 /* Ortho projection or polygon's parallel to window X axis */
385 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
386 for (i
= 0; i
< span
->end
; i
++) {
387 span
->texcoords
[u
][i
][0] = s
* invQ
;
388 span
->texcoords
[u
][i
][1] = t
* invQ
;
389 span
->texcoords
[u
][i
][2] = r
* invQ
;
396 for (i
= 0; i
< span
->end
; i
++) {
397 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
398 span
->texcoords
[u
][i
][0] = s
* invQ
;
399 span
->texcoords
[u
][i
][1] = t
* invQ
;
400 span
->texcoords
[u
][i
][2] = r
* invQ
;
412 if (span
->interpMask
& SPAN_LAMBDA
) {
413 /* just texture unit 0, with lambda */
414 const GLfloat rho
= span
->rho
[0];
415 const GLfloat ds
= span
->texStep
[0][0];
416 const GLfloat dt
= span
->texStep
[0][1];
417 const GLfloat dr
= span
->texStep
[0][2];
418 const GLfloat dq
= span
->texStep
[0][3];
419 GLfloat s
= span
->tex
[0][0];
420 GLfloat t
= span
->tex
[0][1];
421 GLfloat r
= span
->tex
[0][2];
422 GLfloat q
= span
->tex
[0][3];
425 /* Ortho projection or polygon's parallel to window X axis */
426 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
427 const GLfloat lambda
= HALF_LOG2(rho
* invQ
* invQ
);
428 for (i
= 0; i
< span
->end
; i
++) {
429 span
->texcoords
[0][i
][0] = s
* invQ
;
430 span
->texcoords
[0][i
][1] = t
* invQ
;
431 span
->texcoords
[0][i
][2] = r
* invQ
;
432 span
->lambda
[0][i
] = lambda
;
439 for (i
= 0; i
< span
->end
; i
++) {
440 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
441 span
->texcoords
[0][i
][0] = s
* invQ
;
442 span
->texcoords
[0][i
][1] = t
* invQ
;
443 span
->texcoords
[0][i
][2] = r
* invQ
;
444 span
->lambda
[0][i
] = HALF_LOG2(rho
* invQ
* invQ
);
451 span
->arrayMask
|= SPAN_LAMBDA
;
454 /* just texture 0, without lambda */
455 const GLfloat ds
= span
->texStep
[0][0];
456 const GLfloat dt
= span
->texStep
[0][1];
457 const GLfloat dr
= span
->texStep
[0][2];
458 const GLfloat dq
= span
->texStep
[0][3];
459 GLfloat s
= span
->tex
[0][0];
460 GLfloat t
= span
->tex
[0][1];
461 GLfloat r
= span
->tex
[0][2];
462 GLfloat q
= span
->tex
[0][3];
465 /* Ortho projection or polygon's parallel to window X axis */
466 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
467 for (i
= 0; i
< span
->end
; i
++) {
468 span
->texcoords
[0][i
][0] = s
* invQ
;
469 span
->texcoords
[0][i
][1] = t
* invQ
;
470 span
->texcoords
[0][i
][2] = r
* invQ
;
477 for (i
= 0; i
< span
->end
; i
++) {
478 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
479 span
->texcoords
[0][i
][0] = s
* invQ
;
480 span
->texcoords
[0][i
][1] = t
* invQ
;
481 span
->texcoords
[0][i
][2] = r
* invQ
;
494 * Apply the current polygon stipple pattern to a span of pixels.
497 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
499 const GLuint highbit
= 0x80000000;
500 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
503 ASSERT(ctx
->Polygon
.StippleFlag
);
504 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
506 m
= highbit
>> (GLuint
) (span
->x
% 32);
508 for (i
= 0; i
< span
->end
; i
++) {
509 if ((m
& stipple
) == 0) {
517 span
->writeAll
= GL_FALSE
;
522 * Clip a pixel span to the current buffer/window boundaries:
523 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
524 * window clipping and scissoring.
525 * Return: GL_TRUE some pixels still visible
526 * GL_FALSE nothing visible
529 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
531 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
532 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
533 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
534 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
536 if (span
->arrayMask
& SPAN_XY
) {
537 /* arrays of x/y pixel coords */
538 const GLint
*x
= span
->xArray
;
539 const GLint
*y
= span
->yArray
;
540 const GLint n
= span
->end
;
541 GLubyte
*mask
= span
->mask
;
543 if (span
->arrayMask
& SPAN_MASK
) {
544 /* note: using & intead of && to reduce branches */
545 for (i
= 0; i
< n
; i
++) {
546 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
547 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
551 /* note: using & intead of && to reduce branches */
552 for (i
= 0; i
< n
; i
++) {
553 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
554 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
557 return GL_TRUE
; /* some pixels visible */
560 /* horizontal span of pixels */
561 const GLint x
= span
->x
;
562 const GLint y
= span
->y
;
563 const GLint n
= span
->end
;
565 /* Trivial rejection tests */
566 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
568 return GL_FALSE
; /* all pixels clipped */
571 /* Clip to the left */
573 ASSERT(x
+ n
> xmin
);
574 span
->writeAll
= GL_FALSE
;
575 BZERO(span
->mask
, (xmin
- x
) * sizeof(GLubyte
));
581 span
->end
= xmax
- x
;
584 return GL_TRUE
; /* some pixels visible */
591 * Draw to more than one color buffer (or none).
594 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
596 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
599 /* loop over four possible dest color buffers */
600 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
601 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
602 GLuint indexTmp
[MAX_WIDTH
];
603 ASSERT(span
->end
< MAX_WIDTH
);
605 if (bufferBit
== FRONT_LEFT_BIT
)
606 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
607 else if (bufferBit
== FRONT_RIGHT_BIT
)
608 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
609 else if (bufferBit
== BACK_LEFT_BIT
)
610 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
612 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
614 /* make copy of incoming indexes */
615 MEMCPY( indexTmp
, span
->color
.index
, span
->end
* sizeof(GLuint
) );
617 if (ctx
->Color
.IndexLogicOpEnabled
) {
618 _mesa_logicop_ci_span(ctx
, span
, indexTmp
);
621 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
622 _mesa_mask_index_span(ctx
, span
, indexTmp
);
625 if (span
->arrayMask
& SPAN_XY
) {
626 /* array of pixel coords */
627 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
628 span
->xArray
, span
->yArray
,
629 indexTmp
, span
->mask
);
632 /* horizontal run of pixels */
633 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
634 indexTmp
, span
->mask
);
639 /* restore default dest buffer */
640 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
645 * Draw to more than one RGBA color buffer (or none).
646 * All fragment operations, up to (but not) blending/logicop should
647 * have been done first.
650 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
652 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
654 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
656 ASSERT(colorMask
!= 0x0);
658 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
661 /* loop over four possible dest color buffers */
662 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
663 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
664 GLchan rgbaTmp
[MAX_WIDTH
][4];
665 ASSERT(span
->end
< MAX_WIDTH
);
667 if (bufferBit
== FRONT_LEFT_BIT
) {
668 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
669 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontLeftAlpha
;
671 else if (bufferBit
== FRONT_RIGHT_BIT
) {
672 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
673 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontRightAlpha
;
675 else if (bufferBit
== BACK_LEFT_BIT
) {
676 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
677 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackLeftAlpha
;
680 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
681 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackRightAlpha
;
684 /* make copy of incoming colors */
685 MEMCPY( rgbaTmp
, span
->color
.rgba
, 4 * span
->end
* sizeof(GLchan
) );
687 if (ctx
->Color
.ColorLogicOpEnabled
) {
688 _mesa_logicop_rgba_span(ctx
, span
, rgbaTmp
);
690 else if (ctx
->Color
.BlendEnabled
) {
691 _mesa_blend_span(ctx
, span
, rgbaTmp
);
694 if (colorMask
!= 0xffffffff) {
695 _mesa_mask_rgba_span(ctx
, span
, rgbaTmp
);
698 if (span
->arrayMask
& SPAN_XY
) {
699 /* array of pixel coords */
700 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
701 span
->xArray
, span
->yArray
,
702 (const GLchan (*)[4]) rgbaTmp
,
704 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
705 _mesa_write_alpha_pixels(ctx
, span
->end
,
706 span
->xArray
, span
->yArray
,
707 (const GLchan (*)[4]) rgbaTmp
,
712 /* horizontal run of pixels */
713 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
714 (const GLchan (*)[4]) rgbaTmp
,
716 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
717 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
718 (const GLchan (*)[4]) rgbaTmp
,
725 /* restore default dest buffer */
726 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
732 * This function may modify any of the array values in the span.
733 * span->interpMask and span->arrayMask may be changed but will be restored
734 * to their original values before returning.
737 _mesa_write_index_span( GLcontext
*ctx
, struct sw_span
*span
,
740 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
741 const GLuint origInterpMask
= span
->interpMask
;
742 const GLuint origArrayMask
= span
->arrayMask
;
744 ASSERT(span
->end
<= MAX_WIDTH
);
745 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
746 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
748 if (span
->arrayMask
& SPAN_MASK
) {
749 /* mask was initialized by caller, probably glBitmap */
750 span
->writeAll
= GL_FALSE
;
753 MEMSET(span
->mask
, 1, span
->end
);
754 span
->writeAll
= GL_TRUE
;
758 if ((swrast
->_RasterMask
& CLIP_BIT
) || (primitive
== GL_BITMAP
)
759 || (primitive
== GL_POINT
) || (primitive
== GL_LINE
)) {
760 if (!clip_span(ctx
, span
)) {
766 if (span
->arrayMask
& SPAN_XY
) {
768 for (i
= 0; i
< span
->end
; i
++) {
770 assert(span
->xArray
[i
] >= ctx
->DrawBuffer
->_Xmin
);
771 assert(span
->xArray
[i
] < ctx
->DrawBuffer
->_Xmax
);
772 assert(span
->yArray
[i
] >= ctx
->DrawBuffer
->_Ymin
);
773 assert(span
->yArray
[i
] < ctx
->DrawBuffer
->_Ymax
);
779 /* Polygon Stippling */
780 if (ctx
->Polygon
.StippleFlag
&& primitive
== GL_POLYGON
) {
781 stipple_polygon_span(ctx
, span
);
784 /* Depth test and stencil */
785 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
786 if (span
->interpMask
& SPAN_Z
)
787 _mesa_span_interpolate_z(ctx
, span
);
789 if (ctx
->Stencil
.Enabled
) {
790 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
791 span
->arrayMask
= origArrayMask
;
796 ASSERT(ctx
->Depth
.Test
);
797 if (!_mesa_depth_test_span(ctx
, span
)) {
798 span
->arrayMask
= origArrayMask
;
804 /* if we get here, something passed the depth test */
805 ctx
->OcclusionResult
= GL_TRUE
;
807 /* we have to wait until after occlusion to do this test */
808 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
809 /* write no pixels */
810 span
->arrayMask
= origArrayMask
;
814 /* Interpolate the color indexes if needed */
815 if (span
->interpMask
& SPAN_INDEX
) {
816 interpolate_indexes(ctx
, span
);
817 /* clear the bit - this allows the WriteMonoCISpan optimization below */
818 span
->interpMask
&= ~SPAN_INDEX
;
822 if (ctx
->Fog
.Enabled
) {
823 _mesa_fog_ci_span(ctx
, span
);
826 /* Antialias coverage application */
827 if (span
->arrayMask
& SPAN_COVERAGE
) {
829 GLuint
*index
= span
->color
.index
;
830 for (i
= 0; i
< span
->end
; i
++) {
831 ASSERT(span
->coverage
[i
] < 16);
832 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) (span
->coverage
[i
]));
836 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
837 /* draw to zero or two or more buffers */
838 multi_write_index_span(ctx
, span
);
841 /* normal situation: draw to exactly one buffer */
842 if (ctx
->Color
.IndexLogicOpEnabled
) {
843 _mesa_logicop_ci_span(ctx
, span
, span
->color
.index
);
846 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
847 _mesa_mask_index_span(ctx
, span
, span
->color
.index
);
851 if (span
->arrayMask
& SPAN_XY
) {
852 /* array of pixel coords */
853 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
854 /* all pixels have same color index */
855 (*swrast
->Driver
.WriteMonoCIPixels
)(ctx
, span
->end
,
856 span
->xArray
, span
->yArray
,
857 FixedToInt(span
->index
),
861 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->xArray
,
862 span
->yArray
, span
->color
.index
,
867 /* horizontal run of pixels */
868 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
869 /* all pixels have same color index */
870 (*swrast
->Driver
.WriteMonoCISpan
)(ctx
, span
->end
, span
->x
, span
->y
,
871 FixedToInt(span
->index
),
875 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
876 span
->color
.index
, span
->mask
);
881 span
->interpMask
= origInterpMask
;
882 span
->arrayMask
= origArrayMask
;
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.
892 _mesa_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
,
895 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
896 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
897 const GLuint origInterpMask
= span
->interpMask
;
898 const GLuint origArrayMask
= span
->arrayMask
;
901 ASSERT(span
->end
<= MAX_WIDTH
);
902 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
903 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_RGBA
);
905 if (ctx
->Fog
.Enabled
)
906 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
908 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_Z
);
912 printf("%s() interp 0x%x array 0x%x p=0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask, primitive);
915 if (span
->arrayMask
& SPAN_MASK
) {
916 /* mask was initialized by caller, probably glBitmap */
917 span
->writeAll
= GL_FALSE
;
920 MEMSET(span
->mask
, 1, span
->end
);
921 span
->writeAll
= GL_TRUE
;
924 /* Determine if we have mono-chromatic colors */
925 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
926 span
->redStep
== 0 && span
->greenStep
== 0 &&
927 span
->blueStep
== 0 && span
->alphaStep
== 0;
930 if ((swrast
->_RasterMask
& CLIP_BIT
) || (primitive
== GL_BITMAP
)
931 || (primitive
== GL_POINT
) || (primitive
== GL_LINE
)) {
932 if (!clip_span(ctx
, span
)) {
938 if (span
->arrayMask
& SPAN_XY
) {
940 for (i
= 0; i
< span
->end
; i
++) {
942 assert(span
->xArray
[i
] >= ctx
->DrawBuffer
->_Xmin
);
943 assert(span
->xArray
[i
] < ctx
->DrawBuffer
->_Xmax
);
944 assert(span
->yArray
[i
] >= ctx
->DrawBuffer
->_Ymin
);
945 assert(span
->yArray
[i
] < ctx
->DrawBuffer
->_Ymax
);
951 /* Polygon Stippling */
952 if (ctx
->Polygon
.StippleFlag
&& primitive
== GL_POLYGON
) {
953 stipple_polygon_span(ctx
, span
);
956 /* Do the alpha test */
957 if (ctx
->Color
.AlphaEnabled
) {
958 if (!_mesa_alpha_test(ctx
, span
)) {
959 span
->interpMask
= origInterpMask
;
960 span
->arrayMask
= origArrayMask
;
965 /* Stencil and Z testing */
966 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
967 if (span
->interpMask
& SPAN_Z
)
968 _mesa_span_interpolate_z(ctx
, span
);
970 if (ctx
->Stencil
.Enabled
) {
971 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
972 span
->interpMask
= origInterpMask
;
973 span
->arrayMask
= origArrayMask
;
978 ASSERT(ctx
->Depth
.Test
);
979 ASSERT(span
->arrayMask
& SPAN_Z
);
980 /* regular depth testing */
981 if (!_mesa_depth_test_span(ctx
, span
)) {
982 span
->interpMask
= origInterpMask
;
983 span
->arrayMask
= origArrayMask
;
989 /* if we get here, something passed the depth test */
990 ctx
->OcclusionResult
= GL_TRUE
;
992 /* can't abort span-writing until after occlusion testing */
993 if (colorMask
== 0x0) {
994 span
->interpMask
= origInterpMask
;
995 span
->arrayMask
= origArrayMask
;
999 /* Now we may need to interpolate the colors */
1000 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
1001 interpolate_colors(ctx
, span
);
1002 /* clear the bit - this allows the WriteMonoCISpan optimization below */
1003 span
->interpMask
&= ~SPAN_RGBA
;
1007 if (ctx
->Fog
.Enabled
) {
1008 _mesa_fog_rgba_span(ctx
, span
);
1009 monoColor
= GL_FALSE
;
1012 /* Antialias coverage application */
1013 if (span
->arrayMask
& SPAN_COVERAGE
) {
1014 GLchan (*rgba
)[4] = span
->color
.rgba
;
1016 for (i
= 0; i
< span
->end
; i
++) {
1017 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * span
->coverage
[i
]);
1019 monoColor
= GL_FALSE
;
1022 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1023 multi_write_rgba_span(ctx
, span
);
1026 /* normal: write to exactly one buffer */
1027 if (ctx
->Color
.ColorLogicOpEnabled
) {
1028 _mesa_logicop_rgba_span(ctx
, span
, span
->color
.rgba
);
1029 monoColor
= GL_FALSE
;
1031 else if (ctx
->Color
.BlendEnabled
) {
1032 _mesa_blend_span(ctx
, span
, span
->color
.rgba
);
1033 monoColor
= GL_FALSE
;
1036 /* Color component masking */
1037 if (colorMask
!= 0xffffffff) {
1038 _mesa_mask_rgba_span(ctx
, span
, span
->color
.rgba
);
1039 monoColor
= GL_FALSE
;
1043 if (span
->arrayMask
& SPAN_XY
) {
1044 /* array of pixel coords */
1045 /* XXX test for mono color */
1046 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->xArray
,
1047 span
->yArray
, (const GLchan (*)[4]) span
->color
.rgba
, span
->mask
);
1048 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1049 _mesa_write_alpha_pixels(ctx
, span
->end
,
1050 span
->xArray
, span
->yArray
,
1051 (const GLchan (*)[4]) span
->color
.rgba
,
1056 /* horizontal run of pixels */
1058 /* all pixels have same color */
1060 color
[RCOMP
] = FixedToChan(span
->red
);
1061 color
[GCOMP
] = FixedToChan(span
->green
);
1062 color
[BCOMP
] = FixedToChan(span
->blue
);
1063 color
[ACOMP
] = FixedToChan(span
->alpha
);
1064 (*swrast
->Driver
.WriteMonoRGBASpan
)(ctx
, span
->end
, span
->x
,
1065 span
->y
, color
, span
->mask
);
1066 /* XXX software alpha buffer writes! */
1069 /* each pixel is a different color */
1070 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1071 (const GLchan (*)[4]) span
->color
.rgba
,
1072 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->mask
);
1073 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1074 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1075 (const GLchan (*)[4]) span
->color
.rgba
,
1076 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->mask
);
1082 span
->interpMask
= origInterpMask
;
1083 span
->arrayMask
= origArrayMask
;
1088 * Add specular color to base color. This is used only when
1089 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1092 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1095 for (i
= 0; i
< n
; i
++) {
1096 #if CHAN_TYPE == GL_FLOAT
1098 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1099 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1100 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1102 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1103 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1104 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1105 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1106 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1107 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1114 * This function may modify any of the array values in the span.
1115 * span->interpMask and span->arrayMask may be changed but will be restored
1116 * to their original values before returning.
1119 _mesa_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
,
1122 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1123 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1124 const GLuint origArrayMask
= span
->arrayMask
;
1126 ASSERT(span
->end
<= MAX_WIDTH
);
1127 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1128 ASSERT(ctx
->Texture
._ReallyEnabled
);
1131 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1134 if (span
->arrayMask
& SPAN_MASK
) {
1135 /* mask was initialized by caller, probably glBitmap */
1136 span
->writeAll
= GL_FALSE
;
1139 MEMSET(span
->mask
, 1, span
->end
);
1140 span
->writeAll
= GL_TRUE
;
1144 if ((swrast
->_RasterMask
& CLIP_BIT
) || (primitive
== GL_BITMAP
)
1145 || (primitive
== GL_POINT
) || (primitive
== GL_LINE
)) {
1146 if (!clip_span(ctx
, span
)) {
1152 if (span
->arrayMask
& SPAN_XY
) {
1154 for (i
= 0; i
< span
->end
; i
++) {
1155 if (span
->mask
[i
]) {
1156 assert(span
->xArray
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1157 assert(span
->xArray
[i
] < ctx
->DrawBuffer
->_Xmax
);
1158 assert(span
->yArray
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1159 assert(span
->yArray
[i
] < ctx
->DrawBuffer
->_Ymax
);
1165 /* Polygon Stippling */
1166 if (ctx
->Polygon
.StippleFlag
&& primitive
== GL_POLYGON
) {
1167 stipple_polygon_span(ctx
, span
);
1170 /* Need texture coordinates now */
1171 if ((span
->interpMask
& SPAN_TEXTURE
)
1172 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1173 interpolate_texcoords(ctx
, span
);
1175 /* Texture with alpha test */
1176 if (ctx
->Color
.AlphaEnabled
) {
1178 /* Now we need the rgba array, fill it in if needed */
1179 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1180 interpolate_colors(ctx
, span
);
1182 /* Texturing without alpha is done after depth-testing which
1183 * gives a potential speed-up.
1185 _swrast_multitexture_fragments( ctx
, span
);
1187 /* Do the alpha test */
1188 if (!_mesa_alpha_test(ctx
, span
)) {
1189 span
->arrayMask
= origArrayMask
;
1194 /* Stencil and Z testing */
1195 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1196 if (span
->interpMask
& SPAN_Z
)
1197 _mesa_span_interpolate_z(ctx
, span
);
1199 if (ctx
->Stencil
.Enabled
) {
1200 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
1201 span
->arrayMask
= origArrayMask
;
1206 ASSERT(ctx
->Depth
.Test
);
1207 ASSERT(span
->arrayMask
& SPAN_Z
);
1208 /* regular depth testing */
1209 if (!_mesa_depth_test_span(ctx
, span
)) {
1210 span
->arrayMask
= origArrayMask
;
1216 /* if we get here, some fragments passed the depth test */
1217 ctx
->OcclusionResult
= GL_TRUE
;
1219 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1220 * the occlusion test.
1222 if (colorMask
== 0x0) {
1223 span
->arrayMask
= origArrayMask
;
1227 /* Texture without alpha test */
1228 if (!ctx
->Color
.AlphaEnabled
) {
1230 /* Now we need the rgba array, fill it in if needed */
1231 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1232 interpolate_colors(ctx
, span
);
1234 _swrast_multitexture_fragments( ctx
, span
);
1237 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1239 /* Add base and specular colors */
1240 if (ctx
->Fog
.ColorSumEnabled
||
1241 (ctx
->Light
.Enabled
&&
1242 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1243 if (span
->interpMask
& SPAN_SPEC
) {
1244 interpolate_specular(ctx
, span
);
1246 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1247 add_colors( span
->end
, span
->color
.rgba
, span
->specArray
);
1251 if (ctx
->Fog
.Enabled
) {
1252 _mesa_fog_rgba_span(ctx
, span
);
1255 /* Antialias coverage application */
1256 if (span
->arrayMask
& SPAN_COVERAGE
) {
1257 GLchan (*rgba
)[4] = span
->color
.rgba
;
1259 for (i
= 0; i
< span
->end
; i
++) {
1260 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * span
->coverage
[i
]);
1264 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1265 multi_write_rgba_span(ctx
, span
);
1268 /* normal: write to exactly one buffer */
1269 if (ctx
->Color
.ColorLogicOpEnabled
) {
1270 _mesa_logicop_rgba_span(ctx
, span
, span
->color
.rgba
);
1272 else if (ctx
->Color
.BlendEnabled
) {
1273 _mesa_blend_span(ctx
, span
, span
->color
.rgba
);
1276 if (colorMask
!= 0xffffffff) {
1277 _mesa_mask_rgba_span(ctx
, span
, span
->color
.rgba
);
1281 if (span
->arrayMask
& SPAN_XY
) {
1282 /* array of pixel coords */
1283 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->xArray
,
1284 span
->yArray
, (const GLchan (*)[4]) span
->color
.rgba
, span
->mask
);
1285 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1286 _mesa_write_alpha_pixels(ctx
, span
->end
,
1287 span
->xArray
, span
->yArray
,
1288 (const GLchan (*)[4]) span
->color
.rgba
,
1293 /* horizontal run of pixels */
1294 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1295 (const GLchan (*)[4]) span
->color
.rgba
,
1296 span
->writeAll
? NULL
: span
->mask
);
1297 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1298 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1299 (const GLchan (*)[4]) span
->color
.rgba
,
1300 span
->writeAll
? NULL
: span
->mask
);
1305 span
->arrayMask
= origArrayMask
;
1311 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1312 * reading ouside the buffer's boundaries.
1315 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1316 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1318 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1319 if (y
< 0 || y
>= buffer
->Height
1320 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1321 /* completely above, below, or right */
1322 /* XXX maybe leave undefined? */
1323 BZERO(rgba
, 4 * n
* sizeof(GLchan
));
1328 /* left edge clippping */
1330 length
= (GLint
) n
- skip
;
1332 /* completely left of window */
1335 if (length
> buffer
->Width
) {
1336 length
= buffer
->Width
;
1339 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1340 /* right edge clipping */
1342 length
= buffer
->Width
- x
;
1344 /* completely to right of window */
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
);
1363 * Read CI pixels from frame buffer. Clipping will be done to prevent
1364 * reading ouside the buffer's boundaries.
1367 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1368 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1370 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1371 if (y
< 0 || y
>= buffer
->Height
1372 || x
+ (GLint
) n
< 0 || x
>= buffer
->Width
) {
1373 /* completely above, below, or right */
1374 BZERO(indx
, n
* sizeof(GLuint
));
1379 /* left edge clippping */
1381 length
= (GLint
) n
- skip
;
1383 /* completely left of window */
1386 if (length
> buffer
->Width
) {
1387 length
= buffer
->Width
;
1390 else if ((GLint
) (x
+ n
) > buffer
->Width
) {
1391 /* right edge clipping */
1393 length
= buffer
->Width
- x
;
1395 /* completely to right of window */
1405 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);