1 /* $Id: s_span.c,v 1.45 2002/07/09 01:22:52 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
;
123 * Init span's texcoord interpolation values to the RasterPos texcoords.
124 * Used during setup for glDraw/CopyPixels.
127 _mesa_span_default_texcoords( GLcontext
*ctx
, struct sw_span
*span
)
130 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
131 span
->tex
[i
][0] = ctx
->Current
.RasterTexCoords
[i
][0];
132 span
->tex
[i
][1] = ctx
->Current
.RasterTexCoords
[i
][1];
133 span
->tex
[i
][2] = ctx
->Current
.RasterTexCoords
[i
][2];
134 span
->tex
[i
][3] = ctx
->Current
.RasterTexCoords
[i
][3];
135 span
->texStepX
[i
][0] = 0.0;
136 span
->texStepX
[i
][1] = 0.0;
137 span
->texStepX
[i
][2] = 0.0;
138 span
->texStepX
[i
][3] = 0.0;
140 span
->interpMask
|= SPAN_TEXTURE
;
144 /* Fill in the span.color.rgba array from the interpolation values */
146 interpolate_colors(GLcontext
*ctx
, struct sw_span
*span
)
148 GLfixed r
= span
->red
;
149 GLfixed g
= span
->green
;
150 GLfixed b
= span
->blue
;
151 GLfixed a
= span
->alpha
;
152 const GLint dr
= span
->redStep
;
153 const GLint dg
= span
->greenStep
;
154 const GLint db
= span
->blueStep
;
155 const GLint da
= span
->alphaStep
;
156 const GLuint n
= span
->end
;
157 GLchan (*rgba
)[4] = span
->color
.rgba
;
160 ASSERT((span
->interpMask
& SPAN_RGBA
) &&
161 !(span
->arrayMask
& SPAN_RGBA
));
163 if (span
->interpMask
& SPAN_FLAT
) {
166 color
[RCOMP
] = FixedToChan(r
);
167 color
[GCOMP
] = FixedToChan(g
);
168 color
[BCOMP
] = FixedToChan(b
);
169 color
[ACOMP
] = FixedToChan(a
);
170 for (i
= 0; i
< n
; i
++) {
171 COPY_CHAN4(span
->color
.rgba
[i
], color
);
176 for (i
= 0; i
< n
; i
++) {
177 rgba
[i
][RCOMP
] = FixedToChan(r
);
178 rgba
[i
][GCOMP
] = FixedToChan(g
);
179 rgba
[i
][BCOMP
] = FixedToChan(b
);
180 rgba
[i
][ACOMP
] = FixedToChan(a
);
187 span
->arrayMask
|= SPAN_RGBA
;
191 /* Fill in the span.color.index array from the interpolation values */
193 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
195 GLfixed index
= span
->index
;
196 const GLint indexStep
= span
->indexStep
;
197 const GLuint n
= span
->end
;
198 GLuint
*indexes
= span
->color
.index
;
200 ASSERT((span
->interpMask
& SPAN_INDEX
) &&
201 !(span
->arrayMask
& SPAN_INDEX
));
203 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
205 index
= FixedToInt(index
);
206 for (i
= 0; i
< n
; i
++) {
212 for (i
= 0; i
< n
; i
++) {
213 indexes
[i
] = FixedToInt(index
);
217 span
->arrayMask
|= SPAN_INDEX
;
221 /* Fill in the span.specArray array from the interpolation values */
223 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
225 if (span
->interpMask
& SPAN_FLAT
) {
227 const GLchan r
= FixedToChan(span
->specRed
);
228 const GLchan g
= FixedToChan(span
->specGreen
);
229 const GLchan b
= FixedToChan(span
->specBlue
);
231 for (i
= 0; i
< span
->end
; i
++) {
232 span
->specArray
[i
][RCOMP
] = r
;
233 span
->specArray
[i
][GCOMP
] = g
;
234 span
->specArray
[i
][BCOMP
] = b
;
239 #if CHAN_TYPE == GL_FLOAT
240 GLfloat r
= span
->specRed
;
241 GLfloat g
= span
->specGreen
;
242 GLfloat b
= span
->specBlue
;
244 GLfixed r
= span
->specRed
;
245 GLfixed g
= span
->specGreen
;
246 GLfixed b
= span
->specBlue
;
249 for (i
= 0; i
< span
->end
; i
++) {
250 span
->specArray
[i
][RCOMP
] = FixedToChan(r
);
251 span
->specArray
[i
][GCOMP
] = FixedToChan(g
);
252 span
->specArray
[i
][BCOMP
] = FixedToChan(b
);
253 r
+= span
->specRedStep
;
254 g
+= span
->specGreenStep
;
255 b
+= span
->specBlueStep
;
258 span
->arrayMask
|= SPAN_SPEC
;
262 /* Fill in the span.zArray array from the interpolation values */
264 _mesa_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
266 const GLuint n
= span
->end
;
269 ASSERT((span
->interpMask
& SPAN_Z
) &&
270 !(span
->arrayMask
& SPAN_Z
));
272 if (ctx
->Visual
.depthBits
<= 16) {
273 GLfixed zval
= span
->z
;
274 for (i
= 0; i
< n
; i
++) {
275 span
->zArray
[i
] = FixedToInt(zval
);
280 /* Deep Z buffer, no fixed->int shift */
281 GLfixed zval
= span
->z
;
282 for (i
= 0; i
< n
; i
++) {
283 span
->zArray
[i
] = zval
;
287 span
->arrayMask
|= SPAN_Z
;
292 * This the ideal solution, as given in the OpenGL spec.
296 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
297 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
298 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
300 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
301 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
302 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
303 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
304 GLfloat x
= sqrt(dudx
* dudx
+ dvdx
* dvdx
);
305 GLfloat y
= sqrt(dudy
* dudy
+ dvdy
* dvdy
);
306 GLfloat rho
= MAX2(x
, y
);
307 GLfloat lambda
= LOG2(rho
);
314 * This is a faster approximation
317 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
318 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
319 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
321 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
322 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
323 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
324 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
325 GLfloat maxU
, maxV
, rho
, lambda
;
326 dsdx2
= FABSF(dsdx2
);
327 dsdy2
= FABSF(dsdy2
);
328 dtdx2
= FABSF(dtdx2
);
329 dtdy2
= FABSF(dtdy2
);
330 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
331 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
332 rho
= MAX2(maxU
, maxV
);
338 * Fill in the span.texcoords array from the interpolation values.
339 * XXX We could optimize here for the case when dq = 0. That would
340 * usually be the case when using an orthographic projection.
343 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
345 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
346 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
348 if (ctx
->Texture
._EnabledUnits
> 1) {
351 span
->arrayMask
|= SPAN_TEXTURE
;
352 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
353 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
354 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
355 const struct gl_texture_image
*img
= obj
->Image
[obj
->BaseLevel
];
356 GLboolean needLambda
= (obj
->MinFilter
!= obj
->MagFilter
);
358 const GLfloat texW
= (GLfloat
) img
->WidthScale
;
359 const GLfloat texH
= (GLfloat
) img
->HeightScale
;
360 const GLfloat dsdx
= span
->texStepX
[u
][0];
361 const GLfloat dsdy
= span
->texStepY
[u
][0];
362 const GLfloat dtdx
= span
->texStepX
[u
][1];
363 const GLfloat dtdy
= span
->texStepY
[u
][1];
364 const GLfloat drdx
= span
->texStepX
[u
][2];
365 const GLfloat dqdx
= span
->texStepX
[u
][3];
366 const GLfloat dqdy
= span
->texStepY
[u
][3];
367 GLfloat s
= span
->tex
[u
][0];
368 GLfloat t
= span
->tex
[u
][1];
369 GLfloat r
= span
->tex
[u
][2];
370 GLfloat q
= span
->tex
[u
][3];
372 for (i
= 0; i
< span
->end
; i
++) {
373 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
374 span
->texcoords
[u
][i
][0] = s
* invQ
;
375 span
->texcoords
[u
][i
][1] = t
* invQ
;
376 span
->texcoords
[u
][i
][2] = r
* invQ
;
377 span
->lambda
[u
][i
] = compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
378 dqdx
, dqdy
, texW
, texH
,
385 span
->arrayMask
|= SPAN_LAMBDA
;
388 const GLfloat dsdx
= span
->texStepX
[u
][0];
389 const GLfloat dtdx
= span
->texStepX
[u
][1];
390 const GLfloat drdx
= span
->texStepX
[u
][2];
391 const GLfloat dqdx
= span
->texStepX
[u
][3];
392 GLfloat s
= span
->tex
[u
][0];
393 GLfloat t
= span
->tex
[u
][1];
394 GLfloat r
= span
->tex
[u
][2];
395 GLfloat q
= span
->tex
[u
][3];
398 /* Ortho projection or polygon's parallel to window X axis */
399 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
400 for (i
= 0; i
< span
->end
; i
++) {
401 span
->texcoords
[u
][i
][0] = s
* invQ
;
402 span
->texcoords
[u
][i
][1] = t
* invQ
;
403 span
->texcoords
[u
][i
][2] = r
* invQ
;
404 span
->lambda
[u
][i
] = 0.0;
411 for (i
= 0; i
< span
->end
; i
++) {
412 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
413 span
->texcoords
[u
][i
][0] = s
* invQ
;
414 span
->texcoords
[u
][i
][1] = t
* invQ
;
415 span
->texcoords
[u
][i
][2] = r
* invQ
;
416 span
->lambda
[u
][i
] = 0.0;
429 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
430 const struct gl_texture_image
*img
= obj
->Image
[obj
->BaseLevel
];
431 GLboolean needLambda
= (obj
->MinFilter
!= obj
->MagFilter
);
432 span
->arrayMask
|= SPAN_TEXTURE
;
434 /* just texture unit 0, with lambda */
435 const GLfloat texW
= (GLfloat
) img
->WidthScale
;
436 const GLfloat texH
= (GLfloat
) img
->HeightScale
;
437 const GLfloat dsdx
= span
->texStepX
[0][0];
438 const GLfloat dsdy
= span
->texStepY
[0][0];
439 const GLfloat dtdx
= span
->texStepX
[0][1];
440 const GLfloat dtdy
= span
->texStepY
[0][1];
441 const GLfloat drdx
= span
->texStepX
[0][2];
442 const GLfloat dqdx
= span
->texStepX
[0][3];
443 const GLfloat dqdy
= span
->texStepY
[0][3];
444 GLfloat s
= span
->tex
[0][0];
445 GLfloat t
= span
->tex
[0][1];
446 GLfloat r
= span
->tex
[0][2];
447 GLfloat q
= span
->tex
[0][3];
449 for (i
= 0; i
< span
->end
; i
++) {
450 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
451 span
->lambda
[0][i
] = compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
452 dqdx
, dqdy
, texW
, texH
,
454 span
->texcoords
[0][i
][0] = s
* invQ
;
455 span
->texcoords
[0][i
][1] = t
* invQ
;
456 span
->texcoords
[0][i
][2] = r
* invQ
;
462 span
->arrayMask
|= SPAN_LAMBDA
;
465 /* just texture 0, without lambda */
466 const GLfloat dsdx
= span
->texStepX
[0][0];
467 const GLfloat dtdx
= span
->texStepX
[0][1];
468 const GLfloat drdx
= span
->texStepX
[0][2];
469 const GLfloat dqdx
= span
->texStepX
[0][3];
470 GLfloat s
= span
->tex
[0][0];
471 GLfloat t
= span
->tex
[0][1];
472 GLfloat r
= span
->tex
[0][2];
473 GLfloat q
= span
->tex
[0][3];
476 /* Ortho projection or polygon's parallel to window X axis */
477 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
478 for (i
= 0; i
< span
->end
; i
++) {
479 span
->texcoords
[0][i
][0] = s
* invQ
;
480 span
->texcoords
[0][i
][1] = t
* invQ
;
481 span
->texcoords
[0][i
][2] = r
* invQ
;
488 for (i
= 0; i
< span
->end
; i
++) {
489 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
490 span
->texcoords
[0][i
][0] = s
* invQ
;
491 span
->texcoords
[0][i
][1] = t
* invQ
;
492 span
->texcoords
[0][i
][2] = r
* invQ
;
505 * Apply the current polygon stipple pattern to a span of pixels.
508 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
510 const GLuint highbit
= 0x80000000;
511 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
514 ASSERT(ctx
->Polygon
.StippleFlag
);
515 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
517 m
= highbit
>> (GLuint
) (span
->x
% 32);
519 for (i
= 0; i
< span
->end
; i
++) {
520 if ((m
& stipple
) == 0) {
528 span
->writeAll
= GL_FALSE
;
533 * Clip a pixel span to the current buffer/window boundaries:
534 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
535 * window clipping and scissoring.
536 * Return: GL_TRUE some pixels still visible
537 * GL_FALSE nothing visible
540 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
542 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
543 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
544 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
545 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
547 if (span
->arrayMask
& SPAN_XY
) {
548 /* arrays of x/y pixel coords */
549 const GLint
*x
= span
->xArray
;
550 const GLint
*y
= span
->yArray
;
551 const GLint n
= span
->end
;
552 GLubyte
*mask
= span
->mask
;
554 if (span
->arrayMask
& SPAN_MASK
) {
555 /* note: using & intead of && to reduce branches */
556 for (i
= 0; i
< n
; i
++) {
557 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
558 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
562 /* note: using & intead of && to reduce branches */
563 for (i
= 0; i
< n
; i
++) {
564 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
565 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
568 return GL_TRUE
; /* some pixels visible */
571 /* horizontal span of pixels */
572 const GLint x
= span
->x
;
573 const GLint y
= span
->y
;
574 const GLint n
= span
->end
;
576 /* Trivial rejection tests */
577 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
579 return GL_FALSE
; /* all pixels clipped */
582 /* Clip to the left */
584 ASSERT(x
+ n
> xmin
);
585 span
->writeAll
= GL_FALSE
;
586 BZERO(span
->mask
, (xmin
- x
) * sizeof(GLubyte
));
592 span
->end
= xmax
- x
;
595 return GL_TRUE
; /* some pixels visible */
602 * Draw to more than one color buffer (or none).
605 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
607 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
610 /* loop over four possible dest color buffers */
611 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
612 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
613 GLuint indexTmp
[MAX_WIDTH
];
614 ASSERT(span
->end
< MAX_WIDTH
);
616 if (bufferBit
== FRONT_LEFT_BIT
)
617 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, GL_FRONT_LEFT
);
618 else if (bufferBit
== FRONT_RIGHT_BIT
)
619 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, GL_FRONT_RIGHT
);
620 else if (bufferBit
== BACK_LEFT_BIT
)
621 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, GL_BACK_LEFT
);
623 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, GL_BACK_RIGHT
);
625 /* make copy of incoming indexes */
626 MEMCPY( indexTmp
, span
->color
.index
, span
->end
* sizeof(GLuint
) );
628 if (ctx
->Color
.IndexLogicOpEnabled
) {
629 _mesa_logicop_ci_span(ctx
, span
, indexTmp
);
632 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
633 _mesa_mask_index_span(ctx
, span
, indexTmp
);
636 if (span
->arrayMask
& SPAN_XY
) {
637 /* array of pixel coords */
638 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
639 span
->xArray
, span
->yArray
,
640 indexTmp
, span
->mask
);
643 /* horizontal run of pixels */
644 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
645 indexTmp
, span
->mask
);
650 /* restore default dest buffer */
651 _swrast_use_draw_buffer(ctx
);
656 * Draw to more than one RGBA color buffer (or none).
657 * All fragment operations, up to (but not) blending/logicop should
658 * have been done first.
661 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
663 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
665 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
667 ASSERT(colorMask
!= 0x0);
669 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
672 /* loop over four possible dest color buffers */
673 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
674 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
675 GLchan rgbaTmp
[MAX_WIDTH
][4];
676 ASSERT(span
->end
< MAX_WIDTH
);
678 if (bufferBit
== FRONT_LEFT_BIT
) {
679 ctx
->Color
._DriverDrawBuffer
= GL_FRONT_LEFT
;
680 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, GL_FRONT_LEFT
);
682 else if (bufferBit
== FRONT_RIGHT_BIT
) {
683 ctx
->Color
._DriverDrawBuffer
= GL_FRONT_RIGHT
;
684 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, GL_FRONT_RIGHT
);
686 else if (bufferBit
== BACK_LEFT_BIT
) {
687 ctx
->Color
._DriverDrawBuffer
= GL_BACK_LEFT
;
688 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, GL_BACK_LEFT
);
691 ctx
->Color
._DriverDrawBuffer
= GL_BACK_RIGHT
;
692 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, GL_BACK_RIGHT
);
695 /* make copy of incoming colors */
696 MEMCPY( rgbaTmp
, span
->color
.rgba
, 4 * span
->end
* sizeof(GLchan
) );
698 if (ctx
->Color
.ColorLogicOpEnabled
) {
699 _mesa_logicop_rgba_span(ctx
, span
, rgbaTmp
);
701 else if (ctx
->Color
.BlendEnabled
) {
702 _mesa_blend_span(ctx
, span
, rgbaTmp
);
705 if (colorMask
!= 0xffffffff) {
706 _mesa_mask_rgba_span(ctx
, span
, rgbaTmp
);
709 if (span
->arrayMask
& SPAN_XY
) {
710 /* array of pixel coords */
711 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
712 span
->xArray
, span
->yArray
,
713 (const GLchan (*)[4]) rgbaTmp
,
715 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
716 _mesa_write_alpha_pixels(ctx
, span
->end
,
717 span
->xArray
, span
->yArray
,
718 (const GLchan (*)[4]) rgbaTmp
,
723 /* horizontal run of pixels */
724 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
725 (const GLchan (*)[4]) rgbaTmp
,
727 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
728 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
729 (const GLchan (*)[4]) rgbaTmp
,
736 /* restore default dest buffer */
737 _swrast_use_draw_buffer(ctx
);
743 * This function may modify any of the array values in the span.
744 * span->interpMask and span->arrayMask may be changed but will be restored
745 * to their original values before returning.
748 _mesa_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
750 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
751 const GLuint origInterpMask
= span
->interpMask
;
752 const GLuint origArrayMask
= span
->arrayMask
;
754 ASSERT(span
->end
<= MAX_WIDTH
);
755 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
756 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
757 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
758 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
760 if (span
->arrayMask
& SPAN_MASK
) {
761 /* mask was initialized by caller, probably glBitmap */
762 span
->writeAll
= GL_FALSE
;
765 MEMSET(span
->mask
, 1, span
->end
);
766 span
->writeAll
= GL_TRUE
;
770 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
771 if (!clip_span(ctx
, span
)) {
777 if (span
->arrayMask
& SPAN_XY
) {
779 for (i
= 0; i
< span
->end
; i
++) {
781 assert(span
->xArray
[i
] >= ctx
->DrawBuffer
->_Xmin
);
782 assert(span
->xArray
[i
] < ctx
->DrawBuffer
->_Xmax
);
783 assert(span
->yArray
[i
] >= ctx
->DrawBuffer
->_Ymin
);
784 assert(span
->yArray
[i
] < ctx
->DrawBuffer
->_Ymax
);
790 /* Polygon Stippling */
791 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
792 stipple_polygon_span(ctx
, span
);
795 /* Depth test and stencil */
796 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
797 if (span
->interpMask
& SPAN_Z
)
798 _mesa_span_interpolate_z(ctx
, span
);
800 if (ctx
->Stencil
.Enabled
) {
801 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
802 span
->arrayMask
= origArrayMask
;
807 ASSERT(ctx
->Depth
.Test
);
808 if (!_mesa_depth_test_span(ctx
, span
)) {
809 span
->arrayMask
= origArrayMask
;
815 /* if we get here, something passed the depth test */
816 ctx
->OcclusionResult
= GL_TRUE
;
818 /* we have to wait until after occlusion to do this test */
819 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
820 /* write no pixels */
821 span
->arrayMask
= origArrayMask
;
825 /* Interpolate the color indexes if needed */
826 if (span
->interpMask
& SPAN_INDEX
) {
827 interpolate_indexes(ctx
, span
);
828 /* clear the bit - this allows the WriteMonoCISpan optimization below */
829 span
->interpMask
&= ~SPAN_INDEX
;
833 if (ctx
->Fog
.Enabled
) {
834 _mesa_fog_ci_span(ctx
, span
);
837 /* Antialias coverage application */
838 if (span
->arrayMask
& SPAN_COVERAGE
) {
840 GLuint
*index
= span
->color
.index
;
841 for (i
= 0; i
< span
->end
; i
++) {
842 ASSERT(span
->coverage
[i
] < 16);
843 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) (span
->coverage
[i
]));
847 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
848 /* draw to zero or two or more buffers */
849 multi_write_index_span(ctx
, span
);
852 /* normal situation: draw to exactly one buffer */
853 if (ctx
->Color
.IndexLogicOpEnabled
) {
854 _mesa_logicop_ci_span(ctx
, span
, span
->color
.index
);
857 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
858 _mesa_mask_index_span(ctx
, span
, span
->color
.index
);
862 if (span
->arrayMask
& SPAN_XY
) {
863 /* array of pixel coords */
864 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
865 /* all pixels have same color index */
866 (*swrast
->Driver
.WriteMonoCIPixels
)(ctx
, span
->end
,
867 span
->xArray
, span
->yArray
,
868 FixedToInt(span
->index
),
872 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->xArray
,
873 span
->yArray
, span
->color
.index
,
878 /* horizontal run of pixels */
879 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
880 /* all pixels have same color index */
881 (*swrast
->Driver
.WriteMonoCISpan
)(ctx
, span
->end
, span
->x
, span
->y
,
882 FixedToInt(span
->index
),
886 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
887 span
->color
.index
, span
->mask
);
892 span
->interpMask
= origInterpMask
;
893 span
->arrayMask
= origArrayMask
;
898 * This function may modify any of the array values in the span.
899 * span->interpMask and span->arrayMask may be changed but will be restored
900 * to their original values before returning.
903 _mesa_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
905 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
906 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
907 const GLuint origInterpMask
= span
->interpMask
;
908 const GLuint origArrayMask
= span
->arrayMask
;
911 ASSERT(span
->end
<= MAX_WIDTH
);
912 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
913 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
914 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
915 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_RGBA
);
917 if (ctx
->Fog
.Enabled
)
918 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
920 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_Z
);
924 printf("%s() interp 0x%x array 0x%x p=0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask, span->primitive);
927 if (span
->arrayMask
& SPAN_MASK
) {
928 /* mask was initialized by caller, probably glBitmap */
929 span
->writeAll
= GL_FALSE
;
932 MEMSET(span
->mask
, 1, span
->end
);
933 span
->writeAll
= GL_TRUE
;
936 /* Determine if we have mono-chromatic colors */
937 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
938 span
->redStep
== 0 && span
->greenStep
== 0 &&
939 span
->blueStep
== 0 && span
->alphaStep
== 0;
942 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
943 if (!clip_span(ctx
, span
)) {
949 if (span
->arrayMask
& SPAN_XY
) {
951 for (i
= 0; i
< span
->end
; i
++) {
953 assert(span
->xArray
[i
] >= ctx
->DrawBuffer
->_Xmin
);
954 assert(span
->xArray
[i
] < ctx
->DrawBuffer
->_Xmax
);
955 assert(span
->yArray
[i
] >= ctx
->DrawBuffer
->_Ymin
);
956 assert(span
->yArray
[i
] < ctx
->DrawBuffer
->_Ymax
);
962 /* Polygon Stippling */
963 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
964 stipple_polygon_span(ctx
, span
);
967 /* Do the alpha test */
968 if (ctx
->Color
.AlphaEnabled
) {
969 if (!_mesa_alpha_test(ctx
, span
)) {
970 span
->interpMask
= origInterpMask
;
971 span
->arrayMask
= origArrayMask
;
976 /* Stencil and Z testing */
977 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
978 if (span
->interpMask
& SPAN_Z
)
979 _mesa_span_interpolate_z(ctx
, span
);
981 if (ctx
->Stencil
.Enabled
) {
982 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
983 span
->interpMask
= origInterpMask
;
984 span
->arrayMask
= origArrayMask
;
989 ASSERT(ctx
->Depth
.Test
);
990 ASSERT(span
->arrayMask
& SPAN_Z
);
991 /* regular depth testing */
992 if (!_mesa_depth_test_span(ctx
, span
)) {
993 span
->interpMask
= origInterpMask
;
994 span
->arrayMask
= origArrayMask
;
1000 /* if we get here, something passed the depth test */
1001 ctx
->OcclusionResult
= GL_TRUE
;
1003 /* can't abort span-writing until after occlusion testing */
1004 if (colorMask
== 0x0) {
1005 span
->interpMask
= origInterpMask
;
1006 span
->arrayMask
= origArrayMask
;
1010 /* Now we may need to interpolate the colors */
1011 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
1012 interpolate_colors(ctx
, span
);
1013 /* clear the bit - this allows the WriteMonoCISpan optimization below */
1014 span
->interpMask
&= ~SPAN_RGBA
;
1018 if (ctx
->Fog
.Enabled
) {
1019 _mesa_fog_rgba_span(ctx
, span
);
1020 monoColor
= GL_FALSE
;
1023 /* Antialias coverage application */
1024 if (span
->arrayMask
& SPAN_COVERAGE
) {
1025 GLchan (*rgba
)[4] = span
->color
.rgba
;
1027 for (i
= 0; i
< span
->end
; i
++) {
1028 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * span
->coverage
[i
]);
1030 monoColor
= GL_FALSE
;
1033 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1034 multi_write_rgba_span(ctx
, span
);
1037 /* normal: write to exactly one buffer */
1038 if (ctx
->Color
.ColorLogicOpEnabled
) {
1039 _mesa_logicop_rgba_span(ctx
, span
, span
->color
.rgba
);
1040 monoColor
= GL_FALSE
;
1042 else if (ctx
->Color
.BlendEnabled
) {
1043 _mesa_blend_span(ctx
, span
, span
->color
.rgba
);
1044 monoColor
= GL_FALSE
;
1047 /* Color component masking */
1048 if (colorMask
!= 0xffffffff) {
1049 _mesa_mask_rgba_span(ctx
, span
, span
->color
.rgba
);
1050 monoColor
= GL_FALSE
;
1054 if (span
->arrayMask
& SPAN_XY
) {
1055 /* array of pixel coords */
1056 /* XXX test for mono color */
1057 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->xArray
,
1058 span
->yArray
, (const GLchan (*)[4]) span
->color
.rgba
, span
->mask
);
1059 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1060 _mesa_write_alpha_pixels(ctx
, span
->end
,
1061 span
->xArray
, span
->yArray
,
1062 (const GLchan (*)[4]) span
->color
.rgba
,
1067 /* horizontal run of pixels */
1069 /* all pixels have same color */
1071 color
[RCOMP
] = FixedToChan(span
->red
);
1072 color
[GCOMP
] = FixedToChan(span
->green
);
1073 color
[BCOMP
] = FixedToChan(span
->blue
);
1074 color
[ACOMP
] = FixedToChan(span
->alpha
);
1075 (*swrast
->Driver
.WriteMonoRGBASpan
)(ctx
, span
->end
, span
->x
,
1076 span
->y
, color
, span
->mask
);
1077 /* XXX software alpha buffer writes! */
1080 /* each pixel is a different color */
1081 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1082 (const GLchan (*)[4]) span
->color
.rgba
,
1083 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->mask
);
1084 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1085 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1086 (const GLchan (*)[4]) span
->color
.rgba
,
1087 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->mask
);
1093 span
->interpMask
= origInterpMask
;
1094 span
->arrayMask
= origArrayMask
;
1099 * Add specular color to base color. This is used only when
1100 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1103 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1106 for (i
= 0; i
< n
; i
++) {
1107 #if CHAN_TYPE == GL_FLOAT
1109 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1110 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1111 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1113 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1114 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1115 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1116 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1117 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1118 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1125 * This function may modify any of the array values in the span.
1126 * span->interpMask and span->arrayMask may be changed but will be restored
1127 * to their original values before returning.
1130 _mesa_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
1132 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1133 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1134 const GLuint origArrayMask
= span
->arrayMask
;
1136 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1137 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1138 ASSERT(span
->end
<= MAX_WIDTH
);
1139 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1140 ASSERT(ctx
->Texture
._EnabledUnits
);
1143 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1146 if (span
->arrayMask
& SPAN_MASK
) {
1147 /* mask was initialized by caller, probably glBitmap */
1148 span
->writeAll
= GL_FALSE
;
1151 MEMSET(span
->mask
, 1, span
->end
);
1152 span
->writeAll
= GL_TRUE
;
1156 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1157 if (!clip_span(ctx
, span
)) {
1163 if (span
->arrayMask
& SPAN_XY
) {
1165 for (i
= 0; i
< span
->end
; i
++) {
1166 if (span
->mask
[i
]) {
1167 assert(span
->xArray
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1168 assert(span
->xArray
[i
] < ctx
->DrawBuffer
->_Xmax
);
1169 assert(span
->yArray
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1170 assert(span
->yArray
[i
] < ctx
->DrawBuffer
->_Ymax
);
1176 /* Polygon Stippling */
1177 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1178 stipple_polygon_span(ctx
, span
);
1181 /* Need texture coordinates now */
1182 if ((span
->interpMask
& SPAN_TEXTURE
)
1183 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1184 interpolate_texcoords(ctx
, span
);
1186 /* Texture with alpha test */
1187 if (ctx
->Color
.AlphaEnabled
) {
1189 /* Now we need the rgba array, fill it in if needed */
1190 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1191 interpolate_colors(ctx
, span
);
1193 /* Texturing without alpha is done after depth-testing which
1194 * gives a potential speed-up.
1196 _swrast_texture_span( ctx
, span
);
1198 /* Do the alpha test */
1199 if (!_mesa_alpha_test(ctx
, span
)) {
1200 span
->arrayMask
= origArrayMask
;
1205 /* Stencil and Z testing */
1206 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1207 if (span
->interpMask
& SPAN_Z
)
1208 _mesa_span_interpolate_z(ctx
, span
);
1210 if (ctx
->Stencil
.Enabled
) {
1211 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
1212 span
->arrayMask
= origArrayMask
;
1217 ASSERT(ctx
->Depth
.Test
);
1218 ASSERT(span
->arrayMask
& SPAN_Z
);
1219 /* regular depth testing */
1220 if (!_mesa_depth_test_span(ctx
, span
)) {
1221 span
->arrayMask
= origArrayMask
;
1227 /* if we get here, some fragments passed the depth test */
1228 ctx
->OcclusionResult
= GL_TRUE
;
1230 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1231 * the occlusion test.
1233 if (colorMask
== 0x0) {
1234 span
->arrayMask
= origArrayMask
;
1238 /* Texture without alpha test */
1239 if (!ctx
->Color
.AlphaEnabled
) {
1241 /* Now we need the rgba array, fill it in if needed */
1242 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1243 interpolate_colors(ctx
, span
);
1245 _swrast_texture_span( ctx
, span
);
1248 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1250 /* Add base and specular colors */
1251 if (ctx
->Fog
.ColorSumEnabled
||
1252 (ctx
->Light
.Enabled
&&
1253 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1254 if (span
->interpMask
& SPAN_SPEC
) {
1255 interpolate_specular(ctx
, span
);
1257 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1258 add_colors( span
->end
, span
->color
.rgba
, span
->specArray
);
1262 if (ctx
->Fog
.Enabled
) {
1263 _mesa_fog_rgba_span(ctx
, span
);
1266 /* Antialias coverage application */
1267 if (span
->arrayMask
& SPAN_COVERAGE
) {
1268 GLchan (*rgba
)[4] = span
->color
.rgba
;
1270 for (i
= 0; i
< span
->end
; i
++) {
1271 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * span
->coverage
[i
]);
1275 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1276 multi_write_rgba_span(ctx
, span
);
1279 /* normal: write to exactly one buffer */
1280 if (ctx
->Color
.ColorLogicOpEnabled
) {
1281 _mesa_logicop_rgba_span(ctx
, span
, span
->color
.rgba
);
1283 else if (ctx
->Color
.BlendEnabled
) {
1284 _mesa_blend_span(ctx
, span
, span
->color
.rgba
);
1287 if (colorMask
!= 0xffffffff) {
1288 _mesa_mask_rgba_span(ctx
, span
, span
->color
.rgba
);
1292 if (span
->arrayMask
& SPAN_XY
) {
1293 /* array of pixel coords */
1294 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->xArray
,
1295 span
->yArray
, (const GLchan (*)[4]) span
->color
.rgba
, span
->mask
);
1296 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1297 _mesa_write_alpha_pixels(ctx
, span
->end
,
1298 span
->xArray
, span
->yArray
,
1299 (const GLchan (*)[4]) span
->color
.rgba
,
1304 /* horizontal run of pixels */
1305 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1306 (const GLchan (*)[4]) span
->color
.rgba
,
1307 span
->writeAll
? NULL
: span
->mask
);
1308 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1309 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1310 (const GLchan (*)[4]) span
->color
.rgba
,
1311 span
->writeAll
? NULL
: span
->mask
);
1316 span
->arrayMask
= origArrayMask
;
1322 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1323 * reading ouside the buffer's boundaries.
1326 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1327 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1329 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1330 const GLint bufWidth
= (GLint
) buffer
->Width
;
1331 const GLint bufHeight
= (GLint
) buffer
->Height
;
1333 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1334 /* completely above, below, or right */
1335 /* XXX maybe leave undefined? */
1336 BZERO(rgba
, 4 * n
* sizeof(GLchan
));
1341 /* left edge clippping */
1343 length
= (GLint
) n
- skip
;
1345 /* completely left of window */
1348 if (length
> bufWidth
) {
1352 else if ((GLint
) (x
+ n
) > bufWidth
) {
1353 /* right edge clipping */
1355 length
= bufWidth
- x
;
1357 /* completely to right of window */
1367 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1368 if (buffer
->UseSoftwareAlphaBuffers
) {
1369 _mesa_read_alpha_span(ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1376 * Read CI pixels from frame buffer. Clipping will be done to prevent
1377 * reading ouside the buffer's boundaries.
1380 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1381 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1383 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1384 const GLint bufWidth
= (GLint
) buffer
->Width
;
1385 const GLint bufHeight
= (GLint
) buffer
->Height
;
1387 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1388 /* completely above, below, or right */
1389 BZERO(indx
, n
* sizeof(GLuint
));
1394 /* left edge clippping */
1396 length
= (GLint
) n
- skip
;
1398 /* completely left of window */
1401 if (length
> bufWidth
) {
1405 else if ((GLint
) (x
+ n
) > bufWidth
) {
1406 /* right edge clipping */
1408 length
= bufWidth
- x
;
1410 /* completely to right of window */
1420 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);