2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * \file swrast/s_span.c
28 * \brief Span processing functions used by all rasterization functions.
29 * This is where all the per-fragment tests are performed
40 #include "s_alphabuf.h"
42 #include "s_context.h"
46 #include "s_masking.h"
47 #include "s_nvfragprog.h"
49 #include "s_stencil.h"
50 #include "s_texture.h"
54 * Init span's Z interpolation values to the RasterPos Z.
55 * Used during setup for glDraw/CopyPixels.
58 _swrast_span_default_z( GLcontext
*ctx
, struct sw_span
*span
)
60 if (ctx
->Visual
.depthBits
<= 16)
61 span
->z
= FloatToFixed(ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
+ 0.5F
);
63 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
+ 0.5F
);
65 span
->interpMask
|= SPAN_Z
;
70 * Init span's fog interpolation values to the RasterPos fog.
71 * Used during setup for glDraw/CopyPixels.
74 _swrast_span_default_fog( GLcontext
*ctx
, struct sw_span
*span
)
76 span
->fog
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
77 span
->fogStep
= span
->dfogdx
= span
->dfogdy
= 0.0F
;
78 span
->interpMask
|= SPAN_FOG
;
83 * Init span's color or index interpolation values to the RasterPos color.
84 * Used during setup for glDraw/CopyPixels.
87 _swrast_span_default_color( GLcontext
*ctx
, struct sw_span
*span
)
89 if (ctx
->Visual
.rgbMode
) {
91 UNCLAMPED_FLOAT_TO_CHAN(r
, ctx
->Current
.RasterColor
[0]);
92 UNCLAMPED_FLOAT_TO_CHAN(g
, ctx
->Current
.RasterColor
[1]);
93 UNCLAMPED_FLOAT_TO_CHAN(b
, ctx
->Current
.RasterColor
[2]);
94 UNCLAMPED_FLOAT_TO_CHAN(a
, ctx
->Current
.RasterColor
[3]);
95 #if CHAN_TYPE == GL_FLOAT
101 span
->red
= IntToFixed(r
);
102 span
->green
= IntToFixed(g
);
103 span
->blue
= IntToFixed(b
);
104 span
->alpha
= IntToFixed(a
);
110 span
->interpMask
|= SPAN_RGBA
;
113 span
->index
= FloatToFixed(ctx
->Current
.RasterIndex
);
115 span
->interpMask
|= SPAN_INDEX
;
121 * Init span's texcoord interpolation values to the RasterPos texcoords.
122 * Used during setup for glDraw/CopyPixels.
125 _swrast_span_default_texcoords( GLcontext
*ctx
, struct sw_span
*span
)
128 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
129 COPY_4V(span
->tex
[i
], ctx
->Current
.RasterTexCoords
[i
]);
130 ASSIGN_4V(span
->texStepX
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
131 ASSIGN_4V(span
->texStepY
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
133 span
->interpMask
|= SPAN_TEXTURE
;
137 /* Fill in the span.color.rgba array from the interpolation values */
139 interpolate_colors(GLcontext
*ctx
, struct sw_span
*span
)
141 const GLuint n
= span
->end
;
142 GLchan (*rgba
)[4] = span
->array
->rgba
;
145 ASSERT((span
->interpMask
& SPAN_RGBA
) &&
146 !(span
->arrayMask
& SPAN_RGBA
));
148 if (span
->interpMask
& SPAN_FLAT
) {
151 color
[RCOMP
] = FixedToChan(span
->red
);
152 color
[GCOMP
] = FixedToChan(span
->green
);
153 color
[BCOMP
] = FixedToChan(span
->blue
);
154 color
[ACOMP
] = FixedToChan(span
->alpha
);
155 for (i
= 0; i
< n
; i
++) {
156 COPY_CHAN4(span
->array
->rgba
[i
], color
);
161 #if CHAN_TYPE == GL_FLOAT
162 GLfloat r
= span
->red
;
163 GLfloat g
= span
->green
;
164 GLfloat b
= span
->blue
;
165 GLfloat a
= span
->alpha
;
166 const GLfloat dr
= span
->redStep
;
167 const GLfloat dg
= span
->greenStep
;
168 const GLfloat db
= span
->blueStep
;
169 const GLfloat da
= span
->alphaStep
;
171 GLfixed r
= span
->red
;
172 GLfixed g
= span
->green
;
173 GLfixed b
= span
->blue
;
174 GLfixed a
= span
->alpha
;
175 const GLint dr
= span
->redStep
;
176 const GLint dg
= span
->greenStep
;
177 const GLint db
= span
->blueStep
;
178 const GLint da
= span
->alphaStep
;
180 for (i
= 0; i
< n
; i
++) {
181 rgba
[i
][RCOMP
] = FixedToChan(r
);
182 rgba
[i
][GCOMP
] = FixedToChan(g
);
183 rgba
[i
][BCOMP
] = FixedToChan(b
);
184 rgba
[i
][ACOMP
] = FixedToChan(a
);
191 span
->arrayMask
|= SPAN_RGBA
;
195 /* Fill in the span.color.index array from the interpolation values */
197 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
199 GLfixed index
= span
->index
;
200 const GLint indexStep
= span
->indexStep
;
201 const GLuint n
= span
->end
;
202 GLuint
*indexes
= span
->array
->index
;
204 ASSERT((span
->interpMask
& SPAN_INDEX
) &&
205 !(span
->arrayMask
& SPAN_INDEX
));
207 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
209 index
= FixedToInt(index
);
210 for (i
= 0; i
< n
; i
++) {
216 for (i
= 0; i
< n
; i
++) {
217 indexes
[i
] = FixedToInt(index
);
221 span
->arrayMask
|= SPAN_INDEX
;
225 /* Fill in the span.->array->spec array from the interpolation values */
227 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
229 if (span
->interpMask
& SPAN_FLAT
) {
231 const GLchan r
= FixedToChan(span
->specRed
);
232 const GLchan g
= FixedToChan(span
->specGreen
);
233 const GLchan b
= FixedToChan(span
->specBlue
);
235 for (i
= 0; i
< span
->end
; i
++) {
236 span
->array
->spec
[i
][RCOMP
] = r
;
237 span
->array
->spec
[i
][GCOMP
] = g
;
238 span
->array
->spec
[i
][BCOMP
] = b
;
243 #if CHAN_TYPE == GL_FLOAT
244 GLfloat r
= span
->specRed
;
245 GLfloat g
= span
->specGreen
;
246 GLfloat b
= span
->specBlue
;
248 GLfixed r
= span
->specRed
;
249 GLfixed g
= span
->specGreen
;
250 GLfixed b
= span
->specBlue
;
253 for (i
= 0; i
< span
->end
; i
++) {
254 span
->array
->spec
[i
][RCOMP
] = FixedToChan(r
);
255 span
->array
->spec
[i
][GCOMP
] = FixedToChan(g
);
256 span
->array
->spec
[i
][BCOMP
] = FixedToChan(b
);
257 r
+= span
->specRedStep
;
258 g
+= span
->specGreenStep
;
259 b
+= span
->specBlueStep
;
262 span
->arrayMask
|= SPAN_SPEC
;
266 /* Fill in the span.zArray array from the interpolation values */
268 _swrast_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
270 const GLuint n
= span
->end
;
273 ASSERT((span
->interpMask
& SPAN_Z
) &&
274 !(span
->arrayMask
& SPAN_Z
));
276 if (ctx
->Visual
.depthBits
<= 16) {
277 GLfixed zval
= span
->z
;
278 GLdepth
*z
= span
->array
->z
;
279 for (i
= 0; i
< n
; i
++) {
280 z
[i
] = FixedToInt(zval
);
285 /* Deep Z buffer, no fixed->int shift */
286 GLfixed zval
= span
->z
;
287 GLdepth
*z
= span
->array
->z
;
288 for (i
= 0; i
< n
; i
++) {
293 span
->arrayMask
|= SPAN_Z
;
298 * This the ideal solution, as given in the OpenGL spec.
302 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
303 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
304 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
306 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
307 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
308 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
309 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
310 GLfloat x
= SQRTF(dudx
* dudx
+ dvdx
* dvdx
);
311 GLfloat y
= SQRTF(dudy
* dudy
+ dvdy
* dvdy
);
312 GLfloat rho
= MAX2(x
, y
);
313 GLfloat lambda
= LOG2(rho
);
320 * This is a faster approximation
323 _swrast_compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
324 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
325 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
327 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
328 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
329 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
330 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
331 GLfloat maxU
, maxV
, rho
, lambda
;
332 dsdx2
= FABSF(dsdx2
);
333 dsdy2
= FABSF(dsdy2
);
334 dtdx2
= FABSF(dtdx2
);
335 dtdy2
= FABSF(dtdy2
);
336 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
337 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
338 rho
= MAX2(maxU
, maxV
);
344 * Fill in the span.texcoords array from the interpolation values.
345 * XXX We could optimize here for the case when dq = 0. That would
346 * usually be the case when using an orthographic projection.
349 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
351 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
352 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
354 if (ctx
->Texture
._EnabledCoordUnits
> 1) {
357 span
->arrayMask
|= SPAN_TEXTURE
;
358 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
359 if (ctx
->Texture
._EnabledCoordUnits
& (1 << u
)) {
360 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
362 GLboolean needLambda
;
364 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
365 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
366 || ctx
->FragmentProgram
.Enabled
;
367 texW
= img
->WidthScale
;
368 texH
= img
->HeightScale
;
373 needLambda
= GL_FALSE
;
376 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
377 GLfloat
*lambda
= span
->array
->lambda
[u
];
378 const GLfloat dsdx
= span
->texStepX
[u
][0];
379 const GLfloat dsdy
= span
->texStepY
[u
][0];
380 const GLfloat dtdx
= span
->texStepX
[u
][1];
381 const GLfloat dtdy
= span
->texStepY
[u
][1];
382 const GLfloat drdx
= span
->texStepX
[u
][2];
383 const GLfloat dqdx
= span
->texStepX
[u
][3];
384 const GLfloat dqdy
= span
->texStepY
[u
][3];
385 GLfloat s
= span
->tex
[u
][0];
386 GLfloat t
= span
->tex
[u
][1];
387 GLfloat r
= span
->tex
[u
][2];
388 GLfloat q
= span
->tex
[u
][3];
390 for (i
= 0; i
< span
->end
; i
++) {
391 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
392 texcoord
[i
][0] = s
* invQ
;
393 texcoord
[i
][1] = t
* invQ
;
394 texcoord
[i
][2] = r
* invQ
;
396 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
397 dqdx
, dqdy
, texW
, texH
,
404 span
->arrayMask
|= SPAN_LAMBDA
;
407 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
408 GLfloat
*lambda
= span
->array
->lambda
[u
];
409 const GLfloat dsdx
= span
->texStepX
[u
][0];
410 const GLfloat dtdx
= span
->texStepX
[u
][1];
411 const GLfloat drdx
= span
->texStepX
[u
][2];
412 const GLfloat dqdx
= span
->texStepX
[u
][3];
413 GLfloat s
= span
->tex
[u
][0];
414 GLfloat t
= span
->tex
[u
][1];
415 GLfloat r
= span
->tex
[u
][2];
416 GLfloat q
= span
->tex
[u
][3];
419 /* Ortho projection or polygon's parallel to window X axis */
420 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
421 for (i
= 0; i
< span
->end
; i
++) {
422 texcoord
[i
][0] = s
* invQ
;
423 texcoord
[i
][1] = t
* invQ
;
424 texcoord
[i
][2] = r
* invQ
;
433 for (i
= 0; i
< span
->end
; i
++) {
434 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
435 texcoord
[i
][0] = s
* invQ
;
436 texcoord
[i
][1] = t
* invQ
;
437 texcoord
[i
][2] = r
* invQ
;
452 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
454 GLboolean needLambda
;
456 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
457 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
458 || ctx
->FragmentProgram
.Enabled
;
459 texW
= (GLfloat
) img
->WidthScale
;
460 texH
= (GLfloat
) img
->HeightScale
;
463 needLambda
= GL_FALSE
;
466 span
->arrayMask
|= SPAN_TEXTURE
;
468 /* just texture unit 0, with lambda */
469 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
470 GLfloat
*lambda
= span
->array
->lambda
[0];
471 const GLfloat dsdx
= span
->texStepX
[0][0];
472 const GLfloat dsdy
= span
->texStepY
[0][0];
473 const GLfloat dtdx
= span
->texStepX
[0][1];
474 const GLfloat dtdy
= span
->texStepY
[0][1];
475 const GLfloat drdx
= span
->texStepX
[0][2];
476 const GLfloat dqdx
= span
->texStepX
[0][3];
477 const GLfloat dqdy
= span
->texStepY
[0][3];
478 GLfloat s
= span
->tex
[0][0];
479 GLfloat t
= span
->tex
[0][1];
480 GLfloat r
= span
->tex
[0][2];
481 GLfloat q
= span
->tex
[0][3];
483 for (i
= 0; i
< span
->end
; i
++) {
484 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
485 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
486 dqdx
, dqdy
, texW
, texH
,
488 texcoord
[i
][0] = s
* invQ
;
489 texcoord
[i
][1] = t
* invQ
;
490 texcoord
[i
][2] = r
* invQ
;
497 span
->arrayMask
|= SPAN_LAMBDA
;
500 /* just texture 0, without lambda */
501 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
502 const GLfloat dsdx
= span
->texStepX
[0][0];
503 const GLfloat dtdx
= span
->texStepX
[0][1];
504 const GLfloat drdx
= span
->texStepX
[0][2];
505 const GLfloat dqdx
= span
->texStepX
[0][3];
506 GLfloat s
= span
->tex
[0][0];
507 GLfloat t
= span
->tex
[0][1];
508 GLfloat r
= span
->tex
[0][2];
509 GLfloat q
= span
->tex
[0][3];
512 /* Ortho projection or polygon's parallel to window X axis */
513 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
514 for (i
= 0; i
< span
->end
; i
++) {
515 texcoord
[i
][0] = s
* invQ
;
516 texcoord
[i
][1] = t
* invQ
;
517 texcoord
[i
][2] = r
* invQ
;
525 for (i
= 0; i
< span
->end
; i
++) {
526 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
527 texcoord
[i
][0] = s
* invQ
;
528 texcoord
[i
][1] = t
* invQ
;
529 texcoord
[i
][2] = r
* invQ
;
543 * Apply the current polygon stipple pattern to a span of pixels.
546 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
548 const GLuint highbit
= 0x80000000;
549 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
550 GLubyte
*mask
= span
->array
->mask
;
553 ASSERT(ctx
->Polygon
.StippleFlag
);
554 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
556 m
= highbit
>> (GLuint
) (span
->x
% 32);
558 for (i
= 0; i
< span
->end
; i
++) {
559 if ((m
& stipple
) == 0) {
567 span
->writeAll
= GL_FALSE
;
572 * Clip a pixel span to the current buffer/window boundaries:
573 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
574 * window clipping and scissoring.
575 * Return: GL_TRUE some pixels still visible
576 * GL_FALSE nothing visible
579 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
581 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
582 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
583 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
584 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
586 if (span
->arrayMask
& SPAN_XY
) {
587 /* arrays of x/y pixel coords */
588 const GLint
*x
= span
->array
->x
;
589 const GLint
*y
= span
->array
->y
;
590 const GLint n
= span
->end
;
591 GLubyte
*mask
= span
->array
->mask
;
593 if (span
->arrayMask
& SPAN_MASK
) {
594 /* note: using & intead of && to reduce branches */
595 for (i
= 0; i
< n
; i
++) {
596 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
597 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
601 /* note: using & intead of && to reduce branches */
602 for (i
= 0; i
< n
; i
++) {
603 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
604 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
607 return GL_TRUE
; /* some pixels visible */
610 /* horizontal span of pixels */
611 const GLint x
= span
->x
;
612 const GLint y
= span
->y
;
613 const GLint n
= span
->end
;
615 /* Trivial rejection tests */
616 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
618 return GL_FALSE
; /* all pixels clipped */
621 /* Clip to the left */
623 ASSERT(x
+ n
> xmin
);
624 span
->writeAll
= GL_FALSE
;
625 _mesa_bzero(span
->array
->mask
, (xmin
- x
) * sizeof(GLubyte
));
631 span
->end
= xmax
- x
;
634 return GL_TRUE
; /* some pixels visible */
641 * Draw to more than one color buffer (or none).
644 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
646 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
649 /* loop over four possible dest color buffers */
650 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
651 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
652 GLuint indexTmp
[MAX_WIDTH
];
653 ASSERT(span
->end
< MAX_WIDTH
);
655 /* Set the current read/draw buffer */
656 swrast
->CurrentBufferBit
= bufferBit
;
657 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
659 /* make copy of incoming indexes */
660 MEMCPY( indexTmp
, span
->array
->index
, span
->end
* sizeof(GLuint
) );
662 if (ctx
->Color
.IndexLogicOpEnabled
) {
663 _swrast_logicop_ci_span(ctx
, span
, indexTmp
);
666 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
667 _swrast_mask_index_span(ctx
, span
, indexTmp
);
670 if (span
->arrayMask
& SPAN_XY
) {
671 /* array of pixel coords */
672 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
673 span
->array
->x
, span
->array
->y
,
674 indexTmp
, span
->array
->mask
);
677 /* horizontal run of pixels */
678 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
679 indexTmp
, span
->array
->mask
);
684 /* restore default dest buffer */
685 _swrast_use_draw_buffer(ctx
);
690 * Draw to more than one RGBA color buffer (or none).
691 * All fragment operations, up to (but not) blending/logicop should
692 * have been done first.
695 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
697 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
699 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
701 ASSERT(colorMask
!= 0x0);
703 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
706 /* loop over four possible dest color buffers */
707 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
708 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
709 GLchan rgbaTmp
[MAX_WIDTH
][4];
710 ASSERT(span
->end
< MAX_WIDTH
);
712 /* Set the current read/draw buffer */
713 swrast
->CurrentBufferBit
= bufferBit
;
714 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
716 /* make copy of incoming colors */
717 MEMCPY( rgbaTmp
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
) );
719 if (ctx
->Color
._LogicOpEnabled
) {
720 _swrast_logicop_rgba_span(ctx
, span
, rgbaTmp
);
722 else if (ctx
->Color
.BlendEnabled
) {
723 _swrast_blend_span(ctx
, span
, rgbaTmp
);
726 if (colorMask
!= 0xffffffff) {
727 _swrast_mask_rgba_span(ctx
, span
, rgbaTmp
);
730 if (span
->arrayMask
& SPAN_XY
) {
731 /* array of pixel coords */
732 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
733 span
->array
->x
, span
->array
->y
,
734 (const GLchan (*)[4]) rgbaTmp
,
736 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
737 _swrast_write_alpha_pixels(ctx
, span
->end
,
738 span
->array
->x
, span
->array
->y
,
739 (const GLchan (*)[4]) rgbaTmp
,
744 /* horizontal run of pixels */
745 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
746 (const GLchan (*)[4]) rgbaTmp
,
748 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
749 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
750 (const GLchan (*)[4]) rgbaTmp
,
757 /* restore default dest buffer */
758 _swrast_use_draw_buffer(ctx
);
764 * This function may modify any of the array values in the span.
765 * span->interpMask and span->arrayMask may be changed but will be restored
766 * to their original values before returning.
769 _swrast_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
771 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
772 const GLuint origInterpMask
= span
->interpMask
;
773 const GLuint origArrayMask
= span
->arrayMask
;
775 ASSERT(span
->end
<= MAX_WIDTH
);
776 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
777 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
778 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
779 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
781 if (span
->arrayMask
& SPAN_MASK
) {
782 /* mask was initialized by caller, probably glBitmap */
783 span
->writeAll
= GL_FALSE
;
786 MEMSET(span
->array
->mask
, 1, span
->end
);
787 span
->writeAll
= GL_TRUE
;
791 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
792 if (!clip_span(ctx
, span
)) {
797 /* Depth bounds test */
798 if (ctx
->Depth
.BoundsTest
&& ctx
->Visual
.depthBits
> 0) {
799 if (!_swrast_depth_bounds_test(ctx
, span
)) {
805 if (span
->arrayMask
& SPAN_XY
) {
807 for (i
= 0; i
< span
->end
; i
++) {
808 if (span
->array
->mask
[i
]) {
809 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
810 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
811 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
812 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
818 /* Polygon Stippling */
819 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
820 stipple_polygon_span(ctx
, span
);
823 /* Depth test and stencil */
824 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
825 if (span
->interpMask
& SPAN_Z
)
826 _swrast_span_interpolate_z(ctx
, span
);
828 if (ctx
->Stencil
.Enabled
) {
829 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
830 span
->arrayMask
= origArrayMask
;
835 ASSERT(ctx
->Depth
.Test
);
836 if (!_swrast_depth_test_span(ctx
, span
)) {
837 span
->arrayMask
= origArrayMask
;
843 /* if we get here, something passed the depth test */
844 ctx
->OcclusionResult
= GL_TRUE
;
846 #if FEATURE_ARB_occlusion_query
847 if (ctx
->Occlusion
.Active
) {
849 for (i
= 0; i
< span
->end
; i
++)
850 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
854 /* we have to wait until after occlusion to do this test */
855 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
856 /* write no pixels */
857 span
->arrayMask
= origArrayMask
;
861 /* Interpolate the color indexes if needed */
862 if (span
->interpMask
& SPAN_INDEX
) {
863 interpolate_indexes(ctx
, span
);
864 /* clear the bit - this allows the WriteMonoCISpan optimization below */
865 span
->interpMask
&= ~SPAN_INDEX
;
869 if (ctx
->Fog
.Enabled
) {
870 _swrast_fog_ci_span(ctx
, span
);
873 /* Antialias coverage application */
874 if (span
->arrayMask
& SPAN_COVERAGE
) {
876 GLuint
*index
= span
->array
->index
;
877 GLfloat
*coverage
= span
->array
->coverage
;
878 for (i
= 0; i
< span
->end
; i
++) {
879 ASSERT(coverage
[i
] < 16);
880 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) coverage
[i
]);
884 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
885 /* draw to zero or two or more buffers */
886 multi_write_index_span(ctx
, span
);
889 /* normal situation: draw to exactly one buffer */
890 if (ctx
->Color
.IndexLogicOpEnabled
) {
891 _swrast_logicop_ci_span(ctx
, span
, span
->array
->index
);
894 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
895 _swrast_mask_index_span(ctx
, span
, span
->array
->index
);
899 if (span
->arrayMask
& SPAN_XY
) {
900 /* array of pixel coords */
901 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
902 /* all pixels have same color index */
903 (*swrast
->Driver
.WriteMonoCIPixels
)(ctx
, span
->end
,
904 span
->array
->x
, span
->array
->y
,
905 FixedToInt(span
->index
),
909 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->array
->x
,
910 span
->array
->y
, span
->array
->index
,
915 /* horizontal run of pixels */
916 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
917 /* all pixels have same color index */
918 (*swrast
->Driver
.WriteMonoCISpan
)(ctx
, span
->end
, span
->x
, span
->y
,
919 FixedToInt(span
->index
),
923 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
930 span
->interpMask
= origInterpMask
;
931 span
->arrayMask
= origArrayMask
;
936 * This function may modify any of the array values in the span.
937 * span->interpMask and span->arrayMask may be changed but will be restored
938 * to their original values before returning.
941 _swrast_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
943 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
944 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
945 const GLuint origInterpMask
= span
->interpMask
;
946 const GLuint origArrayMask
= span
->arrayMask
;
949 ASSERT(span
->end
<= MAX_WIDTH
);
950 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
951 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
952 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
953 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_RGBA
);
955 if (ctx
->Fog
.Enabled
)
956 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
958 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_Z
);
961 if (span
->arrayMask
& SPAN_MASK
) {
962 /* mask was initialized by caller, probably glBitmap */
963 span
->writeAll
= GL_FALSE
;
966 MEMSET(span
->array
->mask
, 1, span
->end
);
967 span
->writeAll
= GL_TRUE
;
970 /* Determine if we have mono-chromatic colors */
971 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
972 span
->redStep
== 0 && span
->greenStep
== 0 &&
973 span
->blueStep
== 0 && span
->alphaStep
== 0;
976 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
977 if (!clip_span(ctx
, span
)) {
982 /* Depth bounds test */
983 if (ctx
->Depth
.BoundsTest
&& ctx
->Visual
.depthBits
> 0) {
984 if (!_swrast_depth_bounds_test(ctx
, span
)) {
990 if (span
->arrayMask
& SPAN_XY
) {
992 for (i
= 0; i
< span
->end
; i
++) {
993 if (span
->array
->mask
[i
]) {
994 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
995 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
996 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
997 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1003 /* Polygon Stippling */
1004 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1005 stipple_polygon_span(ctx
, span
);
1008 /* Fragment program */
1009 if (ctx
->FragmentProgram
.Enabled
) {
1010 /* Now we may need to interpolate the colors */
1011 if ((span
->interpMask
& SPAN_RGBA
) &&
1012 (span
->arrayMask
& SPAN_RGBA
) == 0) {
1013 interpolate_colors(ctx
, span
);
1014 span
->interpMask
&= ~SPAN_RGBA
;
1016 if (span
->interpMask
& SPAN_SPEC
) {
1017 interpolate_specular(ctx
, span
);
1019 _swrast_exec_fragment_program(ctx
, span
);
1020 monoColor
= GL_FALSE
;
1023 /* Do the alpha test */
1024 if (ctx
->Color
.AlphaEnabled
) {
1025 if (!_swrast_alpha_test(ctx
, span
)) {
1026 span
->interpMask
= origInterpMask
;
1027 span
->arrayMask
= origArrayMask
;
1032 /* Stencil and Z testing */
1033 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1034 if (span
->interpMask
& SPAN_Z
)
1035 _swrast_span_interpolate_z(ctx
, span
);
1037 if (ctx
->Stencil
.Enabled
) {
1038 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1039 span
->interpMask
= origInterpMask
;
1040 span
->arrayMask
= origArrayMask
;
1045 ASSERT(ctx
->Depth
.Test
);
1046 ASSERT(span
->arrayMask
& SPAN_Z
);
1047 /* regular depth testing */
1048 if (!_swrast_depth_test_span(ctx
, span
)) {
1049 span
->interpMask
= origInterpMask
;
1050 span
->arrayMask
= origArrayMask
;
1056 /* if we get here, something passed the depth test */
1057 ctx
->OcclusionResult
= GL_TRUE
;
1059 #if FEATURE_ARB_occlusion_query
1060 if (ctx
->Occlusion
.Active
) {
1062 for (i
= 0; i
< span
->end
; i
++)
1063 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
1067 /* can't abort span-writing until after occlusion testing */
1068 if (colorMask
== 0x0) {
1069 span
->interpMask
= origInterpMask
;
1070 span
->arrayMask
= origArrayMask
;
1074 /* Now we may need to interpolate the colors */
1075 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
1076 interpolate_colors(ctx
, span
);
1077 /* clear the bit - this allows the WriteMonoCISpan optimization below */
1078 span
->interpMask
&= ~SPAN_RGBA
;
1082 if (swrast
->_FogEnabled
) {
1083 _swrast_fog_rgba_span(ctx
, span
);
1084 monoColor
= GL_FALSE
;
1087 /* Antialias coverage application */
1088 if (span
->arrayMask
& SPAN_COVERAGE
) {
1089 GLchan (*rgba
)[4] = span
->array
->rgba
;
1090 GLfloat
*coverage
= span
->array
->coverage
;
1092 for (i
= 0; i
< span
->end
; i
++) {
1093 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1095 monoColor
= GL_FALSE
;
1098 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1099 multi_write_rgba_span(ctx
, span
);
1102 /* normal: write to exactly one buffer */
1103 if (ctx
->Color
._LogicOpEnabled
) {
1104 _swrast_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1105 monoColor
= GL_FALSE
;
1107 else if (ctx
->Color
.BlendEnabled
) {
1108 _swrast_blend_span(ctx
, span
, span
->array
->rgba
);
1109 monoColor
= GL_FALSE
;
1112 /* Color component masking */
1113 if (colorMask
!= 0xffffffff) {
1114 _swrast_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1115 monoColor
= GL_FALSE
;
1119 if (span
->arrayMask
& SPAN_XY
) {
1120 /* array of pixel coords */
1121 /* XXX test for mono color */
1122 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1123 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1124 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1125 _swrast_write_alpha_pixels(ctx
, span
->end
,
1126 span
->array
->x
, span
->array
->y
,
1127 (const GLchan (*)[4]) span
->array
->rgba
,
1132 /* horizontal run of pixels */
1134 /* all pixels have same color */
1136 color
[RCOMP
] = FixedToChan(span
->red
);
1137 color
[GCOMP
] = FixedToChan(span
->green
);
1138 color
[BCOMP
] = FixedToChan(span
->blue
);
1139 color
[ACOMP
] = FixedToChan(span
->alpha
);
1140 (*swrast
->Driver
.WriteMonoRGBASpan
)(ctx
, span
->end
, span
->x
,
1141 span
->y
, color
, span
->array
->mask
);
1142 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1143 _swrast_write_mono_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1145 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1149 /* each pixel is a different color */
1150 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1151 (const GLchan (*)[4]) span
->array
->rgba
,
1152 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1153 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1154 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1155 (const GLchan (*)[4]) span
->array
->rgba
,
1156 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1162 span
->interpMask
= origInterpMask
;
1163 span
->arrayMask
= origArrayMask
;
1168 * Add specular color to base color. This is used only when
1169 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1172 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1175 for (i
= 0; i
< n
; i
++) {
1176 #if CHAN_TYPE == GL_FLOAT
1178 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1179 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1180 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1182 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1183 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1184 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1185 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1186 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1187 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1194 * This function may modify any of the array values in the span.
1195 * span->interpMask and span->arrayMask may be changed but will be restored
1196 * to their original values before returning.
1199 _swrast_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
1201 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1202 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1203 const GLuint origInterpMask
= span
->interpMask
;
1204 const GLuint origArrayMask
= span
->arrayMask
;
1206 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1207 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1208 ASSERT(span
->end
<= MAX_WIDTH
);
1209 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1210 ASSERT(ctx
->Texture
._EnabledCoordUnits
|| ctx
->FragmentProgram
.Enabled
);
1213 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1216 if (span
->arrayMask
& SPAN_MASK
) {
1217 /* mask was initialized by caller, probably glBitmap */
1218 span
->writeAll
= GL_FALSE
;
1221 MEMSET(span
->array
->mask
, 1, span
->end
);
1222 span
->writeAll
= GL_TRUE
;
1226 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1227 if (!clip_span(ctx
, span
)) {
1233 if (span
->arrayMask
& SPAN_XY
) {
1235 for (i
= 0; i
< span
->end
; i
++) {
1236 if (span
->array
->mask
[i
]) {
1237 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1238 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1239 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1240 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1246 /* Polygon Stippling */
1247 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1248 stipple_polygon_span(ctx
, span
);
1251 /* Need texture coordinates now */
1252 if ((span
->interpMask
& SPAN_TEXTURE
)
1253 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1254 interpolate_texcoords(ctx
, span
);
1256 /* Texture with alpha test */
1257 if (ctx
->Color
.AlphaEnabled
) {
1259 /* Now we need the rgba array, fill it in if needed */
1260 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1261 interpolate_colors(ctx
, span
);
1263 if (span
->interpMask
& SPAN_SPEC
) {
1264 interpolate_specular(ctx
, span
);
1267 /* Texturing without alpha is done after depth-testing which
1268 * gives a potential speed-up.
1270 if (ctx
->FragmentProgram
.Enabled
)
1271 _swrast_exec_fragment_program( ctx
, span
);
1273 _swrast_texture_span( ctx
, span
);
1275 /* Do the alpha test */
1276 if (!_swrast_alpha_test(ctx
, span
)) {
1277 span
->arrayMask
= origArrayMask
;
1282 /* Stencil and Z testing */
1283 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1284 if (span
->interpMask
& SPAN_Z
)
1285 _swrast_span_interpolate_z(ctx
, span
);
1287 if (ctx
->Stencil
.Enabled
) {
1288 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1289 span
->interpMask
= origInterpMask
;
1290 span
->arrayMask
= origArrayMask
;
1295 ASSERT(ctx
->Depth
.Test
);
1296 ASSERT(span
->arrayMask
& SPAN_Z
);
1297 /* regular depth testing */
1298 if (!_swrast_depth_test_span(ctx
, span
)) {
1299 span
->interpMask
= origInterpMask
;
1300 span
->arrayMask
= origArrayMask
;
1306 /* if we get here, some fragments passed the depth test */
1307 ctx
->OcclusionResult
= GL_TRUE
;
1309 #if FEATURE_ARB_occlusion_query
1310 if (ctx
->Occlusion
.Active
) {
1312 for (i
= 0; i
< span
->end
; i
++)
1313 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
1317 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1318 * the occlusion test.
1320 if (colorMask
== 0x0) {
1321 span
->interpMask
= origInterpMask
;
1322 span
->arrayMask
= origArrayMask
;
1326 /* Texture without alpha test */
1327 if (!ctx
->Color
.AlphaEnabled
) {
1329 /* Now we need the rgba array, fill it in if needed */
1330 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1331 interpolate_colors(ctx
, span
);
1333 if (span
->interpMask
& SPAN_SPEC
) {
1334 interpolate_specular(ctx
, span
);
1337 if (ctx
->FragmentProgram
.Enabled
)
1338 _swrast_exec_fragment_program( ctx
, span
);
1340 _swrast_texture_span( ctx
, span
);
1343 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1345 /* Add base and specular colors */
1346 if (ctx
->Fog
.ColorSumEnabled
||
1347 (ctx
->Light
.Enabled
&&
1348 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1349 if (span
->interpMask
& SPAN_SPEC
) {
1350 interpolate_specular(ctx
, span
);
1352 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1353 add_colors( span
->end
, span
->array
->rgba
, span
->array
->spec
);
1357 if (swrast
->_FogEnabled
) {
1358 _swrast_fog_rgba_span(ctx
, span
);
1361 /* Antialias coverage application */
1362 if (span
->arrayMask
& SPAN_COVERAGE
) {
1363 GLchan (*rgba
)[4] = span
->array
->rgba
;
1364 GLfloat
*coverage
= span
->array
->coverage
;
1366 for (i
= 0; i
< span
->end
; i
++) {
1367 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1371 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1372 multi_write_rgba_span(ctx
, span
);
1375 /* normal: write to exactly one buffer */
1376 if (ctx
->Color
._LogicOpEnabled
) {
1377 _swrast_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1379 else if (ctx
->Color
.BlendEnabled
) {
1380 _swrast_blend_span(ctx
, span
, span
->array
->rgba
);
1383 /* Color component masking */
1384 if (colorMask
!= 0xffffffff) {
1385 _swrast_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1389 if (span
->arrayMask
& SPAN_XY
) {
1390 /* array of pixel coords */
1391 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1392 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1393 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1394 _swrast_write_alpha_pixels(ctx
, span
->end
,
1395 span
->array
->x
, span
->array
->y
,
1396 (const GLchan (*)[4]) span
->array
->rgba
,
1401 /* horizontal run of pixels */
1402 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1403 (const GLchan (*)[4]) span
->array
->rgba
,
1404 span
->writeAll
? NULL
: span
->array
->mask
);
1405 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1406 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1407 (const GLchan (*)[4]) span
->array
->rgba
,
1408 span
->writeAll
? NULL
: span
->array
->mask
);
1413 span
->interpMask
= origInterpMask
;
1414 span
->arrayMask
= origArrayMask
;
1420 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1421 * reading ouside the buffer's boundaries.
1424 _swrast_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1425 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1427 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1428 const GLint bufWidth
= (GLint
) buffer
->Width
;
1429 const GLint bufHeight
= (GLint
) buffer
->Height
;
1431 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1432 /* completely above, below, or right */
1433 /* XXX maybe leave undefined? */
1434 _mesa_bzero(rgba
, 4 * n
* sizeof(GLchan
));
1439 /* left edge clippping */
1441 length
= (GLint
) n
- skip
;
1443 /* completely left of window */
1446 if (length
> bufWidth
) {
1450 else if ((GLint
) (x
+ n
) > bufWidth
) {
1451 /* right edge clipping */
1453 length
= bufWidth
- x
;
1455 /* completely to right of window */
1465 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1466 if (buffer
->UseSoftwareAlphaBuffers
) {
1467 _swrast_read_alpha_span(ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1474 * Read CI pixels from frame buffer. Clipping will be done to prevent
1475 * reading ouside the buffer's boundaries.
1478 _swrast_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1479 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1481 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1482 const GLint bufWidth
= (GLint
) buffer
->Width
;
1483 const GLint bufHeight
= (GLint
) buffer
->Height
;
1485 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1486 /* completely above, below, or right */
1487 _mesa_bzero(indx
, n
* sizeof(GLuint
));
1492 /* left edge clippping */
1494 length
= (GLint
) n
- skip
;
1496 /* completely left of window */
1499 if (length
> bufWidth
) {
1503 else if ((GLint
) (x
+ n
) > bufWidth
) {
1504 /* right edge clipping */
1506 length
= bufWidth
- x
;
1508 /* completely to right of window */
1518 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);