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
39 #include "s_atifragshader.h"
41 #include "s_arbshader.h"
43 #include "s_context.h"
47 #include "s_masking.h"
48 #include "s_nvfragprog.h"
50 #include "s_stencil.h"
51 #include "s_texcombine.h"
55 * Init span's Z interpolation values to the RasterPos Z.
56 * Used during setup for glDraw/CopyPixels.
59 _swrast_span_default_z( GLcontext
*ctx
, struct sw_span
*span
)
61 const GLfloat depthMax
= ctx
->DrawBuffer
->_DepthMaxF
;
62 if (ctx
->DrawBuffer
->Visual
.depthBits
<= 16)
63 span
->z
= FloatToFixed(ctx
->Current
.RasterPos
[2] * depthMax
+ 0.5F
);
65 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * depthMax
+ 0.5F
);
67 span
->interpMask
|= SPAN_Z
;
72 * Init span's fog interpolation values to the RasterPos fog.
73 * Used during setup for glDraw/CopyPixels.
76 _swrast_span_default_fog( GLcontext
*ctx
, struct sw_span
*span
)
78 span
->fog
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
79 span
->fogStep
= span
->dfogdx
= span
->dfogdy
= 0.0F
;
80 span
->interpMask
|= SPAN_FOG
;
85 * Init span's rgba or index interpolation values to the RasterPos color.
86 * Used during setup for glDraw/CopyPixels.
89 _swrast_span_default_color( GLcontext
*ctx
, struct sw_span
*span
)
91 if (ctx
->Visual
.rgbMode
) {
93 UNCLAMPED_FLOAT_TO_CHAN(r
, ctx
->Current
.RasterColor
[0]);
94 UNCLAMPED_FLOAT_TO_CHAN(g
, ctx
->Current
.RasterColor
[1]);
95 UNCLAMPED_FLOAT_TO_CHAN(b
, ctx
->Current
.RasterColor
[2]);
96 UNCLAMPED_FLOAT_TO_CHAN(a
, ctx
->Current
.RasterColor
[3]);
97 #if CHAN_TYPE == GL_FLOAT
103 span
->red
= IntToFixed(r
);
104 span
->green
= IntToFixed(g
);
105 span
->blue
= IntToFixed(b
);
106 span
->alpha
= IntToFixed(a
);
112 span
->interpMask
|= SPAN_RGBA
;
115 span
->index
= FloatToFixed(ctx
->Current
.RasterIndex
);
117 span
->interpMask
|= SPAN_INDEX
;
123 * Init span's texcoord interpolation values to the RasterPos texcoords.
124 * Used during setup for glDraw/CopyPixels.
127 _swrast_span_default_texcoords( GLcontext
*ctx
, struct sw_span
*span
)
130 for (i
= 0; i
< ctx
->Const
.MaxTextureCoordUnits
; i
++) {
131 const GLfloat
*tc
= ctx
->Current
.RasterTexCoords
[i
];
132 if (ctx
->FragmentProgram
._Enabled
|| ctx
->ATIFragmentShader
._Enabled
) {
133 COPY_4V(span
->tex
[i
], tc
);
135 else if (tc
[3] > 0.0F
) {
136 /* use (s/q, t/q, r/q, 1) */
137 span
->tex
[i
][0] = tc
[0] / tc
[3];
138 span
->tex
[i
][1] = tc
[1] / tc
[3];
139 span
->tex
[i
][2] = tc
[2] / tc
[3];
140 span
->tex
[i
][3] = 1.0;
143 ASSIGN_4V(span
->tex
[i
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
145 ASSIGN_4V(span
->texStepX
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
146 ASSIGN_4V(span
->texStepY
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
148 span
->interpMask
|= SPAN_TEXTURE
;
152 /* Fill in the span.color.rgba array from the interpolation values */
154 interpolate_colors(GLcontext
*ctx
, struct sw_span
*span
)
156 const GLuint n
= span
->end
;
157 GLchan (*rgba
)[4] = span
->array
->rgba
;
161 ASSERT((span
->interpMask
& SPAN_RGBA
) &&
162 !(span
->arrayMask
& SPAN_RGBA
));
164 if (span
->interpMask
& SPAN_FLAT
) {
167 color
[RCOMP
] = FixedToChan(span
->red
);
168 color
[GCOMP
] = FixedToChan(span
->green
);
169 color
[BCOMP
] = FixedToChan(span
->blue
);
170 color
[ACOMP
] = FixedToChan(span
->alpha
);
171 for (i
= 0; i
< n
; i
++) {
172 COPY_CHAN4(span
->array
->rgba
[i
], color
);
177 #if CHAN_TYPE == GL_FLOAT
178 GLfloat r
= span
->red
;
179 GLfloat g
= span
->green
;
180 GLfloat b
= span
->blue
;
181 GLfloat a
= span
->alpha
;
182 const GLfloat dr
= span
->redStep
;
183 const GLfloat dg
= span
->greenStep
;
184 const GLfloat db
= span
->blueStep
;
185 const GLfloat da
= span
->alphaStep
;
187 GLfixed r
= span
->red
;
188 GLfixed g
= span
->green
;
189 GLfixed b
= span
->blue
;
190 GLfixed a
= span
->alpha
;
191 const GLint dr
= span
->redStep
;
192 const GLint dg
= span
->greenStep
;
193 const GLint db
= span
->blueStep
;
194 const GLint da
= span
->alphaStep
;
196 for (i
= 0; i
< n
; i
++) {
197 rgba
[i
][RCOMP
] = FixedToChan(r
);
198 rgba
[i
][GCOMP
] = FixedToChan(g
);
199 rgba
[i
][BCOMP
] = FixedToChan(b
);
200 rgba
[i
][ACOMP
] = FixedToChan(a
);
207 span
->arrayMask
|= SPAN_RGBA
;
211 /* Fill in the span.color.index array from the interpolation values */
213 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
215 GLfixed index
= span
->index
;
216 const GLint indexStep
= span
->indexStep
;
217 const GLuint n
= span
->end
;
218 GLuint
*indexes
= span
->array
->index
;
221 ASSERT((span
->interpMask
& SPAN_INDEX
) &&
222 !(span
->arrayMask
& SPAN_INDEX
));
224 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
226 index
= FixedToInt(index
);
227 for (i
= 0; i
< n
; i
++) {
233 for (i
= 0; i
< n
; i
++) {
234 indexes
[i
] = FixedToInt(index
);
238 span
->arrayMask
|= SPAN_INDEX
;
239 span
->interpMask
&= ~SPAN_INDEX
;
243 /* Fill in the span.->array->spec array from the interpolation values */
245 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
248 if (span
->interpMask
& SPAN_FLAT
) {
250 const GLchan r
= FixedToChan(span
->specRed
);
251 const GLchan g
= FixedToChan(span
->specGreen
);
252 const GLchan b
= FixedToChan(span
->specBlue
);
254 for (i
= 0; i
< span
->end
; i
++) {
255 span
->array
->spec
[i
][RCOMP
] = r
;
256 span
->array
->spec
[i
][GCOMP
] = g
;
257 span
->array
->spec
[i
][BCOMP
] = b
;
262 #if CHAN_TYPE == GL_FLOAT
263 GLfloat r
= span
->specRed
;
264 GLfloat g
= span
->specGreen
;
265 GLfloat b
= span
->specBlue
;
267 GLfixed r
= span
->specRed
;
268 GLfixed g
= span
->specGreen
;
269 GLfixed b
= span
->specBlue
;
272 for (i
= 0; i
< span
->end
; i
++) {
273 span
->array
->spec
[i
][RCOMP
] = FixedToChan(r
);
274 span
->array
->spec
[i
][GCOMP
] = FixedToChan(g
);
275 span
->array
->spec
[i
][BCOMP
] = FixedToChan(b
);
276 r
+= span
->specRedStep
;
277 g
+= span
->specGreenStep
;
278 b
+= span
->specBlueStep
;
281 span
->arrayMask
|= SPAN_SPEC
;
285 /* Fill in the span.array.fog values from the interpolation values */
287 interpolate_fog(const GLcontext
*ctx
, struct sw_span
*span
)
289 GLfloat
*fog
= span
->array
->fog
;
290 const GLfloat fogStep
= span
->fogStep
;
291 GLfloat fogCoord
= span
->fog
;
292 const GLuint haveW
= (span
->interpMask
& SPAN_W
);
293 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
294 GLfloat w
= haveW
? span
->w
: 1.0F
;
296 for (i
= 0; i
< span
->end
; i
++) {
297 fog
[i
] = fogCoord
/ w
;
301 span
->arrayMask
|= SPAN_FOG
;
305 /* Fill in the span.zArray array from the interpolation values */
307 _swrast_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
309 const GLuint n
= span
->end
;
312 ASSERT((span
->interpMask
& SPAN_Z
) &&
313 !(span
->arrayMask
& SPAN_Z
));
315 if (ctx
->DrawBuffer
->Visual
.depthBits
<= 16) {
316 GLfixed zval
= span
->z
;
317 GLuint
*z
= span
->array
->z
;
318 for (i
= 0; i
< n
; i
++) {
319 z
[i
] = FixedToInt(zval
);
324 /* Deep Z buffer, no fixed->int shift */
325 GLuint zval
= span
->z
;
326 GLuint
*z
= span
->array
->z
;
327 for (i
= 0; i
< n
; i
++) {
332 span
->interpMask
&= ~SPAN_Z
;
333 span
->arrayMask
|= SPAN_Z
;
338 * This the ideal solution, as given in the OpenGL spec.
342 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
343 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
344 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
346 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
347 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
348 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
349 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
350 GLfloat x
= SQRTF(dudx
* dudx
+ dvdx
* dvdx
);
351 GLfloat y
= SQRTF(dudy
* dudy
+ dvdy
* dvdy
);
352 GLfloat rho
= MAX2(x
, y
);
353 GLfloat lambda
= LOG2(rho
);
360 * This is a faster approximation
363 _swrast_compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
364 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
365 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
367 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
368 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
369 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
370 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
371 GLfloat maxU
, maxV
, rho
, lambda
;
372 dsdx2
= FABSF(dsdx2
);
373 dsdy2
= FABSF(dsdy2
);
374 dtdx2
= FABSF(dtdx2
);
375 dtdy2
= FABSF(dtdy2
);
376 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
377 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
378 rho
= MAX2(maxU
, maxV
);
385 * Fill in the span.texcoords array from the interpolation values.
386 * Note: in the places where we divide by Q (or mult by invQ) we're
387 * really doing two things: perspective correction and texcoord
388 * projection. Remember, for texcoord (s,t,r,q) we need to index
389 * texels with (s/q, t/q, r/q).
390 * If we're using a fragment program, we never do the division
391 * for texcoord projection. That's done by the TXP instruction
392 * or user-written code.
395 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
397 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
398 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
400 if (ctx
->Texture
._EnabledCoordUnits
> 1) {
403 span
->arrayMask
|= SPAN_TEXTURE
;
404 /* XXX CoordUnits vs. ImageUnits */
405 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
406 if (ctx
->Texture
._EnabledCoordUnits
& (1 << u
)) {
407 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
409 GLboolean needLambda
;
411 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
412 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
413 || ctx
->FragmentProgram
._Enabled
;
414 texW
= img
->WidthScale
;
415 texH
= img
->HeightScale
;
418 /* using a fragment program */
421 needLambda
= GL_FALSE
;
424 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
425 GLfloat
*lambda
= span
->array
->lambda
[u
];
426 const GLfloat dsdx
= span
->texStepX
[u
][0];
427 const GLfloat dsdy
= span
->texStepY
[u
][0];
428 const GLfloat dtdx
= span
->texStepX
[u
][1];
429 const GLfloat dtdy
= span
->texStepY
[u
][1];
430 const GLfloat drdx
= span
->texStepX
[u
][2];
431 const GLfloat dqdx
= span
->texStepX
[u
][3];
432 const GLfloat dqdy
= span
->texStepY
[u
][3];
433 GLfloat s
= span
->tex
[u
][0];
434 GLfloat t
= span
->tex
[u
][1];
435 GLfloat r
= span
->tex
[u
][2];
436 GLfloat q
= span
->tex
[u
][3];
438 if (ctx
->FragmentProgram
._Enabled
|| ctx
->ATIFragmentShader
._Enabled
||
439 ctx
->ShaderObjects
._FragmentShaderPresent
) {
440 /* do perspective correction but don't divide s, t, r by q */
441 const GLfloat dwdx
= span
->dwdx
;
443 for (i
= 0; i
< span
->end
; i
++) {
444 const GLfloat invW
= 1.0F
/ w
;
445 texcoord
[i
][0] = s
* invW
;
446 texcoord
[i
][1] = t
* invW
;
447 texcoord
[i
][2] = r
* invW
;
448 texcoord
[i
][3] = q
* invW
;
449 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
450 dqdx
, dqdy
, texW
, texH
,
461 for (i
= 0; i
< span
->end
; i
++) {
462 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
463 texcoord
[i
][0] = s
* invQ
;
464 texcoord
[i
][1] = t
* invQ
;
465 texcoord
[i
][2] = r
* invQ
;
467 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
468 dqdx
, dqdy
, texW
, texH
,
476 span
->arrayMask
|= SPAN_LAMBDA
;
479 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
480 GLfloat
*lambda
= span
->array
->lambda
[u
];
481 const GLfloat dsdx
= span
->texStepX
[u
][0];
482 const GLfloat dtdx
= span
->texStepX
[u
][1];
483 const GLfloat drdx
= span
->texStepX
[u
][2];
484 const GLfloat dqdx
= span
->texStepX
[u
][3];
485 GLfloat s
= span
->tex
[u
][0];
486 GLfloat t
= span
->tex
[u
][1];
487 GLfloat r
= span
->tex
[u
][2];
488 GLfloat q
= span
->tex
[u
][3];
490 if (ctx
->FragmentProgram
._Enabled
|| ctx
->ATIFragmentShader
._Enabled
||
491 ctx
->ShaderObjects
._FragmentShaderPresent
) {
492 /* do perspective correction but don't divide s, t, r by q */
493 const GLfloat dwdx
= span
->dwdx
;
495 for (i
= 0; i
< span
->end
; i
++) {
496 const GLfloat invW
= 1.0F
/ w
;
497 texcoord
[i
][0] = s
* invW
;
498 texcoord
[i
][1] = t
* invW
;
499 texcoord
[i
][2] = r
* invW
;
500 texcoord
[i
][3] = q
* invW
;
509 else if (dqdx
== 0.0F
) {
510 /* Ortho projection or polygon's parallel to window X axis */
511 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
512 for (i
= 0; i
< span
->end
; i
++) {
513 texcoord
[i
][0] = s
* invQ
;
514 texcoord
[i
][1] = t
* invQ
;
515 texcoord
[i
][2] = r
* invQ
;
524 for (i
= 0; i
< span
->end
; i
++) {
525 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
526 texcoord
[i
][0] = s
* invQ
;
527 texcoord
[i
][1] = t
* invQ
;
528 texcoord
[i
][2] = r
* invQ
;
543 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
545 GLboolean needLambda
;
547 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
548 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
549 || ctx
->FragmentProgram
._Enabled
;
550 texW
= (GLfloat
) img
->WidthScale
;
551 texH
= (GLfloat
) img
->HeightScale
;
554 needLambda
= GL_FALSE
;
557 span
->arrayMask
|= SPAN_TEXTURE
;
559 /* just texture unit 0, with lambda */
560 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
561 GLfloat
*lambda
= span
->array
->lambda
[0];
562 const GLfloat dsdx
= span
->texStepX
[0][0];
563 const GLfloat dsdy
= span
->texStepY
[0][0];
564 const GLfloat dtdx
= span
->texStepX
[0][1];
565 const GLfloat dtdy
= span
->texStepY
[0][1];
566 const GLfloat drdx
= span
->texStepX
[0][2];
567 const GLfloat dqdx
= span
->texStepX
[0][3];
568 const GLfloat dqdy
= span
->texStepY
[0][3];
569 GLfloat s
= span
->tex
[0][0];
570 GLfloat t
= span
->tex
[0][1];
571 GLfloat r
= span
->tex
[0][2];
572 GLfloat q
= span
->tex
[0][3];
574 if (ctx
->FragmentProgram
._Enabled
|| ctx
->ATIFragmentShader
._Enabled
||
575 ctx
->ShaderObjects
._FragmentShaderPresent
) {
576 /* do perspective correction but don't divide s, t, r by q */
577 const GLfloat dwdx
= span
->dwdx
;
579 for (i
= 0; i
< span
->end
; i
++) {
580 const GLfloat invW
= 1.0F
/ w
;
581 texcoord
[i
][0] = s
* invW
;
582 texcoord
[i
][1] = t
* invW
;
583 texcoord
[i
][2] = r
* invW
;
584 texcoord
[i
][3] = q
* invW
;
585 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
586 dqdx
, dqdy
, texW
, texH
,
597 for (i
= 0; i
< span
->end
; i
++) {
598 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
599 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
600 dqdx
, dqdy
, texW
, texH
,
602 texcoord
[i
][0] = s
* invQ
;
603 texcoord
[i
][1] = t
* invQ
;
604 texcoord
[i
][2] = r
* invQ
;
612 span
->arrayMask
|= SPAN_LAMBDA
;
615 /* just texture 0, without lambda */
616 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
617 const GLfloat dsdx
= span
->texStepX
[0][0];
618 const GLfloat dtdx
= span
->texStepX
[0][1];
619 const GLfloat drdx
= span
->texStepX
[0][2];
620 const GLfloat dqdx
= span
->texStepX
[0][3];
621 GLfloat s
= span
->tex
[0][0];
622 GLfloat t
= span
->tex
[0][1];
623 GLfloat r
= span
->tex
[0][2];
624 GLfloat q
= span
->tex
[0][3];
626 if (ctx
->FragmentProgram
._Enabled
|| ctx
->ATIFragmentShader
._Enabled
||
627 ctx
->ShaderObjects
._FragmentShaderPresent
) {
628 /* do perspective correction but don't divide s, t, r by q */
629 const GLfloat dwdx
= span
->dwdx
;
631 for (i
= 0; i
< span
->end
; i
++) {
632 const GLfloat invW
= 1.0F
/ w
;
633 texcoord
[i
][0] = s
* invW
;
634 texcoord
[i
][1] = t
* invW
;
635 texcoord
[i
][2] = r
* invW
;
636 texcoord
[i
][3] = q
* invW
;
644 else if (dqdx
== 0.0F
) {
645 /* Ortho projection or polygon's parallel to window X axis */
646 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
647 for (i
= 0; i
< span
->end
; i
++) {
648 texcoord
[i
][0] = s
* invQ
;
649 texcoord
[i
][1] = t
* invQ
;
650 texcoord
[i
][2] = r
* invQ
;
658 for (i
= 0; i
< span
->end
; i
++) {
659 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
660 texcoord
[i
][0] = s
* invQ
;
661 texcoord
[i
][1] = t
* invQ
;
662 texcoord
[i
][2] = r
* invQ
;
676 * Fill in the span.varying array from the interpolation values.
679 interpolate_varying(GLcontext
*ctx
, struct sw_span
*span
)
683 ASSERT(span
->interpMask
& SPAN_VARYING
);
684 ASSERT(!(span
->arrayMask
& SPAN_VARYING
));
686 span
->arrayMask
|= SPAN_VARYING
;
688 for (i
= 0; i
< MAX_VARYING_VECTORS
; i
++) {
689 for (j
= 0; j
< VARYINGS_PER_VECTOR
; j
++) {
690 const GLfloat dvdx
= span
->varStepX
[i
][j
];
691 GLfloat v
= span
->var
[i
][j
];
692 const GLfloat dwdx
= span
->dwdx
;
696 for (k
= 0; k
< span
->end
; k
++) {
697 GLfloat invW
= 1.0f
/ w
;
698 span
->array
->varying
[k
][i
][j
] = v
* invW
;
708 * Apply the current polygon stipple pattern to a span of pixels.
711 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
713 const GLuint highbit
= 0x80000000;
714 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
715 GLubyte
*mask
= span
->array
->mask
;
718 ASSERT(ctx
->Polygon
.StippleFlag
);
719 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
721 m
= highbit
>> (GLuint
) (span
->x
% 32);
723 for (i
= 0; i
< span
->end
; i
++) {
724 if ((m
& stipple
) == 0) {
732 span
->writeAll
= GL_FALSE
;
737 * Clip a pixel span to the current buffer/window boundaries:
738 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
739 * window clipping and scissoring.
740 * Return: GL_TRUE some pixels still visible
741 * GL_FALSE nothing visible
744 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
746 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
747 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
748 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
749 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
751 if (span
->arrayMask
& SPAN_XY
) {
752 /* arrays of x/y pixel coords */
753 const GLint
*x
= span
->array
->x
;
754 const GLint
*y
= span
->array
->y
;
755 const GLint n
= span
->end
;
756 GLubyte
*mask
= span
->array
->mask
;
758 if (span
->arrayMask
& SPAN_MASK
) {
759 /* note: using & intead of && to reduce branches */
760 for (i
= 0; i
< n
; i
++) {
761 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
762 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
766 /* note: using & intead of && to reduce branches */
767 for (i
= 0; i
< n
; i
++) {
768 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
769 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
772 return GL_TRUE
; /* some pixels visible */
775 /* horizontal span of pixels */
776 const GLint x
= span
->x
;
777 const GLint y
= span
->y
;
778 const GLint n
= span
->end
;
780 /* Trivial rejection tests */
781 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
783 return GL_FALSE
; /* all pixels clipped */
786 /* Clip to the left */
788 ASSERT(x
+ n
> xmin
);
789 span
->writeAll
= GL_FALSE
;
790 _mesa_bzero(span
->array
->mask
, (xmin
- x
) * sizeof(GLubyte
));
796 span
->end
= xmax
- x
;
799 return GL_TRUE
; /* some pixels visible */
805 * Apply all the per-fragment opertions to a span of color index fragments
806 * and write them to the enabled color drawbuffers.
807 * The 'span' parameter can be considered to be const. Note that
808 * span->interpMask and span->arrayMask may be changed but will be restored
809 * to their original values before returning.
812 _swrast_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
814 const SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
815 const GLbitfield origInterpMask
= span
->interpMask
;
816 const GLbitfield origArrayMask
= span
->arrayMask
;
818 ASSERT(span
->end
<= MAX_WIDTH
);
819 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
820 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
821 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
822 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
824 if (span
->arrayMask
& SPAN_MASK
) {
825 /* mask was initialized by caller, probably glBitmap */
826 span
->writeAll
= GL_FALSE
;
829 _mesa_memset(span
->array
->mask
, 1, span
->end
);
830 span
->writeAll
= GL_TRUE
;
834 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
835 if (!clip_span(ctx
, span
)) {
840 /* Depth bounds test */
841 if (ctx
->Depth
.BoundsTest
&& ctx
->DrawBuffer
->Visual
.depthBits
> 0) {
842 if (!_swrast_depth_bounds_test(ctx
, span
)) {
848 /* Make sure all fragments are within window bounds */
849 if (span
->arrayMask
& SPAN_XY
) {
851 for (i
= 0; i
< span
->end
; i
++) {
852 if (span
->array
->mask
[i
]) {
853 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
854 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
855 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
856 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
862 /* Polygon Stippling */
863 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
864 stipple_polygon_span(ctx
, span
);
867 /* Stencil and Z testing */
868 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
869 if (span
->interpMask
& SPAN_Z
)
870 _swrast_span_interpolate_z(ctx
, span
);
872 if (ctx
->Stencil
.Enabled
) {
873 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
874 span
->arrayMask
= origArrayMask
;
879 ASSERT(ctx
->Depth
.Test
);
880 if (!_swrast_depth_test_span(ctx
, span
)) {
881 span
->interpMask
= origInterpMask
;
882 span
->arrayMask
= origArrayMask
;
888 #if FEATURE_ARB_occlusion_query
889 if (ctx
->Query
.CurrentOcclusionObject
) {
890 /* update count of 'passed' fragments */
891 struct gl_query_object
*q
= ctx
->Query
.CurrentOcclusionObject
;
893 for (i
= 0; i
< span
->end
; i
++)
894 q
->Result
+= span
->array
->mask
[i
];
898 /* we have to wait until after occlusion to do this test */
899 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
900 /* write no pixels */
901 span
->arrayMask
= origArrayMask
;
905 /* Interpolate the color indexes if needed */
906 if (swrast
->_FogEnabled
||
907 ctx
->Color
.IndexLogicOpEnabled
||
908 ctx
->Color
.IndexMask
!= 0xffffffff ||
909 (span
->arrayMask
& SPAN_COVERAGE
)) {
910 if (span
->interpMask
& SPAN_INDEX
) {
911 interpolate_indexes(ctx
, span
);
916 if (swrast
->_FogEnabled
) {
917 _swrast_fog_ci_span(ctx
, span
);
920 /* Antialias coverage application */
921 if (span
->arrayMask
& SPAN_COVERAGE
) {
922 const GLfloat
*coverage
= span
->array
->coverage
;
923 GLuint
*index
= span
->array
->index
;
925 for (i
= 0; i
< span
->end
; i
++) {
926 ASSERT(coverage
[i
] < 16);
927 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) coverage
[i
]);
932 * Write to renderbuffers
935 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
936 const GLuint output
= 0; /* only frag progs can write to others */
937 const GLuint numDrawBuffers
= fb
->_NumColorDrawBuffers
[output
];
938 GLuint indexSave
[MAX_WIDTH
];
941 if (numDrawBuffers
> 1) {
942 /* save indexes for second, third renderbuffer writes */
943 _mesa_memcpy(indexSave
, span
->array
->index
,
944 span
->end
* sizeof(indexSave
[0]));
947 for (buf
= 0; buf
< fb
->_NumColorDrawBuffers
[output
]; buf
++) {
948 struct gl_renderbuffer
*rb
= fb
->_ColorDrawBuffers
[output
][buf
];
949 ASSERT(rb
->_BaseFormat
== GL_COLOR_INDEX
);
951 if (ctx
->Color
.IndexLogicOpEnabled
) {
952 _swrast_logicop_ci_span(ctx
, rb
, span
, span
->array
->index
);
955 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
956 _swrast_mask_ci_span(ctx
, rb
, span
, span
->array
->index
);
959 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
960 /* all fragments have same color index */
966 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
967 index8
= FixedToInt(span
->index
);
970 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
971 index16
= FixedToInt(span
->index
);
975 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
);
976 index32
= FixedToInt(span
->index
);
980 if (span
->arrayMask
& SPAN_XY
) {
981 rb
->PutMonoValues(ctx
, rb
, span
->end
, span
->array
->x
,
982 span
->array
->y
, value
, span
->array
->mask
);
985 rb
->PutMonoRow(ctx
, rb
, span
->end
, span
->x
, span
->y
,
986 value
, span
->array
->mask
);
990 /* each fragment is a different color */
991 GLubyte index8
[MAX_WIDTH
];
992 GLushort index16
[MAX_WIDTH
];
995 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
997 for (k
= 0; k
< span
->end
; k
++) {
998 index8
[k
] = (GLubyte
) span
->array
->index
[k
];
1002 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
1004 for (k
= 0; k
< span
->end
; k
++) {
1005 index16
[k
] = (GLushort
) span
->array
->index
[k
];
1010 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
);
1011 values
= span
->array
->index
;
1014 if (span
->arrayMask
& SPAN_XY
) {
1015 rb
->PutValues(ctx
, rb
, span
->end
,
1016 span
->array
->x
, span
->array
->y
,
1017 values
, span
->array
->mask
);
1020 rb
->PutRow(ctx
, rb
, span
->end
, span
->x
, span
->y
,
1021 values
, span
->array
->mask
);
1025 if (buf
+ 1 < numDrawBuffers
) {
1026 /* restore original span values */
1027 _mesa_memcpy(span
->array
->index
, indexSave
,
1028 span
->end
* sizeof(indexSave
[0]));
1033 span
->interpMask
= origInterpMask
;
1034 span
->arrayMask
= origArrayMask
;
1039 * Add specular color to base color. This is used only when
1040 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1043 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1046 for (i
= 0; i
< n
; i
++) {
1047 #if CHAN_TYPE == GL_FLOAT
1049 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1050 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1051 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1053 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1054 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1055 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1056 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1057 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1058 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1065 * Apply all the per-fragment operations to a span.
1066 * This now includes texturing (_swrast_write_texture_span() is history).
1067 * This function may modify any of the array values in the span.
1068 * span->interpMask and span->arrayMask may be changed but will be restored
1069 * to their original values before returning.
1072 _swrast_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
1074 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1075 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1076 const GLbitfield origInterpMask
= span
->interpMask
;
1077 const GLbitfield origArrayMask
= span
->arrayMask
;
1078 const GLboolean deferredTexture
= !(ctx
->Color
.AlphaEnabled
||
1079 ctx
->FragmentProgram
._Enabled
||
1080 ctx
->ShaderObjects
._FragmentShaderPresent
);
1082 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1083 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1084 ASSERT(span
->end
<= MAX_WIDTH
);
1085 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1088 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__,
1089 span->interpMask, span->arrayMask);
1092 if (span
->arrayMask
& SPAN_MASK
) {
1093 /* mask was initialized by caller, probably glBitmap */
1094 span
->writeAll
= GL_FALSE
;
1097 _mesa_memset(span
->array
->mask
, 1, span
->end
);
1098 span
->writeAll
= GL_TRUE
;
1101 /* Clip to window/scissor box */
1102 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1103 if (!clip_span(ctx
, span
)) {
1109 /* Make sure all fragments are within window bounds */
1110 if (span
->arrayMask
& SPAN_XY
) {
1112 for (i
= 0; i
< span
->end
; i
++) {
1113 if (span
->array
->mask
[i
]) {
1114 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1115 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1116 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1117 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1123 /* Polygon Stippling */
1124 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1125 stipple_polygon_span(ctx
, span
);
1128 /* Interpolate texcoords? */
1129 if (ctx
->Texture
._EnabledCoordUnits
1130 && (span
->interpMask
& SPAN_TEXTURE
)
1131 && (span
->arrayMask
& SPAN_TEXTURE
) == 0) {
1132 interpolate_texcoords(ctx
, span
);
1135 if (ctx
->ShaderObjects
._FragmentShaderPresent
) {
1136 interpolate_varying(ctx
, span
);
1139 /* This is the normal place to compute the resulting fragment color/Z.
1140 * As an optimization, we try to defer this until after Z/stencil
1141 * testing in order to try to avoid computing colors that we won't
1144 if (!deferredTexture
) {
1145 /* Now we need the rgba array, fill it in if needed */
1146 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1147 interpolate_colors(ctx
, span
);
1149 if (span
->interpMask
& SPAN_SPEC
)
1150 interpolate_specular(ctx
, span
);
1152 if (span
->interpMask
& SPAN_FOG
)
1153 interpolate_fog(ctx
, span
);
1155 /* Compute fragment colors with fragment program or texture lookups */
1156 #if FEATURE_ARB_fragment_shader
1157 if (ctx
->ShaderObjects
._FragmentShaderPresent
) {
1158 if (span
->interpMask
& SPAN_Z
)
1159 _swrast_span_interpolate_z (ctx
, span
);
1160 _swrast_exec_arbshader (ctx
, span
);
1164 if (ctx
->FragmentProgram
._Enabled
) {
1165 /* frag prog may need Z values */
1166 if (span
->interpMask
& SPAN_Z
)
1167 _swrast_span_interpolate_z(ctx
, span
);
1168 _swrast_exec_fragment_program( ctx
, span
);
1170 else if (ctx
->ATIFragmentShader
._Enabled
)
1171 _swrast_exec_fragment_shader( ctx
, span
);
1172 else if (ctx
->Texture
._EnabledUnits
&& (span
->arrayMask
& SPAN_TEXTURE
))
1173 _swrast_texture_span( ctx
, span
);
1175 /* Do the alpha test */
1176 if (ctx
->Color
.AlphaEnabled
) {
1177 if (!_swrast_alpha_test(ctx
, span
)) {
1178 span
->arrayMask
= origArrayMask
;
1184 /* Stencil and Z testing */
1185 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1186 if (span
->interpMask
& SPAN_Z
)
1187 _swrast_span_interpolate_z(ctx
, span
);
1189 if (ctx
->Stencil
.Enabled
&& ctx
->DrawBuffer
->Visual
.stencilBits
> 0) {
1190 /* Combined Z/stencil tests */
1191 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1192 span
->interpMask
= origInterpMask
;
1193 span
->arrayMask
= origArrayMask
;
1197 else if (ctx
->DrawBuffer
->Visual
.depthBits
> 0) {
1198 /* Just regular depth testing */
1199 ASSERT(ctx
->Depth
.Test
);
1200 ASSERT(span
->arrayMask
& SPAN_Z
);
1201 if (!_swrast_depth_test_span(ctx
, span
)) {
1202 span
->interpMask
= origInterpMask
;
1203 span
->arrayMask
= origArrayMask
;
1209 #if FEATURE_ARB_occlusion_query
1210 if (ctx
->Query
.CurrentOcclusionObject
) {
1211 /* update count of 'passed' fragments */
1212 struct gl_query_object
*q
= ctx
->Query
.CurrentOcclusionObject
;
1214 for (i
= 0; i
< span
->end
; i
++)
1215 q
->Result
+= span
->array
->mask
[i
];
1219 /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1220 * the occlusion test.
1222 if (colorMask
== 0x0) {
1223 span
->interpMask
= origInterpMask
;
1224 span
->arrayMask
= origArrayMask
;
1228 /* If we were able to defer fragment color computation to now, there's
1229 * a good chance that many fragments will have already been killed by
1230 * Z/stencil testing.
1232 if (deferredTexture
) {
1233 /* Now we need the rgba array, fill it in if needed */
1234 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1235 interpolate_colors(ctx
, span
);
1237 if (span
->interpMask
& SPAN_SPEC
)
1238 interpolate_specular(ctx
, span
);
1240 if (span
->interpMask
& SPAN_FOG
)
1241 interpolate_fog(ctx
, span
);
1243 #if FEATURE_ARB_fragment_shader
1244 if (ctx
->ShaderObjects
._FragmentShaderPresent
) {
1245 if (span
->interpMask
& SPAN_Z
)
1246 _swrast_span_interpolate_z (ctx
, span
);
1247 _swrast_exec_arbshader (ctx
, span
);
1251 if (ctx
->FragmentProgram
._Enabled
)
1252 _swrast_exec_fragment_program( ctx
, span
);
1253 else if (ctx
->ATIFragmentShader
._Enabled
)
1254 _swrast_exec_fragment_shader( ctx
, span
);
1255 else if (ctx
->Texture
._EnabledUnits
&& (span
->arrayMask
& SPAN_TEXTURE
))
1256 _swrast_texture_span( ctx
, span
);
1259 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1261 if (!ctx
->FragmentProgram
._Enabled
) {
1262 /* Add base and specular colors */
1263 if (ctx
->Fog
.ColorSumEnabled
||
1264 (ctx
->Light
.Enabled
&&
1265 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1266 if (span
->interpMask
& SPAN_SPEC
) {
1267 interpolate_specular(ctx
, span
);
1269 if (span
->arrayMask
& SPAN_SPEC
) {
1270 add_colors( span
->end
, span
->array
->rgba
, span
->array
->spec
);
1273 /* We probably added the base/specular colors during the
1281 if (swrast
->_FogEnabled
) {
1282 _swrast_fog_rgba_span(ctx
, span
);
1285 /* Antialias coverage application */
1286 if (span
->arrayMask
& SPAN_COVERAGE
) {
1287 GLchan (*rgba
)[4] = span
->array
->rgba
;
1288 GLfloat
*coverage
= span
->array
->coverage
;
1290 for (i
= 0; i
< span
->end
; i
++) {
1291 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1295 /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
1296 #if CHAN_TYPE == GL_FLOAT
1297 if (ctx
->Color
.ClampFragmentColor
) {
1298 GLchan (*rgba
)[4] = span
->array
->rgba
;
1300 for (i
= 0; i
< span
->end
; i
++) {
1301 rgba
[i
][RCOMP
] = CLAMP(rgba
[i
][RCOMP
], 0.0, CHAN_MAXF
);
1302 rgba
[i
][GCOMP
] = CLAMP(rgba
[i
][GCOMP
], 0.0, CHAN_MAXF
);
1303 rgba
[i
][BCOMP
] = CLAMP(rgba
[i
][BCOMP
], 0.0, CHAN_MAXF
);
1304 rgba
[i
][ACOMP
] = CLAMP(rgba
[i
][ACOMP
], 0.0, CHAN_MAXF
);
1310 * Write to renderbuffers
1313 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1314 const GLuint output
= 0; /* only frag progs can write to others */
1315 const GLuint numDrawBuffers
= fb
->_NumColorDrawBuffers
[output
];
1316 GLchan rgbaSave
[MAX_WIDTH
][4];
1319 if (numDrawBuffers
> 1) {
1320 /* save colors for second, third renderbuffer writes */
1321 _mesa_memcpy(rgbaSave
, span
->array
->rgba
,
1322 4 * span
->end
* sizeof(GLchan
));
1325 for (buf
= 0; buf
< numDrawBuffers
; buf
++) {
1326 struct gl_renderbuffer
*rb
= fb
->_ColorDrawBuffers
[output
][buf
];
1327 ASSERT(rb
->_BaseFormat
== GL_RGBA
);
1329 if (ctx
->Color
._LogicOpEnabled
) {
1330 _swrast_logicop_rgba_span(ctx
, rb
, span
, span
->array
->rgba
);
1332 else if (ctx
->Color
.BlendEnabled
) {
1333 _swrast_blend_span(ctx
, rb
, span
, span
->array
->rgba
);
1336 if (colorMask
!= 0xffffffff) {
1337 _swrast_mask_rgba_span(ctx
, rb
, span
, span
->array
->rgba
);
1340 if (span
->arrayMask
& SPAN_XY
) {
1341 /* array of pixel coords */
1342 ASSERT(rb
->PutValues
);
1343 ASSERT(rb
->_BaseFormat
== GL_RGB
|| rb
->_BaseFormat
== GL_RGBA
);
1344 rb
->PutValues(ctx
, rb
, span
->end
,
1345 span
->array
->x
, span
->array
->y
,
1346 span
->array
->rgba
, span
->array
->mask
);
1349 /* horizontal run of pixels */
1351 ASSERT(rb
->_BaseFormat
== GL_RGB
|| rb
->_BaseFormat
== GL_RGBA
);
1352 rb
->PutRow(ctx
, rb
, span
->end
, span
->x
, span
->y
, span
->array
->rgba
,
1353 span
->writeAll
? NULL
: span
->array
->mask
);
1356 if (buf
+ 1 < numDrawBuffers
) {
1357 /* restore original span values */
1358 _mesa_memcpy(span
->array
->rgba
, rgbaSave
,
1359 4 * span
->end
* sizeof(GLchan
));
1364 span
->interpMask
= origInterpMask
;
1365 span
->arrayMask
= origArrayMask
;
1371 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1372 * reading ouside the buffer's boundaries.
1375 _swrast_read_rgba_span( GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1376 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1378 const GLint bufWidth
= (GLint
) rb
->Width
;
1379 const GLint bufHeight
= (GLint
) rb
->Height
;
1381 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1382 /* completely above, below, or right */
1383 /* XXX maybe leave rgba values undefined? */
1384 _mesa_bzero(rgba
, 4 * n
* sizeof(GLchan
));
1389 /* left edge clipping */
1391 length
= (GLint
) n
- skip
;
1393 /* completely left of window */
1396 if (length
> bufWidth
) {
1400 else if ((GLint
) (x
+ n
) > bufWidth
) {
1401 /* right edge clipping */
1403 length
= bufWidth
- x
;
1405 /* completely to right of window */
1417 ASSERT(rb
->_BaseFormat
== GL_RGB
|| rb
->_BaseFormat
== GL_RGBA
);
1418 ASSERT(rb
->DataType
== CHAN_TYPE
);
1419 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
, rgba
+ skip
);
1425 * Read CI pixels from frame buffer. Clipping will be done to prevent
1426 * reading ouside the buffer's boundaries.
1429 _swrast_read_index_span( GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1430 GLuint n
, GLint x
, GLint y
, GLuint index
[] )
1432 const GLint bufWidth
= (GLint
) rb
->Width
;
1433 const GLint bufHeight
= (GLint
) rb
->Height
;
1435 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1436 /* completely above, below, or right */
1437 _mesa_bzero(index
, n
* sizeof(GLuint
));
1442 /* left edge clipping */
1444 length
= (GLint
) n
- skip
;
1446 /* completely left of window */
1449 if (length
> bufWidth
) {
1453 else if ((GLint
) (x
+ n
) > bufWidth
) {
1454 /* right edge clipping */
1456 length
= bufWidth
- x
;
1458 /* completely to right of window */
1469 ASSERT(rb
->_BaseFormat
== GL_COLOR_INDEX
);
1471 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1472 GLubyte index8
[MAX_WIDTH
];
1474 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
, index8
);
1475 for (i
= 0; i
< length
; i
++)
1476 index
[skip
+ i
] = index8
[i
];
1478 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
1479 GLushort index16
[MAX_WIDTH
];
1481 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
, index16
);
1482 for (i
= 0; i
< length
; i
++)
1483 index
[skip
+ i
] = index16
[i
];
1485 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
1486 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
, index
+ skip
);
1493 * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
1494 * reading values outside the buffer bounds.
1495 * We can use this for reading any format/type of renderbuffer.
1496 * \param valueSize is the size in bytes of each value (pixel) put into the
1500 _swrast_get_values(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1501 GLuint count
, const GLint x
[], const GLint y
[],
1502 void *values
, GLuint valueSize
)
1504 GLuint i
, inCount
= 0, inStart
= 0;
1506 for (i
= 0; i
< count
; i
++) {
1507 if (x
[i
] >= 0 && y
[i
] >= 0 && x
[i
] < rb
->Width
&& y
[i
] < rb
->Height
) {
1515 /* read [inStart, inStart + inCount) */
1516 rb
->GetValues(ctx
, rb
, inCount
, x
+ inStart
, y
+ inStart
,
1517 (GLubyte
*) values
+ inStart
* valueSize
);
1523 /* read last values */
1524 rb
->GetValues(ctx
, rb
, inCount
, x
+ inStart
, y
+ inStart
,
1525 (GLubyte
*) values
+ inStart
* valueSize
);
1531 * Wrapper for gl_renderbuffer::PutRow() which does clipping.
1534 _swrast_put_row(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1535 GLuint count
, GLint x
, GLint y
,
1536 const GLvoid
*values
, GLuint valueSize
)
1540 if (y
< 0 || y
>= rb
->Height
)
1541 return; /* above or below */
1543 if (x
+ (GLint
) count
<= 0 || x
>= rb
->Width
)
1544 return; /* entirely left or right */
1546 if (x
+ count
> rb
->Width
) {
1548 GLint clip
= x
+ count
- rb
->Width
;
1559 rb
->PutRow(ctx
, rb
, count
, x
, y
,
1560 (const GLubyte
*) values
+ skip
* valueSize
, NULL
);
1565 * Wrapper for gl_renderbuffer::GetRow() which does clipping.
1568 _swrast_get_row(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1569 GLuint count
, GLint x
, GLint y
,
1570 GLvoid
*values
, GLuint valueSize
)
1574 if (y
< 0 || y
>= rb
->Height
)
1575 return; /* above or below */
1577 if (x
+ (GLint
) count
<= 0 || x
>= rb
->Width
)
1578 return; /* entirely left or right */
1580 if (x
+ count
> rb
->Width
) {
1582 GLint clip
= x
+ count
- rb
->Width
;
1593 rb
->GetRow(ctx
, rb
, count
, x
, y
, (GLubyte
*) values
+ skip
* valueSize
);