1 /* $Id: s_span.c,v 1.55 2003/02/27 18:15:18 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
43 #include "s_alphabuf.h"
45 #include "s_context.h"
49 #include "s_masking.h"
50 #include "s_nvfragprog.h"
52 #include "s_stencil.h"
53 #include "s_texture.h"
57 * Init span's Z interpolation values to the RasterPos Z.
58 * Used during setup for glDraw/CopyPixels.
61 _mesa_span_default_z( GLcontext
*ctx
, struct sw_span
*span
)
63 if (ctx
->Visual
.depthBits
<= 16)
64 span
->z
= FloatToFixed(ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
+ 0.5F
);
66 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
+ 0.5F
);
68 span
->interpMask
|= SPAN_Z
;
73 * Init span's fog interpolation values to the RasterPos fog.
74 * Used during setup for glDraw/CopyPixels.
77 _mesa_span_default_fog( GLcontext
*ctx
, struct sw_span
*span
)
79 span
->fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
81 span
->interpMask
|= SPAN_FOG
;
86 * Init span's color or index interpolation values to the RasterPos color.
87 * Used during setup for glDraw/CopyPixels.
90 _mesa_span_default_color( GLcontext
*ctx
, struct sw_span
*span
)
92 if (ctx
->Visual
.rgbMode
) {
94 UNCLAMPED_FLOAT_TO_CHAN(r
, ctx
->Current
.RasterColor
[0]);
95 UNCLAMPED_FLOAT_TO_CHAN(g
, ctx
->Current
.RasterColor
[1]);
96 UNCLAMPED_FLOAT_TO_CHAN(b
, ctx
->Current
.RasterColor
[2]);
97 UNCLAMPED_FLOAT_TO_CHAN(a
, ctx
->Current
.RasterColor
[3]);
98 #if CHAN_TYPE == GL_FLOAT
104 span
->red
= IntToFixed(r
);
105 span
->green
= IntToFixed(g
);
106 span
->blue
= IntToFixed(b
);
107 span
->alpha
= IntToFixed(a
);
113 span
->interpMask
|= SPAN_RGBA
;
116 span
->index
= IntToFixed(ctx
->Current
.RasterIndex
);
118 span
->interpMask
|= SPAN_INDEX
;
124 * Init span's texcoord interpolation values to the RasterPos texcoords.
125 * Used during setup for glDraw/CopyPixels.
128 _mesa_span_default_texcoords( GLcontext
*ctx
, struct sw_span
*span
)
131 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
132 COPY_4V(span
->tex
[i
], ctx
->Current
.RasterTexCoords
[i
]);
133 ASSIGN_4V(span
->texStepX
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
134 ASSIGN_4V(span
->texStepY
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
136 span
->interpMask
|= SPAN_TEXTURE
;
140 /* Fill in the span.color.rgba array from the interpolation values */
142 interpolate_colors(GLcontext
*ctx
, struct sw_span
*span
)
144 const GLuint n
= span
->end
;
145 GLchan (*rgba
)[4] = span
->array
->rgba
;
148 ASSERT((span
->interpMask
& SPAN_RGBA
) &&
149 !(span
->arrayMask
& SPAN_RGBA
));
151 if (span
->interpMask
& SPAN_FLAT
) {
154 color
[RCOMP
] = FixedToChan(span
->red
);
155 color
[GCOMP
] = FixedToChan(span
->green
);
156 color
[BCOMP
] = FixedToChan(span
->blue
);
157 color
[ACOMP
] = FixedToChan(span
->alpha
);
158 for (i
= 0; i
< n
; i
++) {
159 COPY_CHAN4(span
->array
->rgba
[i
], color
);
164 #if CHAN_TYPE == GL_FLOAT
165 GLfloat r
= span
->red
;
166 GLfloat g
= span
->green
;
167 GLfloat b
= span
->blue
;
168 GLfloat a
= span
->alpha
;
169 const GLfloat dr
= span
->redStep
;
170 const GLfloat dg
= span
->greenStep
;
171 const GLfloat db
= span
->blueStep
;
172 const GLfloat da
= span
->alphaStep
;
174 GLfixed r
= span
->red
;
175 GLfixed g
= span
->green
;
176 GLfixed b
= span
->blue
;
177 GLfixed a
= span
->alpha
;
178 const GLint dr
= span
->redStep
;
179 const GLint dg
= span
->greenStep
;
180 const GLint db
= span
->blueStep
;
181 const GLint da
= span
->alphaStep
;
183 for (i
= 0; i
< n
; i
++) {
184 rgba
[i
][RCOMP
] = FixedToChan(r
);
185 rgba
[i
][GCOMP
] = FixedToChan(g
);
186 rgba
[i
][BCOMP
] = FixedToChan(b
);
187 rgba
[i
][ACOMP
] = FixedToChan(a
);
194 span
->arrayMask
|= SPAN_RGBA
;
198 /* Fill in the span.color.index array from the interpolation values */
200 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
202 GLfixed index
= span
->index
;
203 const GLint indexStep
= span
->indexStep
;
204 const GLuint n
= span
->end
;
205 GLuint
*indexes
= span
->array
->index
;
207 ASSERT((span
->interpMask
& SPAN_INDEX
) &&
208 !(span
->arrayMask
& SPAN_INDEX
));
210 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
212 index
= FixedToInt(index
);
213 for (i
= 0; i
< n
; i
++) {
219 for (i
= 0; i
< n
; i
++) {
220 indexes
[i
] = FixedToInt(index
);
224 span
->arrayMask
|= SPAN_INDEX
;
228 /* Fill in the span.->array->spec array from the interpolation values */
230 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
232 if (span
->interpMask
& SPAN_FLAT
) {
234 const GLchan r
= FixedToChan(span
->specRed
);
235 const GLchan g
= FixedToChan(span
->specGreen
);
236 const GLchan b
= FixedToChan(span
->specBlue
);
238 for (i
= 0; i
< span
->end
; i
++) {
239 span
->array
->spec
[i
][RCOMP
] = r
;
240 span
->array
->spec
[i
][GCOMP
] = g
;
241 span
->array
->spec
[i
][BCOMP
] = b
;
246 #if CHAN_TYPE == GL_FLOAT
247 GLfloat r
= span
->specRed
;
248 GLfloat g
= span
->specGreen
;
249 GLfloat b
= span
->specBlue
;
251 GLfixed r
= span
->specRed
;
252 GLfixed g
= span
->specGreen
;
253 GLfixed b
= span
->specBlue
;
256 for (i
= 0; i
< span
->end
; i
++) {
257 span
->array
->spec
[i
][RCOMP
] = FixedToChan(r
);
258 span
->array
->spec
[i
][GCOMP
] = FixedToChan(g
);
259 span
->array
->spec
[i
][BCOMP
] = FixedToChan(b
);
260 r
+= span
->specRedStep
;
261 g
+= span
->specGreenStep
;
262 b
+= span
->specBlueStep
;
265 span
->arrayMask
|= SPAN_SPEC
;
269 /* Fill in the span.zArray array from the interpolation values */
271 _mesa_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
273 const GLuint n
= span
->end
;
276 ASSERT((span
->interpMask
& SPAN_Z
) &&
277 !(span
->arrayMask
& SPAN_Z
));
279 if (ctx
->Visual
.depthBits
<= 16) {
280 GLfixed zval
= span
->z
;
281 GLdepth
*z
= span
->array
->z
;
282 for (i
= 0; i
< n
; i
++) {
283 z
[i
] = FixedToInt(zval
);
288 /* Deep Z buffer, no fixed->int shift */
289 GLfixed zval
= span
->z
;
290 GLdepth
*z
= span
->array
->z
;
291 for (i
= 0; i
< n
; i
++) {
296 span
->arrayMask
|= SPAN_Z
;
301 * This the ideal solution, as given in the OpenGL spec.
305 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
306 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
307 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
309 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
310 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
311 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
312 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
313 GLfloat x
= sqrt(dudx
* dudx
+ dvdx
* dvdx
);
314 GLfloat y
= sqrt(dudy
* dudy
+ dvdy
* dvdy
);
315 GLfloat rho
= MAX2(x
, y
);
316 GLfloat lambda
= LOG2(rho
);
323 * This is a faster approximation
326 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
327 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
328 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
330 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
331 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
332 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
333 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
334 GLfloat maxU
, maxV
, rho
, lambda
;
335 dsdx2
= FABSF(dsdx2
);
336 dsdy2
= FABSF(dsdy2
);
337 dtdx2
= FABSF(dtdx2
);
338 dtdy2
= FABSF(dtdy2
);
339 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
340 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
341 rho
= MAX2(maxU
, maxV
);
347 * Fill in the span.texcoords array from the interpolation values.
348 * XXX We could optimize here for the case when dq = 0. That would
349 * usually be the case when using an orthographic projection.
352 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
354 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
355 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
357 if (ctx
->Texture
._EnabledUnits
> 1) {
360 span
->arrayMask
|= SPAN_TEXTURE
;
361 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
362 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
363 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
364 const struct gl_texture_image
*img
= obj
->Image
[obj
->BaseLevel
];
365 GLboolean needLambda
= (obj
->MinFilter
!= obj
->MagFilter
);
367 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
368 GLfloat
*lambda
= span
->array
->lambda
[u
];
369 const GLfloat texW
= (GLfloat
) img
->WidthScale
;
370 const GLfloat texH
= (GLfloat
) img
->HeightScale
;
371 const GLfloat dsdx
= span
->texStepX
[u
][0];
372 const GLfloat dsdy
= span
->texStepY
[u
][0];
373 const GLfloat dtdx
= span
->texStepX
[u
][1];
374 const GLfloat dtdy
= span
->texStepY
[u
][1];
375 const GLfloat drdx
= span
->texStepX
[u
][2];
376 const GLfloat dqdx
= span
->texStepX
[u
][3];
377 const GLfloat dqdy
= span
->texStepY
[u
][3];
378 GLfloat s
= span
->tex
[u
][0];
379 GLfloat t
= span
->tex
[u
][1];
380 GLfloat r
= span
->tex
[u
][2];
381 GLfloat q
= span
->tex
[u
][3];
383 for (i
= 0; i
< span
->end
; i
++) {
384 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
385 texcoord
[i
][0] = s
* invQ
;
386 texcoord
[i
][1] = t
* invQ
;
387 texcoord
[i
][2] = r
* invQ
;
388 lambda
[i
] = compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
389 dqdx
, dqdy
, texW
, texH
,
396 span
->arrayMask
|= SPAN_LAMBDA
;
399 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
400 GLfloat
*lambda
= span
->array
->lambda
[u
];
401 const GLfloat dsdx
= span
->texStepX
[u
][0];
402 const GLfloat dtdx
= span
->texStepX
[u
][1];
403 const GLfloat drdx
= span
->texStepX
[u
][2];
404 const GLfloat dqdx
= span
->texStepX
[u
][3];
405 GLfloat s
= span
->tex
[u
][0];
406 GLfloat t
= span
->tex
[u
][1];
407 GLfloat r
= span
->tex
[u
][2];
408 GLfloat q
= span
->tex
[u
][3];
411 /* Ortho projection or polygon's parallel to window X axis */
412 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
413 for (i
= 0; i
< span
->end
; i
++) {
414 texcoord
[i
][0] = s
* invQ
;
415 texcoord
[i
][1] = t
* invQ
;
416 texcoord
[i
][2] = r
* invQ
;
424 for (i
= 0; i
< span
->end
; i
++) {
425 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
426 texcoord
[i
][0] = s
* invQ
;
427 texcoord
[i
][1] = t
* invQ
;
428 texcoord
[i
][2] = r
* invQ
;
442 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
443 const struct gl_texture_image
*img
= obj
->Image
[obj
->BaseLevel
];
444 GLboolean needLambda
= (obj
->MinFilter
!= obj
->MagFilter
);
445 span
->arrayMask
|= SPAN_TEXTURE
;
447 /* just texture unit 0, with lambda */
448 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
449 GLfloat
*lambda
= span
->array
->lambda
[0];
450 const GLfloat texW
= (GLfloat
) img
->WidthScale
;
451 const GLfloat texH
= (GLfloat
) img
->HeightScale
;
452 const GLfloat dsdx
= span
->texStepX
[0][0];
453 const GLfloat dsdy
= span
->texStepY
[0][0];
454 const GLfloat dtdx
= span
->texStepX
[0][1];
455 const GLfloat dtdy
= span
->texStepY
[0][1];
456 const GLfloat drdx
= span
->texStepX
[0][2];
457 const GLfloat dqdx
= span
->texStepX
[0][3];
458 const GLfloat dqdy
= span
->texStepY
[0][3];
459 GLfloat s
= span
->tex
[0][0];
460 GLfloat t
= span
->tex
[0][1];
461 GLfloat r
= span
->tex
[0][2];
462 GLfloat q
= span
->tex
[0][3];
464 for (i
= 0; i
< span
->end
; i
++) {
465 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
466 lambda
[i
] = compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
467 dqdx
, dqdy
, texW
, texH
,
469 texcoord
[i
][0] = s
* invQ
;
470 texcoord
[i
][1] = t
* invQ
;
471 texcoord
[i
][2] = r
* invQ
;
477 span
->arrayMask
|= SPAN_LAMBDA
;
480 /* just texture 0, without lambda */
481 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
482 const GLfloat dsdx
= span
->texStepX
[0][0];
483 const GLfloat dtdx
= span
->texStepX
[0][1];
484 const GLfloat drdx
= span
->texStepX
[0][2];
485 const GLfloat dqdx
= span
->texStepX
[0][3];
486 GLfloat s
= span
->tex
[0][0];
487 GLfloat t
= span
->tex
[0][1];
488 GLfloat r
= span
->tex
[0][2];
489 GLfloat q
= span
->tex
[0][3];
492 /* Ortho projection or polygon's parallel to window X axis */
493 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
494 for (i
= 0; i
< span
->end
; i
++) {
495 texcoord
[i
][0] = s
* invQ
;
496 texcoord
[i
][1] = t
* invQ
;
497 texcoord
[i
][2] = r
* invQ
;
504 for (i
= 0; i
< span
->end
; i
++) {
505 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
506 texcoord
[i
][0] = s
* invQ
;
507 texcoord
[i
][1] = t
* invQ
;
508 texcoord
[i
][2] = r
* invQ
;
521 * Apply the current polygon stipple pattern to a span of pixels.
524 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
526 const GLuint highbit
= 0x80000000;
527 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
528 GLubyte
*mask
= span
->array
->mask
;
531 ASSERT(ctx
->Polygon
.StippleFlag
);
532 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
534 m
= highbit
>> (GLuint
) (span
->x
% 32);
536 for (i
= 0; i
< span
->end
; i
++) {
537 if ((m
& stipple
) == 0) {
545 span
->writeAll
= GL_FALSE
;
550 * Clip a pixel span to the current buffer/window boundaries:
551 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
552 * window clipping and scissoring.
553 * Return: GL_TRUE some pixels still visible
554 * GL_FALSE nothing visible
557 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
559 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
560 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
561 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
562 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
564 if (span
->arrayMask
& SPAN_XY
) {
565 /* arrays of x/y pixel coords */
566 const GLint
*x
= span
->array
->x
;
567 const GLint
*y
= span
->array
->y
;
568 const GLint n
= span
->end
;
569 GLubyte
*mask
= span
->array
->mask
;
571 if (span
->arrayMask
& SPAN_MASK
) {
572 /* note: using & intead of && to reduce branches */
573 for (i
= 0; i
< n
; i
++) {
574 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
575 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
579 /* note: using & intead of && to reduce branches */
580 for (i
= 0; i
< n
; i
++) {
581 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
582 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
585 return GL_TRUE
; /* some pixels visible */
588 /* horizontal span of pixels */
589 const GLint x
= span
->x
;
590 const GLint y
= span
->y
;
591 const GLint n
= span
->end
;
593 /* Trivial rejection tests */
594 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
596 return GL_FALSE
; /* all pixels clipped */
599 /* Clip to the left */
601 ASSERT(x
+ n
> xmin
);
602 span
->writeAll
= GL_FALSE
;
603 _mesa_bzero(span
->array
->mask
, (xmin
- x
) * sizeof(GLubyte
));
609 span
->end
= xmax
- x
;
612 return GL_TRUE
; /* some pixels visible */
619 * Draw to more than one color buffer (or none).
622 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
624 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
627 /* loop over four possible dest color buffers */
628 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
629 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
630 GLuint indexTmp
[MAX_WIDTH
];
631 ASSERT(span
->end
< MAX_WIDTH
);
633 /* Set the current read/draw buffer */
634 swrast
->CurrentBuffer
= bufferBit
;
635 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
637 /* make copy of incoming indexes */
638 MEMCPY( indexTmp
, span
->array
->index
, span
->end
* sizeof(GLuint
) );
640 if (ctx
->Color
.IndexLogicOpEnabled
) {
641 _mesa_logicop_ci_span(ctx
, span
, indexTmp
);
644 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
645 _mesa_mask_index_span(ctx
, span
, indexTmp
);
648 if (span
->arrayMask
& SPAN_XY
) {
649 /* array of pixel coords */
650 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
651 span
->array
->x
, span
->array
->y
,
652 indexTmp
, span
->array
->mask
);
655 /* horizontal run of pixels */
656 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
657 indexTmp
, span
->array
->mask
);
662 /* restore default dest buffer */
663 _swrast_use_draw_buffer(ctx
);
668 * Draw to more than one RGBA color buffer (or none).
669 * All fragment operations, up to (but not) blending/logicop should
670 * have been done first.
673 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
675 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
677 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
679 ASSERT(colorMask
!= 0x0);
681 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
684 /* loop over four possible dest color buffers */
685 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
686 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
687 GLchan rgbaTmp
[MAX_WIDTH
][4];
688 ASSERT(span
->end
< MAX_WIDTH
);
690 /* Set the current read/draw buffer */
691 swrast
->CurrentBuffer
= bufferBit
;
692 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
694 /* make copy of incoming colors */
695 MEMCPY( rgbaTmp
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
) );
697 if (ctx
->Color
.ColorLogicOpEnabled
) {
698 _mesa_logicop_rgba_span(ctx
, span
, rgbaTmp
);
700 else if (ctx
->Color
.BlendEnabled
) {
701 _mesa_blend_span(ctx
, span
, rgbaTmp
);
704 if (colorMask
!= 0xffffffff) {
705 _mesa_mask_rgba_span(ctx
, span
, rgbaTmp
);
708 if (span
->arrayMask
& SPAN_XY
) {
709 /* array of pixel coords */
710 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
711 span
->array
->x
, span
->array
->y
,
712 (const GLchan (*)[4]) rgbaTmp
,
714 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
715 _mesa_write_alpha_pixels(ctx
, span
->end
,
716 span
->array
->x
, span
->array
->y
,
717 (const GLchan (*)[4]) rgbaTmp
,
722 /* horizontal run of pixels */
723 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
724 (const GLchan (*)[4]) rgbaTmp
,
726 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
727 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
728 (const GLchan (*)[4]) rgbaTmp
,
735 /* restore default dest buffer */
736 _swrast_use_draw_buffer(ctx
);
742 * This function may modify any of the array values in the span.
743 * span->interpMask and span->arrayMask may be changed but will be restored
744 * to their original values before returning.
747 _mesa_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
749 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
750 const GLuint origInterpMask
= span
->interpMask
;
751 const GLuint origArrayMask
= span
->arrayMask
;
753 ASSERT(span
->end
<= MAX_WIDTH
);
754 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
755 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
756 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
757 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
759 if (span
->arrayMask
& SPAN_MASK
) {
760 /* mask was initialized by caller, probably glBitmap */
761 span
->writeAll
= GL_FALSE
;
764 MEMSET(span
->array
->mask
, 1, span
->end
);
765 span
->writeAll
= GL_TRUE
;
769 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
770 if (!clip_span(ctx
, span
)) {
776 if (span
->arrayMask
& SPAN_XY
) {
778 for (i
= 0; i
< span
->end
; i
++) {
779 if (span
->array
->mask
[i
]) {
780 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
781 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
782 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
783 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
789 /* Polygon Stippling */
790 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
791 stipple_polygon_span(ctx
, span
);
794 /* Depth test and stencil */
795 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
796 if (span
->interpMask
& SPAN_Z
)
797 _mesa_span_interpolate_z(ctx
, span
);
799 if (ctx
->Stencil
.Enabled
) {
800 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
801 span
->arrayMask
= origArrayMask
;
806 ASSERT(ctx
->Depth
.Test
);
807 if (!_mesa_depth_test_span(ctx
, span
)) {
808 span
->arrayMask
= origArrayMask
;
814 /* if we get here, something passed the depth test */
815 ctx
->OcclusionResult
= GL_TRUE
;
817 /* we have to wait until after occlusion to do this test */
818 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
819 /* write no pixels */
820 span
->arrayMask
= origArrayMask
;
824 /* Interpolate the color indexes if needed */
825 if (span
->interpMask
& SPAN_INDEX
) {
826 interpolate_indexes(ctx
, span
);
827 /* clear the bit - this allows the WriteMonoCISpan optimization below */
828 span
->interpMask
&= ~SPAN_INDEX
;
832 if (ctx
->Fog
.Enabled
) {
833 _mesa_fog_ci_span(ctx
, span
);
836 /* Antialias coverage application */
837 if (span
->arrayMask
& SPAN_COVERAGE
) {
839 GLuint
*index
= span
->array
->index
;
840 GLfloat
*coverage
= span
->array
->coverage
;
841 for (i
= 0; i
< span
->end
; i
++) {
842 ASSERT(coverage
[i
] < 16);
843 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) 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
->array
->index
);
857 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
858 _mesa_mask_index_span(ctx
, span
, span
->array
->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
->array
->x
, span
->array
->y
,
868 FixedToInt(span
->index
),
872 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->array
->x
,
873 span
->array
->y
, span
->array
->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
,
893 span
->interpMask
= origInterpMask
;
894 span
->arrayMask
= origArrayMask
;
899 * This function may modify any of the array values in the span.
900 * span->interpMask and span->arrayMask may be changed but will be restored
901 * to their original values before returning.
904 _mesa_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
906 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
907 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
908 const GLuint origInterpMask
= span
->interpMask
;
909 const GLuint origArrayMask
= span
->arrayMask
;
912 ASSERT(span
->end
<= MAX_WIDTH
);
913 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
914 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
915 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
916 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_RGBA
);
918 if (ctx
->Fog
.Enabled
)
919 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
921 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_Z
);
924 if (span
->arrayMask
& SPAN_MASK
) {
925 /* mask was initialized by caller, probably glBitmap */
926 span
->writeAll
= GL_FALSE
;
929 MEMSET(span
->array
->mask
, 1, span
->end
);
930 span
->writeAll
= GL_TRUE
;
933 /* Determine if we have mono-chromatic colors */
934 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
935 span
->redStep
== 0 && span
->greenStep
== 0 &&
936 span
->blueStep
== 0 && span
->alphaStep
== 0;
939 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
940 if (!clip_span(ctx
, span
)) {
946 if (span
->arrayMask
& SPAN_XY
) {
948 for (i
= 0; i
< span
->end
; i
++) {
949 if (span
->array
->mask
[i
]) {
950 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
951 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
952 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
953 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
959 /* Polygon Stippling */
960 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
961 stipple_polygon_span(ctx
, span
);
964 /* Fragment program */
965 if (ctx
->FragmentProgram
.Enabled
) {
966 /* Now we may need to interpolate the colors */
967 if ((span
->interpMask
& SPAN_RGBA
) &&
968 (span
->arrayMask
& SPAN_RGBA
) == 0) {
969 interpolate_colors(ctx
, span
);
970 span
->interpMask
&= ~SPAN_RGBA
;
972 _swrast_exec_nv_fragment_program(ctx
, span
);
973 monoColor
= GL_FALSE
;
976 /* Do the alpha test */
977 if (ctx
->Color
.AlphaEnabled
) {
978 if (!_mesa_alpha_test(ctx
, span
)) {
979 span
->interpMask
= origInterpMask
;
980 span
->arrayMask
= origArrayMask
;
985 /* Stencil and Z testing */
986 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
987 if (span
->interpMask
& SPAN_Z
)
988 _mesa_span_interpolate_z(ctx
, span
);
990 if (ctx
->Stencil
.Enabled
) {
991 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
992 span
->interpMask
= origInterpMask
;
993 span
->arrayMask
= origArrayMask
;
998 ASSERT(ctx
->Depth
.Test
);
999 ASSERT(span
->arrayMask
& SPAN_Z
);
1000 /* regular depth testing */
1001 if (!_mesa_depth_test_span(ctx
, span
)) {
1002 span
->interpMask
= origInterpMask
;
1003 span
->arrayMask
= origArrayMask
;
1009 /* if we get here, something passed the depth test */
1010 ctx
->OcclusionResult
= GL_TRUE
;
1012 /* can't abort span-writing until after occlusion testing */
1013 if (colorMask
== 0x0) {
1014 span
->interpMask
= origInterpMask
;
1015 span
->arrayMask
= origArrayMask
;
1019 /* Now we may need to interpolate the colors */
1020 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
1021 interpolate_colors(ctx
, span
);
1022 /* clear the bit - this allows the WriteMonoCISpan optimization below */
1023 span
->interpMask
&= ~SPAN_RGBA
;
1027 if (ctx
->Fog
.Enabled
) {
1028 _mesa_fog_rgba_span(ctx
, span
);
1029 monoColor
= GL_FALSE
;
1032 /* Antialias coverage application */
1033 if (span
->arrayMask
& SPAN_COVERAGE
) {
1034 GLchan (*rgba
)[4] = span
->array
->rgba
;
1035 GLfloat
*coverage
= span
->array
->coverage
;
1037 for (i
= 0; i
< span
->end
; i
++) {
1038 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1040 monoColor
= GL_FALSE
;
1043 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1044 multi_write_rgba_span(ctx
, span
);
1047 /* normal: write to exactly one buffer */
1048 if (ctx
->Color
.ColorLogicOpEnabled
) {
1049 _mesa_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1050 monoColor
= GL_FALSE
;
1052 else if (ctx
->Color
.BlendEnabled
) {
1053 _mesa_blend_span(ctx
, span
, span
->array
->rgba
);
1054 monoColor
= GL_FALSE
;
1057 /* Color component masking */
1058 if (colorMask
!= 0xffffffff) {
1059 _mesa_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1060 monoColor
= GL_FALSE
;
1064 if (span
->arrayMask
& SPAN_XY
) {
1065 /* array of pixel coords */
1066 /* XXX test for mono color */
1067 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1068 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1069 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1070 _mesa_write_alpha_pixels(ctx
, span
->end
,
1071 span
->array
->x
, span
->array
->y
,
1072 (const GLchan (*)[4]) span
->array
->rgba
,
1077 /* horizontal run of pixels */
1079 /* all pixels have same color */
1081 color
[RCOMP
] = FixedToChan(span
->red
);
1082 color
[GCOMP
] = FixedToChan(span
->green
);
1083 color
[BCOMP
] = FixedToChan(span
->blue
);
1084 color
[ACOMP
] = FixedToChan(span
->alpha
);
1085 (*swrast
->Driver
.WriteMonoRGBASpan
)(ctx
, span
->end
, span
->x
,
1086 span
->y
, color
, span
->array
->mask
);
1087 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1088 _mesa_write_mono_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1090 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1094 /* each pixel is a different color */
1095 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1096 (const GLchan (*)[4]) span
->array
->rgba
,
1097 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1098 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1099 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1100 (const GLchan (*)[4]) span
->array
->rgba
,
1101 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1107 span
->interpMask
= origInterpMask
;
1108 span
->arrayMask
= origArrayMask
;
1113 * Add specular color to base color. This is used only when
1114 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1117 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1120 for (i
= 0; i
< n
; i
++) {
1121 #if CHAN_TYPE == GL_FLOAT
1123 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1124 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1125 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1127 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1128 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1129 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1130 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1131 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1132 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1139 * This function may modify any of the array values in the span.
1140 * span->interpMask and span->arrayMask may be changed but will be restored
1141 * to their original values before returning.
1144 _mesa_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
1146 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1147 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1148 const GLuint origArrayMask
= span
->arrayMask
;
1150 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1151 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1152 ASSERT(span
->end
<= MAX_WIDTH
);
1153 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1154 ASSERT(ctx
->Texture
._EnabledUnits
);
1157 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1160 if (span
->arrayMask
& SPAN_MASK
) {
1161 /* mask was initialized by caller, probably glBitmap */
1162 span
->writeAll
= GL_FALSE
;
1165 MEMSET(span
->array
->mask
, 1, span
->end
);
1166 span
->writeAll
= GL_TRUE
;
1170 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1171 if (!clip_span(ctx
, span
)) {
1177 if (span
->arrayMask
& SPAN_XY
) {
1179 for (i
= 0; i
< span
->end
; i
++) {
1180 if (span
->array
->mask
[i
]) {
1181 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1182 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1183 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1184 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1190 /* Polygon Stippling */
1191 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1192 stipple_polygon_span(ctx
, span
);
1195 /* Need texture coordinates now */
1196 if ((span
->interpMask
& SPAN_TEXTURE
)
1197 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1198 interpolate_texcoords(ctx
, span
);
1200 /* Texture with alpha test */
1201 if (ctx
->Color
.AlphaEnabled
) {
1203 /* Now we need the rgba array, fill it in if needed */
1204 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1205 interpolate_colors(ctx
, span
);
1207 /* Texturing without alpha is done after depth-testing which
1208 * gives a potential speed-up.
1210 if (ctx
->FragmentProgram
.Enabled
)
1211 _swrast_exec_nv_fragment_program( ctx
, span
);
1213 _swrast_texture_span( ctx
, span
);
1215 /* Do the alpha test */
1216 if (!_mesa_alpha_test(ctx
, span
)) {
1217 span
->arrayMask
= origArrayMask
;
1222 /* Stencil and Z testing */
1223 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1224 if (span
->interpMask
& SPAN_Z
)
1225 _mesa_span_interpolate_z(ctx
, span
);
1227 if (ctx
->Stencil
.Enabled
) {
1228 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
1229 span
->arrayMask
= origArrayMask
;
1234 ASSERT(ctx
->Depth
.Test
);
1235 ASSERT(span
->arrayMask
& SPAN_Z
);
1236 /* regular depth testing */
1237 if (!_mesa_depth_test_span(ctx
, span
)) {
1238 span
->arrayMask
= origArrayMask
;
1244 /* if we get here, some fragments passed the depth test */
1245 ctx
->OcclusionResult
= GL_TRUE
;
1247 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1248 * the occlusion test.
1250 if (colorMask
== 0x0) {
1251 span
->arrayMask
= origArrayMask
;
1255 /* Texture without alpha test */
1256 if (!ctx
->Color
.AlphaEnabled
) {
1258 /* Now we need the rgba array, fill it in if needed */
1259 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1260 interpolate_colors(ctx
, span
);
1262 if (ctx
->FragmentProgram
.Enabled
)
1263 _swrast_exec_nv_fragment_program( ctx
, span
);
1265 _swrast_texture_span( ctx
, span
);
1268 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1270 /* Add base and specular colors */
1271 if (ctx
->Fog
.ColorSumEnabled
||
1272 (ctx
->Light
.Enabled
&&
1273 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1274 if (span
->interpMask
& SPAN_SPEC
) {
1275 interpolate_specular(ctx
, span
);
1277 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1278 add_colors( span
->end
, span
->array
->rgba
, span
->array
->spec
);
1282 if (ctx
->Fog
.Enabled
) {
1283 _mesa_fog_rgba_span(ctx
, span
);
1286 /* Antialias coverage application */
1287 if (span
->arrayMask
& SPAN_COVERAGE
) {
1288 GLchan (*rgba
)[4] = span
->array
->rgba
;
1289 GLfloat
*coverage
= span
->array
->coverage
;
1291 for (i
= 0; i
< span
->end
; i
++) {
1292 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1296 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1297 multi_write_rgba_span(ctx
, span
);
1300 /* normal: write to exactly one buffer */
1301 if (ctx
->Color
.ColorLogicOpEnabled
) {
1302 _mesa_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1304 else if (ctx
->Color
.BlendEnabled
) {
1305 _mesa_blend_span(ctx
, span
, span
->array
->rgba
);
1308 if (colorMask
!= 0xffffffff) {
1309 _mesa_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1313 if (span
->arrayMask
& SPAN_XY
) {
1314 /* array of pixel coords */
1315 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1316 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1317 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1318 _mesa_write_alpha_pixels(ctx
, span
->end
,
1319 span
->array
->x
, span
->array
->y
,
1320 (const GLchan (*)[4]) span
->array
->rgba
,
1325 /* horizontal run of pixels */
1326 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1327 (const GLchan (*)[4]) span
->array
->rgba
,
1328 span
->writeAll
? NULL
: span
->array
->mask
);
1329 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1330 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1331 (const GLchan (*)[4]) span
->array
->rgba
,
1332 span
->writeAll
? NULL
: span
->array
->mask
);
1337 span
->arrayMask
= origArrayMask
;
1343 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1344 * reading ouside the buffer's boundaries.
1347 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1348 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1350 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1351 const GLint bufWidth
= (GLint
) buffer
->Width
;
1352 const GLint bufHeight
= (GLint
) buffer
->Height
;
1354 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1355 /* completely above, below, or right */
1356 /* XXX maybe leave undefined? */
1357 _mesa_bzero(rgba
, 4 * n
* sizeof(GLchan
));
1362 /* left edge clippping */
1364 length
= (GLint
) n
- skip
;
1366 /* completely left of window */
1369 if (length
> bufWidth
) {
1373 else if ((GLint
) (x
+ n
) > bufWidth
) {
1374 /* right edge clipping */
1376 length
= bufWidth
- x
;
1378 /* completely to right of window */
1388 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1389 if (buffer
->UseSoftwareAlphaBuffers
) {
1390 _mesa_read_alpha_span(ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1397 * Read CI pixels from frame buffer. Clipping will be done to prevent
1398 * reading ouside the buffer's boundaries.
1401 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1402 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1404 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1405 const GLint bufWidth
= (GLint
) buffer
->Width
;
1406 const GLint bufHeight
= (GLint
) buffer
->Height
;
1408 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1409 /* completely above, below, or right */
1410 _mesa_bzero(indx
, n
* sizeof(GLuint
));
1415 /* left edge clippping */
1417 length
= (GLint
) n
- skip
;
1419 /* completely left of window */
1422 if (length
> bufWidth
) {
1426 else if ((GLint
) (x
+ n
) > bufWidth
) {
1427 /* right edge clipping */
1429 length
= bufWidth
- x
;
1431 /* completely to right of window */
1441 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);