2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 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"
42 #include "s_context.h"
46 #include "s_masking.h"
47 #include "s_nvfragprog.h"
49 #include "s_stencil.h"
50 #include "s_texture.h"
54 * Init span's Z interpolation values to the RasterPos Z.
55 * Used during setup for glDraw/CopyPixels.
58 _swrast_span_default_z( GLcontext
*ctx
, struct sw_span
*span
)
60 const GLfloat depthMax
= ctx
->DrawBuffer
->_DepthMaxF
;
61 if (ctx
->Visual
.depthBits
<= 16)
62 span
->z
= FloatToFixed(ctx
->Current
.RasterPos
[2] * depthMax
+ 0.5F
);
64 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * 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
._Active
|| 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
;
238 span
->interpMask
&= ~SPAN_INDEX
;
242 /* Fill in the span.->array->spec array from the interpolation values */
244 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
247 if (span
->interpMask
& SPAN_FLAT
) {
249 const GLchan r
= FixedToChan(span
->specRed
);
250 const GLchan g
= FixedToChan(span
->specGreen
);
251 const GLchan b
= FixedToChan(span
->specBlue
);
253 for (i
= 0; i
< span
->end
; i
++) {
254 span
->array
->spec
[i
][RCOMP
] = r
;
255 span
->array
->spec
[i
][GCOMP
] = g
;
256 span
->array
->spec
[i
][BCOMP
] = b
;
261 #if CHAN_TYPE == GL_FLOAT
262 GLfloat r
= span
->specRed
;
263 GLfloat g
= span
->specGreen
;
264 GLfloat b
= span
->specBlue
;
266 GLfixed r
= span
->specRed
;
267 GLfixed g
= span
->specGreen
;
268 GLfixed b
= span
->specBlue
;
271 for (i
= 0; i
< span
->end
; i
++) {
272 span
->array
->spec
[i
][RCOMP
] = FixedToChan(r
);
273 span
->array
->spec
[i
][GCOMP
] = FixedToChan(g
);
274 span
->array
->spec
[i
][BCOMP
] = FixedToChan(b
);
275 r
+= span
->specRedStep
;
276 g
+= span
->specGreenStep
;
277 b
+= span
->specBlueStep
;
280 span
->arrayMask
|= SPAN_SPEC
;
284 /* Fill in the span.array.fog values from the interpolation values */
286 interpolate_fog(const GLcontext
*ctx
, struct sw_span
*span
)
288 GLfloat
*fog
= span
->array
->fog
;
289 const GLfloat fogStep
= span
->fogStep
;
290 GLfloat fogCoord
= span
->fog
;
291 const GLuint haveW
= (span
->interpMask
& SPAN_W
);
292 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
293 GLfloat w
= haveW
? span
->w
: 1.0F
;
295 for (i
= 0; i
< span
->end
; i
++) {
296 fog
[i
] = fogCoord
/ w
;
300 span
->arrayMask
|= SPAN_FOG
;
304 /* Fill in the span.zArray array from the interpolation values */
306 _swrast_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
308 const GLuint n
= span
->end
;
311 ASSERT((span
->interpMask
& SPAN_Z
) &&
312 !(span
->arrayMask
& SPAN_Z
));
314 if (ctx
->Visual
.depthBits
<= 16) {
315 GLfixed zval
= span
->z
;
316 GLdepth
*z
= span
->array
->z
;
317 for (i
= 0; i
< n
; i
++) {
318 z
[i
] = FixedToInt(zval
);
323 /* Deep Z buffer, no fixed->int shift */
324 GLfixed zval
= span
->z
;
325 GLdepth
*z
= span
->array
->z
;
326 for (i
= 0; i
< n
; i
++) {
331 span
->arrayMask
|= SPAN_Z
;
336 * This the ideal solution, as given in the OpenGL spec.
340 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 dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
345 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
346 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
347 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
348 GLfloat x
= SQRTF(dudx
* dudx
+ dvdx
* dvdx
);
349 GLfloat y
= SQRTF(dudy
* dudy
+ dvdy
* dvdy
);
350 GLfloat rho
= MAX2(x
, y
);
351 GLfloat lambda
= LOG2(rho
);
358 * This is a faster approximation
361 _swrast_compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
362 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
363 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
365 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
366 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
367 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
368 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
369 GLfloat maxU
, maxV
, rho
, lambda
;
370 dsdx2
= FABSF(dsdx2
);
371 dsdy2
= FABSF(dsdy2
);
372 dtdx2
= FABSF(dtdx2
);
373 dtdy2
= FABSF(dtdy2
);
374 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
375 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
376 rho
= MAX2(maxU
, maxV
);
383 * Fill in the span.texcoords array from the interpolation values.
384 * Note: in the places where we divide by Q (or mult by invQ) we're
385 * really doing two things: perspective correction and texcoord
386 * projection. Remember, for texcoord (s,t,r,q) we need to index
387 * texels with (s/q, t/q, r/q).
388 * If we're using a fragment program, we never do the division
389 * for texcoord projection. That's done by the TXP instruction
390 * or user-written code.
393 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
395 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
396 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
398 if (ctx
->Texture
._EnabledCoordUnits
> 1) {
401 span
->arrayMask
|= SPAN_TEXTURE
;
402 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
403 if (ctx
->Texture
._EnabledCoordUnits
& (1 << u
)) {
404 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
406 GLboolean needLambda
;
408 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
409 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
410 || ctx
->FragmentProgram
._Active
;
411 texW
= img
->WidthScale
;
412 texH
= img
->HeightScale
;
415 /* using a fragment program */
418 needLambda
= GL_FALSE
;
421 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
422 GLfloat
*lambda
= span
->array
->lambda
[u
];
423 const GLfloat dsdx
= span
->texStepX
[u
][0];
424 const GLfloat dsdy
= span
->texStepY
[u
][0];
425 const GLfloat dtdx
= span
->texStepX
[u
][1];
426 const GLfloat dtdy
= span
->texStepY
[u
][1];
427 const GLfloat drdx
= span
->texStepX
[u
][2];
428 const GLfloat dqdx
= span
->texStepX
[u
][3];
429 const GLfloat dqdy
= span
->texStepY
[u
][3];
430 GLfloat s
= span
->tex
[u
][0];
431 GLfloat t
= span
->tex
[u
][1];
432 GLfloat r
= span
->tex
[u
][2];
433 GLfloat q
= span
->tex
[u
][3];
435 if (ctx
->FragmentProgram
._Active
) {
436 /* do perspective correction but don't divide s, t, r by q */
437 const GLfloat dwdx
= span
->dwdx
;
439 for (i
= 0; i
< span
->end
; i
++) {
440 const GLfloat invW
= 1.0F
/ w
;
441 texcoord
[i
][0] = s
* invW
;
442 texcoord
[i
][1] = t
* invW
;
443 texcoord
[i
][2] = r
* invW
;
444 texcoord
[i
][3] = q
* invW
;
445 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
446 dqdx
, dqdy
, texW
, texH
,
457 for (i
= 0; i
< span
->end
; i
++) {
458 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
459 texcoord
[i
][0] = s
* invQ
;
460 texcoord
[i
][1] = t
* invQ
;
461 texcoord
[i
][2] = r
* invQ
;
463 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
464 dqdx
, dqdy
, texW
, texH
,
472 span
->arrayMask
|= SPAN_LAMBDA
;
475 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
476 GLfloat
*lambda
= span
->array
->lambda
[u
];
477 const GLfloat dsdx
= span
->texStepX
[u
][0];
478 const GLfloat dtdx
= span
->texStepX
[u
][1];
479 const GLfloat drdx
= span
->texStepX
[u
][2];
480 const GLfloat dqdx
= span
->texStepX
[u
][3];
481 GLfloat s
= span
->tex
[u
][0];
482 GLfloat t
= span
->tex
[u
][1];
483 GLfloat r
= span
->tex
[u
][2];
484 GLfloat q
= span
->tex
[u
][3];
486 if (ctx
->FragmentProgram
._Active
) {
487 /* do perspective correction but don't divide s, t, r by q */
488 const GLfloat dwdx
= span
->dwdx
;
490 for (i
= 0; i
< span
->end
; i
++) {
491 const GLfloat invW
= 1.0F
/ w
;
492 texcoord
[i
][0] = s
* invW
;
493 texcoord
[i
][1] = t
* invW
;
494 texcoord
[i
][2] = r
* invW
;
495 texcoord
[i
][3] = q
* invW
;
504 else if (dqdx
== 0.0F
) {
505 /* Ortho projection or polygon's parallel to window X axis */
506 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
507 for (i
= 0; i
< span
->end
; i
++) {
508 texcoord
[i
][0] = s
* invQ
;
509 texcoord
[i
][1] = t
* invQ
;
510 texcoord
[i
][2] = r
* invQ
;
519 for (i
= 0; i
< span
->end
; i
++) {
520 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
521 texcoord
[i
][0] = s
* invQ
;
522 texcoord
[i
][1] = t
* invQ
;
523 texcoord
[i
][2] = r
* invQ
;
538 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
540 GLboolean needLambda
;
542 const struct gl_texture_image
*img
= obj
->Image
[0][obj
->BaseLevel
];
543 needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
544 || ctx
->FragmentProgram
._Active
;
545 texW
= (GLfloat
) img
->WidthScale
;
546 texH
= (GLfloat
) img
->HeightScale
;
549 needLambda
= GL_FALSE
;
552 span
->arrayMask
|= SPAN_TEXTURE
;
554 /* just texture unit 0, with lambda */
555 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
556 GLfloat
*lambda
= span
->array
->lambda
[0];
557 const GLfloat dsdx
= span
->texStepX
[0][0];
558 const GLfloat dsdy
= span
->texStepY
[0][0];
559 const GLfloat dtdx
= span
->texStepX
[0][1];
560 const GLfloat dtdy
= span
->texStepY
[0][1];
561 const GLfloat drdx
= span
->texStepX
[0][2];
562 const GLfloat dqdx
= span
->texStepX
[0][3];
563 const GLfloat dqdy
= span
->texStepY
[0][3];
564 GLfloat s
= span
->tex
[0][0];
565 GLfloat t
= span
->tex
[0][1];
566 GLfloat r
= span
->tex
[0][2];
567 GLfloat q
= span
->tex
[0][3];
569 if (ctx
->FragmentProgram
._Active
) {
570 /* do perspective correction but don't divide s, t, r by q */
571 const GLfloat dwdx
= span
->dwdx
;
573 for (i
= 0; i
< span
->end
; i
++) {
574 const GLfloat invW
= 1.0F
/ w
;
575 texcoord
[i
][0] = s
* invW
;
576 texcoord
[i
][1] = t
* invW
;
577 texcoord
[i
][2] = r
* invW
;
578 texcoord
[i
][3] = q
* invW
;
579 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
580 dqdx
, dqdy
, texW
, texH
,
591 for (i
= 0; i
< span
->end
; i
++) {
592 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
593 lambda
[i
] = _swrast_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
594 dqdx
, dqdy
, texW
, texH
,
596 texcoord
[i
][0] = s
* invQ
;
597 texcoord
[i
][1] = t
* invQ
;
598 texcoord
[i
][2] = r
* invQ
;
606 span
->arrayMask
|= SPAN_LAMBDA
;
609 /* just texture 0, without lambda */
610 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
611 const GLfloat dsdx
= span
->texStepX
[0][0];
612 const GLfloat dtdx
= span
->texStepX
[0][1];
613 const GLfloat drdx
= span
->texStepX
[0][2];
614 const GLfloat dqdx
= span
->texStepX
[0][3];
615 GLfloat s
= span
->tex
[0][0];
616 GLfloat t
= span
->tex
[0][1];
617 GLfloat r
= span
->tex
[0][2];
618 GLfloat q
= span
->tex
[0][3];
620 if (ctx
->FragmentProgram
._Active
) {
621 /* do perspective correction but don't divide s, t, r by q */
622 const GLfloat dwdx
= span
->dwdx
;
624 for (i
= 0; i
< span
->end
; i
++) {
625 const GLfloat invW
= 1.0F
/ w
;
626 texcoord
[i
][0] = s
* invW
;
627 texcoord
[i
][1] = t
* invW
;
628 texcoord
[i
][2] = r
* invW
;
629 texcoord
[i
][3] = q
* invW
;
637 else if (dqdx
== 0.0F
) {
638 /* Ortho projection or polygon's parallel to window X axis */
639 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
640 for (i
= 0; i
< span
->end
; i
++) {
641 texcoord
[i
][0] = s
* invQ
;
642 texcoord
[i
][1] = t
* invQ
;
643 texcoord
[i
][2] = r
* invQ
;
651 for (i
= 0; i
< span
->end
; i
++) {
652 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
653 texcoord
[i
][0] = s
* invQ
;
654 texcoord
[i
][1] = t
* invQ
;
655 texcoord
[i
][2] = r
* invQ
;
669 * Apply the current polygon stipple pattern to a span of pixels.
672 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
674 const GLuint highbit
= 0x80000000;
675 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
676 GLubyte
*mask
= span
->array
->mask
;
679 ASSERT(ctx
->Polygon
.StippleFlag
);
680 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
682 m
= highbit
>> (GLuint
) (span
->x
% 32);
684 for (i
= 0; i
< span
->end
; i
++) {
685 if ((m
& stipple
) == 0) {
693 span
->writeAll
= GL_FALSE
;
698 * Clip a pixel span to the current buffer/window boundaries:
699 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
700 * window clipping and scissoring.
701 * Return: GL_TRUE some pixels still visible
702 * GL_FALSE nothing visible
705 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
707 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
708 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
709 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
710 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
712 if (span
->arrayMask
& SPAN_XY
) {
713 /* arrays of x/y pixel coords */
714 const GLint
*x
= span
->array
->x
;
715 const GLint
*y
= span
->array
->y
;
716 const GLint n
= span
->end
;
717 GLubyte
*mask
= span
->array
->mask
;
719 if (span
->arrayMask
& SPAN_MASK
) {
720 /* note: using & intead of && to reduce branches */
721 for (i
= 0; i
< n
; i
++) {
722 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
723 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
727 /* note: using & intead of && to reduce branches */
728 for (i
= 0; i
< n
; i
++) {
729 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
730 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
733 return GL_TRUE
; /* some pixels visible */
736 /* horizontal span of pixels */
737 const GLint x
= span
->x
;
738 const GLint y
= span
->y
;
739 const GLint n
= span
->end
;
741 /* Trivial rejection tests */
742 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
744 return GL_FALSE
; /* all pixels clipped */
747 /* Clip to the left */
749 ASSERT(x
+ n
> xmin
);
750 span
->writeAll
= GL_FALSE
;
751 _mesa_bzero(span
->array
->mask
, (xmin
- x
) * sizeof(GLubyte
));
757 span
->end
= xmax
- x
;
760 return GL_TRUE
; /* some pixels visible */
766 * Apply all the per-fragment opertions to a span of color index fragments
767 * and write them to the enabled color drawbuffers.
768 * The 'span' parameter can be considered to be const. Note that
769 * span->interpMask and span->arrayMask may be changed but will be restored
770 * to their original values before returning.
773 _swrast_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
775 const SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
776 const struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
777 const GLuint output
= 0;
778 const GLuint origInterpMask
= span
->interpMask
;
779 const GLuint origArrayMask
= span
->arrayMask
;
782 ASSERT(span
->end
<= MAX_WIDTH
);
783 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
784 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
785 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
786 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
788 if (span
->arrayMask
& SPAN_MASK
) {
789 /* mask was initialized by caller, probably glBitmap */
790 span
->writeAll
= GL_FALSE
;
793 _mesa_memset(span
->array
->mask
, 1, span
->end
);
794 span
->writeAll
= GL_TRUE
;
798 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
799 if (!clip_span(ctx
, span
)) {
804 /* Depth bounds test */
805 if (ctx
->Depth
.BoundsTest
&& ctx
->Visual
.depthBits
> 0) {
806 if (!_swrast_depth_bounds_test(ctx
, span
)) {
812 /* Make sure all fragments are within window bounds */
813 if (span
->arrayMask
& SPAN_XY
) {
815 for (i
= 0; i
< span
->end
; i
++) {
816 if (span
->array
->mask
[i
]) {
817 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
818 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
819 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
820 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
826 /* Polygon Stippling */
827 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
828 stipple_polygon_span(ctx
, span
);
831 /* Stencil and Z testing */
832 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
833 if (span
->interpMask
& SPAN_Z
)
834 _swrast_span_interpolate_z(ctx
, span
);
836 if (ctx
->Stencil
.Enabled
) {
837 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
838 span
->arrayMask
= origArrayMask
;
843 ASSERT(ctx
->Depth
.Test
);
844 if (!_swrast_depth_test_span(ctx
, span
)) {
845 span
->interpMask
= origInterpMask
;
846 span
->arrayMask
= origArrayMask
;
852 /* if we get here, something passed the depth test */
853 if (ctx
->Depth
.OcclusionTest
) {
854 ctx
->OcclusionResult
= GL_TRUE
;
857 #if FEATURE_ARB_occlusion_query
858 if (ctx
->Occlusion
.Active
) {
859 /* update count of 'passed' fragments */
861 for (i
= 0; i
< span
->end
; i
++)
862 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
866 /* we have to wait until after occlusion to do this test */
867 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
868 /* write no pixels */
869 span
->arrayMask
= origArrayMask
;
873 /* Interpolate the color indexes if needed */
874 if (ctx
->Fog
.Enabled
||
875 ctx
->Color
.IndexLogicOpEnabled
||
876 ctx
->Color
.IndexMask
!= 0xffffffff ||
877 (span
->arrayMask
& SPAN_COVERAGE
)) {
878 if (span
->interpMask
& SPAN_INDEX
) {
879 interpolate_indexes(ctx
, span
);
884 if (ctx
->Fog
.Enabled
) {
885 _swrast_fog_ci_span(ctx
, span
);
888 /* Antialias coverage application */
889 if (span
->arrayMask
& SPAN_COVERAGE
) {
890 const GLfloat
*coverage
= span
->array
->coverage
;
891 GLuint
*index
= span
->array
->index
;
893 for (i
= 0; i
< span
->end
; i
++) {
894 ASSERT(coverage
[i
] < 16);
895 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) coverage
[i
]);
899 /* Loop over drawing buffers */
900 for (buf
= 0; buf
< fb
->_NumColorDrawBuffers
[output
]; buf
++) {
901 struct gl_renderbuffer
*rb
= fb
->_ColorDrawBuffers
[output
][buf
];
902 GLuint indexTemp
[MAX_WIDTH
], *index32
;
904 ASSERT(rb
->_BaseFormat
== GL_COLOR_INDEX
);
906 if (ctx
->Color
.IndexLogicOpEnabled
||
907 ctx
->Color
.IndexMask
!= 0xffffffff) {
908 /* make copy of incoming indexes */
909 MEMCPY(indexTemp
, span
->array
->index
, span
->end
* sizeof(GLuint
));
911 if (ctx
->Color
.IndexLogicOpEnabled
) {
912 _swrast_logicop_ci_span(ctx
, rb
, span
, indexTemp
);
915 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
916 _swrast_mask_ci_span(ctx
, rb
, span
, indexTemp
);
921 index32
= span
->array
->index
;
924 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
925 /* all fragments have same color index */
931 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
932 index8
= FixedToInt(span
->index
);
935 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
936 index16
= FixedToInt(span
->index
);
940 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
);
941 index32
= FixedToInt(span
->index
);
945 if (span
->arrayMask
& SPAN_XY
) {
946 rb
->PutMonoValues(ctx
, rb
, span
->end
, span
->array
->x
,
947 span
->array
->y
, value
, span
->array
->mask
);
950 rb
->PutMonoRow(ctx
, rb
, span
->end
, span
->x
, span
->y
,
951 value
, span
->array
->mask
);
955 /* each fragment is a different color */
956 GLubyte index8
[MAX_WIDTH
];
957 GLushort index16
[MAX_WIDTH
];
960 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
962 for (k
= 0; k
< span
->end
; k
++) {
963 index8
[k
] = (GLubyte
) index32
[k
];
967 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
969 for (k
= 0; k
< span
->end
; k
++) {
970 index16
[k
] = (GLushort
) index32
[k
];
975 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
);
979 if (span
->arrayMask
& SPAN_XY
) {
980 rb
->PutValues(ctx
, rb
, span
->end
, span
->array
->x
, span
->array
->y
,
981 values
, span
->array
->mask
);
984 rb
->PutRow(ctx
, rb
, span
->end
, span
->x
, span
->y
,
985 values
, span
->array
->mask
);
991 /* restore default dest buffer */
992 _swrast_use_draw_buffer(ctx
);
995 span
->interpMask
= origInterpMask
;
996 span
->arrayMask
= origArrayMask
;
1001 * Add specular color to base color. This is used only when
1002 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1005 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1008 for (i
= 0; i
< n
; i
++) {
1009 #if CHAN_TYPE == GL_FLOAT
1011 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1012 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1013 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1015 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1016 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1017 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1018 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1019 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1020 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1027 * XXX merge this code into the _swrast_write_rgba_span() routine!
1029 * Draw to more than one RGBA color buffer (or none).
1030 * All fragment operations, up to (but not) blending/logicop should
1031 * have been done first.
1034 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
1036 #if OLD_RENDERBUFFER || NEW_RENDERBUFFER
1037 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1039 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1040 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1041 const GLuint output
= 0;
1044 ASSERT(span
->end
< MAX_WIDTH
);
1045 ASSERT(colorMask
!= 0x0);
1047 for (i
= 0; i
< fb
->_NumColorDrawBuffers
[output
]; i
++) {
1048 struct gl_renderbuffer
*rb
= fb
->_ColorDrawBuffers
[output
][i
];
1049 GLchan rgbaTmp
[MAX_WIDTH
][4];
1051 #if OLD_RENDERBUFFER || NEW_RENDERBUFFER
1053 GLuint bufferBit
= fb
->_ColorDrawBit
[output
][i
];
1054 /* Set the current read/draw buffer */
1055 swrast
->CurrentBufferBit
= bufferBit
;
1056 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
1059 /* make copy of incoming colors */
1060 MEMCPY( rgbaTmp
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
) );
1062 if (ctx
->Color
._LogicOpEnabled
) {
1063 _swrast_logicop_rgba_span(ctx
, rb
, span
, rgbaTmp
);
1065 else if (ctx
->Color
.BlendEnabled
) {
1066 _swrast_blend_span(ctx
, rb
, span
, rgbaTmp
);
1069 if (colorMask
!= 0xffffffff) {
1070 _swrast_mask_rgba_span(ctx
, rb
, span
, rgbaTmp
);
1073 if (span
->arrayMask
& SPAN_XY
) {
1074 /* array of pixel coords */
1075 ASSERT(rb
->PutValues
);
1076 rb
->PutValues(ctx
, rb
, span
->end
, span
->array
->x
,
1077 span
->array
->y
, rgbaTmp
, span
->array
->mask
);
1080 /* horizontal run of pixels */
1082 rb
->PutRow(ctx
, rb
, span
->end
, span
->x
, span
->y
, rgbaTmp
,
1087 #if OLD_RENDERBUFFER || NEW_RENDERBUFFER
1088 /* restore default dest buffer */
1089 _swrast_use_draw_buffer(ctx
);
1095 * Apply all the per-fragment operations to a span.
1096 * This now includes texturing (_swrast_write_texture_span() is history).
1097 * This function may modify any of the array values in the span.
1098 * span->interpMask and span->arrayMask may be changed but will be restored
1099 * to their original values before returning.
1102 _swrast_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
1104 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1105 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1106 const GLuint origInterpMask
= span
->interpMask
;
1107 const GLuint origArrayMask
= span
->arrayMask
;
1109 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1110 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1111 ASSERT(span
->end
<= MAX_WIDTH
);
1112 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1115 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__,
1116 span->interpMask, span->arrayMask);
1119 if (span
->arrayMask
& SPAN_MASK
) {
1120 /* mask was initialized by caller, probably glBitmap */
1121 span
->writeAll
= GL_FALSE
;
1124 _mesa_memset(span
->array
->mask
, 1, span
->end
);
1125 span
->writeAll
= GL_TRUE
;
1128 /* Clip to window/scissor box */
1129 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1130 if (!clip_span(ctx
, span
)) {
1136 /* Make sure all fragments are within window bounds */
1137 if (span
->arrayMask
& SPAN_XY
) {
1139 for (i
= 0; i
< span
->end
; i
++) {
1140 if (span
->array
->mask
[i
]) {
1141 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1142 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1143 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1144 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1150 /* Polygon Stippling */
1151 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1152 stipple_polygon_span(ctx
, span
);
1155 /* Interpolate texcoords? */
1156 if (ctx
->Texture
._EnabledCoordUnits
1157 && (span
->interpMask
& SPAN_TEXTURE
)
1158 && (span
->arrayMask
& SPAN_TEXTURE
) == 0) {
1159 interpolate_texcoords(ctx
, span
);
1162 /* If the alpha test is enabled, we have to compute the fragment colors
1163 * at this point and do the alpha test.
1164 * Else, if alpha test is not enabled, we'll try to defer fragment
1165 * color computation (by interpolation, texture mapping, fragment program)
1166 * until after the Z/stencil tests in the hope that many fragments will
1167 * get culled, leaving less work to do.
1169 if (ctx
->Color
.AlphaEnabled
) {
1170 /* Now we need the rgba array, fill it in if needed */
1171 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1172 interpolate_colors(ctx
, span
);
1174 if (span
->interpMask
& SPAN_SPEC
)
1175 interpolate_specular(ctx
, span
);
1177 if (span
->interpMask
& SPAN_FOG
)
1178 interpolate_fog(ctx
, span
);
1180 /* Compute fragment colors with fragment program or texture lookups */
1181 if (ctx
->FragmentProgram
._Active
)
1182 /* XXX interpolate depth values here??? */
1183 _swrast_exec_fragment_program( ctx
, span
);
1184 else if (ctx
->ATIFragmentShader
._Enabled
)
1185 _swrast_exec_fragment_shader( ctx
, span
);
1186 else if (ctx
->Texture
._EnabledUnits
)
1187 _swrast_texture_span( ctx
, span
);
1189 /* Do the alpha test */
1190 if (!_swrast_alpha_test(ctx
, span
)) {
1191 span
->arrayMask
= origArrayMask
;
1196 /* Stencil and Z testing */
1197 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1198 if (span
->interpMask
& SPAN_Z
)
1199 _swrast_span_interpolate_z(ctx
, span
);
1201 if (ctx
->Stencil
.Enabled
&& ctx
->DrawBuffer
->Visual
.stencilBits
> 0) {
1202 /* Combined Z/stencil tests */
1203 if (!_swrast_stencil_and_ztest_span(ctx
, span
)) {
1204 span
->interpMask
= origInterpMask
;
1205 span
->arrayMask
= origArrayMask
;
1209 else if (ctx
->DrawBuffer
->Visual
.depthBits
> 0) {
1210 /* Just regular depth testing */
1211 ASSERT(ctx
->Depth
.Test
);
1212 ASSERT(span
->arrayMask
& SPAN_Z
);
1213 if (!_swrast_depth_test_span(ctx
, span
)) {
1214 span
->interpMask
= origInterpMask
;
1215 span
->arrayMask
= origArrayMask
;
1221 /* if we get here, some fragments passed the depth test */
1222 if (ctx
->Depth
.OcclusionTest
) {
1223 ctx
->OcclusionResult
= GL_TRUE
;
1226 #if FEATURE_ARB_occlusion_query
1227 if (ctx
->Occlusion
.Active
) {
1228 /* update count of 'passed' fragments */
1230 for (i
= 0; i
< span
->end
; i
++)
1231 ctx
->Occlusion
.PassedCounter
+= span
->array
->mask
[i
];
1235 /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1236 * the occlusion test.
1238 if (colorMask
== 0x0) {
1239 span
->interpMask
= origInterpMask
;
1240 span
->arrayMask
= origArrayMask
;
1244 /* If the alpha test isn't enabled, we're able to defer computing fragment
1245 * colors (by interpolation, texturing, fragment program) until now.
1246 * Hopefully, Z/stencil tests culled many of the fragments!
1248 if (!ctx
->Color
.AlphaEnabled
) {
1249 /* Now we need the rgba array, fill it in if needed */
1250 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1251 interpolate_colors(ctx
, span
);
1253 if (span
->interpMask
& SPAN_SPEC
)
1254 interpolate_specular(ctx
, span
);
1256 if (span
->interpMask
& SPAN_FOG
)
1257 interpolate_fog(ctx
, span
);
1259 if (ctx
->FragmentProgram
._Active
)
1260 _swrast_exec_fragment_program( ctx
, span
);
1261 else if (ctx
->ATIFragmentShader
._Enabled
)
1262 _swrast_exec_fragment_shader( ctx
, span
);
1263 else if (ctx
->Texture
._EnabledUnits
)
1264 _swrast_texture_span( ctx
, span
);
1267 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1269 if (!ctx
->FragmentProgram
._Enabled
) {
1270 /* Add base and specular colors */
1271 if (ctx
->Fog
.ColorSumEnabled
||
1272 (ctx
->Light
.Enabled
&&
1273 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1274 if (span
->interpMask
& SPAN_SPEC
) {
1275 interpolate_specular(ctx
, span
);
1277 if (span
->arrayMask
& SPAN_SPEC
) {
1278 add_colors( span
->end
, span
->array
->rgba
, span
->array
->spec
);
1281 /* We probably added the base/specular colors during the
1289 if (swrast
->_FogEnabled
) {
1290 _swrast_fog_rgba_span(ctx
, span
);
1293 /* Antialias coverage application */
1294 if (span
->arrayMask
& SPAN_COVERAGE
) {
1295 GLchan (*rgba
)[4] = span
->array
->rgba
;
1296 GLfloat
*coverage
= span
->array
->coverage
;
1298 for (i
= 0; i
< span
->end
; i
++) {
1299 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1303 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1304 /* need to do blend/logicop separately for each color buffer */
1305 multi_write_rgba_span(ctx
, span
);
1308 /* normal: write to exactly one buffer */
1309 struct gl_renderbuffer
*rb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[0][0];
1311 if (ctx
->Color
._LogicOpEnabled
) {
1312 _swrast_logicop_rgba_span(ctx
, rb
, span
, span
->array
->rgba
);
1314 else if (ctx
->Color
.BlendEnabled
) {
1315 _swrast_blend_span(ctx
, rb
, span
, span
->array
->rgba
);
1318 /* Color component masking */
1319 if (colorMask
!= 0xffffffff) {
1320 _swrast_mask_rgba_span(ctx
, rb
, span
, span
->array
->rgba
);
1323 /* Finally, write the pixels to a color buffer */
1324 if (span
->arrayMask
& SPAN_XY
) {
1325 /* array of pixel coords */
1326 ASSERT(rb
->PutValues
);
1327 ASSERT(rb
->_BaseFormat
== GL_RGB
|| rb
->_BaseFormat
== GL_RGBA
);
1328 /* XXX check datatype */
1329 rb
->PutValues(ctx
, rb
, span
->end
, span
->array
->x
, span
->array
->y
,
1330 span
->array
->rgba
, span
->array
->mask
);
1333 /* horizontal run of pixels */
1335 ASSERT(rb
->_BaseFormat
== GL_RGB
|| rb
->_BaseFormat
== GL_RGBA
);
1336 /* XXX check datatype */
1337 rb
->PutRow(ctx
, rb
, span
->end
, span
->x
, span
->y
, span
->array
->rgba
,
1338 span
->writeAll
? NULL
: span
->array
->mask
);
1342 span
->interpMask
= origInterpMask
;
1343 span
->arrayMask
= origArrayMask
;
1349 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1350 * reading ouside the buffer's boundaries.
1353 _swrast_read_rgba_span( GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1354 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1356 const GLint bufWidth
= (GLint
) rb
->Width
;
1357 const GLint bufHeight
= (GLint
) rb
->Height
;
1359 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1360 /* completely above, below, or right */
1361 /* XXX maybe leave rgba values undefined? */
1362 _mesa_bzero(rgba
, 4 * n
* sizeof(GLchan
));
1367 /* left edge clippping */
1369 length
= (GLint
) n
- skip
;
1371 /* completely left of window */
1374 if (length
> bufWidth
) {
1378 else if ((GLint
) (x
+ n
) > bufWidth
) {
1379 /* right edge clipping */
1381 length
= bufWidth
- x
;
1383 /* completely to right of window */
1395 ASSERT(rb
->_BaseFormat
== GL_RGB
|| rb
->_BaseFormat
== GL_RGBA
);
1396 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
1397 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
, rgba
+ skip
);
1403 * Read CI pixels from frame buffer. Clipping will be done to prevent
1404 * reading ouside the buffer's boundaries.
1407 _swrast_read_index_span( GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1408 GLuint n
, GLint x
, GLint y
, GLuint index
[] )
1410 const GLint bufWidth
= (GLint
) rb
->Width
;
1411 const GLint bufHeight
= (GLint
) rb
->Height
;
1413 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1414 /* completely above, below, or right */
1415 _mesa_bzero(index
, n
* sizeof(GLuint
));
1420 /* left edge clippping */
1422 length
= (GLint
) n
- skip
;
1424 /* completely left of window */
1427 if (length
> bufWidth
) {
1431 else if ((GLint
) (x
+ n
) > bufWidth
) {
1432 /* right edge clipping */
1434 length
= bufWidth
- x
;
1436 /* completely to right of window */
1447 ASSERT(rb
->_BaseFormat
== GL_COLOR_INDEX
);
1449 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1450 GLubyte index8
[MAX_WIDTH
];
1452 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
, index8
);
1453 for (i
= 0; i
< length
; i
++)
1454 index
[skip
+ i
] = index8
[i
];
1456 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
1457 GLushort index16
[MAX_WIDTH
];
1459 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
, index16
);
1460 for (i
= 0; i
< length
; i
++)
1461 index
[skip
+ i
] = index16
[i
];
1463 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
1464 rb
->GetRow(ctx
, rb
, length
, x
+ skip
, y
, index
+ skip
);