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
39 #include "s_atifragshader.h"
41 #include "s_alphabuf.h"
43 #include "s_context.h"
47 #include "s_masking.h"
48 #include "s_nvfragprog.h"
50 #include "s_stencil.h"
51 #include "s_texture.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 if (ctx
->Visual
.depthBits
<= 16)
62 span
->z
= FloatToFixed(ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
+ 0.5F
);
64 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
+ 0.5F
);
66 span
->interpMask
|= SPAN_Z
;
71 * Init span's fog interpolation values to the RasterPos fog.
72 * Used during setup for glDraw/CopyPixels.
75 _swrast_span_default_fog( GLcontext
*ctx
, struct sw_span
*span
)
77 span
->fog
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
78 span
->fogStep
= span
->dfogdx
= span
->dfogdy
= 0.0F
;
79 span
->interpMask
|= SPAN_FOG
;
84 * Init span's rgba or index interpolation values to the RasterPos color.
85 * Used during setup for glDraw/CopyPixels.
88 _swrast_span_default_color( GLcontext
*ctx
, struct sw_span
*span
)
90 if (ctx
->Visual
.rgbMode
) {
92 UNCLAMPED_FLOAT_TO_CHAN(r
, ctx
->Current
.RasterColor
[0]);
93 UNCLAMPED_FLOAT_TO_CHAN(g
, ctx
->Current
.RasterColor
[1]);
94 UNCLAMPED_FLOAT_TO_CHAN(b
, ctx
->Current
.RasterColor
[2]);
95 UNCLAMPED_FLOAT_TO_CHAN(a
, ctx
->Current
.RasterColor
[3]);
96 #if CHAN_TYPE == GL_FLOAT
102 span
->red
= IntToFixed(r
);
103 span
->green
= IntToFixed(g
);
104 span
->blue
= IntToFixed(b
);
105 span
->alpha
= IntToFixed(a
);
111 span
->interpMask
|= SPAN_RGBA
;
114 span
->index
= FloatToFixed(ctx
->Current
.RasterIndex
);
116 span
->interpMask
|= SPAN_INDEX
;
122 * Init span's texcoord interpolation values to the RasterPos texcoords.
123 * Used during setup for glDraw/CopyPixels.
126 _swrast_span_default_texcoords( GLcontext
*ctx
, struct sw_span
*span
)
129 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
130 const GLfloat
*tc
= ctx
->Current
.RasterTexCoords
[i
];
131 if (ctx
->FragmentProgram
._Enabled
|| ctx
->ATIFragmentShader
._Enabled
) {
132 COPY_4V(span
->tex
[i
], tc
);
134 else if (tc
[3] > 0.0F
) {
135 /* use (s/q, t/q, r/q, 1) */
136 span
->tex
[i
][0] = tc
[0] / tc
[3];
137 span
->tex
[i
][1] = tc
[1] / tc
[3];
138 span
->tex
[i
][2] = tc
[2] / tc
[3];
139 span
->tex
[i
][3] = 1.0;
142 ASSIGN_4V(span
->tex
[i
], 0.0F
, 0.0F
, 0.0F
, 1.0F
);
144 ASSIGN_4V(span
->texStepX
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
145 ASSIGN_4V(span
->texStepY
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
147 span
->interpMask
|= SPAN_TEXTURE
;
151 /* Fill in the span.color.rgba array from the interpolation values */
153 interpolate_colors(GLcontext
*ctx
, struct sw_span
*span
)
155 const GLuint n
= span
->end
;
156 GLchan (*rgba
)[4] = span
->array
->rgba
;
160 ASSERT((span
->interpMask
& SPAN_RGBA
) &&
161 !(span
->arrayMask
& SPAN_RGBA
));
163 if (span
->interpMask
& SPAN_FLAT
) {
166 color
[RCOMP
] = FixedToChan(span
->red
);
167 color
[GCOMP
] = FixedToChan(span
->green
);
168 color
[BCOMP
] = FixedToChan(span
->blue
);
169 color
[ACOMP
] = FixedToChan(span
->alpha
);
170 for (i
= 0; i
< n
; i
++) {
171 COPY_CHAN4(span
->array
->rgba
[i
], color
);
176 #if CHAN_TYPE == GL_FLOAT
177 GLfloat r
= span
->red
;
178 GLfloat g
= span
->green
;
179 GLfloat b
= span
->blue
;
180 GLfloat a
= span
->alpha
;
181 const GLfloat dr
= span
->redStep
;
182 const GLfloat dg
= span
->greenStep
;
183 const GLfloat db
= span
->blueStep
;
184 const GLfloat da
= span
->alphaStep
;
186 GLfixed r
= span
->red
;
187 GLfixed g
= span
->green
;
188 GLfixed b
= span
->blue
;
189 GLfixed a
= span
->alpha
;
190 const GLint dr
= span
->redStep
;
191 const GLint dg
= span
->greenStep
;
192 const GLint db
= span
->blueStep
;
193 const GLint da
= span
->alphaStep
;
195 for (i
= 0; i
< n
; i
++) {
196 rgba
[i
][RCOMP
] = FixedToChan(r
);
197 rgba
[i
][GCOMP
] = FixedToChan(g
);
198 rgba
[i
][BCOMP
] = FixedToChan(b
);
199 rgba
[i
][ACOMP
] = FixedToChan(a
);
206 span
->arrayMask
|= SPAN_RGBA
;
210 /* Fill in the span.color.index array from the interpolation values */
212 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
214 GLfixed index
= span
->index
;
215 const GLint indexStep
= span
->indexStep
;
216 const GLuint n
= span
->end
;
217 GLuint
*indexes
= span
->array
->index
;
220 ASSERT((span
->interpMask
& SPAN_INDEX
) &&
221 !(span
->arrayMask
& SPAN_INDEX
));
223 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
225 index
= FixedToInt(index
);
226 for (i
= 0; i
< n
; i
++) {
232 for (i
= 0; i
< n
; i
++) {
233 indexes
[i
] = FixedToInt(index
);
237 span
->arrayMask
|= SPAN_INDEX
;
241 /* Fill in the span.->array->spec array from the interpolation values */
243 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
246 if (span
->interpMask
& SPAN_FLAT
) {
248 const GLchan r
= FixedToChan(span
->specRed
);
249 const GLchan g
= FixedToChan(span
->specGreen
);
250 const GLchan b
= FixedToChan(span
->specBlue
);
252 for (i
= 0; i
< span
->end
; i
++) {
253 span
->array
->spec
[i
][RCOMP
] = r
;
254 span
->array
->spec
[i
][GCOMP
] = g
;
255 span
->array
->spec
[i
][BCOMP
] = b
;
260 #if CHAN_TYPE == GL_FLOAT
261 GLfloat r
= span
->specRed
;
262 GLfloat g
= span
->specGreen
;
263 GLfloat b
= span
->specBlue
;
265 GLfixed r
= span
->specRed
;
266 GLfixed g
= span
->specGreen
;
267 GLfixed b
= span
->specBlue
;
270 for (i
= 0; i
< span
->end
; i
++) {
271 span
->array
->spec
[i
][RCOMP
] = FixedToChan(r
);
272 span
->array
->spec
[i
][GCOMP
] = FixedToChan(g
);
273 span
->array
->spec
[i
][BCOMP
] = FixedToChan(b
);
274 r
+= span
->specRedStep
;
275 g
+= span
->specGreenStep
;
276 b
+= span
->specBlueStep
;
279 span
->arrayMask
|= SPAN_SPEC
;
283 /* Fill in the span.zArray array from the interpolation values */
285 _swrast_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
287 const GLuint n
= span
->end
;
290 ASSERT((span
->interpMask
& SPAN_Z
) &&
291 !(span
->arrayMask
& SPAN_Z
));
293 if (ctx
->Visual
.depthBits
<= 16) {
294 GLfixed zval
= span
->z
;
295 GLdepth
*z
= span
->array
->z
;
296 for (i
= 0; i
< n
; i
++) {
297 z
[i
] = FixedToInt(zval
);
302 /* Deep Z buffer, no fixed->int shift */
303 GLfixed zval
= span
->z
;
304 GLdepth
*z
= span
->array
->z
;
305 for (i
= 0; i
< n
; i
++) {
310 span
->arrayMask
|= SPAN_Z
;
315 * This the ideal solution, as given in the OpenGL spec.
319 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
320 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
321 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
323 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
324 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
325 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
326 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
327 GLfloat x
= SQRTF(dudx
* dudx
+ dvdx
* dvdx
);
328 GLfloat y
= SQRTF(dudy
* dudy
+ dvdy
* dvdy
);
329 GLfloat rho
= MAX2(x
, y
);
330 GLfloat lambda
= LOG2(rho
);
337 * This is a faster approximation
340 _swrast_compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
341 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
342 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
344 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
345 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
346 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
347 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
348 GLfloat maxU
, maxV
, rho
, lambda
;
349 dsdx2
= FABSF(dsdx2
);
350 dsdy2
= FABSF(dsdy2
);
351 dtdx2
= FABSF(dtdx2
);
352 dtdy2
= FABSF(dtdy2
);
353 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
354 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
355 rho
= MAX2(maxU
, maxV
);
362 * Fill in the span.texcoords array from the interpolation values.
363 * Note: in the places where we divide by Q (or mult by invQ) we're
364 * really doing two things: perspective correction and texcoord
365 * projection. Remember, for texcoord (s,t,r,q) we need to index
366 * texels with (s/q, t/q, r/q).
367 * If we're using a fragment program, we never do the division
368 * for texcoord projection. That's done by the TXP instruction
369 * or user-written code.
372 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
374 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
375 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
377 if (ctx
->Texture
._EnabledCoordUnits
> 1) {
380 span
->arrayMask
|= SPAN_TEXTURE
;
381 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
382 if (ctx
->Texture
._EnabledCoordUnits
& (1 << u
)) {
383 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
385 GLboolean needLambda
;
387 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
388 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
389 || ctx
->FragmentProgram
._Enabled
;
390 texW
= img
->WidthScale
;
391 texH
= img
->HeightScale
;
394 /* using a fragment program */
397 needLambda
= GL_FALSE
;
400 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
401 GLfloat
*lambda
= span
->array
->lambda
[u
];
402 const GLfloat dsdx
= span
->texStepX
[u
][0];
403 const GLfloat dsdy
= span
->texStepY
[u
][0];
404 const GLfloat dtdx
= span
->texStepX
[u
][1];
405 const GLfloat dtdy
= span
->texStepY
[u
][1];
406 const GLfloat drdx
= span
->texStepX
[u
][2];
407 const GLfloat dqdx
= span
->texStepX
[u
][3];
408 const GLfloat dqdy
= span
->texStepY
[u
][3];
409 GLfloat s
= span
->tex
[u
][0];
410 GLfloat t
= span
->tex
[u
][1];
411 GLfloat r
= span
->tex
[u
][2];
412 GLfloat q
= span
->tex
[u
][3];
414 if (ctx
->FragmentProgram
._Enabled
) {
415 /* do perspective correction but don't divide s, t, r by q */
416 const GLfloat dwdx
= span
->dwdx
;
418 for (i
= 0; i
< span
->end
; i
++) {
419 const GLfloat invW
= 1.0F
/ w
;
420 texcoord
[i
][0] = s
* invW
;
421 texcoord
[i
][1] = t
* invW
;
422 texcoord
[i
][2] = r
* invW
;
423 texcoord
[i
][3] = q
* invW
;
424 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
425 dqdx
, dqdy
, texW
, texH
,
436 for (i
= 0; i
< span
->end
; i
++) {
437 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
438 texcoord
[i
][0] = s
* invQ
;
439 texcoord
[i
][1] = t
* invQ
;
440 texcoord
[i
][2] = r
* invQ
;
442 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
443 dqdx
, dqdy
, texW
, texH
,
451 span
->arrayMask
|= SPAN_LAMBDA
;
454 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
455 GLfloat
*lambda
= span
->array
->lambda
[u
];
456 const GLfloat dsdx
= span
->texStepX
[u
][0];
457 const GLfloat dtdx
= span
->texStepX
[u
][1];
458 const GLfloat drdx
= span
->texStepX
[u
][2];
459 const GLfloat dqdx
= span
->texStepX
[u
][3];
460 GLfloat s
= span
->tex
[u
][0];
461 GLfloat t
= span
->tex
[u
][1];
462 GLfloat r
= span
->tex
[u
][2];
463 GLfloat q
= span
->tex
[u
][3];
465 if (ctx
->FragmentProgram
._Enabled
) {
466 /* do perspective correction but don't divide s, t, r by q */
467 const GLfloat dwdx
= span
->dwdx
;
469 for (i
= 0; i
< span
->end
; i
++) {
470 const GLfloat invW
= 1.0F
/ w
;
471 texcoord
[i
][0] = s
* invW
;
472 texcoord
[i
][1] = t
* invW
;
473 texcoord
[i
][2] = r
* invW
;
474 texcoord
[i
][3] = q
* invW
;
483 else if (dqdx
== 0.0F
) {
484 /* Ortho projection or polygon's parallel to window X axis */
485 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
486 for (i
= 0; i
< span
->end
; i
++) {
487 texcoord
[i
][0] = s
* invQ
;
488 texcoord
[i
][1] = t
* invQ
;
489 texcoord
[i
][2] = r
* invQ
;
498 for (i
= 0; i
< span
->end
; i
++) {
499 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
500 texcoord
[i
][0] = s
* invQ
;
501 texcoord
[i
][1] = t
* invQ
;
502 texcoord
[i
][2] = r
* invQ
;
517 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
519 GLboolean needLambda
;
521 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
522 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
523 || ctx
->FragmentProgram
._Enabled
;
524 texW
= (GLfloat
) img
->WidthScale
;
525 texH
= (GLfloat
) img
->HeightScale
;
528 needLambda
= GL_FALSE
;
531 span
->arrayMask
|= SPAN_TEXTURE
;
533 /* just texture unit 0, with lambda */
534 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
535 GLfloat
*lambda
= span
->array
->lambda
[0];
536 const GLfloat dsdx
= span
->texStepX
[0][0];
537 const GLfloat dsdy
= span
->texStepY
[0][0];
538 const GLfloat dtdx
= span
->texStepX
[0][1];
539 const GLfloat dtdy
= span
->texStepY
[0][1];
540 const GLfloat drdx
= span
->texStepX
[0][2];
541 const GLfloat dqdx
= span
->texStepX
[0][3];
542 const GLfloat dqdy
= span
->texStepY
[0][3];
543 GLfloat s
= span
->tex
[0][0];
544 GLfloat t
= span
->tex
[0][1];
545 GLfloat r
= span
->tex
[0][2];
546 GLfloat q
= span
->tex
[0][3];
548 if (ctx
->FragmentProgram
._Enabled
) {
549 /* do perspective correction but don't divide s, t, r by q */
550 const GLfloat dwdx
= span
->dwdx
;
552 for (i
= 0; i
< span
->end
; i
++) {
553 const GLfloat invW
= 1.0F
/ w
;
554 texcoord
[i
][0] = s
* invW
;
555 texcoord
[i
][1] = t
* invW
;
556 texcoord
[i
][2] = r
* invW
;
557 texcoord
[i
][3] = q
* invW
;
558 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
559 dqdx
, dqdy
, texW
, texH
,
570 for (i
= 0; i
< span
->end
; i
++) {
571 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
572 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
573 dqdx
, dqdy
, texW
, texH
,
575 texcoord
[i
][0] = s
* invQ
;
576 texcoord
[i
][1] = t
* invQ
;
577 texcoord
[i
][2] = r
* invQ
;
585 span
->arrayMask
|= SPAN_LAMBDA
;
588 /* just texture 0, without lambda */
589 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
590 const GLfloat dsdx
= span
->texStepX
[0][0];
591 const GLfloat dtdx
= span
->texStepX
[0][1];
592 const GLfloat drdx
= span
->texStepX
[0][2];
593 const GLfloat dqdx
= span
->texStepX
[0][3];
594 GLfloat s
= span
->tex
[0][0];
595 GLfloat t
= span
->tex
[0][1];
596 GLfloat r
= span
->tex
[0][2];
597 GLfloat q
= span
->tex
[0][3];
599 if (ctx
->FragmentProgram
._Enabled
) {
600 /* do perspective correction but don't divide s, t, r by q */
601 const GLfloat dwdx
= span
->dwdx
;
603 for (i
= 0; i
< span
->end
; i
++) {
604 const GLfloat invW
= 1.0F
/ w
;
605 texcoord
[i
][0] = s
* invW
;
606 texcoord
[i
][1] = t
* invW
;
607 texcoord
[i
][2] = r
* invW
;
608 texcoord
[i
][3] = q
* invW
;
616 else if (dqdx
== 0.0F
) {
617 /* Ortho projection or polygon's parallel to window X axis */
618 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
619 for (i
= 0; i
< span
->end
; i
++) {
620 texcoord
[i
][0] = s
* invQ
;
621 texcoord
[i
][1] = t
* invQ
;
622 texcoord
[i
][2] = r
* invQ
;
630 for (i
= 0; i
< span
->end
; i
++) {
631 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
632 texcoord
[i
][0] = s
* invQ
;
633 texcoord
[i
][1] = t
* invQ
;
634 texcoord
[i
][2] = r
* invQ
;
648 * Apply the current polygon stipple pattern to a span of pixels.
651 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
653 const GLuint highbit
= 0x80000000;
654 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
655 GLubyte
*mask
= span
->array
->mask
;
658 ASSERT(ctx
->Polygon
.StippleFlag
);
659 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
661 m
= highbit
>> (GLuint
) (span
->x
% 32);
663 for (i
= 0; i
< span
->end
; i
++) {
664 if ((m
& stipple
) == 0) {
672 span
->writeAll
= GL_FALSE
;
677 * Clip a pixel span to the current buffer/window boundaries:
678 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
679 * window clipping and scissoring.
680 * Return: GL_TRUE some pixels still visible
681 * GL_FALSE nothing visible
684 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
686 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
687 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
688 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
689 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
691 if (span
->arrayMask
& SPAN_XY
) {
692 /* arrays of x/y pixel coords */
693 const GLint
*x
= span
->array
->x
;
694 const GLint
*y
= span
->array
->y
;
695 const GLint n
= span
->end
;
696 GLubyte
*mask
= span
->array
->mask
;
698 if (span
->arrayMask
& SPAN_MASK
) {
699 /* note: using & intead of && to reduce branches */
700 for (i
= 0; i
< n
; i
++) {
701 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
702 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
706 /* note: using & intead of && to reduce branches */
707 for (i
= 0; i
< n
; i
++) {
708 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
709 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
712 return GL_TRUE
; /* some pixels visible */
715 /* horizontal span of pixels */
716 const GLint x
= span
->x
;
717 const GLint y
= span
->y
;
718 const GLint n
= span
->end
;
720 /* Trivial rejection tests */
721 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
723 return GL_FALSE
; /* all pixels clipped */
726 /* Clip to the left */
728 ASSERT(x
+ n
> xmin
);
729 span
->writeAll
= GL_FALSE
;
730 _mesa_bzero(span
->array
->mask
, (xmin
- x
) * sizeof(GLubyte
));
736 span
->end
= xmax
- x
;
739 return GL_TRUE
; /* some pixels visible */
746 * Draw to more than one color buffer (or none).
749 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
751 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
754 /* loop over four possible dest color buffers */
755 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
756 if (bufferBit
& ctx
->Color
._DrawDestMask
[0]) {
757 GLuint indexTmp
[MAX_WIDTH
];
758 ASSERT(span
->end
< MAX_WIDTH
);
760 /* Set the current read/draw buffer */
761 swrast
->CurrentBufferBit
= bufferBit
;
762 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
764 /* make copy of incoming indexes */
765 MEMCPY( indexTmp
, span
->array
->index
, span
->end
* sizeof(GLuint
) );
767 if (ctx
->Color
.IndexLogicOpEnabled
) {
768 _swrast_logicop_ci_span(ctx
, span
, indexTmp
);
771 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
772 _swrast_mask_index_span(ctx
, span
, indexTmp
);
775 if (span
->arrayMask
& SPAN_XY
) {
776 /* array of pixel coords */
777 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
778 span
->array
->x
, span
->array
->y
,
779 indexTmp
, span
->array
->mask
);
782 /* horizontal run of pixels */
783 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
784 indexTmp
, span
->array
->mask
);
789 /* restore default dest buffer */
790 _swrast_use_draw_buffer(ctx
);
795 * Draw to more than one RGBA color buffer (or none).
796 * All fragment operations, up to (but not) blending/logicop should
797 * have been done first.
800 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
802 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
804 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
806 ASSERT(colorMask
!= 0x0);
808 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
811 /* loop over four possible dest color buffers */
812 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
813 if (bufferBit
& ctx
->Color
._DrawDestMask
[0]) {
814 GLchan rgbaTmp
[MAX_WIDTH
][4];
815 ASSERT(span
->end
< MAX_WIDTH
);
817 /* Set the current read/draw buffer */
818 swrast
->CurrentBufferBit
= bufferBit
;
819 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
821 /* make copy of incoming colors */
822 MEMCPY( rgbaTmp
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
) );
824 if (ctx
->Color
._LogicOpEnabled
) {
825 _swrast_logicop_rgba_span(ctx
, span
, rgbaTmp
);
827 else if (ctx
->Color
.BlendEnabled
) {
828 _swrast_blend_span(ctx
, span
, rgbaTmp
);
831 if (colorMask
!= 0xffffffff) {
832 _swrast_mask_rgba_span(ctx
, span
, rgbaTmp
);
835 if (span
->arrayMask
& SPAN_XY
) {
836 /* array of pixel coords */
837 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
838 span
->array
->x
, span
->array
->y
,
839 (const GLchan (*)[4]) rgbaTmp
,
841 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
842 _swrast_write_alpha_pixels(ctx
, span
->end
,
843 span
->array
->x
, span
->array
->y
,
844 (const GLchan (*)[4]) rgbaTmp
,
849 /* horizontal run of pixels */
850 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
851 (const GLchan (*)[4]) rgbaTmp
,
853 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
854 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
855 (const GLchan (*)[4]) rgbaTmp
,
862 /* restore default dest buffer */
863 _swrast_use_draw_buffer(ctx
);
869 * This function may modify any of the array values in the span.
870 * span->interpMask and span->arrayMask may be changed but will be restored
871 * to their original values before returning.
874 _swrast_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
876 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
877 const GLuint origInterpMask
= span
->interpMask
;
878 const GLuint origArrayMask
= span
->arrayMask
;
880 ASSERT(span
->end
<= MAX_WIDTH
);
881 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
882 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
883 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
884 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
886 if (span
->arrayMask
& SPAN_MASK
) {
887 /* mask was initialized by caller, probably glBitmap */
888 span
->writeAll
= GL_FALSE
;
891 _mesa_memset(span
->array
->mask
, 1, span
->end
);
892 span
->writeAll
= GL_TRUE
;
896 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
897 if (!clip_span(ctx
, span
)) {
902 /* Depth bounds test */
903 if (ctx
->Depth
.BoundsTest
&& ctx
->Visual
.depthBits
> 0) {
904 if (!_swrast_depth_bounds_test(ctx
, span
)) {
910 /* Make sure all fragments are within window bounds */
911 if (span
->arrayMask
& SPAN_XY
) {
913 for (i
= 0; i
< span
->end
; i
++) {
914 if (span
->array
->mask
[i
]) {
915 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
916 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
917 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
918 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
924 /* Polygon Stippling */
925 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
926 stipple_polygon_span(ctx
, span
);
929 /* Depth test and stencil */
930 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
931 if (span
->interpMask
& SPAN_Z
)
932 _swrast_span_interpolate_z(ctx
, span
);
934 if (ctx
->Stencil
.Enabled
) {
935 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
936 span
->arrayMask
= origArrayMask
;
941 ASSERT(ctx
->Depth
.Test
);
942 if (!_swrast_depth_test_span(ctx
, span
)) {
943 span
->arrayMask
= origArrayMask
;
949 /* if we get here, something passed the depth test */
950 if (ctx
->Depth
.OcclusionTest
) {
951 ctx
->OcclusionResult
= GL_TRUE
;
954 #if FEATURE_ARB_occlusion_query
955 if (ctx
->Occlusion
.Active
) {
956 /* update count of 'passed' fragments */
958 for (i
= 0; i
< span
->end
; i
++)
959 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
963 /* we have to wait until after occlusion to do this test */
964 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
965 /* write no pixels */
966 span
->arrayMask
= origArrayMask
;
970 /* Interpolate the color indexes if needed */
971 if (span
->interpMask
& SPAN_INDEX
) {
972 interpolate_indexes(ctx
, span
);
973 /* clear the bit - this allows the WriteMonoCISpan optimization below */
974 span
->interpMask
&= ~SPAN_INDEX
;
978 if (ctx
->Fog
.Enabled
) {
979 _swrast_fog_ci_span(ctx
, span
);
982 /* Antialias coverage application */
983 if (span
->arrayMask
& SPAN_COVERAGE
) {
985 GLuint
*index
= span
->array
->index
;
986 GLfloat
*coverage
= span
->array
->coverage
;
987 for (i
= 0; i
< span
->end
; i
++) {
988 ASSERT(coverage
[i
] < 16);
989 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) coverage
[i
]);
993 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
994 /* draw to zero or two or more buffers */
995 multi_write_index_span(ctx
, span
);
998 /* normal situation: draw to exactly one buffer */
999 if (ctx
->Color
.IndexLogicOpEnabled
) {
1000 _swrast_logicop_ci_span(ctx
, span
, span
->array
->index
);
1003 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
1004 _swrast_mask_index_span(ctx
, span
, span
->array
->index
);
1008 if (span
->arrayMask
& SPAN_XY
) {
1009 /* array of pixel coords */
1010 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
1011 /* all pixels have same color index */
1012 (*swrast
->Driver
.WriteMonoCIPixels
)(ctx
, span
->end
,
1013 span
->array
->x
, span
->array
->y
,
1014 FixedToInt(span
->index
),
1018 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->array
->x
,
1019 span
->array
->y
, span
->array
->index
,
1020 span
->array
->mask
);
1024 /* horizontal run of pixels */
1025 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
1026 /* all pixels have same color index */
1027 (*swrast
->Driver
.WriteMonoCISpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1028 FixedToInt(span
->index
),
1032 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
1039 span
->interpMask
= origInterpMask
;
1040 span
->arrayMask
= origArrayMask
;
1045 * Add specular color to base color. This is used only when
1046 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1049 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1052 for (i
= 0; i
< n
; i
++) {
1053 #if CHAN_TYPE == GL_FLOAT
1055 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1056 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1057 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1059 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1060 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1061 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1062 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1063 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1064 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1071 * Apply all the per-fragment operations to a span.
1072 * This now includes texturing (_swrast_write_texture_span() is history).
1073 * This function may modify any of the array values in the span.
1074 * span->interpMask and span->arrayMask may be changed but will be restored
1075 * to their original values before returning.
1078 _swrast_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
1080 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1081 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1082 const GLuint origInterpMask
= span
->interpMask
;
1083 const GLuint origArrayMask
= span
->arrayMask
;
1085 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1086 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1087 ASSERT(span
->end
<= MAX_WIDTH
);
1088 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1091 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__,
1092 span->interpMask, span->arrayMask);
1095 if (span
->arrayMask
& SPAN_MASK
) {
1096 /* mask was initialized by caller, probably glBitmap */
1097 span
->writeAll
= GL_FALSE
;
1100 _mesa_memset(span
->array
->mask
, 1, span
->end
);
1101 span
->writeAll
= GL_TRUE
;
1104 /* Clip to window/scissor box */
1105 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1106 if (!clip_span(ctx
, span
)) {
1112 /* Make sure all fragments are within window bounds */
1113 if (span
->arrayMask
& SPAN_XY
) {
1115 for (i
= 0; i
< span
->end
; i
++) {
1116 if (span
->array
->mask
[i
]) {
1117 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1118 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1119 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1120 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1126 /* Polygon Stippling */
1127 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1128 stipple_polygon_span(ctx
, span
);
1131 /* Interpolate texcoords? */
1132 if (ctx
->Texture
._EnabledCoordUnits
1133 && (span
->interpMask
& SPAN_TEXTURE
)
1134 && (span
->arrayMask
& SPAN_TEXTURE
) == 0) {
1135 interpolate_texcoords(ctx
, span
);
1138 /* If the alpha test is enabled, we have to compute the fragment colors
1139 * at this point and do the alpha test.
1140 * Else, if alpha test is not enabled, we'll try to defer fragment
1141 * color computation (by interpolation, texture mapping, fragment program)
1142 * until after the Z/stencil tests in the hope that many fragments will
1143 * get culled, leaving less work to do.
1145 if (ctx
->Color
.AlphaEnabled
) {
1146 /* Now we need the rgba array, fill it in if needed */
1147 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1148 interpolate_colors(ctx
, span
);
1150 if (span
->interpMask
& SPAN_SPEC
)
1151 interpolate_specular(ctx
, span
);
1153 /* Compute fragment colors with fragment program or texture lookups */
1154 if (ctx
->FragmentProgram
._Enabled
)
1155 /* XXX interpolate depth values here??? */
1156 _swrast_exec_fragment_program( ctx
, span
);
1157 else if (ctx
->ATIFragmentShader
._Enabled
)
1158 _swrast_exec_fragment_shader( ctx
, span
);
1159 else if (ctx
->Texture
._EnabledUnits
)
1160 _swrast_texture_span( ctx
, span
);
1162 /* Do the alpha test */
1163 if (!_swrast_alpha_test(ctx
, span
)) {
1164 span
->arrayMask
= origArrayMask
;
1169 /* Stencil and Z testing */
1170 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1171 if (span
->interpMask
& SPAN_Z
)
1172 _swrast_span_interpolate_z(ctx
, span
);
1174 if (ctx
->Stencil
.Enabled
) {
1175 /* Combined Z/stencil tests */
1176 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1177 span
->interpMask
= origInterpMask
;
1178 span
->arrayMask
= origArrayMask
;
1183 /* Just regular depth testing */
1184 ASSERT(ctx
->Depth
.Test
);
1185 ASSERT(span
->arrayMask
& SPAN_Z
);
1186 if (!_swrast_depth_test_span(ctx
, span
)) {
1187 span
->interpMask
= origInterpMask
;
1188 span
->arrayMask
= origArrayMask
;
1194 /* if we get here, some fragments passed the depth test */
1195 if (ctx
->Depth
.OcclusionTest
) {
1196 ctx
->OcclusionResult
= GL_TRUE
;
1199 #if FEATURE_ARB_occlusion_query
1200 if (ctx
->Occlusion
.Active
) {
1201 /* update count of 'passed' fragments */
1203 for (i
= 0; i
< span
->end
; i
++)
1204 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
1208 /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1209 * the occlusion test.
1211 if (colorMask
== 0x0) {
1212 span
->interpMask
= origInterpMask
;
1213 span
->arrayMask
= origArrayMask
;
1217 /* If the alpha test isn't enabled, we're able to defer computing fragment
1218 * colors (by interpolation, texturing, fragment program) until now.
1219 * Hopefully, Z/stencil tests culled many of the fragments!
1221 if (!ctx
->Color
.AlphaEnabled
) {
1222 /* Now we need the rgba array, fill it in if needed */
1223 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1224 interpolate_colors(ctx
, span
);
1226 if (span
->interpMask
& SPAN_SPEC
)
1227 interpolate_specular(ctx
, span
);
1229 if (ctx
->FragmentProgram
._Enabled
)
1230 _swrast_exec_fragment_program( ctx
, span
);
1231 else if (ctx
->ATIFragmentShader
._Enabled
)
1232 _swrast_exec_fragment_shader( ctx
, span
);
1233 else if (ctx
->Texture
._EnabledUnits
)
1234 _swrast_texture_span( ctx
, span
);
1237 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1239 if (!ctx
->FragmentProgram
._Enabled
) {
1240 /* Add base and specular colors */
1241 if (ctx
->Fog
.ColorSumEnabled
||
1242 (ctx
->Light
.Enabled
&&
1243 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1244 if (span
->interpMask
& SPAN_SPEC
) {
1245 interpolate_specular(ctx
, span
);
1247 if (span
->arrayMask
& SPAN_SPEC
) {
1248 add_colors( span
->end
, span
->array
->rgba
, span
->array
->spec
);
1251 /* We probably added the base/specular colors during the
1259 if (swrast
->_FogEnabled
) {
1260 _swrast_fog_rgba_span(ctx
, span
);
1263 /* Antialias coverage application */
1264 if (span
->arrayMask
& SPAN_COVERAGE
) {
1265 GLchan (*rgba
)[4] = span
->array
->rgba
;
1266 GLfloat
*coverage
= span
->array
->coverage
;
1268 for (i
= 0; i
< span
->end
; i
++) {
1269 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1273 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1274 /* need to do blend/logicop separately for each color buffer */
1275 multi_write_rgba_span(ctx
, span
);
1278 /* normal: write to exactly one buffer */
1279 if (ctx
->Color
._LogicOpEnabled
) {
1280 _swrast_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1282 else if (ctx
->Color
.BlendEnabled
) {
1283 _swrast_blend_span(ctx
, span
, span
->array
->rgba
);
1286 /* Color component masking */
1287 if (colorMask
!= 0xffffffff) {
1288 _swrast_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1291 /* Finally, write the pixels to a color buffer */
1292 if (span
->arrayMask
& SPAN_XY
) {
1293 /* array of pixel coords */
1294 swrast
->Driver
.WriteRGBAPixels(ctx
, span
->end
, span
->array
->x
,
1295 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
,
1297 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1298 _swrast_write_alpha_pixels(ctx
, span
->end
,
1299 span
->array
->x
, span
->array
->y
,
1300 (const GLchan (*)[4]) span
->array
->rgba
,
1305 /* horizontal run of pixels */
1306 swrast
->Driver
.WriteRGBASpan(ctx
, span
->end
, span
->x
, span
->y
,
1307 (const GLchan (*)[4]) span
->array
->rgba
,
1308 span
->writeAll
? NULL
: span
->array
->mask
);
1309 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1310 _swrast_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1311 (const GLchan (*)[4]) span
->array
->rgba
,
1312 span
->writeAll
? NULL
: span
->array
->mask
);
1317 span
->interpMask
= origInterpMask
;
1318 span
->arrayMask
= origArrayMask
;
1324 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1325 * reading ouside the buffer's boundaries.
1328 _swrast_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1329 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1331 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1332 const GLint bufWidth
= (GLint
) buffer
->Width
;
1333 const GLint bufHeight
= (GLint
) buffer
->Height
;
1335 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1336 /* completely above, below, or right */
1337 /* XXX maybe leave undefined? */
1338 _mesa_bzero(rgba
, 4 * n
* sizeof(GLchan
));
1343 /* left edge clippping */
1345 length
= (GLint
) n
- skip
;
1347 /* completely left of window */
1350 if (length
> bufWidth
) {
1354 else if ((GLint
) (x
+ n
) > bufWidth
) {
1355 /* right edge clipping */
1357 length
= bufWidth
- x
;
1359 /* completely to right of window */
1369 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1370 if (buffer
->UseSoftwareAlphaBuffers
) {
1371 _swrast_read_alpha_span(ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1378 * Read CI pixels from frame buffer. Clipping will be done to prevent
1379 * reading ouside the buffer's boundaries.
1382 _swrast_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1383 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1385 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1386 const GLint bufWidth
= (GLint
) buffer
->Width
;
1387 const GLint bufHeight
= (GLint
) buffer
->Height
;
1389 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1390 /* completely above, below, or right */
1391 _mesa_bzero(indx
, n
* sizeof(GLuint
));
1396 /* left edge clippping */
1398 length
= (GLint
) n
- skip
;
1400 /* completely left of window */
1403 if (length
> bufWidth
) {
1407 else if ((GLint
) (x
+ n
) > bufWidth
) {
1408 /* right edge clipping */
1410 length
= bufWidth
- x
;
1412 /* completely to right of window */
1422 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);