2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 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
);
345 * Fill in the span.texcoords array from the interpolation values.
346 * Note: in the places where we divide by Q (or mult by invQ) we're
347 * really doing two things: perspective correction and texcoord
348 * projection. Remember, for texcoord (s,t,r,q) we need to index
349 * texels with (s/q, t/q, r/q).
350 * If we're using a fragment program, we never do the division
351 * for texcoord projection. That's done by the TXP instruction
352 * or user-written code.
355 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
357 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
358 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
360 if (ctx
->Texture
._EnabledCoordUnits
> 1) {
363 span
->arrayMask
|= SPAN_TEXTURE
;
364 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
365 if (ctx
->Texture
._EnabledCoordUnits
& (1 << u
)) {
366 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
368 GLboolean needLambda
;
370 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
371 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
372 || ctx
->FragmentProgram
.Enabled
;
373 texW
= img
->WidthScale
;
374 texH
= img
->HeightScale
;
377 /* using a fragment program */
380 needLambda
= GL_FALSE
;
383 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
384 GLfloat
*lambda
= span
->array
->lambda
[u
];
385 const GLfloat dsdx
= span
->texStepX
[u
][0];
386 const GLfloat dsdy
= span
->texStepY
[u
][0];
387 const GLfloat dtdx
= span
->texStepX
[u
][1];
388 const GLfloat dtdy
= span
->texStepY
[u
][1];
389 const GLfloat drdx
= span
->texStepX
[u
][2];
390 const GLfloat dqdx
= span
->texStepX
[u
][3];
391 const GLfloat dqdy
= span
->texStepY
[u
][3];
392 GLfloat s
= span
->tex
[u
][0];
393 GLfloat t
= span
->tex
[u
][1];
394 GLfloat r
= span
->tex
[u
][2];
395 GLfloat q
= span
->tex
[u
][3];
397 if (ctx
->FragmentProgram
.Enabled
) {
398 /* do perspective correction but don't divide s, t, r by q */
399 const GLfloat dwdx
= span
->dwdx
;
401 for (i
= 0; i
< span
->end
; i
++) {
402 const GLfloat invW
= 1.0F
/ w
;
403 texcoord
[i
][0] = s
* invW
;
404 texcoord
[i
][1] = t
* invW
;
405 texcoord
[i
][2] = r
* invW
;
406 texcoord
[i
][3] = q
* invW
;
407 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
408 dqdx
, dqdy
, texW
, texH
,
419 for (i
= 0; i
< span
->end
; i
++) {
420 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
421 texcoord
[i
][0] = s
* invQ
;
422 texcoord
[i
][1] = t
* invQ
;
423 texcoord
[i
][2] = r
* invQ
;
425 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
426 dqdx
, dqdy
, texW
, texH
,
434 span
->arrayMask
|= SPAN_LAMBDA
;
437 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
438 GLfloat
*lambda
= span
->array
->lambda
[u
];
439 const GLfloat dsdx
= span
->texStepX
[u
][0];
440 const GLfloat dtdx
= span
->texStepX
[u
][1];
441 const GLfloat drdx
= span
->texStepX
[u
][2];
442 const GLfloat dqdx
= span
->texStepX
[u
][3];
443 GLfloat s
= span
->tex
[u
][0];
444 GLfloat t
= span
->tex
[u
][1];
445 GLfloat r
= span
->tex
[u
][2];
446 GLfloat q
= span
->tex
[u
][3];
448 if (ctx
->FragmentProgram
.Enabled
) {
449 /* do perspective correction but don't divide s, t, r by q */
450 const GLfloat dwdx
= span
->dwdx
;
452 for (i
= 0; i
< span
->end
; i
++) {
453 const GLfloat invW
= 1.0F
/ w
;
454 texcoord
[i
][0] = s
* invW
;
455 texcoord
[i
][1] = t
* invW
;
456 texcoord
[i
][2] = r
* invW
;
457 texcoord
[i
][3] = q
* invW
;
466 else if (dqdx
== 0.0F
) {
467 /* Ortho projection or polygon's parallel to window X axis */
468 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
469 for (i
= 0; i
< span
->end
; i
++) {
470 texcoord
[i
][0] = s
* invQ
;
471 texcoord
[i
][1] = t
* invQ
;
472 texcoord
[i
][2] = r
* invQ
;
481 for (i
= 0; i
< span
->end
; i
++) {
482 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
483 texcoord
[i
][0] = s
* invQ
;
484 texcoord
[i
][1] = t
* invQ
;
485 texcoord
[i
][2] = r
* invQ
;
500 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
502 GLboolean needLambda
;
504 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
505 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
506 || ctx
->FragmentProgram
.Enabled
;
507 texW
= (GLfloat
) img
->WidthScale
;
508 texH
= (GLfloat
) img
->HeightScale
;
511 needLambda
= GL_FALSE
;
514 span
->arrayMask
|= SPAN_TEXTURE
;
516 /* just texture unit 0, with lambda */
517 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
518 GLfloat
*lambda
= span
->array
->lambda
[0];
519 const GLfloat dsdx
= span
->texStepX
[0][0];
520 const GLfloat dsdy
= span
->texStepY
[0][0];
521 const GLfloat dtdx
= span
->texStepX
[0][1];
522 const GLfloat dtdy
= span
->texStepY
[0][1];
523 const GLfloat drdx
= span
->texStepX
[0][2];
524 const GLfloat dqdx
= span
->texStepX
[0][3];
525 const GLfloat dqdy
= span
->texStepY
[0][3];
526 GLfloat s
= span
->tex
[0][0];
527 GLfloat t
= span
->tex
[0][1];
528 GLfloat r
= span
->tex
[0][2];
529 GLfloat q
= span
->tex
[0][3];
531 if (ctx
->FragmentProgram
.Enabled
) {
532 /* do perspective correction but don't divide s, t, r by q */
533 const GLfloat dwdx
= span
->dwdx
;
535 for (i
= 0; i
< span
->end
; i
++) {
536 const GLfloat invW
= 1.0F
/ w
;
537 texcoord
[i
][0] = s
* invW
;
538 texcoord
[i
][1] = t
* invW
;
539 texcoord
[i
][2] = r
* invW
;
540 texcoord
[i
][3] = q
* invW
;
541 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
542 dqdx
, dqdy
, texW
, texH
,
554 GLfloat dwdx
= span
->dwdx
;
555 assert(span
->interpMask
& SPAN_W
);
556 for (i
= 0; i
< span
->end
; i
++) {
557 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
558 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
559 dqdx
, dqdy
, texW
, texH
,
561 texcoord
[i
][0] = s
* invQ
;
562 texcoord
[i
][1] = t
* invQ
;
563 texcoord
[i
][2] = r
* invQ
;
572 span
->arrayMask
|= SPAN_LAMBDA
;
575 /* just texture 0, without lambda */
576 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
577 const GLfloat dsdx
= span
->texStepX
[0][0];
578 const GLfloat dtdx
= span
->texStepX
[0][1];
579 const GLfloat drdx
= span
->texStepX
[0][2];
580 const GLfloat dqdx
= span
->texStepX
[0][3];
581 GLfloat s
= span
->tex
[0][0];
582 GLfloat t
= span
->tex
[0][1];
583 GLfloat r
= span
->tex
[0][2];
584 GLfloat q
= span
->tex
[0][3];
586 if (ctx
->FragmentProgram
.Enabled
) {
587 /* do perspective correction but don't divide s, t, r by q */
588 const GLfloat dwdx
= span
->dwdx
;
590 for (i
= 0; i
< span
->end
; i
++) {
591 const GLfloat invW
= 1.0F
/ w
;
592 texcoord
[i
][0] = s
* invW
;
593 texcoord
[i
][1] = t
* invW
;
594 texcoord
[i
][2] = r
* invW
;
595 texcoord
[i
][3] = q
* invW
;
603 else if (dqdx
== 0.0F
) {
604 /* Ortho projection or polygon's parallel to window X axis */
605 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
606 for (i
= 0; i
< span
->end
; i
++) {
607 texcoord
[i
][0] = s
* invQ
;
608 texcoord
[i
][1] = t
* invQ
;
609 texcoord
[i
][2] = r
* invQ
;
617 for (i
= 0; i
< span
->end
; i
++) {
618 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
619 texcoord
[i
][0] = s
* invQ
;
620 texcoord
[i
][1] = t
* invQ
;
621 texcoord
[i
][2] = r
* invQ
;
635 * Apply the current polygon stipple pattern to a span of pixels.
638 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
640 const GLuint highbit
= 0x80000000;
641 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
642 GLubyte
*mask
= span
->array
->mask
;
645 ASSERT(ctx
->Polygon
.StippleFlag
);
646 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
648 m
= highbit
>> (GLuint
) (span
->x
% 32);
650 for (i
= 0; i
< span
->end
; i
++) {
651 if ((m
& stipple
) == 0) {
659 span
->writeAll
= GL_FALSE
;
664 * Clip a pixel span to the current buffer/window boundaries:
665 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
666 * window clipping and scissoring.
667 * Return: GL_TRUE some pixels still visible
668 * GL_FALSE nothing visible
671 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
673 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
674 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
675 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
676 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
678 if (span
->arrayMask
& SPAN_XY
) {
679 /* arrays of x/y pixel coords */
680 const GLint
*x
= span
->array
->x
;
681 const GLint
*y
= span
->array
->y
;
682 const GLint n
= span
->end
;
683 GLubyte
*mask
= span
->array
->mask
;
685 if (span
->arrayMask
& SPAN_MASK
) {
686 /* note: using & intead of && to reduce branches */
687 for (i
= 0; i
< n
; i
++) {
688 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
689 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
693 /* note: using & intead of && to reduce branches */
694 for (i
= 0; i
< n
; i
++) {
695 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
696 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
699 return GL_TRUE
; /* some pixels visible */
702 /* horizontal span of pixels */
703 const GLint x
= span
->x
;
704 const GLint y
= span
->y
;
705 const GLint n
= span
->end
;
707 /* Trivial rejection tests */
708 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
710 return GL_FALSE
; /* all pixels clipped */
713 /* Clip to the left */
715 ASSERT(x
+ n
> xmin
);
716 span
->writeAll
= GL_FALSE
;
717 _mesa_bzero(span
->array
->mask
, (xmin
- x
) * sizeof(GLubyte
));
723 span
->end
= xmax
- x
;
726 return GL_TRUE
; /* some pixels visible */
733 * Draw to more than one color buffer (or none).
736 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
738 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
741 /* loop over four possible dest color buffers */
742 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
743 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
744 GLuint indexTmp
[MAX_WIDTH
];
745 ASSERT(span
->end
< MAX_WIDTH
);
747 /* Set the current read/draw buffer */
748 swrast
->CurrentBufferBit
= bufferBit
;
749 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
751 /* make copy of incoming indexes */
752 MEMCPY( indexTmp
, span
->array
->index
, span
->end
* sizeof(GLuint
) );
754 if (ctx
->Color
.IndexLogicOpEnabled
) {
755 _swrast_logicop_ci_span(ctx
, span
, indexTmp
);
758 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
759 _swrast_mask_index_span(ctx
, span
, indexTmp
);
762 if (span
->arrayMask
& SPAN_XY
) {
763 /* array of pixel coords */
764 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
765 span
->array
->x
, span
->array
->y
,
766 indexTmp
, span
->array
->mask
);
769 /* horizontal run of pixels */
770 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
771 indexTmp
, span
->array
->mask
);
776 /* restore default dest buffer */
777 _swrast_use_draw_buffer(ctx
);
782 * Draw to more than one RGBA color buffer (or none).
783 * All fragment operations, up to (but not) blending/logicop should
784 * have been done first.
787 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
789 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
791 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
793 ASSERT(colorMask
!= 0x0);
795 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
798 /* loop over four possible dest color buffers */
799 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
800 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
801 GLchan rgbaTmp
[MAX_WIDTH
][4];
802 ASSERT(span
->end
< MAX_WIDTH
);
804 /* Set the current read/draw buffer */
805 swrast
->CurrentBufferBit
= bufferBit
;
806 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
808 /* make copy of incoming colors */
809 MEMCPY( rgbaTmp
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
) );
811 if (ctx
->Color
._LogicOpEnabled
) {
812 _swrast_logicop_rgba_span(ctx
, span
, rgbaTmp
);
814 else if (ctx
->Color
.BlendEnabled
) {
815 _swrast_blend_span(ctx
, span
, rgbaTmp
);
818 if (colorMask
!= 0xffffffff) {
819 _swrast_mask_rgba_span(ctx
, span
, rgbaTmp
);
822 if (span
->arrayMask
& SPAN_XY
) {
823 /* array of pixel coords */
824 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
825 span
->array
->x
, span
->array
->y
,
826 (const GLchan (*)[4]) rgbaTmp
,
828 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
829 _swrast_write_alpha_pixels(ctx
, span
->end
,
830 span
->array
->x
, span
->array
->y
,
831 (const GLchan (*)[4]) rgbaTmp
,
836 /* horizontal run of pixels */
837 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
838 (const GLchan (*)[4]) rgbaTmp
,
840 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
841 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
842 (const GLchan (*)[4]) rgbaTmp
,
849 /* restore default dest buffer */
850 _swrast_use_draw_buffer(ctx
);
856 * This function may modify any of the array values in the span.
857 * span->interpMask and span->arrayMask may be changed but will be restored
858 * to their original values before returning.
861 _swrast_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
863 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
864 const GLuint origInterpMask
= span
->interpMask
;
865 const GLuint origArrayMask
= span
->arrayMask
;
867 ASSERT(span
->end
<= MAX_WIDTH
);
868 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
869 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
870 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
871 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
873 if (span
->arrayMask
& SPAN_MASK
) {
874 /* mask was initialized by caller, probably glBitmap */
875 span
->writeAll
= GL_FALSE
;
878 MEMSET(span
->array
->mask
, 1, span
->end
);
879 span
->writeAll
= GL_TRUE
;
883 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
884 if (!clip_span(ctx
, span
)) {
889 /* Depth bounds test */
890 if (ctx
->Depth
.BoundsTest
&& ctx
->Visual
.depthBits
> 0) {
891 if (!_swrast_depth_bounds_test(ctx
, span
)) {
897 if (span
->arrayMask
& SPAN_XY
) {
899 for (i
= 0; i
< span
->end
; i
++) {
900 if (span
->array
->mask
[i
]) {
901 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
902 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
903 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
904 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
910 /* Polygon Stippling */
911 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
912 stipple_polygon_span(ctx
, span
);
915 /* Depth test and stencil */
916 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
917 if (span
->interpMask
& SPAN_Z
)
918 _swrast_span_interpolate_z(ctx
, span
);
920 if (ctx
->Stencil
.Enabled
) {
921 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
922 span
->arrayMask
= origArrayMask
;
927 ASSERT(ctx
->Depth
.Test
);
928 if (!_swrast_depth_test_span(ctx
, span
)) {
929 span
->arrayMask
= origArrayMask
;
935 /* if we get here, something passed the depth test */
936 ctx
->OcclusionResult
= GL_TRUE
;
938 #if FEATURE_ARB_occlusion_query
939 if (ctx
->Occlusion
.Active
) {
941 for (i
= 0; i
< span
->end
; i
++)
942 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
946 /* we have to wait until after occlusion to do this test */
947 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
948 /* write no pixels */
949 span
->arrayMask
= origArrayMask
;
953 /* Interpolate the color indexes if needed */
954 if (span
->interpMask
& SPAN_INDEX
) {
955 interpolate_indexes(ctx
, span
);
956 /* clear the bit - this allows the WriteMonoCISpan optimization below */
957 span
->interpMask
&= ~SPAN_INDEX
;
961 if (ctx
->Fog
.Enabled
) {
962 _swrast_fog_ci_span(ctx
, span
);
965 /* Antialias coverage application */
966 if (span
->arrayMask
& SPAN_COVERAGE
) {
968 GLuint
*index
= span
->array
->index
;
969 GLfloat
*coverage
= span
->array
->coverage
;
970 for (i
= 0; i
< span
->end
; i
++) {
971 ASSERT(coverage
[i
] < 16);
972 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) coverage
[i
]);
976 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
977 /* draw to zero or two or more buffers */
978 multi_write_index_span(ctx
, span
);
981 /* normal situation: draw to exactly one buffer */
982 if (ctx
->Color
.IndexLogicOpEnabled
) {
983 _swrast_logicop_ci_span(ctx
, span
, span
->array
->index
);
986 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
987 _swrast_mask_index_span(ctx
, span
, span
->array
->index
);
991 if (span
->arrayMask
& SPAN_XY
) {
992 /* array of pixel coords */
993 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
994 /* all pixels have same color index */
995 (*swrast
->Driver
.WriteMonoCIPixels
)(ctx
, span
->end
,
996 span
->array
->x
, span
->array
->y
,
997 FixedToInt(span
->index
),
1001 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->array
->x
,
1002 span
->array
->y
, span
->array
->index
,
1003 span
->array
->mask
);
1007 /* horizontal run of pixels */
1008 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
1009 /* all pixels have same color index */
1010 (*swrast
->Driver
.WriteMonoCISpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1011 FixedToInt(span
->index
),
1015 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
1022 span
->interpMask
= origInterpMask
;
1023 span
->arrayMask
= origArrayMask
;
1028 * This function may modify any of the array values in the span.
1029 * span->interpMask and span->arrayMask may be changed but will be restored
1030 * to their original values before returning.
1033 _swrast_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
1035 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1036 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1037 const GLuint origInterpMask
= span
->interpMask
;
1038 const GLuint origArrayMask
= span
->arrayMask
;
1039 GLboolean monoColor
;
1041 ASSERT(span
->end
<= MAX_WIDTH
);
1042 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1043 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1044 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1045 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_RGBA
);
1047 if (ctx
->Fog
.Enabled
)
1048 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
1049 if (ctx
->Depth
.Test
)
1050 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_Z
);
1053 if (span
->arrayMask
& SPAN_MASK
) {
1054 /* mask was initialized by caller, probably glBitmap */
1055 span
->writeAll
= GL_FALSE
;
1058 MEMSET(span
->array
->mask
, 1, span
->end
);
1059 span
->writeAll
= GL_TRUE
;
1062 /* Determine if we have mono-chromatic colors */
1063 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
1064 span
->redStep
== 0 && span
->greenStep
== 0 &&
1065 span
->blueStep
== 0 && span
->alphaStep
== 0;
1068 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1069 if (!clip_span(ctx
, span
)) {
1074 /* Depth bounds test */
1075 if (ctx
->Depth
.BoundsTest
&& ctx
->Visual
.depthBits
> 0) {
1076 if (!_swrast_depth_bounds_test(ctx
, span
)) {
1082 if (span
->arrayMask
& SPAN_XY
) {
1084 for (i
= 0; i
< span
->end
; i
++) {
1085 if (span
->array
->mask
[i
]) {
1086 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1087 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1088 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1089 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1095 /* Polygon Stippling */
1096 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1097 stipple_polygon_span(ctx
, span
);
1100 /* Fragment program */
1101 if (ctx
->FragmentProgram
.Enabled
) {
1102 /* Now we may need to interpolate the colors and texcoords */
1103 if ((span
->interpMask
& SPAN_RGBA
) &&
1104 (span
->arrayMask
& SPAN_RGBA
) == 0) {
1105 interpolate_colors(ctx
, span
);
1106 span
->interpMask
&= ~SPAN_RGBA
;
1108 if (span
->interpMask
& SPAN_SPEC
) {
1109 interpolate_specular(ctx
, span
);
1111 if ((span
->interpMask
& SPAN_TEXTURE
)
1112 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1113 interpolate_texcoords(ctx
, span
);
1114 _swrast_exec_fragment_program(ctx
, span
);
1115 monoColor
= GL_FALSE
;
1118 /* Do the alpha test */
1119 if (ctx
->Color
.AlphaEnabled
) {
1120 if (!_swrast_alpha_test(ctx
, span
)) {
1121 span
->interpMask
= origInterpMask
;
1122 span
->arrayMask
= origArrayMask
;
1127 /* Stencil and Z testing */
1128 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1129 if (span
->interpMask
& SPAN_Z
)
1130 _swrast_span_interpolate_z(ctx
, span
);
1132 if (ctx
->Stencil
.Enabled
) {
1133 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1134 span
->interpMask
= origInterpMask
;
1135 span
->arrayMask
= origArrayMask
;
1140 ASSERT(ctx
->Depth
.Test
);
1141 ASSERT(span
->arrayMask
& SPAN_Z
);
1142 /* regular depth testing */
1143 if (!_swrast_depth_test_span(ctx
, span
)) {
1144 span
->interpMask
= origInterpMask
;
1145 span
->arrayMask
= origArrayMask
;
1151 /* if we get here, something passed the depth test */
1152 ctx
->OcclusionResult
= GL_TRUE
;
1154 #if FEATURE_ARB_occlusion_query
1155 if (ctx
->Occlusion
.Active
) {
1157 for (i
= 0; i
< span
->end
; i
++)
1158 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
1162 /* can't abort span-writing until after occlusion testing */
1163 if (colorMask
== 0x0) {
1164 span
->interpMask
= origInterpMask
;
1165 span
->arrayMask
= origArrayMask
;
1169 /* Now we may need to interpolate the colors */
1170 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
1171 interpolate_colors(ctx
, span
);
1172 /* clear the bit - this allows the WriteMonoCISpan optimization below */
1173 span
->interpMask
&= ~SPAN_RGBA
;
1177 if (swrast
->_FogEnabled
) {
1178 _swrast_fog_rgba_span(ctx
, span
);
1179 monoColor
= GL_FALSE
;
1182 /* Antialias coverage application */
1183 if (span
->arrayMask
& SPAN_COVERAGE
) {
1184 GLchan (*rgba
)[4] = span
->array
->rgba
;
1185 GLfloat
*coverage
= span
->array
->coverage
;
1187 for (i
= 0; i
< span
->end
; i
++) {
1188 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1190 monoColor
= GL_FALSE
;
1193 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1194 multi_write_rgba_span(ctx
, span
);
1197 /* normal: write to exactly one buffer */
1198 if (ctx
->Color
._LogicOpEnabled
) {
1199 _swrast_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1200 monoColor
= GL_FALSE
;
1202 else if (ctx
->Color
.BlendEnabled
) {
1203 _swrast_blend_span(ctx
, span
, span
->array
->rgba
);
1204 monoColor
= GL_FALSE
;
1207 /* Color component masking */
1208 if (colorMask
!= 0xffffffff) {
1209 _swrast_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1210 monoColor
= GL_FALSE
;
1214 if (span
->arrayMask
& SPAN_XY
) {
1215 /* array of pixel coords */
1217 /* all pixels have same color */
1219 color
[RCOMP
] = FixedToChan(span
->red
);
1220 color
[GCOMP
] = FixedToChan(span
->green
);
1221 color
[BCOMP
] = FixedToChan(span
->blue
);
1222 color
[ACOMP
] = FixedToChan(span
->alpha
);
1223 (*swrast
->Driver
.WriteMonoRGBAPixels
)(ctx
, span
->end
,
1224 span
->array
->x
, span
->array
->y
, color
, span
->array
->mask
);
1225 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1226 _swrast_write_mono_alpha_pixels(ctx
, span
->end
,
1227 span
->array
->x
, span
->array
->y
,
1228 color
[ACOMP
], span
->array
->mask
);
1232 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
1233 span
->array
->x
, span
->array
->y
,
1234 (const GLchan (*)[4]) span
->array
->rgba
,
1236 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1237 _swrast_write_alpha_pixels(ctx
, span
->end
,
1238 span
->array
->x
, span
->array
->y
,
1239 (const GLchan (*)[4]) span
->array
->rgba
,
1245 /* horizontal run of pixels */
1247 /* all pixels have same color */
1249 color
[RCOMP
] = FixedToChan(span
->red
);
1250 color
[GCOMP
] = FixedToChan(span
->green
);
1251 color
[BCOMP
] = FixedToChan(span
->blue
);
1252 color
[ACOMP
] = FixedToChan(span
->alpha
);
1253 (*swrast
->Driver
.WriteMonoRGBASpan
)(ctx
, span
->end
, span
->x
,
1254 span
->y
, color
, span
->array
->mask
);
1255 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1256 _swrast_write_mono_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1258 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1262 /* each pixel is a different color */
1263 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1264 (const GLchan (*)[4]) span
->array
->rgba
,
1265 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1266 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1267 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1268 (const GLchan (*)[4]) span
->array
->rgba
,
1269 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1275 span
->interpMask
= origInterpMask
;
1276 span
->arrayMask
= origArrayMask
;
1281 * Add specular color to base color. This is used only when
1282 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1285 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1288 for (i
= 0; i
< n
; i
++) {
1289 #if CHAN_TYPE == GL_FLOAT
1291 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1292 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1293 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1295 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1296 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1297 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1298 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1299 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1300 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1307 * This function may modify any of the array values in the span.
1308 * span->interpMask and span->arrayMask may be changed but will be restored
1309 * to their original values before returning.
1312 _swrast_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
1314 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1315 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1316 const GLuint origInterpMask
= span
->interpMask
;
1317 const GLuint origArrayMask
= span
->arrayMask
;
1319 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1320 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1321 ASSERT(span
->end
<= MAX_WIDTH
);
1322 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1323 ASSERT(ctx
->Texture
._EnabledCoordUnits
|| ctx
->FragmentProgram
.Enabled
);
1326 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1329 if (span
->arrayMask
& SPAN_MASK
) {
1330 /* mask was initialized by caller, probably glBitmap */
1331 span
->writeAll
= GL_FALSE
;
1334 MEMSET(span
->array
->mask
, 1, span
->end
);
1335 span
->writeAll
= GL_TRUE
;
1339 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1340 if (!clip_span(ctx
, span
)) {
1346 if (span
->arrayMask
& SPAN_XY
) {
1348 for (i
= 0; i
< span
->end
; i
++) {
1349 if (span
->array
->mask
[i
]) {
1350 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1351 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1352 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1353 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1359 /* Polygon Stippling */
1360 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1361 stipple_polygon_span(ctx
, span
);
1364 /* Need texture coordinates now */
1365 if ((span
->interpMask
& SPAN_TEXTURE
)
1366 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1367 interpolate_texcoords(ctx
, span
);
1369 /* Texture with alpha test */
1370 if (ctx
->Color
.AlphaEnabled
) {
1372 /* Now we need the rgba array, fill it in if needed */
1373 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1374 interpolate_colors(ctx
, span
);
1376 if (span
->interpMask
& SPAN_SPEC
) {
1377 interpolate_specular(ctx
, span
);
1380 /* Texturing without alpha is done after depth-testing which
1381 * gives a potential speed-up.
1383 if (ctx
->FragmentProgram
.Enabled
)
1384 _swrast_exec_fragment_program( ctx
, span
);
1386 _swrast_texture_span( ctx
, span
);
1388 /* Do the alpha test */
1389 if (!_swrast_alpha_test(ctx
, span
)) {
1390 span
->arrayMask
= origArrayMask
;
1395 /* Stencil and Z testing */
1396 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1397 if (span
->interpMask
& SPAN_Z
)
1398 _swrast_span_interpolate_z(ctx
, span
);
1400 if (ctx
->Stencil
.Enabled
) {
1401 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1402 span
->interpMask
= origInterpMask
;
1403 span
->arrayMask
= origArrayMask
;
1408 ASSERT(ctx
->Depth
.Test
);
1409 ASSERT(span
->arrayMask
& SPAN_Z
);
1410 /* regular depth testing */
1411 if (!_swrast_depth_test_span(ctx
, span
)) {
1412 span
->interpMask
= origInterpMask
;
1413 span
->arrayMask
= origArrayMask
;
1419 /* if we get here, some fragments passed the depth test */
1420 ctx
->OcclusionResult
= GL_TRUE
;
1422 #if FEATURE_ARB_occlusion_query
1423 if (ctx
->Occlusion
.Active
) {
1425 for (i
= 0; i
< span
->end
; i
++)
1426 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
1430 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1431 * the occlusion test.
1433 if (colorMask
== 0x0) {
1434 span
->interpMask
= origInterpMask
;
1435 span
->arrayMask
= origArrayMask
;
1439 /* Texture without alpha test */
1440 if (!ctx
->Color
.AlphaEnabled
) {
1442 /* Now we need the rgba array, fill it in if needed */
1443 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1444 interpolate_colors(ctx
, span
);
1446 if (span
->interpMask
& SPAN_SPEC
) {
1447 interpolate_specular(ctx
, span
);
1450 if (ctx
->FragmentProgram
.Enabled
)
1451 _swrast_exec_fragment_program( ctx
, span
);
1453 _swrast_texture_span( ctx
, span
);
1456 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1458 /* Add base and specular colors */
1459 if (ctx
->Fog
.ColorSumEnabled
||
1460 (ctx
->Light
.Enabled
&&
1461 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1462 if (span
->interpMask
& SPAN_SPEC
) {
1463 interpolate_specular(ctx
, span
);
1465 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1466 add_colors( span
->end
, span
->array
->rgba
, span
->array
->spec
);
1470 if (swrast
->_FogEnabled
) {
1471 _swrast_fog_rgba_span(ctx
, span
);
1474 /* Antialias coverage application */
1475 if (span
->arrayMask
& SPAN_COVERAGE
) {
1476 GLchan (*rgba
)[4] = span
->array
->rgba
;
1477 GLfloat
*coverage
= span
->array
->coverage
;
1479 for (i
= 0; i
< span
->end
; i
++) {
1480 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1484 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1485 multi_write_rgba_span(ctx
, span
);
1488 /* normal: write to exactly one buffer */
1489 if (ctx
->Color
._LogicOpEnabled
) {
1490 _swrast_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1492 else if (ctx
->Color
.BlendEnabled
) {
1493 _swrast_blend_span(ctx
, span
, span
->array
->rgba
);
1496 /* Color component masking */
1497 if (colorMask
!= 0xffffffff) {
1498 _swrast_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1502 if (span
->arrayMask
& SPAN_XY
) {
1503 /* array of pixel coords */
1504 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1505 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1506 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1507 _swrast_write_alpha_pixels(ctx
, span
->end
,
1508 span
->array
->x
, span
->array
->y
,
1509 (const GLchan (*)[4]) span
->array
->rgba
,
1514 /* horizontal run of pixels */
1515 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1516 (const GLchan (*)[4]) span
->array
->rgba
,
1517 span
->writeAll
? NULL
: span
->array
->mask
);
1518 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1519 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1520 (const GLchan (*)[4]) span
->array
->rgba
,
1521 span
->writeAll
? NULL
: span
->array
->mask
);
1526 span
->interpMask
= origInterpMask
;
1527 span
->arrayMask
= origArrayMask
;
1533 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1534 * reading ouside the buffer's boundaries.
1537 _swrast_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1538 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1540 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1541 const GLint bufWidth
= (GLint
) buffer
->Width
;
1542 const GLint bufHeight
= (GLint
) buffer
->Height
;
1544 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1545 /* completely above, below, or right */
1546 /* XXX maybe leave undefined? */
1547 _mesa_bzero(rgba
, 4 * n
* sizeof(GLchan
));
1552 /* left edge clippping */
1554 length
= (GLint
) n
- skip
;
1556 /* completely left of window */
1559 if (length
> bufWidth
) {
1563 else if ((GLint
) (x
+ n
) > bufWidth
) {
1564 /* right edge clipping */
1566 length
= bufWidth
- x
;
1568 /* completely to right of window */
1578 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1579 if (buffer
->UseSoftwareAlphaBuffers
) {
1580 _swrast_read_alpha_span(ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1587 * Read CI pixels from frame buffer. Clipping will be done to prevent
1588 * reading ouside the buffer's boundaries.
1591 _swrast_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1592 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1594 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1595 const GLint bufWidth
= (GLint
) buffer
->Width
;
1596 const GLint bufHeight
= (GLint
) buffer
->Height
;
1598 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1599 /* completely above, below, or right */
1600 _mesa_bzero(indx
, n
* sizeof(GLuint
));
1605 /* left edge clippping */
1607 length
= (GLint
) n
- skip
;
1609 /* completely left of window */
1612 if (length
> bufWidth
) {
1616 else if ((GLint
) (x
+ n
) > bufWidth
) {
1617 /* right edge clipping */
1619 length
= bufWidth
- x
;
1621 /* completely to right of window */
1631 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);