1 /* $Id: s_span.c,v 1.42 2002/05/02 00:59:20 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
43 #include "s_alphabuf.h"
45 #include "s_context.h"
49 #include "s_masking.h"
51 #include "s_stencil.h"
52 #include "s_texture.h"
56 * Init span's Z interpolation values to the RasterPos Z.
57 * Used during setup for glDraw/CopyPixels.
60 _mesa_span_default_z( GLcontext
*ctx
, struct sw_span
*span
)
62 if (ctx
->Visual
.depthBits
<= 16)
63 span
->z
= FloatToFixed(ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
);
65 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
);
67 span
->interpMask
|= SPAN_Z
;
72 * Init span's fog interpolation values to the RasterPos fog.
73 * Used during setup for glDraw/CopyPixels.
76 _mesa_span_default_fog( GLcontext
*ctx
, struct sw_span
*span
)
78 span
->fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
80 span
->interpMask
|= SPAN_FOG
;
85 * Init span's color or index interpolation values to the RasterPos color.
86 * Used during setup for glDraw/CopyPixels.
89 _mesa_span_default_color( GLcontext
*ctx
, struct sw_span
*span
)
91 if (ctx
->Visual
.rgbMode
) {
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
103 span
->red
= IntToFixed(r
);
104 span
->green
= IntToFixed(g
);
105 span
->blue
= IntToFixed(b
);
106 span
->alpha
= IntToFixed(a
);
112 span
->interpMask
|= SPAN_RGBA
;
115 span
->index
= IntToFixed(ctx
->Current
.RasterIndex
);
117 span
->interpMask
|= SPAN_INDEX
;
122 /* Fill in the span.color.rgba array from the interpolation values */
124 interpolate_colors(GLcontext
*ctx
, struct sw_span
*span
)
126 GLfixed r
= span
->red
;
127 GLfixed g
= span
->green
;
128 GLfixed b
= span
->blue
;
129 GLfixed a
= span
->alpha
;
130 const GLint dr
= span
->redStep
;
131 const GLint dg
= span
->greenStep
;
132 const GLint db
= span
->blueStep
;
133 const GLint da
= span
->alphaStep
;
134 const GLuint n
= span
->end
;
135 GLchan (*rgba
)[4] = span
->color
.rgba
;
138 ASSERT((span
->interpMask
& SPAN_RGBA
) &&
139 !(span
->arrayMask
& SPAN_RGBA
));
141 if (span
->interpMask
& SPAN_FLAT
) {
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
);
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
);
165 span
->arrayMask
|= SPAN_RGBA
;
169 /* Fill in the span.color.index array from the interpolation values */
171 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
173 GLfixed index
= span
->index
;
174 const GLint indexStep
= span
->indexStep
;
175 const GLuint n
= span
->end
;
176 GLuint
*indexes
= span
->color
.index
;
178 ASSERT((span
->interpMask
& SPAN_INDEX
) &&
179 !(span
->arrayMask
& SPAN_INDEX
));
181 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
183 index
= FixedToInt(index
);
184 for (i
= 0; i
< n
; i
++) {
190 for (i
= 0; i
< n
; i
++) {
191 indexes
[i
] = FixedToInt(index
);
195 span
->arrayMask
|= SPAN_INDEX
;
199 /* Fill in the span.specArray array from the interpolation values */
201 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
203 if (span
->interpMask
& SPAN_FLAT
) {
205 const GLchan r
= FixedToChan(span
->specRed
);
206 const GLchan g
= FixedToChan(span
->specGreen
);
207 const GLchan b
= FixedToChan(span
->specBlue
);
209 for (i
= 0; i
< span
->end
; i
++) {
210 span
->specArray
[i
][RCOMP
] = r
;
211 span
->specArray
[i
][GCOMP
] = g
;
212 span
->specArray
[i
][BCOMP
] = b
;
217 #if CHAN_TYPE == GL_FLOAT
218 GLfloat r
= span
->specRed
;
219 GLfloat g
= span
->specGreen
;
220 GLfloat b
= span
->specBlue
;
222 GLfixed r
= span
->specRed
;
223 GLfixed g
= span
->specGreen
;
224 GLfixed b
= span
->specBlue
;
227 for (i
= 0; i
< span
->end
; i
++) {
228 span
->specArray
[i
][RCOMP
] = FixedToChan(r
);
229 span
->specArray
[i
][GCOMP
] = FixedToChan(g
);
230 span
->specArray
[i
][BCOMP
] = FixedToChan(b
);
231 r
+= span
->specRedStep
;
232 g
+= span
->specGreenStep
;
233 b
+= span
->specBlueStep
;
236 span
->arrayMask
|= SPAN_SPEC
;
240 /* Fill in the span.zArray array from the interpolation values */
242 _mesa_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
244 const GLuint n
= span
->end
;
247 ASSERT((span
->interpMask
& SPAN_Z
) &&
248 !(span
->arrayMask
& SPAN_Z
));
250 if (ctx
->Visual
.depthBits
<= 16) {
251 GLfixed zval
= span
->z
;
252 for (i
= 0; i
< n
; i
++) {
253 span
->zArray
[i
] = FixedToInt(zval
);
258 /* Deep Z buffer, no fixed->int shift */
259 GLfixed zval
= span
->z
;
260 for (i
= 0; i
< n
; i
++) {
261 span
->zArray
[i
] = zval
;
265 span
->arrayMask
|= SPAN_Z
;
270 * This the ideal solution, as given in the OpenGL spec.
274 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
275 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
276 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
278 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
279 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
280 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
281 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
282 GLfloat x
= sqrt(dudx
* dudx
+ dvdx
* dvdx
);
283 GLfloat y
= sqrt(dudy
* dudy
+ dvdy
* dvdy
);
284 GLfloat rho
= MAX2(x
, y
);
285 GLfloat lambda
= LOG2(rho
);
292 * This is a faster approximation
295 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
296 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
297 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
299 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
300 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
301 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
302 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
303 GLfloat maxU
, maxV
, rho
, lambda
;
304 dsdx2
= FABSF(dsdx2
);
305 dsdy2
= FABSF(dsdy2
);
306 dtdx2
= FABSF(dtdx2
);
307 dtdy2
= FABSF(dtdy2
);
308 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
309 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
310 rho
= MAX2(maxU
, maxV
);
316 * Fill in the span.texcoords array from the interpolation values.
317 * XXX We could optimize here for the case when dq = 0. That would
318 * usually be the case when using an orthographic projection.
321 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
323 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
324 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
326 if (ctx
->Texture
._ReallyEnabled
& ~TEXTURE0_ANY
) {
329 span
->arrayMask
|= SPAN_TEXTURE
;
330 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
331 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
332 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
333 const struct gl_texture_image
*img
= obj
->Image
[obj
->BaseLevel
];
334 GLboolean needLambda
= (obj
->MinFilter
!= obj
->MagFilter
);
336 const GLfloat texW
= (GLfloat
) img
->Width
;
337 const GLfloat texH
= (GLfloat
) img
->Height
;
338 const GLfloat dsdx
= span
->texStepX
[u
][0];
339 const GLfloat dsdy
= span
->texStepY
[u
][0];
340 const GLfloat dtdx
= span
->texStepX
[u
][1];
341 const GLfloat dtdy
= span
->texStepY
[u
][1];
342 const GLfloat drdx
= span
->texStepX
[u
][2];
343 const GLfloat dqdx
= span
->texStepX
[u
][3];
344 const GLfloat dqdy
= span
->texStepY
[u
][3];
345 GLfloat s
= span
->tex
[u
][0];
346 GLfloat t
= span
->tex
[u
][1];
347 GLfloat r
= span
->tex
[u
][2];
348 GLfloat q
= span
->tex
[u
][3];
350 for (i
= 0; i
< span
->end
; i
++) {
351 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
352 span
->texcoords
[u
][i
][0] = s
* invQ
;
353 span
->texcoords
[u
][i
][1] = t
* invQ
;
354 span
->texcoords
[u
][i
][2] = r
* invQ
;
355 span
->lambda
[u
][i
] = compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
356 dqdx
, dqdy
, texW
, texH
,
363 span
->arrayMask
|= SPAN_LAMBDA
;
366 const GLfloat dsdx
= span
->texStepX
[u
][0];
367 const GLfloat dtdx
= span
->texStepX
[u
][1];
368 const GLfloat drdx
= span
->texStepX
[u
][2];
369 const GLfloat dqdx
= span
->texStepX
[u
][3];
370 GLfloat s
= span
->tex
[u
][0];
371 GLfloat t
= span
->tex
[u
][1];
372 GLfloat r
= span
->tex
[u
][2];
373 GLfloat q
= span
->tex
[u
][3];
376 /* Ortho projection or polygon's parallel to window X axis */
377 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
378 for (i
= 0; i
< span
->end
; i
++) {
379 span
->texcoords
[u
][i
][0] = s
* invQ
;
380 span
->texcoords
[u
][i
][1] = t
* invQ
;
381 span
->texcoords
[u
][i
][2] = r
* invQ
;
382 span
->lambda
[u
][i
] = 0.0;
389 for (i
= 0; i
< span
->end
; i
++) {
390 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
391 span
->texcoords
[u
][i
][0] = s
* invQ
;
392 span
->texcoords
[u
][i
][1] = t
* invQ
;
393 span
->texcoords
[u
][i
][2] = r
* invQ
;
394 span
->lambda
[u
][i
] = 0.0;
407 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
408 const struct gl_texture_image
*img
= obj
->Image
[obj
->BaseLevel
];
409 GLboolean needLambda
= (obj
->MinFilter
!= obj
->MagFilter
);
410 span
->arrayMask
|= SPAN_TEXTURE
;
412 /* just texture unit 0, with lambda */
413 const GLfloat texW
= (GLfloat
) img
->Width
;
414 const GLfloat texH
= (GLfloat
) img
->Height
;
415 const GLfloat dsdx
= span
->texStepX
[0][0];
416 const GLfloat dsdy
= span
->texStepY
[0][0];
417 const GLfloat dtdx
= span
->texStepX
[0][1];
418 const GLfloat dtdy
= span
->texStepY
[0][1];
419 const GLfloat drdx
= span
->texStepX
[0][2];
420 const GLfloat dqdx
= span
->texStepX
[0][3];
421 const GLfloat dqdy
= span
->texStepY
[0][3];
422 GLfloat s
= span
->tex
[0][0];
423 GLfloat t
= span
->tex
[0][1];
424 GLfloat r
= span
->tex
[0][2];
425 GLfloat q
= span
->tex
[0][3];
427 for (i
= 0; i
< span
->end
; i
++) {
428 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
429 span
->lambda
[0][i
] = compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
430 dqdx
, dqdy
, texW
, texH
,
432 span
->texcoords
[0][i
][0] = s
* invQ
;
433 span
->texcoords
[0][i
][1] = t
* invQ
;
434 span
->texcoords
[0][i
][2] = r
* invQ
;
440 span
->arrayMask
|= SPAN_LAMBDA
;
443 /* just texture 0, without lambda */
444 const GLfloat dsdx
= span
->texStepX
[0][0];
445 const GLfloat dtdx
= span
->texStepX
[0][1];
446 const GLfloat drdx
= span
->texStepX
[0][2];
447 const GLfloat dqdx
= span
->texStepX
[0][3];
448 GLfloat s
= span
->tex
[0][0];
449 GLfloat t
= span
->tex
[0][1];
450 GLfloat r
= span
->tex
[0][2];
451 GLfloat q
= span
->tex
[0][3];
454 /* Ortho projection or polygon's parallel to window X axis */
455 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
456 for (i
= 0; i
< span
->end
; i
++) {
457 span
->texcoords
[0][i
][0] = s
* invQ
;
458 span
->texcoords
[0][i
][1] = t
* invQ
;
459 span
->texcoords
[0][i
][2] = r
* invQ
;
466 for (i
= 0; i
< span
->end
; i
++) {
467 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
468 span
->texcoords
[0][i
][0] = s
* invQ
;
469 span
->texcoords
[0][i
][1] = t
* invQ
;
470 span
->texcoords
[0][i
][2] = r
* invQ
;
483 * Apply the current polygon stipple pattern to a span of pixels.
486 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
488 const GLuint highbit
= 0x80000000;
489 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
492 ASSERT(ctx
->Polygon
.StippleFlag
);
493 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
495 m
= highbit
>> (GLuint
) (span
->x
% 32);
497 for (i
= 0; i
< span
->end
; i
++) {
498 if ((m
& stipple
) == 0) {
506 span
->writeAll
= GL_FALSE
;
511 * Clip a pixel span to the current buffer/window boundaries:
512 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
513 * window clipping and scissoring.
514 * Return: GL_TRUE some pixels still visible
515 * GL_FALSE nothing visible
518 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
520 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
521 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
522 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
523 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
525 if (span
->arrayMask
& SPAN_XY
) {
526 /* arrays of x/y pixel coords */
527 const GLint
*x
= span
->xArray
;
528 const GLint
*y
= span
->yArray
;
529 const GLint n
= span
->end
;
530 GLubyte
*mask
= span
->mask
;
532 if (span
->arrayMask
& SPAN_MASK
) {
533 /* note: using & intead of && to reduce branches */
534 for (i
= 0; i
< n
; i
++) {
535 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
536 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
540 /* note: using & intead of && to reduce branches */
541 for (i
= 0; i
< n
; i
++) {
542 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
543 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
546 return GL_TRUE
; /* some pixels visible */
549 /* horizontal span of pixels */
550 const GLint x
= span
->x
;
551 const GLint y
= span
->y
;
552 const GLint n
= span
->end
;
554 /* Trivial rejection tests */
555 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
557 return GL_FALSE
; /* all pixels clipped */
560 /* Clip to the left */
562 ASSERT(x
+ n
> xmin
);
563 span
->writeAll
= GL_FALSE
;
564 BZERO(span
->mask
, (xmin
- x
) * sizeof(GLubyte
));
570 span
->end
= xmax
- x
;
573 return GL_TRUE
; /* some pixels visible */
580 * Draw to more than one color buffer (or none).
583 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
585 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
588 /* loop over four possible dest color buffers */
589 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
590 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
591 GLuint indexTmp
[MAX_WIDTH
];
592 ASSERT(span
->end
< MAX_WIDTH
);
594 if (bufferBit
== FRONT_LEFT_BIT
)
595 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
596 else if (bufferBit
== FRONT_RIGHT_BIT
)
597 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
598 else if (bufferBit
== BACK_LEFT_BIT
)
599 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
601 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
603 /* make copy of incoming indexes */
604 MEMCPY( indexTmp
, span
->color
.index
, span
->end
* sizeof(GLuint
) );
606 if (ctx
->Color
.IndexLogicOpEnabled
) {
607 _mesa_logicop_ci_span(ctx
, span
, indexTmp
);
610 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
611 _mesa_mask_index_span(ctx
, span
, indexTmp
);
614 if (span
->arrayMask
& SPAN_XY
) {
615 /* array of pixel coords */
616 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
617 span
->xArray
, span
->yArray
,
618 indexTmp
, span
->mask
);
621 /* horizontal run of pixels */
622 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
623 indexTmp
, span
->mask
);
628 /* restore default dest buffer */
629 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
634 * Draw to more than one RGBA color buffer (or none).
635 * All fragment operations, up to (but not) blending/logicop should
636 * have been done first.
639 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
641 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
643 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
645 ASSERT(colorMask
!= 0x0);
647 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
650 /* loop over four possible dest color buffers */
651 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
= bufferBit
<< 1) {
652 if (bufferBit
& ctx
->Color
.DrawDestMask
) {
653 GLchan rgbaTmp
[MAX_WIDTH
][4];
654 ASSERT(span
->end
< MAX_WIDTH
);
656 if (bufferBit
== FRONT_LEFT_BIT
) {
657 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_LEFT
);
658 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontLeftAlpha
;
660 else if (bufferBit
== FRONT_RIGHT_BIT
) {
661 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_FRONT_RIGHT
);
662 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->FrontRightAlpha
;
664 else if (bufferBit
== BACK_LEFT_BIT
) {
665 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_LEFT
);
666 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackLeftAlpha
;
669 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, GL_BACK_RIGHT
);
670 ctx
->DrawBuffer
->Alpha
= ctx
->DrawBuffer
->BackRightAlpha
;
673 /* make copy of incoming colors */
674 MEMCPY( rgbaTmp
, span
->color
.rgba
, 4 * span
->end
* sizeof(GLchan
) );
676 if (ctx
->Color
.ColorLogicOpEnabled
) {
677 _mesa_logicop_rgba_span(ctx
, span
, rgbaTmp
);
679 else if (ctx
->Color
.BlendEnabled
) {
680 _mesa_blend_span(ctx
, span
, rgbaTmp
);
683 if (colorMask
!= 0xffffffff) {
684 _mesa_mask_rgba_span(ctx
, span
, rgbaTmp
);
687 if (span
->arrayMask
& SPAN_XY
) {
688 /* array of pixel coords */
689 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
690 span
->xArray
, span
->yArray
,
691 (const GLchan (*)[4]) rgbaTmp
,
693 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
694 _mesa_write_alpha_pixels(ctx
, span
->end
,
695 span
->xArray
, span
->yArray
,
696 (const GLchan (*)[4]) rgbaTmp
,
701 /* horizontal run of pixels */
702 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
703 (const GLchan (*)[4]) rgbaTmp
,
705 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
706 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
707 (const GLchan (*)[4]) rgbaTmp
,
714 /* restore default dest buffer */
715 (void) (*ctx
->Driver
.SetDrawBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
721 * This function may modify any of the array values in the span.
722 * span->interpMask and span->arrayMask may be changed but will be restored
723 * to their original values before returning.
726 _mesa_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
728 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
729 const GLuint origInterpMask
= span
->interpMask
;
730 const GLuint origArrayMask
= span
->arrayMask
;
732 ASSERT(span
->end
<= MAX_WIDTH
);
733 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
734 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
735 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
736 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
738 if (span
->arrayMask
& SPAN_MASK
) {
739 /* mask was initialized by caller, probably glBitmap */
740 span
->writeAll
= GL_FALSE
;
743 MEMSET(span
->mask
, 1, span
->end
);
744 span
->writeAll
= GL_TRUE
;
748 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
749 if (!clip_span(ctx
, span
)) {
755 if (span
->arrayMask
& SPAN_XY
) {
757 for (i
= 0; i
< span
->end
; i
++) {
759 assert(span
->xArray
[i
] >= ctx
->DrawBuffer
->_Xmin
);
760 assert(span
->xArray
[i
] < ctx
->DrawBuffer
->_Xmax
);
761 assert(span
->yArray
[i
] >= ctx
->DrawBuffer
->_Ymin
);
762 assert(span
->yArray
[i
] < ctx
->DrawBuffer
->_Ymax
);
768 /* Polygon Stippling */
769 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
770 stipple_polygon_span(ctx
, span
);
773 /* Depth test and stencil */
774 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
775 if (span
->interpMask
& SPAN_Z
)
776 _mesa_span_interpolate_z(ctx
, span
);
778 if (ctx
->Stencil
.Enabled
) {
779 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
780 span
->arrayMask
= origArrayMask
;
785 ASSERT(ctx
->Depth
.Test
);
786 if (!_mesa_depth_test_span(ctx
, span
)) {
787 span
->arrayMask
= origArrayMask
;
793 /* if we get here, something passed the depth test */
794 ctx
->OcclusionResult
= GL_TRUE
;
796 /* we have to wait until after occlusion to do this test */
797 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
798 /* write no pixels */
799 span
->arrayMask
= origArrayMask
;
803 /* Interpolate the color indexes if needed */
804 if (span
->interpMask
& SPAN_INDEX
) {
805 interpolate_indexes(ctx
, span
);
806 /* clear the bit - this allows the WriteMonoCISpan optimization below */
807 span
->interpMask
&= ~SPAN_INDEX
;
811 if (ctx
->Fog
.Enabled
) {
812 _mesa_fog_ci_span(ctx
, span
);
815 /* Antialias coverage application */
816 if (span
->arrayMask
& SPAN_COVERAGE
) {
818 GLuint
*index
= span
->color
.index
;
819 for (i
= 0; i
< span
->end
; i
++) {
820 ASSERT(span
->coverage
[i
] < 16);
821 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) (span
->coverage
[i
]));
825 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
826 /* draw to zero or two or more buffers */
827 multi_write_index_span(ctx
, span
);
830 /* normal situation: draw to exactly one buffer */
831 if (ctx
->Color
.IndexLogicOpEnabled
) {
832 _mesa_logicop_ci_span(ctx
, span
, span
->color
.index
);
835 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
836 _mesa_mask_index_span(ctx
, span
, span
->color
.index
);
840 if (span
->arrayMask
& SPAN_XY
) {
841 /* array of pixel coords */
842 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
843 /* all pixels have same color index */
844 (*swrast
->Driver
.WriteMonoCIPixels
)(ctx
, span
->end
,
845 span
->xArray
, span
->yArray
,
846 FixedToInt(span
->index
),
850 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->xArray
,
851 span
->yArray
, span
->color
.index
,
856 /* horizontal run of pixels */
857 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
858 /* all pixels have same color index */
859 (*swrast
->Driver
.WriteMonoCISpan
)(ctx
, span
->end
, span
->x
, span
->y
,
860 FixedToInt(span
->index
),
864 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
865 span
->color
.index
, span
->mask
);
870 span
->interpMask
= origInterpMask
;
871 span
->arrayMask
= origArrayMask
;
876 * This function may modify any of the array values in the span.
877 * span->interpMask and span->arrayMask may be changed but will be restored
878 * to their original values before returning.
881 _mesa_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
883 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
884 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
885 const GLuint origInterpMask
= span
->interpMask
;
886 const GLuint origArrayMask
= span
->arrayMask
;
889 ASSERT(span
->end
<= MAX_WIDTH
);
890 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
891 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
892 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
893 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_RGBA
);
895 if (ctx
->Fog
.Enabled
)
896 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
898 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_Z
);
902 printf("%s() interp 0x%x array 0x%x p=0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask, span->primitive);
905 if (span
->arrayMask
& SPAN_MASK
) {
906 /* mask was initialized by caller, probably glBitmap */
907 span
->writeAll
= GL_FALSE
;
910 MEMSET(span
->mask
, 1, span
->end
);
911 span
->writeAll
= GL_TRUE
;
914 /* Determine if we have mono-chromatic colors */
915 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
916 span
->redStep
== 0 && span
->greenStep
== 0 &&
917 span
->blueStep
== 0 && span
->alphaStep
== 0;
920 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
921 if (!clip_span(ctx
, span
)) {
927 if (span
->arrayMask
& SPAN_XY
) {
929 for (i
= 0; i
< span
->end
; i
++) {
931 assert(span
->xArray
[i
] >= ctx
->DrawBuffer
->_Xmin
);
932 assert(span
->xArray
[i
] < ctx
->DrawBuffer
->_Xmax
);
933 assert(span
->yArray
[i
] >= ctx
->DrawBuffer
->_Ymin
);
934 assert(span
->yArray
[i
] < ctx
->DrawBuffer
->_Ymax
);
940 /* Polygon Stippling */
941 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
942 stipple_polygon_span(ctx
, span
);
945 /* Do the alpha test */
946 if (ctx
->Color
.AlphaEnabled
) {
947 if (!_mesa_alpha_test(ctx
, span
)) {
948 span
->interpMask
= origInterpMask
;
949 span
->arrayMask
= origArrayMask
;
954 /* Stencil and Z testing */
955 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
956 if (span
->interpMask
& SPAN_Z
)
957 _mesa_span_interpolate_z(ctx
, span
);
959 if (ctx
->Stencil
.Enabled
) {
960 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
961 span
->interpMask
= origInterpMask
;
962 span
->arrayMask
= origArrayMask
;
967 ASSERT(ctx
->Depth
.Test
);
968 ASSERT(span
->arrayMask
& SPAN_Z
);
969 /* regular depth testing */
970 if (!_mesa_depth_test_span(ctx
, span
)) {
971 span
->interpMask
= origInterpMask
;
972 span
->arrayMask
= origArrayMask
;
978 /* if we get here, something passed the depth test */
979 ctx
->OcclusionResult
= GL_TRUE
;
981 /* can't abort span-writing until after occlusion testing */
982 if (colorMask
== 0x0) {
983 span
->interpMask
= origInterpMask
;
984 span
->arrayMask
= origArrayMask
;
988 /* Now we may need to interpolate the colors */
989 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
990 interpolate_colors(ctx
, span
);
991 /* clear the bit - this allows the WriteMonoCISpan optimization below */
992 span
->interpMask
&= ~SPAN_RGBA
;
996 if (ctx
->Fog
.Enabled
) {
997 _mesa_fog_rgba_span(ctx
, span
);
998 monoColor
= GL_FALSE
;
1001 /* Antialias coverage application */
1002 if (span
->arrayMask
& SPAN_COVERAGE
) {
1003 GLchan (*rgba
)[4] = span
->color
.rgba
;
1005 for (i
= 0; i
< span
->end
; i
++) {
1006 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * span
->coverage
[i
]);
1008 monoColor
= GL_FALSE
;
1011 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1012 multi_write_rgba_span(ctx
, span
);
1015 /* normal: write to exactly one buffer */
1016 if (ctx
->Color
.ColorLogicOpEnabled
) {
1017 _mesa_logicop_rgba_span(ctx
, span
, span
->color
.rgba
);
1018 monoColor
= GL_FALSE
;
1020 else if (ctx
->Color
.BlendEnabled
) {
1021 _mesa_blend_span(ctx
, span
, span
->color
.rgba
);
1022 monoColor
= GL_FALSE
;
1025 /* Color component masking */
1026 if (colorMask
!= 0xffffffff) {
1027 _mesa_mask_rgba_span(ctx
, span
, span
->color
.rgba
);
1028 monoColor
= GL_FALSE
;
1032 if (span
->arrayMask
& SPAN_XY
) {
1033 /* array of pixel coords */
1034 /* XXX test for mono color */
1035 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->xArray
,
1036 span
->yArray
, (const GLchan (*)[4]) span
->color
.rgba
, span
->mask
);
1037 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1038 _mesa_write_alpha_pixels(ctx
, span
->end
,
1039 span
->xArray
, span
->yArray
,
1040 (const GLchan (*)[4]) span
->color
.rgba
,
1045 /* horizontal run of pixels */
1047 /* all pixels have same color */
1049 color
[RCOMP
] = FixedToChan(span
->red
);
1050 color
[GCOMP
] = FixedToChan(span
->green
);
1051 color
[BCOMP
] = FixedToChan(span
->blue
);
1052 color
[ACOMP
] = FixedToChan(span
->alpha
);
1053 (*swrast
->Driver
.WriteMonoRGBASpan
)(ctx
, span
->end
, span
->x
,
1054 span
->y
, color
, span
->mask
);
1055 /* XXX software alpha buffer writes! */
1058 /* each pixel is a different color */
1059 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1060 (const GLchan (*)[4]) span
->color
.rgba
,
1061 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->mask
);
1062 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1063 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1064 (const GLchan (*)[4]) span
->color
.rgba
,
1065 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->mask
);
1071 span
->interpMask
= origInterpMask
;
1072 span
->arrayMask
= origArrayMask
;
1077 * Add specular color to base color. This is used only when
1078 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1081 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1084 for (i
= 0; i
< n
; i
++) {
1085 #if CHAN_TYPE == GL_FLOAT
1087 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1088 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1089 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1091 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1092 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1093 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1094 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1095 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1096 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1103 * This function may modify any of the array values in the span.
1104 * span->interpMask and span->arrayMask may be changed but will be restored
1105 * to their original values before returning.
1108 _mesa_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
1110 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1111 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1112 const GLuint origArrayMask
= span
->arrayMask
;
1114 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1115 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1116 ASSERT(span
->end
<= MAX_WIDTH
);
1117 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1118 ASSERT(ctx
->Texture
._ReallyEnabled
);
1121 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1124 if (span
->arrayMask
& SPAN_MASK
) {
1125 /* mask was initialized by caller, probably glBitmap */
1126 span
->writeAll
= GL_FALSE
;
1129 MEMSET(span
->mask
, 1, span
->end
);
1130 span
->writeAll
= GL_TRUE
;
1134 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1135 if (!clip_span(ctx
, span
)) {
1141 if (span
->arrayMask
& SPAN_XY
) {
1143 for (i
= 0; i
< span
->end
; i
++) {
1144 if (span
->mask
[i
]) {
1145 assert(span
->xArray
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1146 assert(span
->xArray
[i
] < ctx
->DrawBuffer
->_Xmax
);
1147 assert(span
->yArray
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1148 assert(span
->yArray
[i
] < ctx
->DrawBuffer
->_Ymax
);
1154 /* Polygon Stippling */
1155 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1156 stipple_polygon_span(ctx
, span
);
1159 /* Need texture coordinates now */
1160 if ((span
->interpMask
& SPAN_TEXTURE
)
1161 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1162 interpolate_texcoords(ctx
, span
);
1164 /* Texture with alpha test */
1165 if (ctx
->Color
.AlphaEnabled
) {
1167 /* Now we need the rgba array, fill it in if needed */
1168 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1169 interpolate_colors(ctx
, span
);
1171 /* Texturing without alpha is done after depth-testing which
1172 * gives a potential speed-up.
1174 _swrast_texture_span( ctx
, span
);
1176 /* Do the alpha test */
1177 if (!_mesa_alpha_test(ctx
, span
)) {
1178 span
->arrayMask
= origArrayMask
;
1183 /* Stencil and Z testing */
1184 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1185 if (span
->interpMask
& SPAN_Z
)
1186 _mesa_span_interpolate_z(ctx
, span
);
1188 if (ctx
->Stencil
.Enabled
) {
1189 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
1190 span
->arrayMask
= origArrayMask
;
1195 ASSERT(ctx
->Depth
.Test
);
1196 ASSERT(span
->arrayMask
& SPAN_Z
);
1197 /* regular depth testing */
1198 if (!_mesa_depth_test_span(ctx
, span
)) {
1199 span
->arrayMask
= origArrayMask
;
1205 /* if we get here, some fragments passed the depth test */
1206 ctx
->OcclusionResult
= GL_TRUE
;
1208 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1209 * the occlusion test.
1211 if (colorMask
== 0x0) {
1212 span
->arrayMask
= origArrayMask
;
1216 /* Texture without alpha test */
1217 if (!ctx
->Color
.AlphaEnabled
) {
1219 /* Now we need the rgba array, fill it in if needed */
1220 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1221 interpolate_colors(ctx
, span
);
1223 _swrast_texture_span( ctx
, span
);
1226 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1228 /* Add base and specular colors */
1229 if (ctx
->Fog
.ColorSumEnabled
||
1230 (ctx
->Light
.Enabled
&&
1231 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1232 if (span
->interpMask
& SPAN_SPEC
) {
1233 interpolate_specular(ctx
, span
);
1235 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1236 add_colors( span
->end
, span
->color
.rgba
, span
->specArray
);
1240 if (ctx
->Fog
.Enabled
) {
1241 _mesa_fog_rgba_span(ctx
, span
);
1244 /* Antialias coverage application */
1245 if (span
->arrayMask
& SPAN_COVERAGE
) {
1246 GLchan (*rgba
)[4] = span
->color
.rgba
;
1248 for (i
= 0; i
< span
->end
; i
++) {
1249 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * span
->coverage
[i
]);
1253 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1254 multi_write_rgba_span(ctx
, span
);
1257 /* normal: write to exactly one buffer */
1258 if (ctx
->Color
.ColorLogicOpEnabled
) {
1259 _mesa_logicop_rgba_span(ctx
, span
, span
->color
.rgba
);
1261 else if (ctx
->Color
.BlendEnabled
) {
1262 _mesa_blend_span(ctx
, span
, span
->color
.rgba
);
1265 if (colorMask
!= 0xffffffff) {
1266 _mesa_mask_rgba_span(ctx
, span
, span
->color
.rgba
);
1270 if (span
->arrayMask
& SPAN_XY
) {
1271 /* array of pixel coords */
1272 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->xArray
,
1273 span
->yArray
, (const GLchan (*)[4]) span
->color
.rgba
, span
->mask
);
1274 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1275 _mesa_write_alpha_pixels(ctx
, span
->end
,
1276 span
->xArray
, span
->yArray
,
1277 (const GLchan (*)[4]) span
->color
.rgba
,
1282 /* horizontal run of pixels */
1283 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1284 (const GLchan (*)[4]) span
->color
.rgba
,
1285 span
->writeAll
? NULL
: span
->mask
);
1286 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1287 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1288 (const GLchan (*)[4]) span
->color
.rgba
,
1289 span
->writeAll
? NULL
: span
->mask
);
1294 span
->arrayMask
= origArrayMask
;
1300 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1301 * reading ouside the buffer's boundaries.
1304 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1305 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1307 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1308 const GLint bufWidth
= (GLint
) buffer
->Width
;
1309 const GLint bufHeight
= (GLint
) buffer
->Height
;
1311 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1312 /* completely above, below, or right */
1313 /* XXX maybe leave undefined? */
1314 BZERO(rgba
, 4 * n
* sizeof(GLchan
));
1319 /* left edge clippping */
1321 length
= (GLint
) n
- skip
;
1323 /* completely left of window */
1326 if (length
> bufWidth
) {
1330 else if ((GLint
) (x
+ n
) > bufWidth
) {
1331 /* right edge clipping */
1333 length
= bufWidth
- x
;
1335 /* completely to right of window */
1345 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1346 if (buffer
->UseSoftwareAlphaBuffers
) {
1347 _mesa_read_alpha_span(ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1354 * Read CI pixels from frame buffer. Clipping will be done to prevent
1355 * reading ouside the buffer's boundaries.
1358 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1359 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1361 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1362 const GLint bufWidth
= (GLint
) buffer
->Width
;
1363 const GLint bufHeight
= (GLint
) buffer
->Height
;
1365 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1366 /* completely above, below, or right */
1367 BZERO(indx
, n
* sizeof(GLuint
));
1372 /* left edge clippping */
1374 length
= (GLint
) n
- skip
;
1376 /* completely left of window */
1379 if (length
> bufWidth
) {
1383 else if ((GLint
) (x
+ n
) > bufWidth
) {
1384 /* right edge clipping */
1386 length
= bufWidth
- x
;
1388 /* completely to right of window */
1398 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);