2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 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_atifragshader.h"
42 #include "s_arbshader.h"
44 #include "s_context.h"
48 #include "s_masking.h"
49 #include "s_nvfragprog.h"
51 #include "s_stencil.h"
52 #include "s_texcombine.h"
56 * Init span's Z interpolation values to the RasterPos Z.
57 * Used during setup for glDraw/CopyPixels.
60 _swrast_span_default_z( GLcontext
*ctx
, SWspan
*span
)
62 const GLfloat depthMax
= ctx
->DrawBuffer
->_DepthMaxF
;
63 if (ctx
->DrawBuffer
->Visual
.depthBits
<= 16)
64 span
->z
= FloatToFixed(ctx
->Current
.RasterPos
[2] * depthMax
+ 0.5F
);
66 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * 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 _swrast_span_default_fog( GLcontext
*ctx
, SWspan
*span
)
79 span
->fog
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
80 span
->fogStep
= span
->dfogdx
= span
->dfogdy
= 0.0F
;
81 span
->interpMask
|= SPAN_FOG
;
86 * Init span's rgba or index interpolation values to the RasterPos color.
87 * Used during setup for glDraw/CopyPixels.
90 _swrast_span_default_color( GLcontext
*ctx
, SWspan
*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
= FloatToFixed(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 _swrast_span_default_texcoords( GLcontext
*ctx
, SWspan
*span
)
131 for (i
= 0; i
< ctx
->Const
.MaxTextureCoordUnits
; i
++) {
132 const GLfloat
*tc
= ctx
->Current
.RasterTexCoords
[i
];
133 if (ctx
->FragmentProgram
._Enabled
|| ctx
->ATIFragmentShader
._Enabled
) {
134 COPY_4V(span
->tex
[i
], tc
);
136 else if (tc
[3] > 0.0F
) {
137 /* use (s/q, t/q, r/q, 1) */
138 span
->tex
[i
][0] = tc
[0] / tc
[3];
139 span
->tex
[i
][1] = tc
[1] / tc
[3];
140 span
->tex
[i
][2] = tc
[2] / tc
[3];
141 span
->tex
[i
][3] = 1.0;
144 ASSIGN_4V(span
->tex
[i
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
146 ASSIGN_4V(span
->texStepX
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
147 ASSIGN_4V(span
->texStepY
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
149 span
->interpMask
|= SPAN_TEXTURE
;
154 * Interpolate primary colors to fill in the span->array->color array.
157 interpolate_colors(SWspan
*span
)
159 const GLuint n
= span
->end
;
162 ASSERT((span
->interpMask
& SPAN_RGBA
) &&
163 !(span
->arrayMask
& SPAN_RGBA
));
165 switch (span
->array
->ChanType
) {
167 case GL_UNSIGNED_BYTE
:
169 GLubyte (*rgba
)[4] = span
->array
->color
.sz1
.rgba
;
170 if (span
->interpMask
& SPAN_FLAT
) {
172 color
[RCOMP
] = FixedToInt(span
->red
);
173 color
[GCOMP
] = FixedToInt(span
->green
);
174 color
[BCOMP
] = FixedToInt(span
->blue
);
175 color
[ACOMP
] = FixedToInt(span
->alpha
);
176 for (i
= 0; i
< n
; i
++) {
177 COPY_4UBV(rgba
[i
], color
);
181 GLfixed r
= span
->red
;
182 GLfixed g
= span
->green
;
183 GLfixed b
= span
->blue
;
184 GLfixed a
= span
->alpha
;
185 GLint dr
= span
->redStep
;
186 GLint dg
= span
->greenStep
;
187 GLint db
= span
->blueStep
;
188 GLint da
= span
->alphaStep
;
189 for (i
= 0; i
< n
; i
++) {
190 rgba
[i
][RCOMP
] = FixedToChan(r
);
191 rgba
[i
][GCOMP
] = FixedToChan(g
);
192 rgba
[i
][BCOMP
] = FixedToChan(b
);
193 rgba
[i
][ACOMP
] = FixedToChan(a
);
202 case GL_UNSIGNED_SHORT
:
204 GLushort (*rgba
)[4] = span
->array
->color
.sz2
.rgba
;
205 if (span
->interpMask
& SPAN_FLAT
) {
207 color
[RCOMP
] = FixedToInt(span
->red
);
208 color
[GCOMP
] = FixedToInt(span
->green
);
209 color
[BCOMP
] = FixedToInt(span
->blue
);
210 color
[ACOMP
] = FixedToInt(span
->alpha
);
211 for (i
= 0; i
< n
; i
++) {
212 COPY_4V(rgba
[i
], color
);
216 GLushort (*rgba
)[4] = span
->array
->color
.sz2
.rgba
;
218 GLint dr
, dg
, db
, da
;
224 dg
= span
->greenStep
;
226 da
= span
->alphaStep
;
227 for (i
= 0; i
< n
; i
++) {
228 rgba
[i
][RCOMP
] = FixedToChan(r
);
229 rgba
[i
][GCOMP
] = FixedToChan(g
);
230 rgba
[i
][BCOMP
] = FixedToChan(b
);
231 rgba
[i
][ACOMP
] = FixedToChan(a
);
243 GLfloat (*rgba
)[4] = span
->array
->color
.sz4
.rgba
;
244 GLfloat r
, g
, b
, a
, dr
, dg
, db
, da
;
249 if (span
->interpMask
& SPAN_FLAT
) {
250 dr
= dg
= db
= da
= 0.0;
254 dg
= span
->greenStep
;
256 da
= span
->alphaStep
;
258 for (i
= 0; i
< n
; i
++) {
271 _mesa_problem(NULL
, "bad datatype in interpolate_colors");
273 span
->arrayMask
|= SPAN_RGBA
;
278 * Interpolate specular/secondary colors.
281 interpolate_specular(SWspan
*span
)
283 const GLuint n
= span
->end
;
286 switch (span
->array
->ChanType
) {
288 case GL_UNSIGNED_BYTE
:
290 GLubyte (*spec
)[4] = span
->array
->color
.sz1
.spec
;
291 if (span
->interpMask
& SPAN_FLAT
) {
293 color
[RCOMP
] = FixedToInt(span
->specRed
);
294 color
[GCOMP
] = FixedToInt(span
->specGreen
);
295 color
[BCOMP
] = FixedToInt(span
->specBlue
);
297 for (i
= 0; i
< n
; i
++) {
298 COPY_4UBV(spec
[i
], color
);
302 GLfixed r
= span
->specRed
;
303 GLfixed g
= span
->specGreen
;
304 GLfixed b
= span
->specBlue
;
305 GLint dr
= span
->specRedStep
;
306 GLint dg
= span
->specGreenStep
;
307 GLint db
= span
->specBlueStep
;
308 for (i
= 0; i
< n
; i
++) {
309 spec
[i
][RCOMP
] = CLAMP(FixedToChan(r
), 0, 255);
310 spec
[i
][GCOMP
] = CLAMP(FixedToChan(g
), 0, 255);
311 spec
[i
][BCOMP
] = CLAMP(FixedToChan(b
), 0, 255);
320 case GL_UNSIGNED_SHORT
:
322 GLushort (*spec
)[4] = span
->array
->color
.sz2
.spec
;
323 if (span
->interpMask
& SPAN_FLAT
) {
325 color
[RCOMP
] = FixedToInt(span
->specRed
);
326 color
[GCOMP
] = FixedToInt(span
->specGreen
);
327 color
[BCOMP
] = FixedToInt(span
->specBlue
);
329 for (i
= 0; i
< n
; i
++) {
330 COPY_4V(spec
[i
], color
);
334 GLfixed r
= FloatToFixed(span
->specRed
);
335 GLfixed g
= FloatToFixed(span
->specGreen
);
336 GLfixed b
= FloatToFixed(span
->specBlue
);
337 GLint dr
= FloatToFixed(span
->specRedStep
);
338 GLint dg
= FloatToFixed(span
->specGreenStep
);
339 GLint db
= FloatToFixed(span
->specBlueStep
);
340 for (i
= 0; i
< n
; i
++) {
341 spec
[i
][RCOMP
] = FixedToInt(r
);
342 spec
[i
][GCOMP
] = FixedToInt(g
);
343 spec
[i
][BCOMP
] = FixedToInt(b
);
355 GLfloat (*spec
)[4] = span
->array
->color
.sz4
.spec
;
357 GLfloat r
= CHAN_TO_FLOAT(FixedToChan(span
->specRed
));
358 GLfloat g
= CHAN_TO_FLOAT(FixedToChan(span
->specGreen
));
359 GLfloat b
= CHAN_TO_FLOAT(FixedToChan(span
->specBlue
));
361 GLfloat r
= span
->specRed
;
362 GLfloat g
= span
->specGreen
;
363 GLfloat b
= span
->specBlue
;
366 if (span
->interpMask
& SPAN_FLAT
) {
371 dr
= CHAN_TO_FLOAT(FixedToChan(span
->specRedStep
));
372 dg
= CHAN_TO_FLOAT(FixedToChan(span
->specGreenStep
));
373 db
= CHAN_TO_FLOAT(FixedToChan(span
->specBlueStep
));
375 dr
= span
->specRedStep
;
376 dg
= span
->specGreenStep
;
377 db
= span
->specBlueStep
;
380 for (i
= 0; i
< n
; i
++) {
384 spec
[i
][ACOMP
] = 0.0F
;
392 _mesa_problem(NULL
, "bad datatype in interpolate_specular");
394 span
->arrayMask
|= SPAN_SPEC
;
398 /* Fill in the span.color.index array from the interpolation values */
400 interpolate_indexes(GLcontext
*ctx
, SWspan
*span
)
402 GLfixed index
= span
->index
;
403 const GLint indexStep
= span
->indexStep
;
404 const GLuint n
= span
->end
;
405 GLuint
*indexes
= span
->array
->index
;
408 ASSERT((span
->interpMask
& SPAN_INDEX
) &&
409 !(span
->arrayMask
& SPAN_INDEX
));
411 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
413 index
= FixedToInt(index
);
414 for (i
= 0; i
< n
; i
++) {
420 for (i
= 0; i
< n
; i
++) {
421 indexes
[i
] = FixedToInt(index
);
425 span
->arrayMask
|= SPAN_INDEX
;
426 span
->interpMask
&= ~SPAN_INDEX
;
430 /* Fill in the span.array.fog values from the interpolation values */
432 interpolate_fog(const GLcontext
*ctx
, SWspan
*span
)
434 GLfloat
*fog
= span
->array
->fog
;
435 const GLfloat fogStep
= span
->fogStep
;
436 GLfloat fogCoord
= span
->fog
;
437 const GLuint haveW
= (span
->interpMask
& SPAN_W
);
438 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
439 GLfloat w
= haveW
? span
->w
: 1.0F
;
441 for (i
= 0; i
< span
->end
; i
++) {
442 fog
[i
] = fogCoord
/ w
;
446 span
->arrayMask
|= SPAN_FOG
;
450 /* Fill in the span.zArray array from the interpolation values */
452 _swrast_span_interpolate_z( const GLcontext
*ctx
, SWspan
*span
)
454 const GLuint n
= span
->end
;
457 ASSERT((span
->interpMask
& SPAN_Z
) &&
458 !(span
->arrayMask
& SPAN_Z
));
460 if (ctx
->DrawBuffer
->Visual
.depthBits
<= 16) {
461 GLfixed zval
= span
->z
;
462 GLuint
*z
= span
->array
->z
;
463 for (i
= 0; i
< n
; i
++) {
464 z
[i
] = FixedToInt(zval
);
469 /* Deep Z buffer, no fixed->int shift */
470 GLuint zval
= span
->z
;
471 GLuint
*z
= span
->array
->z
;
472 for (i
= 0; i
< n
; i
++) {
477 span
->interpMask
&= ~SPAN_Z
;
478 span
->arrayMask
|= SPAN_Z
;
483 * This the ideal solution, as given in the OpenGL spec.
487 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
488 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
489 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
491 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
492 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
493 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
494 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
495 GLfloat x
= SQRTF(dudx
* dudx
+ dvdx
* dvdx
);
496 GLfloat y
= SQRTF(dudy
* dudy
+ dvdy
* dvdy
);
497 GLfloat rho
= MAX2(x
, y
);
498 GLfloat lambda
= LOG2(rho
);
505 * This is a faster approximation
508 _swrast_compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
509 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
510 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
512 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
513 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
514 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
515 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
516 GLfloat maxU
, maxV
, rho
, lambda
;
517 dsdx2
= FABSF(dsdx2
);
518 dsdy2
= FABSF(dsdy2
);
519 dtdx2
= FABSF(dtdx2
);
520 dtdy2
= FABSF(dtdy2
);
521 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
522 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
523 rho
= MAX2(maxU
, maxV
);
530 * Fill in the span.texcoords array from the interpolation values.
531 * Note: in the places where we divide by Q (or mult by invQ) we're
532 * really doing two things: perspective correction and texcoord
533 * projection. Remember, for texcoord (s,t,r,q) we need to index
534 * texels with (s/q, t/q, r/q).
535 * If we're using a fragment program, we never do the division
536 * for texcoord projection. That's done by the TXP instruction
537 * or user-written code.
540 interpolate_texcoords(GLcontext
*ctx
, SWspan
*span
)
542 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
543 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
545 if (ctx
->Texture
._EnabledCoordUnits
> 1) {
548 span
->arrayMask
|= SPAN_TEXTURE
;
549 /* XXX CoordUnits vs. ImageUnits */
550 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
551 if (ctx
->Texture
._EnabledCoordUnits
& (1 << u
)) {
552 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
554 GLboolean needLambda
;
556 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
557 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
558 || ctx
->FragmentProgram
._Enabled
;
559 texW
= img
->WidthScale
;
560 texH
= img
->HeightScale
;
563 /* using a fragment program */
566 needLambda
= GL_FALSE
;
569 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
570 GLfloat
*lambda
= span
->array
->lambda
[u
];
571 const GLfloat dsdx
= span
->texStepX
[u
][0];
572 const GLfloat dsdy
= span
->texStepY
[u
][0];
573 const GLfloat dtdx
= span
->texStepX
[u
][1];
574 const GLfloat dtdy
= span
->texStepY
[u
][1];
575 const GLfloat drdx
= span
->texStepX
[u
][2];
576 const GLfloat dqdx
= span
->texStepX
[u
][3];
577 const GLfloat dqdy
= span
->texStepY
[u
][3];
578 GLfloat s
= span
->tex
[u
][0];
579 GLfloat t
= span
->tex
[u
][1];
580 GLfloat r
= span
->tex
[u
][2];
581 GLfloat q
= span
->tex
[u
][3];
583 if (ctx
->FragmentProgram
._Enabled
|| ctx
->ATIFragmentShader
._Enabled
||
584 ctx
->ShaderObjects
._FragmentShaderPresent
) {
585 /* do perspective correction but don't divide s, t, r by q */
586 const GLfloat dwdx
= span
->dwdx
;
588 for (i
= 0; i
< span
->end
; i
++) {
589 const GLfloat invW
= 1.0F
/ w
;
590 texcoord
[i
][0] = s
* invW
;
591 texcoord
[i
][1] = t
* invW
;
592 texcoord
[i
][2] = r
* invW
;
593 texcoord
[i
][3] = q
* invW
;
594 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
595 dqdx
, dqdy
, texW
, texH
,
606 for (i
= 0; i
< span
->end
; i
++) {
607 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
608 texcoord
[i
][0] = s
* invQ
;
609 texcoord
[i
][1] = t
* invQ
;
610 texcoord
[i
][2] = r
* invQ
;
612 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
613 dqdx
, dqdy
, texW
, texH
,
621 span
->arrayMask
|= SPAN_LAMBDA
;
624 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
625 GLfloat
*lambda
= span
->array
->lambda
[u
];
626 const GLfloat dsdx
= span
->texStepX
[u
][0];
627 const GLfloat dtdx
= span
->texStepX
[u
][1];
628 const GLfloat drdx
= span
->texStepX
[u
][2];
629 const GLfloat dqdx
= span
->texStepX
[u
][3];
630 GLfloat s
= span
->tex
[u
][0];
631 GLfloat t
= span
->tex
[u
][1];
632 GLfloat r
= span
->tex
[u
][2];
633 GLfloat q
= span
->tex
[u
][3];
635 if (ctx
->FragmentProgram
._Enabled
|| ctx
->ATIFragmentShader
._Enabled
||
636 ctx
->ShaderObjects
._FragmentShaderPresent
) {
637 /* do perspective correction but don't divide s, t, r by q */
638 const GLfloat dwdx
= span
->dwdx
;
640 for (i
= 0; i
< span
->end
; i
++) {
641 const GLfloat invW
= 1.0F
/ w
;
642 texcoord
[i
][0] = s
* invW
;
643 texcoord
[i
][1] = t
* invW
;
644 texcoord
[i
][2] = r
* invW
;
645 texcoord
[i
][3] = q
* invW
;
654 else if (dqdx
== 0.0F
) {
655 /* Ortho projection or polygon's parallel to window X axis */
656 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
657 for (i
= 0; i
< span
->end
; i
++) {
658 texcoord
[i
][0] = s
* invQ
;
659 texcoord
[i
][1] = t
* invQ
;
660 texcoord
[i
][2] = r
* invQ
;
669 for (i
= 0; i
< span
->end
; i
++) {
670 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
671 texcoord
[i
][0] = s
* invQ
;
672 texcoord
[i
][1] = t
* invQ
;
673 texcoord
[i
][2] = r
* invQ
;
688 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
690 GLboolean needLambda
;
692 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
693 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
694 || ctx
->FragmentProgram
._Enabled
;
695 texW
= (GLfloat
) img
->WidthScale
;
696 texH
= (GLfloat
) img
->HeightScale
;
699 needLambda
= GL_FALSE
;
702 span
->arrayMask
|= SPAN_TEXTURE
;
704 /* just texture unit 0, with lambda */
705 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
706 GLfloat
*lambda
= span
->array
->lambda
[0];
707 const GLfloat dsdx
= span
->texStepX
[0][0];
708 const GLfloat dsdy
= span
->texStepY
[0][0];
709 const GLfloat dtdx
= span
->texStepX
[0][1];
710 const GLfloat dtdy
= span
->texStepY
[0][1];
711 const GLfloat drdx
= span
->texStepX
[0][2];
712 const GLfloat dqdx
= span
->texStepX
[0][3];
713 const GLfloat dqdy
= span
->texStepY
[0][3];
714 GLfloat s
= span
->tex
[0][0];
715 GLfloat t
= span
->tex
[0][1];
716 GLfloat r
= span
->tex
[0][2];
717 GLfloat q
= span
->tex
[0][3];
719 if (ctx
->FragmentProgram
._Enabled
|| ctx
->ATIFragmentShader
._Enabled
||
720 ctx
->ShaderObjects
._FragmentShaderPresent
) {
721 /* do perspective correction but don't divide s, t, r by q */
722 const GLfloat dwdx
= span
->dwdx
;
724 for (i
= 0; i
< span
->end
; i
++) {
725 const GLfloat invW
= 1.0F
/ w
;
726 texcoord
[i
][0] = s
* invW
;
727 texcoord
[i
][1] = t
* invW
;
728 texcoord
[i
][2] = r
* invW
;
729 texcoord
[i
][3] = q
* invW
;
730 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
731 dqdx
, dqdy
, texW
, texH
,
742 for (i
= 0; i
< span
->end
; i
++) {
743 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
744 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
745 dqdx
, dqdy
, texW
, texH
,
747 texcoord
[i
][0] = s
* invQ
;
748 texcoord
[i
][1] = t
* invQ
;
749 texcoord
[i
][2] = r
* invQ
;
757 span
->arrayMask
|= SPAN_LAMBDA
;
760 /* just texture 0, without lambda */
761 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
762 const GLfloat dsdx
= span
->texStepX
[0][0];
763 const GLfloat dtdx
= span
->texStepX
[0][1];
764 const GLfloat drdx
= span
->texStepX
[0][2];
765 const GLfloat dqdx
= span
->texStepX
[0][3];
766 GLfloat s
= span
->tex
[0][0];
767 GLfloat t
= span
->tex
[0][1];
768 GLfloat r
= span
->tex
[0][2];
769 GLfloat q
= span
->tex
[0][3];
771 if (ctx
->FragmentProgram
._Enabled
|| ctx
->ATIFragmentShader
._Enabled
||
772 ctx
->ShaderObjects
._FragmentShaderPresent
) {
773 /* do perspective correction but don't divide s, t, r by q */
774 const GLfloat dwdx
= span
->dwdx
;
776 for (i
= 0; i
< span
->end
; i
++) {
777 const GLfloat invW
= 1.0F
/ w
;
778 texcoord
[i
][0] = s
* invW
;
779 texcoord
[i
][1] = t
* invW
;
780 texcoord
[i
][2] = r
* invW
;
781 texcoord
[i
][3] = q
* invW
;
789 else if (dqdx
== 0.0F
) {
790 /* Ortho projection or polygon's parallel to window X axis */
791 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
792 for (i
= 0; i
< span
->end
; i
++) {
793 texcoord
[i
][0] = s
* invQ
;
794 texcoord
[i
][1] = t
* invQ
;
795 texcoord
[i
][2] = r
* invQ
;
803 for (i
= 0; i
< span
->end
; i
++) {
804 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
805 texcoord
[i
][0] = s
* invQ
;
806 texcoord
[i
][1] = t
* invQ
;
807 texcoord
[i
][2] = r
* invQ
;
821 * Fill in the span.varying array from the interpolation values.
824 interpolate_varying(GLcontext
*ctx
, SWspan
*span
)
828 ASSERT(span
->interpMask
& SPAN_VARYING
);
829 ASSERT(!(span
->arrayMask
& SPAN_VARYING
));
831 span
->arrayMask
|= SPAN_VARYING
;
833 for (i
= 0; i
< MAX_VARYING_VECTORS
; i
++) {
834 for (j
= 0; j
< VARYINGS_PER_VECTOR
; j
++) {
835 const GLfloat dvdx
= span
->varStepX
[i
][j
];
836 GLfloat v
= span
->var
[i
][j
];
837 const GLfloat dwdx
= span
->dwdx
;
841 for (k
= 0; k
< span
->end
; k
++) {
842 GLfloat invW
= 1.0f
/ w
;
843 span
->array
->varying
[k
][i
][j
] = v
* invW
;
853 * Apply the current polygon stipple pattern to a span of pixels.
856 stipple_polygon_span( GLcontext
*ctx
, SWspan
*span
)
858 const GLuint highbit
= 0x80000000;
859 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
860 GLubyte
*mask
= span
->array
->mask
;
863 ASSERT(ctx
->Polygon
.StippleFlag
);
864 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
866 m
= highbit
>> (GLuint
) (span
->x
% 32);
868 for (i
= 0; i
< span
->end
; i
++) {
869 if ((m
& stipple
) == 0) {
877 span
->writeAll
= GL_FALSE
;
882 * Clip a pixel span to the current buffer/window boundaries:
883 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
884 * window clipping and scissoring.
885 * Return: GL_TRUE some pixels still visible
886 * GL_FALSE nothing visible
889 clip_span( GLcontext
*ctx
, SWspan
*span
)
891 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
892 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
893 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
894 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
896 if (span
->arrayMask
& SPAN_XY
) {
897 /* arrays of x/y pixel coords */
898 const GLint
*x
= span
->array
->x
;
899 const GLint
*y
= span
->array
->y
;
900 const GLint n
= span
->end
;
901 GLubyte
*mask
= span
->array
->mask
;
903 if (span
->arrayMask
& SPAN_MASK
) {
904 /* note: using & intead of && to reduce branches */
905 for (i
= 0; i
< n
; i
++) {
906 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
907 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
911 /* note: using & intead of && to reduce branches */
912 for (i
= 0; i
< n
; i
++) {
913 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
914 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
917 return GL_TRUE
; /* some pixels visible */
920 /* horizontal span of pixels */
921 const GLint x
= span
->x
;
922 const GLint y
= span
->y
;
923 const GLint n
= span
->end
;
925 /* Trivial rejection tests */
926 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
928 return GL_FALSE
; /* all pixels clipped */
931 /* Clip to the left */
933 ASSERT(x
+ n
> xmin
);
934 span
->writeAll
= GL_FALSE
;
935 _mesa_bzero(span
->array
->mask
, (xmin
- x
) * sizeof(GLubyte
));
941 span
->end
= xmax
- x
;
944 return GL_TRUE
; /* some pixels visible */
950 * Apply all the per-fragment opertions to a span of color index fragments
951 * and write them to the enabled color drawbuffers.
952 * The 'span' parameter can be considered to be const. Note that
953 * span->interpMask and span->arrayMask may be changed but will be restored
954 * to their original values before returning.
957 _swrast_write_index_span( GLcontext
*ctx
, SWspan
*span
)
959 const SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
960 const GLbitfield origInterpMask
= span
->interpMask
;
961 const GLbitfield origArrayMask
= span
->arrayMask
;
963 ASSERT(span
->end
<= MAX_WIDTH
);
964 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
965 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
966 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
967 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
969 if (span
->arrayMask
& SPAN_MASK
) {
970 /* mask was initialized by caller, probably glBitmap */
971 span
->writeAll
= GL_FALSE
;
974 _mesa_memset(span
->array
->mask
, 1, span
->end
);
975 span
->writeAll
= GL_TRUE
;
979 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
980 if (!clip_span(ctx
, span
)) {
985 /* Depth bounds test */
986 if (ctx
->Depth
.BoundsTest
&& ctx
->DrawBuffer
->Visual
.depthBits
> 0) {
987 if (!_swrast_depth_bounds_test(ctx
, span
)) {
993 /* Make sure all fragments are within window bounds */
994 if (span
->arrayMask
& SPAN_XY
) {
996 for (i
= 0; i
< span
->end
; i
++) {
997 if (span
->array
->mask
[i
]) {
998 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
999 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1000 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1001 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1007 /* Polygon Stippling */
1008 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1009 stipple_polygon_span(ctx
, span
);
1012 /* Stencil and Z testing */
1013 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
1014 if (span
->interpMask
& SPAN_Z
)
1015 _swrast_span_interpolate_z(ctx
, span
);
1017 if (ctx
->Stencil
.Enabled
) {
1018 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1019 span
->arrayMask
= origArrayMask
;
1024 ASSERT(ctx
->Depth
.Test
);
1025 if (!_swrast_depth_test_span(ctx
, span
)) {
1026 span
->interpMask
= origInterpMask
;
1027 span
->arrayMask
= origArrayMask
;
1033 #if FEATURE_ARB_occlusion_query
1034 if (ctx
->Query
.CurrentOcclusionObject
) {
1035 /* update count of 'passed' fragments */
1036 struct gl_query_object
*q
= ctx
->Query
.CurrentOcclusionObject
;
1038 for (i
= 0; i
< span
->end
; i
++)
1039 q
->Result
+= span
->array
->mask
[i
];
1043 /* we have to wait until after occlusion to do this test */
1044 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
1045 /* write no pixels */
1046 span
->arrayMask
= origArrayMask
;
1050 /* Interpolate the color indexes if needed */
1051 if (swrast
->_FogEnabled
||
1052 ctx
->Color
.IndexLogicOpEnabled
||
1053 ctx
->Color
.IndexMask
!= 0xffffffff ||
1054 (span
->arrayMask
& SPAN_COVERAGE
)) {
1055 if (span
->interpMask
& SPAN_INDEX
) {
1056 interpolate_indexes(ctx
, span
);
1061 if (swrast
->_FogEnabled
) {
1062 _swrast_fog_ci_span(ctx
, span
);
1065 /* Antialias coverage application */
1066 if (span
->arrayMask
& SPAN_COVERAGE
) {
1067 const GLfloat
*coverage
= span
->array
->coverage
;
1068 GLuint
*index
= span
->array
->index
;
1070 for (i
= 0; i
< span
->end
; i
++) {
1071 ASSERT(coverage
[i
] < 16);
1072 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) coverage
[i
]);
1077 * Write to renderbuffers
1080 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1081 const GLuint output
= 0; /* only frag progs can write to other outputs */
1082 const GLuint numDrawBuffers
= fb
->_NumColorDrawBuffers
[output
];
1083 GLuint indexSave
[MAX_WIDTH
];
1086 if (numDrawBuffers
> 1) {
1087 /* save indexes for second, third renderbuffer writes */
1088 _mesa_memcpy(indexSave
, span
->array
->index
,
1089 span
->end
* sizeof(indexSave
[0]));
1092 for (buf
= 0; buf
< fb
->_NumColorDrawBuffers
[output
]; buf
++) {
1093 struct gl_renderbuffer
*rb
= fb
->_ColorDrawBuffers
[output
][buf
];
1094 ASSERT(rb
->_BaseFormat
== GL_COLOR_INDEX
);
1096 if (ctx
->Color
.IndexLogicOpEnabled
) {
1097 _swrast_logicop_ci_span(ctx
, rb
, span
);
1100 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
1101 _swrast_mask_ci_span(ctx
, rb
, span
);
1104 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
1105 /* all fragments have same color index */
1111 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1112 index8
= FixedToInt(span
->index
);
1115 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
1116 index16
= FixedToInt(span
->index
);
1120 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
);
1121 index32
= FixedToInt(span
->index
);
1125 if (span
->arrayMask
& SPAN_XY
) {
1126 rb
->PutMonoValues(ctx
, rb
, span
->end
, span
->array
->x
,
1127 span
->array
->y
, value
, span
->array
->mask
);
1130 rb
->PutMonoRow(ctx
, rb
, span
->end
, span
->x
, span
->y
,
1131 value
, span
->array
->mask
);
1135 /* each fragment is a different color */
1136 GLubyte index8
[MAX_WIDTH
];
1137 GLushort index16
[MAX_WIDTH
];
1140 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1142 for (k
= 0; k
< span
->end
; k
++) {
1143 index8
[k
] = (GLubyte
) span
->array
->index
[k
];
1147 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
1149 for (k
= 0; k
< span
->end
; k
++) {
1150 index16
[k
] = (GLushort
) span
->array
->index
[k
];
1155 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
);
1156 values
= span
->array
->index
;
1159 if (span
->arrayMask
& SPAN_XY
) {
1160 rb
->PutValues(ctx
, rb
, span
->end
,
1161 span
->array
->x
, span
->array
->y
,
1162 values
, span
->array
->mask
);
1165 rb
->PutRow(ctx
, rb
, span
->end
, span
->x
, span
->y
,
1166 values
, span
->array
->mask
);
1170 if (buf
+ 1 < numDrawBuffers
) {
1171 /* restore original span values */
1172 _mesa_memcpy(span
->array
->index
, indexSave
,
1173 span
->end
* sizeof(indexSave
[0]));
1178 span
->interpMask
= origInterpMask
;
1179 span
->arrayMask
= origArrayMask
;
1184 * Add specular color to base color. This is used only when
1185 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1188 add_specular(GLcontext
*ctx
, SWspan
*span
)
1190 switch (span
->array
->ChanType
) {
1191 case GL_UNSIGNED_BYTE
:
1193 GLubyte (*rgba
)[4] = span
->array
->color
.sz1
.rgba
;
1194 GLubyte (*spec
)[4] = span
->array
->color
.sz1
.spec
;
1196 for (i
= 0; i
< span
->end
; i
++) {
1197 GLint r
= rgba
[i
][RCOMP
] + spec
[i
][RCOMP
];
1198 GLint g
= rgba
[i
][GCOMP
] + spec
[i
][GCOMP
];
1199 GLint b
= rgba
[i
][BCOMP
] + spec
[i
][BCOMP
];
1200 GLint a
= rgba
[i
][ACOMP
] + spec
[i
][ACOMP
];
1201 rgba
[i
][RCOMP
] = MIN2(r
, 255);
1202 rgba
[i
][GCOMP
] = MIN2(g
, 255);
1203 rgba
[i
][BCOMP
] = MIN2(b
, 255);
1204 rgba
[i
][ACOMP
] = MIN2(a
, 255);
1208 case GL_UNSIGNED_SHORT
:
1210 GLushort (*rgba
)[4] = span
->array
->color
.sz2
.rgba
;
1211 GLushort (*spec
)[4] = span
->array
->color
.sz2
.spec
;
1213 for (i
= 0; i
< span
->end
; i
++) {
1214 GLint r
= rgba
[i
][RCOMP
] + spec
[i
][RCOMP
];
1215 GLint g
= rgba
[i
][GCOMP
] + spec
[i
][GCOMP
];
1216 GLint b
= rgba
[i
][BCOMP
] + spec
[i
][BCOMP
];
1217 GLint a
= rgba
[i
][ACOMP
] + spec
[i
][ACOMP
];
1218 rgba
[i
][RCOMP
] = MIN2(r
, 65535);
1219 rgba
[i
][GCOMP
] = MIN2(g
, 65535);
1220 rgba
[i
][BCOMP
] = MIN2(b
, 65535);
1221 rgba
[i
][ACOMP
] = MIN2(a
, 65535);
1227 GLfloat (*rgba
)[4] = span
->array
->color
.sz4
.rgba
;
1228 GLfloat (*spec
)[4] = span
->array
->color
.sz4
.spec
;
1230 for (i
= 0; i
< span
->end
; i
++) {
1231 rgba
[i
][RCOMP
] += spec
[i
][RCOMP
];
1232 rgba
[i
][GCOMP
] += spec
[i
][GCOMP
];
1233 rgba
[i
][BCOMP
] += spec
[i
][BCOMP
];
1234 rgba
[i
][ACOMP
] += spec
[i
][ACOMP
];
1239 _mesa_problem(ctx
, "Invalid datatype in add_specular");
1245 * Apply antialiasing coverage value to alpha values.
1248 apply_aa_coverage(SWspan
*span
)
1250 const GLfloat
*coverage
= span
->array
->coverage
;
1252 if (span
->array
->ChanType
== GL_UNSIGNED_BYTE
) {
1253 GLubyte (*rgba
)[4] = span
->array
->color
.sz1
.rgba
;
1254 for (i
= 0; i
< span
->end
; i
++) {
1255 const GLfloat a
= rgba
[i
][ACOMP
] * coverage
[i
];
1256 rgba
[i
][ACOMP
] = (GLubyte
) CLAMP(a
, 0.0, 255.0);
1257 ASSERT(coverage
[i
] >= 0.0);
1258 ASSERT(coverage
[i
] <= 1.0);
1261 else if (span
->array
->ChanType
== GL_UNSIGNED_SHORT
) {
1262 GLushort (*rgba
)[4] = span
->array
->color
.sz2
.rgba
;
1263 for (i
= 0; i
< span
->end
; i
++) {
1264 const GLfloat a
= rgba
[i
][ACOMP
] * coverage
[i
];
1265 rgba
[i
][ACOMP
] = (GLushort
) CLAMP(a
, 0.0, 65535.0);
1269 GLfloat (*rgba
)[4] = span
->array
->color
.sz4
.rgba
;
1270 for (i
= 0; i
< span
->end
; i
++) {
1271 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * coverage
[i
];
1278 * Clamp span's float colors to [0,1]
1281 clamp_colors(SWspan
*span
)
1283 GLfloat (*rgba
)[4] = span
->array
->color
.sz4
.rgba
;
1285 ASSERT(span
->array
->ChanType
== GL_FLOAT
);
1286 for (i
= 0; i
< span
->end
; i
++) {
1287 rgba
[i
][RCOMP
] = CLAMP(rgba
[i
][RCOMP
], 0.0F
, 1.0F
);
1288 rgba
[i
][GCOMP
] = CLAMP(rgba
[i
][GCOMP
], 0.0F
, 1.0F
);
1289 rgba
[i
][BCOMP
] = CLAMP(rgba
[i
][BCOMP
], 0.0F
, 1.0F
);
1290 rgba
[i
][ACOMP
] = CLAMP(rgba
[i
][ACOMP
], 0.0F
, 1.0F
);
1296 * Convert the span's color arrays to the given type.
1299 convert_color_type(GLcontext
*ctx
, SWspan
*span
, GLenum newType
)
1302 if (span
->array
->ChanType
== GL_UNSIGNED_BYTE
) {
1303 src
= span
->array
->color
.sz1
.rgba
;
1305 else if (span
->array
->ChanType
== GL_UNSIGNED_BYTE
) {
1306 src
= span
->array
->color
.sz2
.rgba
;
1309 src
= span
->array
->color
.sz4
.rgba
;
1311 if (newType
== GL_UNSIGNED_BYTE
) {
1312 dst
= span
->array
->color
.sz1
.rgba
;
1314 else if (newType
== GL_UNSIGNED_BYTE
) {
1315 dst
= span
->array
->color
.sz2
.rgba
;
1318 dst
= span
->array
->color
.sz4
.rgba
;
1321 _mesa_convert_colors(span
->array
->ChanType
, src
,
1323 span
->end
, span
->array
->mask
);
1325 span
->array
->ChanType
= newType
;
1331 * Apply fragment shader, fragment program or normal texturing to span.
1334 shade_texture_span(GLcontext
*ctx
, SWspan
*span
)
1336 /* Now we need the rgba array, fill it in if needed */
1337 if (span
->interpMask
& SPAN_RGBA
)
1338 interpolate_colors(span
);
1340 if (ctx
->Texture
._EnabledCoordUnits
&& (span
->interpMask
& SPAN_TEXTURE
))
1341 interpolate_texcoords(ctx
, span
);
1343 if (ctx
->ShaderObjects
._FragmentShaderPresent
||
1344 ctx
->FragmentProgram
._Enabled
||
1345 ctx
->ATIFragmentShader
._Enabled
) {
1347 /* use float colors if running a fragment program or shader */
1348 const GLenum oldType
= span
->array
->ChanType
;
1349 const GLenum newType
= GL_FLOAT
;
1350 if (oldType
!= newType
) {
1351 GLvoid
*src
= (oldType
== GL_UNSIGNED_BYTE
)
1352 ? (GLvoid
*) span
->array
->color
.sz1
.rgba
1353 : (GLvoid
*) span
->array
->color
.sz2
.rgba
;
1354 _mesa_convert_colors(oldType
, src
,
1355 newType
, span
->array
->color
.sz4
.rgba
,
1356 span
->end
, span
->array
->mask
);
1357 span
->array
->ChanType
= newType
;
1360 /* fragment programs/shaders may need specular, fog and Z coords */
1361 if (span
->interpMask
& SPAN_SPEC
)
1362 interpolate_specular(span
);
1364 if (span
->interpMask
& SPAN_FOG
)
1365 interpolate_fog(ctx
, span
);
1367 if (span
->interpMask
& SPAN_Z
)
1368 _swrast_span_interpolate_z (ctx
, span
);
1370 /* Run fragment program/shader now */
1371 if (ctx
->ShaderObjects
._FragmentShaderPresent
) {
1372 interpolate_varying(ctx
, span
);
1373 _swrast_exec_arbshader(ctx
, span
);
1375 else if (ctx
->FragmentProgram
._Enabled
) {
1376 _swrast_exec_fragment_program(ctx
, span
);
1379 ASSERT(ctx
->ATIFragmentShader
._Enabled
);
1380 _swrast_exec_fragment_shader(ctx
, span
);
1383 else if (ctx
->Texture
._EnabledUnits
&& (span
->arrayMask
& SPAN_TEXTURE
)) {
1384 /* conventional texturing */
1385 _swrast_texture_span(ctx
, span
);
1392 * Apply all the per-fragment operations to a span.
1393 * This now includes texturing (_swrast_write_texture_span() is history).
1394 * This function may modify any of the array values in the span.
1395 * span->interpMask and span->arrayMask may be changed but will be restored
1396 * to their original values before returning.
1399 _swrast_write_rgba_span( GLcontext
*ctx
, SWspan
*span
)
1401 const SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1402 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1403 const GLbitfield origInterpMask
= span
->interpMask
;
1404 const GLbitfield origArrayMask
= span
->arrayMask
;
1405 const GLenum chanType
= span
->array
->ChanType
;
1406 const GLboolean shader
1407 = ctx
->FragmentProgram
._Enabled
1408 || ctx
->ShaderObjects
._FragmentShaderPresent
1409 || ctx
->ATIFragmentShader
._Enabled
;
1410 const GLboolean shaderOrTexture
= shader
|| ctx
->Texture
._EnabledUnits
;
1411 GLboolean deferredTexture
;
1414 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__,
1415 span->interpMask, span->arrayMask);
1418 ASSERT(span
->primitive
== GL_POINT
||
1419 span
->primitive
== GL_LINE
||
1420 span
->primitive
== GL_POLYGON
||
1421 span
->primitive
== GL_BITMAP
);
1422 ASSERT(span
->end
<= MAX_WIDTH
);
1423 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1424 ASSERT((span
->interpMask
& SPAN_RGBA
) ^ (span
->arrayMask
& SPAN_RGBA
));
1426 /* check for conditions that prevent deferred shading */
1427 if (ctx
->Color
.AlphaEnabled
) {
1428 /* alpha test depends on post-texture/shader colors */
1429 deferredTexture
= GL_FALSE
;
1431 else if (shaderOrTexture
) {
1432 if (ctx
->FragmentProgram
._Enabled
) {
1433 if (ctx
->FragmentProgram
.Current
->Base
.OutputsWritten
1434 & (1 << FRAG_RESULT_DEPR
)) {
1435 /* Z comes from fragment program */
1436 deferredTexture
= GL_FALSE
;
1439 deferredTexture
= GL_TRUE
;
1442 else if (ctx
->ShaderObjects
._FragmentShaderPresent
) {
1443 /* XXX how do we test if Z is written by shader? */
1444 deferredTexture
= GL_FALSE
; /* never defer to be safe */
1447 /* ATI frag shader or conventional texturing */
1448 deferredTexture
= GL_TRUE
;
1452 /* no texturing or shadering */
1453 deferredTexture
= GL_FALSE
;
1456 /* Fragment write masks */
1457 if (span
->arrayMask
& SPAN_MASK
) {
1458 /* mask was initialized by caller, probably glBitmap */
1459 span
->writeAll
= GL_FALSE
;
1462 _mesa_memset(span
->array
->mask
, 1, span
->end
);
1463 span
->writeAll
= GL_TRUE
;
1466 /* Clip to window/scissor box */
1467 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1468 if (!clip_span(ctx
, span
)) {
1474 /* Make sure all fragments are within window bounds */
1475 if (span
->arrayMask
& SPAN_XY
) {
1477 for (i
= 0; i
< span
->end
; i
++) {
1478 if (span
->array
->mask
[i
]) {
1479 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1480 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1481 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1482 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1488 /* Polygon Stippling */
1489 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1490 stipple_polygon_span(ctx
, span
);
1493 /* This is the normal place to compute the resulting fragment color/Z.
1494 * As an optimization, we try to defer this until after Z/stencil
1495 * testing in order to try to avoid computing colors that we won't
1498 if (shaderOrTexture
&& !deferredTexture
) {
1499 shade_texture_span(ctx
, span
);
1502 /* Do the alpha test */
1503 if (ctx
->Color
.AlphaEnabled
) {
1504 if (!_swrast_alpha_test(ctx
, span
)) {
1509 /* Stencil and Z testing */
1510 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1511 if (span
->interpMask
& SPAN_Z
)
1512 _swrast_span_interpolate_z(ctx
, span
);
1514 if (ctx
->Stencil
.Enabled
&& ctx
->DrawBuffer
->Visual
.stencilBits
> 0) {
1515 /* Combined Z/stencil tests */
1516 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1520 else if (ctx
->DrawBuffer
->Visual
.depthBits
> 0) {
1521 /* Just regular depth testing */
1522 ASSERT(ctx
->Depth
.Test
);
1523 ASSERT(span
->arrayMask
& SPAN_Z
);
1524 if (!_swrast_depth_test_span(ctx
, span
)) {
1530 #if FEATURE_ARB_occlusion_query
1531 if (ctx
->Query
.CurrentOcclusionObject
) {
1532 /* update count of 'passed' fragments */
1533 struct gl_query_object
*q
= ctx
->Query
.CurrentOcclusionObject
;
1535 for (i
= 0; i
< span
->end
; i
++)
1536 q
->Result
+= span
->array
->mask
[i
];
1540 /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1541 * the occlusion test.
1543 if (colorMask
== 0x0) {
1547 /* If we were able to defer fragment color computation to now, there's
1548 * a good chance that many fragments will have already been killed by
1549 * Z/stencil testing.
1551 if (deferredTexture
) {
1552 ASSERT(shaderOrTexture
);
1553 shade_texture_span(ctx
, span
);
1556 if ((span
->arrayMask
& SPAN_RGBA
) == 0) {
1557 interpolate_colors(span
);
1560 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1563 /* Add base and specular colors */
1564 if (ctx
->Fog
.ColorSumEnabled
||
1565 (ctx
->Light
.Enabled
&&
1566 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1567 if (span
->interpMask
& SPAN_SPEC
) {
1568 interpolate_specular(span
);
1570 if (span
->arrayMask
& SPAN_SPEC
) {
1571 add_specular(ctx
, span
);
1574 /* We probably added the base/specular colors during the
1582 if (swrast
->_FogEnabled
) {
1583 _swrast_fog_rgba_span(ctx
, span
);
1586 /* Antialias coverage application */
1587 if (span
->arrayMask
& SPAN_COVERAGE
) {
1588 apply_aa_coverage(span
);
1591 /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
1592 if (ctx
->Color
.ClampFragmentColor
== GL_TRUE
&&
1593 span
->array
->ChanType
== GL_FLOAT
) {
1598 * Write to renderbuffers
1601 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1602 const GLuint output
= 0; /* only frag progs can write to other outputs */
1603 const GLuint numDrawBuffers
= fb
->_NumColorDrawBuffers
[output
];
1604 GLchan rgbaSave
[MAX_WIDTH
][4];
1607 if (numDrawBuffers
> 0) {
1608 if (fb
->_ColorDrawBuffers
[output
][0]->DataType
1609 != span
->array
->ChanType
) {
1610 convert_color_type(ctx
, span
,
1611 fb
->_ColorDrawBuffers
[output
][0]->DataType
);
1615 if (numDrawBuffers
> 1) {
1616 /* save colors for second, third renderbuffer writes */
1617 _mesa_memcpy(rgbaSave
, span
->array
->rgba
,
1618 4 * span
->end
* sizeof(GLchan
));
1621 for (buf
= 0; buf
< numDrawBuffers
; buf
++) {
1622 struct gl_renderbuffer
*rb
= fb
->_ColorDrawBuffers
[output
][buf
];
1623 ASSERT(rb
->_BaseFormat
== GL_RGBA
|| rb
->_BaseFormat
== GL_RGB
);
1625 if (ctx
->Color
._LogicOpEnabled
) {
1626 _swrast_logicop_rgba_span(ctx
, rb
, span
);
1628 else if (ctx
->Color
.BlendEnabled
) {
1629 _swrast_blend_span(ctx
, rb
, span
);
1632 if (colorMask
!= 0xffffffff) {
1633 _swrast_mask_rgba_span(ctx
, rb
, span
);
1636 if (span
->arrayMask
& SPAN_XY
) {
1637 /* array of pixel coords */
1638 ASSERT(rb
->PutValues
);
1639 rb
->PutValues(ctx
, rb
, span
->end
,
1640 span
->array
->x
, span
->array
->y
,
1641 span
->array
->rgba
, span
->array
->mask
);
1644 /* horizontal run of pixels */
1646 rb
->PutRow(ctx
, rb
, span
->end
, span
->x
, span
->y
, span
->array
->rgba
,
1647 span
->writeAll
? NULL
: span
->array
->mask
);
1650 if (buf
+ 1 < numDrawBuffers
) {
1651 /* restore original span values */
1652 _mesa_memcpy(span
->array
->rgba
, rgbaSave
,
1653 4 * span
->end
* sizeof(GLchan
));
1660 /* restore these values before returning */
1661 span
->interpMask
= origInterpMask
;
1662 span
->arrayMask
= origArrayMask
;
1663 span
->array
->ChanType
= chanType
;
1668 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1669 * reading ouside the buffer's boundaries.
1670 * \param type datatype for returned colors
1671 * \param rgba the returned colors
1674 _swrast_read_rgba_span( GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1675 GLuint n
, GLint x
, GLint y
, GLenum dstType
,
1678 const GLint bufWidth
= (GLint
) rb
->Width
;
1679 const GLint bufHeight
= (GLint
) rb
->Height
;
1681 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1682 /* completely above, below, or right */
1683 /* XXX maybe leave rgba values undefined? */
1684 _mesa_bzero(rgba
, 4 * n
* sizeof(GLchan
));
1689 /* left edge clipping */
1691 length
= (GLint
) n
- skip
;
1693 /* completely left of window */
1696 if (length
> bufWidth
) {
1700 else if ((GLint
) (x
+ n
) > bufWidth
) {
1701 /* right edge clipping */
1703 length
= bufWidth
- x
;
1705 /* completely to right of window */
1717 ASSERT(rb
->_BaseFormat
== GL_RGB
|| rb
->_BaseFormat
== GL_RGBA
);
1719 if (rb
->DataType
== dstType
) {
1720 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
,
1721 (GLubyte
*) rgba
+ skip
* RGBA_PIXEL_SIZE(rb
->DataType
));
1724 GLuint temp
[MAX_WIDTH
* 4];
1725 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
, temp
);
1726 _mesa_convert_colors(rb
->DataType
, temp
,
1727 dstType
, (GLubyte
*) rgba
+ skip
* RGBA_PIXEL_SIZE(dstType
),
1735 * Read CI pixels from frame buffer. Clipping will be done to prevent
1736 * reading ouside the buffer's boundaries.
1739 _swrast_read_index_span( GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1740 GLuint n
, GLint x
, GLint y
, GLuint index
[] )
1742 const GLint bufWidth
= (GLint
) rb
->Width
;
1743 const GLint bufHeight
= (GLint
) rb
->Height
;
1745 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1746 /* completely above, below, or right */
1747 _mesa_bzero(index
, n
* sizeof(GLuint
));
1752 /* left edge clipping */
1754 length
= (GLint
) n
- skip
;
1756 /* completely left of window */
1759 if (length
> bufWidth
) {
1763 else if ((GLint
) (x
+ n
) > bufWidth
) {
1764 /* right edge clipping */
1766 length
= bufWidth
- x
;
1768 /* completely to right of window */
1779 ASSERT(rb
->_BaseFormat
== GL_COLOR_INDEX
);
1781 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1782 GLubyte index8
[MAX_WIDTH
];
1784 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
, index8
);
1785 for (i
= 0; i
< length
; i
++)
1786 index
[skip
+ i
] = index8
[i
];
1788 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
1789 GLushort index16
[MAX_WIDTH
];
1791 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
, index16
);
1792 for (i
= 0; i
< length
; i
++)
1793 index
[skip
+ i
] = index16
[i
];
1795 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
1796 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
, index
+ skip
);
1803 * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
1804 * reading values outside the buffer bounds.
1805 * We can use this for reading any format/type of renderbuffer.
1806 * \param valueSize is the size in bytes of each value (pixel) put into the
1810 _swrast_get_values(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1811 GLuint count
, const GLint x
[], const GLint y
[],
1812 void *values
, GLuint valueSize
)
1814 GLuint i
, inCount
= 0, inStart
= 0;
1816 for (i
= 0; i
< count
; i
++) {
1817 if (x
[i
] >= 0 && y
[i
] >= 0 && x
[i
] < rb
->Width
&& y
[i
] < rb
->Height
) {
1825 /* read [inStart, inStart + inCount) */
1826 rb
->GetValues(ctx
, rb
, inCount
, x
+ inStart
, y
+ inStart
,
1827 (GLubyte
*) values
+ inStart
* valueSize
);
1833 /* read last values */
1834 rb
->GetValues(ctx
, rb
, inCount
, x
+ inStart
, y
+ inStart
,
1835 (GLubyte
*) values
+ inStart
* valueSize
);
1841 * Wrapper for gl_renderbuffer::PutRow() which does clipping.
1842 * \param valueSize size of each value (pixel) in bytes
1845 _swrast_put_row(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1846 GLuint count
, GLint x
, GLint y
,
1847 const GLvoid
*values
, GLuint valueSize
)
1851 if (y
< 0 || y
>= rb
->Height
)
1852 return; /* above or below */
1854 if (x
+ (GLint
) count
<= 0 || x
>= rb
->Width
)
1855 return; /* entirely left or right */
1857 if (x
+ count
> rb
->Width
) {
1859 GLint clip
= x
+ count
- rb
->Width
;
1870 rb
->PutRow(ctx
, rb
, count
, x
, y
,
1871 (const GLubyte
*) values
+ skip
* valueSize
, NULL
);
1876 * Wrapper for gl_renderbuffer::GetRow() which does clipping.
1877 * \param valueSize size of each value (pixel) in bytes
1880 _swrast_get_row(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1881 GLuint count
, GLint x
, GLint y
,
1882 GLvoid
*values
, GLuint valueSize
)
1886 if (y
< 0 || y
>= rb
->Height
)
1887 return; /* above or below */
1889 if (x
+ (GLint
) count
<= 0 || x
>= rb
->Width
)
1890 return; /* entirely left or right */
1892 if (x
+ count
> rb
->Width
) {
1894 GLint clip
= x
+ count
- rb
->Width
;
1905 rb
->GetRow(ctx
, rb
, count
, x
, y
, (GLubyte
*) values
+ skip
* valueSize
);
1910 * Get RGBA pixels from the given renderbuffer. Put the pixel colors into
1911 * the span's specular color arrays. The specular color arrays should no
1912 * longer be needed by time this function is called.
1913 * Used by blending, logicop and masking functions.
1914 * \return pointer to the colors we read.
1917 _swrast_get_dest_rgba(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1920 const GLuint pixelSize
= RGBA_PIXEL_SIZE(span
->array
->ChanType
);
1924 * Determine pixel size (in bytes).
1925 * Point rbPixels to a temporary space (use specular color arrays).
1927 if (span
->array
->ChanType
== GL_UNSIGNED_BYTE
) {
1928 rbPixels
= span
->array
->color
.sz1
.spec
;
1930 else if (span
->array
->ChanType
== GL_UNSIGNED_SHORT
) {
1931 rbPixels
= span
->array
->color
.sz2
.spec
;
1934 rbPixels
= span
->array
->color
.sz4
.spec
;
1937 /* Get destination values from renderbuffer */
1938 if (span
->arrayMask
& SPAN_XY
) {
1939 _swrast_get_values(ctx
, rb
, span
->end
, span
->array
->x
, span
->array
->y
,
1940 rbPixels
, pixelSize
);
1943 _swrast_get_row(ctx
, rb
, span
->end
, span
->x
, span
->y
,
1944 rbPixels
, pixelSize
);