1 /* $Id: s_span.c,v 1.57 2003/03/04 16:34:03 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2003 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"
49 #include "s_nvfragprog.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
+ 0.5F
);
65 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
+ 0.5F
);
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 COPY_4V(span
->tex
[i
], ctx
->Current
.RasterTexCoords
[i
]);
132 ASSIGN_4V(span
->texStepX
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
133 ASSIGN_4V(span
->texStepY
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
135 span
->interpMask
|= SPAN_TEXTURE
;
139 /* Fill in the span.color.rgba array from the interpolation values */
141 interpolate_colors(GLcontext
*ctx
, struct sw_span
*span
)
143 const GLuint n
= span
->end
;
144 GLchan (*rgba
)[4] = span
->array
->rgba
;
147 ASSERT((span
->interpMask
& SPAN_RGBA
) &&
148 !(span
->arrayMask
& SPAN_RGBA
));
150 if (span
->interpMask
& SPAN_FLAT
) {
153 color
[RCOMP
] = FixedToChan(span
->red
);
154 color
[GCOMP
] = FixedToChan(span
->green
);
155 color
[BCOMP
] = FixedToChan(span
->blue
);
156 color
[ACOMP
] = FixedToChan(span
->alpha
);
157 for (i
= 0; i
< n
; i
++) {
158 COPY_CHAN4(span
->array
->rgba
[i
], color
);
163 #if CHAN_TYPE == GL_FLOAT
164 GLfloat r
= span
->red
;
165 GLfloat g
= span
->green
;
166 GLfloat b
= span
->blue
;
167 GLfloat a
= span
->alpha
;
168 const GLfloat dr
= span
->redStep
;
169 const GLfloat dg
= span
->greenStep
;
170 const GLfloat db
= span
->blueStep
;
171 const GLfloat da
= span
->alphaStep
;
173 GLfixed r
= span
->red
;
174 GLfixed g
= span
->green
;
175 GLfixed b
= span
->blue
;
176 GLfixed a
= span
->alpha
;
177 const GLint dr
= span
->redStep
;
178 const GLint dg
= span
->greenStep
;
179 const GLint db
= span
->blueStep
;
180 const GLint da
= span
->alphaStep
;
182 for (i
= 0; i
< n
; i
++) {
183 rgba
[i
][RCOMP
] = FixedToChan(r
);
184 rgba
[i
][GCOMP
] = FixedToChan(g
);
185 rgba
[i
][BCOMP
] = FixedToChan(b
);
186 rgba
[i
][ACOMP
] = FixedToChan(a
);
193 span
->arrayMask
|= SPAN_RGBA
;
197 /* Fill in the span.color.index array from the interpolation values */
199 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
201 GLfixed index
= span
->index
;
202 const GLint indexStep
= span
->indexStep
;
203 const GLuint n
= span
->end
;
204 GLuint
*indexes
= span
->array
->index
;
206 ASSERT((span
->interpMask
& SPAN_INDEX
) &&
207 !(span
->arrayMask
& SPAN_INDEX
));
209 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
211 index
= FixedToInt(index
);
212 for (i
= 0; i
< n
; i
++) {
218 for (i
= 0; i
< n
; i
++) {
219 indexes
[i
] = FixedToInt(index
);
223 span
->arrayMask
|= SPAN_INDEX
;
227 /* Fill in the span.->array->spec array from the interpolation values */
229 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
231 if (span
->interpMask
& SPAN_FLAT
) {
233 const GLchan r
= FixedToChan(span
->specRed
);
234 const GLchan g
= FixedToChan(span
->specGreen
);
235 const GLchan b
= FixedToChan(span
->specBlue
);
237 for (i
= 0; i
< span
->end
; i
++) {
238 span
->array
->spec
[i
][RCOMP
] = r
;
239 span
->array
->spec
[i
][GCOMP
] = g
;
240 span
->array
->spec
[i
][BCOMP
] = b
;
245 #if CHAN_TYPE == GL_FLOAT
246 GLfloat r
= span
->specRed
;
247 GLfloat g
= span
->specGreen
;
248 GLfloat b
= span
->specBlue
;
250 GLfixed r
= span
->specRed
;
251 GLfixed g
= span
->specGreen
;
252 GLfixed b
= span
->specBlue
;
255 for (i
= 0; i
< span
->end
; i
++) {
256 span
->array
->spec
[i
][RCOMP
] = FixedToChan(r
);
257 span
->array
->spec
[i
][GCOMP
] = FixedToChan(g
);
258 span
->array
->spec
[i
][BCOMP
] = FixedToChan(b
);
259 r
+= span
->specRedStep
;
260 g
+= span
->specGreenStep
;
261 b
+= span
->specBlueStep
;
264 span
->arrayMask
|= SPAN_SPEC
;
268 /* Fill in the span.zArray array from the interpolation values */
270 _mesa_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
272 const GLuint n
= span
->end
;
275 ASSERT((span
->interpMask
& SPAN_Z
) &&
276 !(span
->arrayMask
& SPAN_Z
));
278 if (ctx
->Visual
.depthBits
<= 16) {
279 GLfixed zval
= span
->z
;
280 GLdepth
*z
= span
->array
->z
;
281 for (i
= 0; i
< n
; i
++) {
282 z
[i
] = FixedToInt(zval
);
287 /* Deep Z buffer, no fixed->int shift */
288 GLfixed zval
= span
->z
;
289 GLdepth
*z
= span
->array
->z
;
290 for (i
= 0; i
< n
; i
++) {
295 span
->arrayMask
|= SPAN_Z
;
300 * This the ideal solution, as given in the OpenGL spec.
304 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
305 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
306 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
308 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
309 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
310 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
311 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
312 GLfloat x
= SQRTF(dudx
* dudx
+ dvdx
* dvdx
);
313 GLfloat y
= SQRTF(dudy
* dudy
+ dvdy
* dvdy
);
314 GLfloat rho
= MAX2(x
, y
);
315 GLfloat lambda
= LOG2(rho
);
322 * This is a faster approximation
325 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
326 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
327 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
329 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
330 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
331 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
332 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
333 GLfloat maxU
, maxV
, rho
, lambda
;
334 dsdx2
= FABSF(dsdx2
);
335 dsdy2
= FABSF(dsdy2
);
336 dtdx2
= FABSF(dtdx2
);
337 dtdy2
= FABSF(dtdy2
);
338 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
339 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
340 rho
= MAX2(maxU
, maxV
);
346 * Fill in the span.texcoords array from the interpolation values.
347 * XXX We could optimize here for the case when dq = 0. That would
348 * usually be the case when using an orthographic projection.
351 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
353 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
354 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
356 if (ctx
->Texture
._EnabledUnits
> 1) {
359 span
->arrayMask
|= SPAN_TEXTURE
;
360 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
361 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
362 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
363 const struct gl_texture_image
*img
= obj
->Image
[obj
->BaseLevel
];
364 GLboolean needLambda
= (obj
->MinFilter
!= obj
->MagFilter
);
366 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
367 GLfloat
*lambda
= span
->array
->lambda
[u
];
368 const GLfloat texW
= (GLfloat
) img
->WidthScale
;
369 const GLfloat texH
= (GLfloat
) img
->HeightScale
;
370 const GLfloat dsdx
= span
->texStepX
[u
][0];
371 const GLfloat dsdy
= span
->texStepY
[u
][0];
372 const GLfloat dtdx
= span
->texStepX
[u
][1];
373 const GLfloat dtdy
= span
->texStepY
[u
][1];
374 const GLfloat drdx
= span
->texStepX
[u
][2];
375 const GLfloat dqdx
= span
->texStepX
[u
][3];
376 const GLfloat dqdy
= span
->texStepY
[u
][3];
377 GLfloat s
= span
->tex
[u
][0];
378 GLfloat t
= span
->tex
[u
][1];
379 GLfloat r
= span
->tex
[u
][2];
380 GLfloat q
= span
->tex
[u
][3];
382 for (i
= 0; i
< span
->end
; i
++) {
383 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
384 texcoord
[i
][0] = s
* invQ
;
385 texcoord
[i
][1] = t
* invQ
;
386 texcoord
[i
][2] = r
* invQ
;
387 lambda
[i
] = compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
388 dqdx
, dqdy
, texW
, texH
,
395 span
->arrayMask
|= SPAN_LAMBDA
;
398 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
399 GLfloat
*lambda
= span
->array
->lambda
[u
];
400 const GLfloat dsdx
= span
->texStepX
[u
][0];
401 const GLfloat dtdx
= span
->texStepX
[u
][1];
402 const GLfloat drdx
= span
->texStepX
[u
][2];
403 const GLfloat dqdx
= span
->texStepX
[u
][3];
404 GLfloat s
= span
->tex
[u
][0];
405 GLfloat t
= span
->tex
[u
][1];
406 GLfloat r
= span
->tex
[u
][2];
407 GLfloat q
= span
->tex
[u
][3];
410 /* Ortho projection or polygon's parallel to window X axis */
411 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
412 for (i
= 0; i
< span
->end
; i
++) {
413 texcoord
[i
][0] = s
* invQ
;
414 texcoord
[i
][1] = t
* invQ
;
415 texcoord
[i
][2] = r
* invQ
;
423 for (i
= 0; i
< span
->end
; i
++) {
424 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
425 texcoord
[i
][0] = s
* invQ
;
426 texcoord
[i
][1] = t
* invQ
;
427 texcoord
[i
][2] = r
* invQ
;
441 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
442 const struct gl_texture_image
*img
= obj
->Image
[obj
->BaseLevel
];
443 GLboolean needLambda
= (obj
->MinFilter
!= obj
->MagFilter
);
444 span
->arrayMask
|= SPAN_TEXTURE
;
446 /* just texture unit 0, with lambda */
447 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
448 GLfloat
*lambda
= span
->array
->lambda
[0];
449 const GLfloat texW
= (GLfloat
) img
->WidthScale
;
450 const GLfloat texH
= (GLfloat
) img
->HeightScale
;
451 const GLfloat dsdx
= span
->texStepX
[0][0];
452 const GLfloat dsdy
= span
->texStepY
[0][0];
453 const GLfloat dtdx
= span
->texStepX
[0][1];
454 const GLfloat dtdy
= span
->texStepY
[0][1];
455 const GLfloat drdx
= span
->texStepX
[0][2];
456 const GLfloat dqdx
= span
->texStepX
[0][3];
457 const GLfloat dqdy
= span
->texStepY
[0][3];
458 GLfloat s
= span
->tex
[0][0];
459 GLfloat t
= span
->tex
[0][1];
460 GLfloat r
= span
->tex
[0][2];
461 GLfloat q
= span
->tex
[0][3];
463 for (i
= 0; i
< span
->end
; i
++) {
464 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
465 lambda
[i
] = compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
466 dqdx
, dqdy
, texW
, texH
,
468 texcoord
[i
][0] = s
* invQ
;
469 texcoord
[i
][1] = t
* invQ
;
470 texcoord
[i
][2] = r
* invQ
;
476 span
->arrayMask
|= SPAN_LAMBDA
;
479 /* just texture 0, without lambda */
480 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
481 const GLfloat dsdx
= span
->texStepX
[0][0];
482 const GLfloat dtdx
= span
->texStepX
[0][1];
483 const GLfloat drdx
= span
->texStepX
[0][2];
484 const GLfloat dqdx
= span
->texStepX
[0][3];
485 GLfloat s
= span
->tex
[0][0];
486 GLfloat t
= span
->tex
[0][1];
487 GLfloat r
= span
->tex
[0][2];
488 GLfloat q
= span
->tex
[0][3];
491 /* Ortho projection or polygon's parallel to window X axis */
492 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
493 for (i
= 0; i
< span
->end
; i
++) {
494 texcoord
[i
][0] = s
* invQ
;
495 texcoord
[i
][1] = t
* invQ
;
496 texcoord
[i
][2] = r
* invQ
;
503 for (i
= 0; i
< span
->end
; i
++) {
504 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
505 texcoord
[i
][0] = s
* invQ
;
506 texcoord
[i
][1] = t
* invQ
;
507 texcoord
[i
][2] = r
* invQ
;
520 * Apply the current polygon stipple pattern to a span of pixels.
523 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
525 const GLuint highbit
= 0x80000000;
526 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
527 GLubyte
*mask
= span
->array
->mask
;
530 ASSERT(ctx
->Polygon
.StippleFlag
);
531 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
533 m
= highbit
>> (GLuint
) (span
->x
% 32);
535 for (i
= 0; i
< span
->end
; i
++) {
536 if ((m
& stipple
) == 0) {
544 span
->writeAll
= GL_FALSE
;
549 * Clip a pixel span to the current buffer/window boundaries:
550 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
551 * window clipping and scissoring.
552 * Return: GL_TRUE some pixels still visible
553 * GL_FALSE nothing visible
556 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
558 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
559 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
560 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
561 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
563 if (span
->arrayMask
& SPAN_XY
) {
564 /* arrays of x/y pixel coords */
565 const GLint
*x
= span
->array
->x
;
566 const GLint
*y
= span
->array
->y
;
567 const GLint n
= span
->end
;
568 GLubyte
*mask
= span
->array
->mask
;
570 if (span
->arrayMask
& SPAN_MASK
) {
571 /* note: using & intead of && to reduce branches */
572 for (i
= 0; i
< n
; i
++) {
573 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
574 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
578 /* note: using & intead of && to reduce branches */
579 for (i
= 0; i
< n
; i
++) {
580 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
581 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
584 return GL_TRUE
; /* some pixels visible */
587 /* horizontal span of pixels */
588 const GLint x
= span
->x
;
589 const GLint y
= span
->y
;
590 const GLint n
= span
->end
;
592 /* Trivial rejection tests */
593 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
595 return GL_FALSE
; /* all pixels clipped */
598 /* Clip to the left */
600 ASSERT(x
+ n
> xmin
);
601 span
->writeAll
= GL_FALSE
;
602 _mesa_bzero(span
->array
->mask
, (xmin
- x
) * sizeof(GLubyte
));
608 span
->end
= xmax
- x
;
611 return GL_TRUE
; /* some pixels visible */
618 * Draw to more than one color buffer (or none).
621 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
623 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
626 /* loop over four possible dest color buffers */
627 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
628 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
629 GLuint indexTmp
[MAX_WIDTH
];
630 ASSERT(span
->end
< MAX_WIDTH
);
632 /* Set the current read/draw buffer */
633 swrast
->CurrentBuffer
= bufferBit
;
634 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
636 /* make copy of incoming indexes */
637 MEMCPY( indexTmp
, span
->array
->index
, span
->end
* sizeof(GLuint
) );
639 if (ctx
->Color
.IndexLogicOpEnabled
) {
640 _mesa_logicop_ci_span(ctx
, span
, indexTmp
);
643 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
644 _mesa_mask_index_span(ctx
, span
, indexTmp
);
647 if (span
->arrayMask
& SPAN_XY
) {
648 /* array of pixel coords */
649 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
650 span
->array
->x
, span
->array
->y
,
651 indexTmp
, span
->array
->mask
);
654 /* horizontal run of pixels */
655 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
656 indexTmp
, span
->array
->mask
);
661 /* restore default dest buffer */
662 _swrast_use_draw_buffer(ctx
);
667 * Draw to more than one RGBA color buffer (or none).
668 * All fragment operations, up to (but not) blending/logicop should
669 * have been done first.
672 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
674 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
676 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
678 ASSERT(colorMask
!= 0x0);
680 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
683 /* loop over four possible dest color buffers */
684 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
685 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
686 GLchan rgbaTmp
[MAX_WIDTH
][4];
687 ASSERT(span
->end
< MAX_WIDTH
);
689 /* Set the current read/draw buffer */
690 swrast
->CurrentBuffer
= bufferBit
;
691 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
693 /* make copy of incoming colors */
694 MEMCPY( rgbaTmp
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
) );
696 if (ctx
->Color
.ColorLogicOpEnabled
) {
697 _mesa_logicop_rgba_span(ctx
, span
, rgbaTmp
);
699 else if (ctx
->Color
.BlendEnabled
) {
700 _mesa_blend_span(ctx
, span
, rgbaTmp
);
703 if (colorMask
!= 0xffffffff) {
704 _mesa_mask_rgba_span(ctx
, span
, rgbaTmp
);
707 if (span
->arrayMask
& SPAN_XY
) {
708 /* array of pixel coords */
709 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
710 span
->array
->x
, span
->array
->y
,
711 (const GLchan (*)[4]) rgbaTmp
,
713 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
714 _mesa_write_alpha_pixels(ctx
, span
->end
,
715 span
->array
->x
, span
->array
->y
,
716 (const GLchan (*)[4]) rgbaTmp
,
721 /* horizontal run of pixels */
722 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
723 (const GLchan (*)[4]) rgbaTmp
,
725 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
726 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
727 (const GLchan (*)[4]) rgbaTmp
,
734 /* restore default dest buffer */
735 _swrast_use_draw_buffer(ctx
);
741 * This function may modify any of the array values in the span.
742 * span->interpMask and span->arrayMask may be changed but will be restored
743 * to their original values before returning.
746 _mesa_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
748 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
749 const GLuint origInterpMask
= span
->interpMask
;
750 const GLuint origArrayMask
= span
->arrayMask
;
752 ASSERT(span
->end
<= MAX_WIDTH
);
753 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
754 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
755 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
756 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
758 if (span
->arrayMask
& SPAN_MASK
) {
759 /* mask was initialized by caller, probably glBitmap */
760 span
->writeAll
= GL_FALSE
;
763 MEMSET(span
->array
->mask
, 1, span
->end
);
764 span
->writeAll
= GL_TRUE
;
768 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
769 if (!clip_span(ctx
, span
)) {
775 if (span
->arrayMask
& SPAN_XY
) {
777 for (i
= 0; i
< span
->end
; i
++) {
778 if (span
->array
->mask
[i
]) {
779 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
780 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
781 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
782 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
788 /* Polygon Stippling */
789 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
790 stipple_polygon_span(ctx
, span
);
793 /* Depth test and stencil */
794 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
795 if (span
->interpMask
& SPAN_Z
)
796 _mesa_span_interpolate_z(ctx
, span
);
798 if (ctx
->Stencil
.Enabled
) {
799 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
800 span
->arrayMask
= origArrayMask
;
805 ASSERT(ctx
->Depth
.Test
);
806 if (!_mesa_depth_test_span(ctx
, span
)) {
807 span
->arrayMask
= origArrayMask
;
813 /* if we get here, something passed the depth test */
814 ctx
->OcclusionResult
= GL_TRUE
;
816 /* we have to wait until after occlusion to do this test */
817 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
818 /* write no pixels */
819 span
->arrayMask
= origArrayMask
;
823 /* Interpolate the color indexes if needed */
824 if (span
->interpMask
& SPAN_INDEX
) {
825 interpolate_indexes(ctx
, span
);
826 /* clear the bit - this allows the WriteMonoCISpan optimization below */
827 span
->interpMask
&= ~SPAN_INDEX
;
831 if (ctx
->Fog
.Enabled
) {
832 _mesa_fog_ci_span(ctx
, span
);
835 /* Antialias coverage application */
836 if (span
->arrayMask
& SPAN_COVERAGE
) {
838 GLuint
*index
= span
->array
->index
;
839 GLfloat
*coverage
= span
->array
->coverage
;
840 for (i
= 0; i
< span
->end
; i
++) {
841 ASSERT(coverage
[i
] < 16);
842 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) coverage
[i
]);
846 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
847 /* draw to zero or two or more buffers */
848 multi_write_index_span(ctx
, span
);
851 /* normal situation: draw to exactly one buffer */
852 if (ctx
->Color
.IndexLogicOpEnabled
) {
853 _mesa_logicop_ci_span(ctx
, span
, span
->array
->index
);
856 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
857 _mesa_mask_index_span(ctx
, span
, span
->array
->index
);
861 if (span
->arrayMask
& SPAN_XY
) {
862 /* array of pixel coords */
863 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
864 /* all pixels have same color index */
865 (*swrast
->Driver
.WriteMonoCIPixels
)(ctx
, span
->end
,
866 span
->array
->x
, span
->array
->y
,
867 FixedToInt(span
->index
),
871 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->array
->x
,
872 span
->array
->y
, span
->array
->index
,
877 /* horizontal run of pixels */
878 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
879 /* all pixels have same color index */
880 (*swrast
->Driver
.WriteMonoCISpan
)(ctx
, span
->end
, span
->x
, span
->y
,
881 FixedToInt(span
->index
),
885 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
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
);
923 if (span
->arrayMask
& SPAN_MASK
) {
924 /* mask was initialized by caller, probably glBitmap */
925 span
->writeAll
= GL_FALSE
;
928 MEMSET(span
->array
->mask
, 1, span
->end
);
929 span
->writeAll
= GL_TRUE
;
932 /* Determine if we have mono-chromatic colors */
933 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
934 span
->redStep
== 0 && span
->greenStep
== 0 &&
935 span
->blueStep
== 0 && span
->alphaStep
== 0;
938 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
939 if (!clip_span(ctx
, span
)) {
945 if (span
->arrayMask
& SPAN_XY
) {
947 for (i
= 0; i
< span
->end
; i
++) {
948 if (span
->array
->mask
[i
]) {
949 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
950 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
951 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
952 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
958 /* Polygon Stippling */
959 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
960 stipple_polygon_span(ctx
, span
);
963 /* Fragment program */
964 if (ctx
->FragmentProgram
.Enabled
) {
965 /* Now we may need to interpolate the colors */
966 if ((span
->interpMask
& SPAN_RGBA
) &&
967 (span
->arrayMask
& SPAN_RGBA
) == 0) {
968 interpolate_colors(ctx
, span
);
969 span
->interpMask
&= ~SPAN_RGBA
;
971 _swrast_exec_nv_fragment_program(ctx
, span
);
972 monoColor
= GL_FALSE
;
975 /* Do the alpha test */
976 if (ctx
->Color
.AlphaEnabled
) {
977 if (!_mesa_alpha_test(ctx
, span
)) {
978 span
->interpMask
= origInterpMask
;
979 span
->arrayMask
= origArrayMask
;
984 /* Stencil and Z testing */
985 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
986 if (span
->interpMask
& SPAN_Z
)
987 _mesa_span_interpolate_z(ctx
, span
);
989 if (ctx
->Stencil
.Enabled
) {
990 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
991 span
->interpMask
= origInterpMask
;
992 span
->arrayMask
= origArrayMask
;
997 ASSERT(ctx
->Depth
.Test
);
998 ASSERT(span
->arrayMask
& SPAN_Z
);
999 /* regular depth testing */
1000 if (!_mesa_depth_test_span(ctx
, span
)) {
1001 span
->interpMask
= origInterpMask
;
1002 span
->arrayMask
= origArrayMask
;
1008 /* if we get here, something passed the depth test */
1009 ctx
->OcclusionResult
= GL_TRUE
;
1011 /* can't abort span-writing until after occlusion testing */
1012 if (colorMask
== 0x0) {
1013 span
->interpMask
= origInterpMask
;
1014 span
->arrayMask
= origArrayMask
;
1018 /* Now we may need to interpolate the colors */
1019 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
1020 interpolate_colors(ctx
, span
);
1021 /* clear the bit - this allows the WriteMonoCISpan optimization below */
1022 span
->interpMask
&= ~SPAN_RGBA
;
1026 if (ctx
->Fog
.Enabled
) {
1027 _mesa_fog_rgba_span(ctx
, span
);
1028 monoColor
= GL_FALSE
;
1031 /* Antialias coverage application */
1032 if (span
->arrayMask
& SPAN_COVERAGE
) {
1033 GLchan (*rgba
)[4] = span
->array
->rgba
;
1034 GLfloat
*coverage
= span
->array
->coverage
;
1036 for (i
= 0; i
< span
->end
; i
++) {
1037 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1039 monoColor
= GL_FALSE
;
1042 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1043 multi_write_rgba_span(ctx
, span
);
1046 /* normal: write to exactly one buffer */
1047 if (ctx
->Color
.ColorLogicOpEnabled
) {
1048 _mesa_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1049 monoColor
= GL_FALSE
;
1051 else if (ctx
->Color
.BlendEnabled
) {
1052 _mesa_blend_span(ctx
, span
, span
->array
->rgba
);
1053 monoColor
= GL_FALSE
;
1056 /* Color component masking */
1057 if (colorMask
!= 0xffffffff) {
1058 _mesa_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1059 monoColor
= GL_FALSE
;
1063 if (span
->arrayMask
& SPAN_XY
) {
1064 /* array of pixel coords */
1065 /* XXX test for mono color */
1066 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1067 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1068 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1069 _mesa_write_alpha_pixels(ctx
, span
->end
,
1070 span
->array
->x
, span
->array
->y
,
1071 (const GLchan (*)[4]) span
->array
->rgba
,
1076 /* horizontal run of pixels */
1078 /* all pixels have same color */
1080 color
[RCOMP
] = FixedToChan(span
->red
);
1081 color
[GCOMP
] = FixedToChan(span
->green
);
1082 color
[BCOMP
] = FixedToChan(span
->blue
);
1083 color
[ACOMP
] = FixedToChan(span
->alpha
);
1084 (*swrast
->Driver
.WriteMonoRGBASpan
)(ctx
, span
->end
, span
->x
,
1085 span
->y
, color
, span
->array
->mask
);
1086 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1087 _mesa_write_mono_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1089 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1093 /* each pixel is a different color */
1094 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1095 (const GLchan (*)[4]) span
->array
->rgba
,
1096 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1097 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1098 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1099 (const GLchan (*)[4]) span
->array
->rgba
,
1100 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1106 span
->interpMask
= origInterpMask
;
1107 span
->arrayMask
= origArrayMask
;
1112 * Add specular color to base color. This is used only when
1113 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1116 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1119 for (i
= 0; i
< n
; i
++) {
1120 #if CHAN_TYPE == GL_FLOAT
1122 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1123 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1124 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1126 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1127 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1128 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1129 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1130 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1131 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1138 * This function may modify any of the array values in the span.
1139 * span->interpMask and span->arrayMask may be changed but will be restored
1140 * to their original values before returning.
1143 _mesa_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
1145 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1146 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1147 const GLuint origArrayMask
= span
->arrayMask
;
1149 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1150 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1151 ASSERT(span
->end
<= MAX_WIDTH
);
1152 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1153 ASSERT(ctx
->Texture
._EnabledUnits
);
1156 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1159 if (span
->arrayMask
& SPAN_MASK
) {
1160 /* mask was initialized by caller, probably glBitmap */
1161 span
->writeAll
= GL_FALSE
;
1164 MEMSET(span
->array
->mask
, 1, span
->end
);
1165 span
->writeAll
= GL_TRUE
;
1169 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1170 if (!clip_span(ctx
, span
)) {
1176 if (span
->arrayMask
& SPAN_XY
) {
1178 for (i
= 0; i
< span
->end
; i
++) {
1179 if (span
->array
->mask
[i
]) {
1180 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1181 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1182 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1183 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1189 /* Polygon Stippling */
1190 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1191 stipple_polygon_span(ctx
, span
);
1194 /* Need texture coordinates now */
1195 if ((span
->interpMask
& SPAN_TEXTURE
)
1196 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1197 interpolate_texcoords(ctx
, span
);
1199 /* Texture with alpha test */
1200 if (ctx
->Color
.AlphaEnabled
) {
1202 /* Now we need the rgba array, fill it in if needed */
1203 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1204 interpolate_colors(ctx
, span
);
1206 /* Texturing without alpha is done after depth-testing which
1207 * gives a potential speed-up.
1209 if (ctx
->FragmentProgram
.Enabled
)
1210 _swrast_exec_nv_fragment_program( ctx
, span
);
1212 _swrast_texture_span( ctx
, span
);
1214 /* Do the alpha test */
1215 if (!_mesa_alpha_test(ctx
, span
)) {
1216 span
->arrayMask
= origArrayMask
;
1221 /* Stencil and Z testing */
1222 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1223 if (span
->interpMask
& SPAN_Z
)
1224 _mesa_span_interpolate_z(ctx
, span
);
1226 if (ctx
->Stencil
.Enabled
) {
1227 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
1228 span
->arrayMask
= origArrayMask
;
1233 ASSERT(ctx
->Depth
.Test
);
1234 ASSERT(span
->arrayMask
& SPAN_Z
);
1235 /* regular depth testing */
1236 if (!_mesa_depth_test_span(ctx
, span
)) {
1237 span
->arrayMask
= origArrayMask
;
1243 /* if we get here, some fragments passed the depth test */
1244 ctx
->OcclusionResult
= GL_TRUE
;
1246 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1247 * the occlusion test.
1249 if (colorMask
== 0x0) {
1250 span
->arrayMask
= origArrayMask
;
1254 /* Texture without alpha test */
1255 if (!ctx
->Color
.AlphaEnabled
) {
1257 /* Now we need the rgba array, fill it in if needed */
1258 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1259 interpolate_colors(ctx
, span
);
1261 if (ctx
->FragmentProgram
.Enabled
)
1262 _swrast_exec_nv_fragment_program( ctx
, span
);
1264 _swrast_texture_span( ctx
, span
);
1267 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1269 /* Add base and specular colors */
1270 if (ctx
->Fog
.ColorSumEnabled
||
1271 (ctx
->Light
.Enabled
&&
1272 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1273 if (span
->interpMask
& SPAN_SPEC
) {
1274 interpolate_specular(ctx
, span
);
1276 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1277 add_colors( span
->end
, span
->array
->rgba
, span
->array
->spec
);
1281 if (ctx
->Fog
.Enabled
) {
1282 _mesa_fog_rgba_span(ctx
, span
);
1285 /* Antialias coverage application */
1286 if (span
->arrayMask
& SPAN_COVERAGE
) {
1287 GLchan (*rgba
)[4] = span
->array
->rgba
;
1288 GLfloat
*coverage
= span
->array
->coverage
;
1290 for (i
= 0; i
< span
->end
; i
++) {
1291 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1295 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1296 multi_write_rgba_span(ctx
, span
);
1299 /* normal: write to exactly one buffer */
1300 if (ctx
->Color
.ColorLogicOpEnabled
) {
1301 _mesa_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1303 else if (ctx
->Color
.BlendEnabled
) {
1304 _mesa_blend_span(ctx
, span
, span
->array
->rgba
);
1307 if (colorMask
!= 0xffffffff) {
1308 _mesa_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1312 if (span
->arrayMask
& SPAN_XY
) {
1313 /* array of pixel coords */
1314 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1315 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1316 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1317 _mesa_write_alpha_pixels(ctx
, span
->end
,
1318 span
->array
->x
, span
->array
->y
,
1319 (const GLchan (*)[4]) span
->array
->rgba
,
1324 /* horizontal run of pixels */
1325 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1326 (const GLchan (*)[4]) span
->array
->rgba
,
1327 span
->writeAll
? NULL
: span
->array
->mask
);
1328 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1329 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1330 (const GLchan (*)[4]) span
->array
->rgba
,
1331 span
->writeAll
? NULL
: span
->array
->mask
);
1336 span
->arrayMask
= origArrayMask
;
1342 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1343 * reading ouside the buffer's boundaries.
1346 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1347 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1349 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1350 const GLint bufWidth
= (GLint
) buffer
->Width
;
1351 const GLint bufHeight
= (GLint
) buffer
->Height
;
1353 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1354 /* completely above, below, or right */
1355 /* XXX maybe leave undefined? */
1356 _mesa_bzero(rgba
, 4 * n
* sizeof(GLchan
));
1361 /* left edge clippping */
1363 length
= (GLint
) n
- skip
;
1365 /* completely left of window */
1368 if (length
> bufWidth
) {
1372 else if ((GLint
) (x
+ n
) > bufWidth
) {
1373 /* right edge clipping */
1375 length
= bufWidth
- x
;
1377 /* completely to right of window */
1387 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1388 if (buffer
->UseSoftwareAlphaBuffers
) {
1389 _mesa_read_alpha_span(ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1396 * Read CI pixels from frame buffer. Clipping will be done to prevent
1397 * reading ouside the buffer's boundaries.
1400 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1401 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1403 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1404 const GLint bufWidth
= (GLint
) buffer
->Width
;
1405 const GLint bufHeight
= (GLint
) buffer
->Height
;
1407 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1408 /* completely above, below, or right */
1409 _mesa_bzero(indx
, n
* sizeof(GLuint
));
1414 /* left edge clippping */
1416 length
= (GLint
) n
- skip
;
1418 /* completely left of window */
1421 if (length
> bufWidth
) {
1425 else if ((GLint
) (x
+ n
) > bufWidth
) {
1426 /* right edge clipping */
1428 length
= bufWidth
- x
;
1430 /* completely to right of window */
1440 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);