1 /* $Id: s_span.c,v 1.49 2002/10/11 17:41:06 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * \file swrast/s_span.c
30 * \brief Span processing functions used by all rasterization functions.
31 * This is where all the per-fragment tests are performed
43 #include "s_alphabuf.h"
45 #include "s_context.h"
49 #include "s_masking.h"
51 #include "s_stencil.h"
52 #include "s_texture.h"
56 * Init span's Z interpolation values to the RasterPos Z.
57 * Used during setup for glDraw/CopyPixels.
60 _mesa_span_default_z( GLcontext
*ctx
, struct sw_span
*span
)
62 if (ctx
->Visual
.depthBits
<= 16)
63 span
->z
= FloatToFixed(ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
);
65 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
);
67 span
->interpMask
|= SPAN_Z
;
72 * Init span's fog interpolation values to the RasterPos fog.
73 * Used during setup for glDraw/CopyPixels.
76 _mesa_span_default_fog( GLcontext
*ctx
, struct sw_span
*span
)
78 span
->fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
80 span
->interpMask
|= SPAN_FOG
;
85 * Init span's color or index interpolation values to the RasterPos color.
86 * Used during setup for glDraw/CopyPixels.
89 _mesa_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
= IntToFixed(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 _mesa_span_default_texcoords( GLcontext
*ctx
, struct sw_span
*span
)
130 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
131 COPY_4V(span
->tex
[i
], ctx
->Current
.RasterTexCoords
[i
]);
132 ASSIGN_4V(span
->texStepX
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
133 ASSIGN_4V(span
->texStepY
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
135 span
->interpMask
|= SPAN_TEXTURE
;
139 /* Fill in the span.color.rgba array from the interpolation values */
141 interpolate_colors(GLcontext
*ctx
, struct sw_span
*span
)
143 GLfixed r
= span
->red
;
144 GLfixed g
= span
->green
;
145 GLfixed b
= span
->blue
;
146 GLfixed a
= span
->alpha
;
147 const GLint dr
= span
->redStep
;
148 const GLint dg
= span
->greenStep
;
149 const GLint db
= span
->blueStep
;
150 const GLint da
= span
->alphaStep
;
151 const GLuint n
= span
->end
;
152 GLchan (*rgba
)[4] = span
->array
->rgba
;
155 ASSERT((span
->interpMask
& SPAN_RGBA
) &&
156 !(span
->arrayMask
& SPAN_RGBA
));
158 if (span
->interpMask
& SPAN_FLAT
) {
161 color
[RCOMP
] = FixedToChan(r
);
162 color
[GCOMP
] = FixedToChan(g
);
163 color
[BCOMP
] = FixedToChan(b
);
164 color
[ACOMP
] = FixedToChan(a
);
165 for (i
= 0; i
< n
; i
++) {
166 COPY_CHAN4(span
->array
->rgba
[i
], color
);
171 for (i
= 0; i
< n
; i
++) {
172 rgba
[i
][RCOMP
] = FixedToChan(r
);
173 rgba
[i
][GCOMP
] = FixedToChan(g
);
174 rgba
[i
][BCOMP
] = FixedToChan(b
);
175 rgba
[i
][ACOMP
] = FixedToChan(a
);
182 span
->arrayMask
|= SPAN_RGBA
;
186 /* Fill in the span.color.index array from the interpolation values */
188 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
190 GLfixed index
= span
->index
;
191 const GLint indexStep
= span
->indexStep
;
192 const GLuint n
= span
->end
;
193 GLuint
*indexes
= span
->array
->index
;
195 ASSERT((span
->interpMask
& SPAN_INDEX
) &&
196 !(span
->arrayMask
& SPAN_INDEX
));
198 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
200 index
= FixedToInt(index
);
201 for (i
= 0; i
< n
; i
++) {
207 for (i
= 0; i
< n
; i
++) {
208 indexes
[i
] = FixedToInt(index
);
212 span
->arrayMask
|= SPAN_INDEX
;
216 /* Fill in the span.->array->spec array from the interpolation values */
218 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
220 if (span
->interpMask
& SPAN_FLAT
) {
222 const GLchan r
= FixedToChan(span
->specRed
);
223 const GLchan g
= FixedToChan(span
->specGreen
);
224 const GLchan b
= FixedToChan(span
->specBlue
);
226 for (i
= 0; i
< span
->end
; i
++) {
227 span
->array
->spec
[i
][RCOMP
] = r
;
228 span
->array
->spec
[i
][GCOMP
] = g
;
229 span
->array
->spec
[i
][BCOMP
] = b
;
234 #if CHAN_TYPE == GL_FLOAT
235 GLfloat r
= span
->specRed
;
236 GLfloat g
= span
->specGreen
;
237 GLfloat b
= span
->specBlue
;
239 GLfixed r
= span
->specRed
;
240 GLfixed g
= span
->specGreen
;
241 GLfixed b
= span
->specBlue
;
244 for (i
= 0; i
< span
->end
; i
++) {
245 span
->array
->spec
[i
][RCOMP
] = FixedToChan(r
);
246 span
->array
->spec
[i
][GCOMP
] = FixedToChan(g
);
247 span
->array
->spec
[i
][BCOMP
] = FixedToChan(b
);
248 r
+= span
->specRedStep
;
249 g
+= span
->specGreenStep
;
250 b
+= span
->specBlueStep
;
253 span
->arrayMask
|= SPAN_SPEC
;
257 /* Fill in the span.zArray array from the interpolation values */
259 _mesa_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
261 const GLuint n
= span
->end
;
264 ASSERT((span
->interpMask
& SPAN_Z
) &&
265 !(span
->arrayMask
& SPAN_Z
));
267 if (ctx
->Visual
.depthBits
<= 16) {
268 GLfixed zval
= span
->z
;
269 GLdepth
*z
= span
->array
->z
;
270 for (i
= 0; i
< n
; i
++) {
271 z
[i
] = FixedToInt(zval
);
276 /* Deep Z buffer, no fixed->int shift */
277 GLfixed zval
= span
->z
;
278 GLdepth
*z
= span
->array
->z
;
279 for (i
= 0; i
< n
; i
++) {
284 span
->arrayMask
|= SPAN_Z
;
289 * This the ideal solution, as given in the OpenGL spec.
293 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
294 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
295 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
297 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
298 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
299 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
300 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
301 GLfloat x
= sqrt(dudx
* dudx
+ dvdx
* dvdx
);
302 GLfloat y
= sqrt(dudy
* dudy
+ dvdy
* dvdy
);
303 GLfloat rho
= MAX2(x
, y
);
304 GLfloat lambda
= LOG2(rho
);
311 * This is a faster approximation
314 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
315 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
316 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
318 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
319 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
320 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
321 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
322 GLfloat maxU
, maxV
, rho
, lambda
;
323 dsdx2
= FABSF(dsdx2
);
324 dsdy2
= FABSF(dsdy2
);
325 dtdx2
= FABSF(dtdx2
);
326 dtdy2
= FABSF(dtdy2
);
327 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
328 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
329 rho
= MAX2(maxU
, maxV
);
335 * Fill in the span.texcoords array from the interpolation values.
336 * XXX We could optimize here for the case when dq = 0. That would
337 * usually be the case when using an orthographic projection.
340 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
342 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
343 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
345 if (ctx
->Texture
._EnabledUnits
> 1) {
348 span
->arrayMask
|= SPAN_TEXTURE
;
349 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
350 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
351 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
352 const struct gl_texture_image
*img
= obj
->Image
[obj
->BaseLevel
];
353 GLboolean needLambda
= (obj
->MinFilter
!= obj
->MagFilter
);
355 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
356 GLfloat
*lambda
= span
->array
->lambda
[u
];
357 const GLfloat texW
= (GLfloat
) img
->WidthScale
;
358 const GLfloat texH
= (GLfloat
) img
->HeightScale
;
359 const GLfloat dsdx
= span
->texStepX
[u
][0];
360 const GLfloat dsdy
= span
->texStepY
[u
][0];
361 const GLfloat dtdx
= span
->texStepX
[u
][1];
362 const GLfloat dtdy
= span
->texStepY
[u
][1];
363 const GLfloat drdx
= span
->texStepX
[u
][2];
364 const GLfloat dqdx
= span
->texStepX
[u
][3];
365 const GLfloat dqdy
= span
->texStepY
[u
][3];
366 GLfloat s
= span
->tex
[u
][0];
367 GLfloat t
= span
->tex
[u
][1];
368 GLfloat r
= span
->tex
[u
][2];
369 GLfloat q
= span
->tex
[u
][3];
371 for (i
= 0; i
< span
->end
; i
++) {
372 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
373 texcoord
[i
][0] = s
* invQ
;
374 texcoord
[i
][1] = t
* invQ
;
375 texcoord
[i
][2] = r
* invQ
;
376 lambda
[i
] = compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
377 dqdx
, dqdy
, texW
, texH
,
384 span
->arrayMask
|= SPAN_LAMBDA
;
387 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
388 GLfloat
*lambda
= span
->array
->lambda
[u
];
389 const GLfloat dsdx
= span
->texStepX
[u
][0];
390 const GLfloat dtdx
= span
->texStepX
[u
][1];
391 const GLfloat drdx
= span
->texStepX
[u
][2];
392 const GLfloat dqdx
= span
->texStepX
[u
][3];
393 GLfloat s
= span
->tex
[u
][0];
394 GLfloat t
= span
->tex
[u
][1];
395 GLfloat r
= span
->tex
[u
][2];
396 GLfloat q
= span
->tex
[u
][3];
399 /* Ortho projection or polygon's parallel to window X axis */
400 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
401 for (i
= 0; i
< span
->end
; i
++) {
402 texcoord
[i
][0] = s
* invQ
;
403 texcoord
[i
][1] = t
* invQ
;
404 texcoord
[i
][2] = r
* invQ
;
412 for (i
= 0; i
< span
->end
; i
++) {
413 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
414 texcoord
[i
][0] = s
* invQ
;
415 texcoord
[i
][1] = t
* invQ
;
416 texcoord
[i
][2] = r
* invQ
;
430 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
431 const struct gl_texture_image
*img
= obj
->Image
[obj
->BaseLevel
];
432 GLboolean needLambda
= (obj
->MinFilter
!= obj
->MagFilter
);
433 span
->arrayMask
|= SPAN_TEXTURE
;
435 /* just texture unit 0, with lambda */
436 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
437 GLfloat
*lambda
= span
->array
->lambda
[0];
438 const GLfloat texW
= (GLfloat
) img
->WidthScale
;
439 const GLfloat texH
= (GLfloat
) img
->HeightScale
;
440 const GLfloat dsdx
= span
->texStepX
[0][0];
441 const GLfloat dsdy
= span
->texStepY
[0][0];
442 const GLfloat dtdx
= span
->texStepX
[0][1];
443 const GLfloat dtdy
= span
->texStepY
[0][1];
444 const GLfloat drdx
= span
->texStepX
[0][2];
445 const GLfloat dqdx
= span
->texStepX
[0][3];
446 const GLfloat dqdy
= span
->texStepY
[0][3];
447 GLfloat s
= span
->tex
[0][0];
448 GLfloat t
= span
->tex
[0][1];
449 GLfloat r
= span
->tex
[0][2];
450 GLfloat q
= span
->tex
[0][3];
452 for (i
= 0; i
< span
->end
; i
++) {
453 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
454 lambda
[i
] = compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
455 dqdx
, dqdy
, texW
, texH
,
457 texcoord
[i
][0] = s
* invQ
;
458 texcoord
[i
][1] = t
* invQ
;
459 texcoord
[i
][2] = r
* invQ
;
465 span
->arrayMask
|= SPAN_LAMBDA
;
468 /* just texture 0, without lambda */
469 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
470 const GLfloat dsdx
= span
->texStepX
[0][0];
471 const GLfloat dtdx
= span
->texStepX
[0][1];
472 const GLfloat drdx
= span
->texStepX
[0][2];
473 const GLfloat dqdx
= span
->texStepX
[0][3];
474 GLfloat s
= span
->tex
[0][0];
475 GLfloat t
= span
->tex
[0][1];
476 GLfloat r
= span
->tex
[0][2];
477 GLfloat q
= span
->tex
[0][3];
480 /* Ortho projection or polygon's parallel to window X axis */
481 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
482 for (i
= 0; i
< span
->end
; i
++) {
483 texcoord
[i
][0] = s
* invQ
;
484 texcoord
[i
][1] = t
* invQ
;
485 texcoord
[i
][2] = r
* invQ
;
492 for (i
= 0; i
< span
->end
; i
++) {
493 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
494 texcoord
[i
][0] = s
* invQ
;
495 texcoord
[i
][1] = t
* invQ
;
496 texcoord
[i
][2] = r
* invQ
;
509 * Apply the current polygon stipple pattern to a span of pixels.
512 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
514 const GLuint highbit
= 0x80000000;
515 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
516 GLubyte
*mask
= span
->array
->mask
;
519 ASSERT(ctx
->Polygon
.StippleFlag
);
520 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
522 m
= highbit
>> (GLuint
) (span
->x
% 32);
524 for (i
= 0; i
< span
->end
; i
++) {
525 if ((m
& stipple
) == 0) {
533 span
->writeAll
= GL_FALSE
;
538 * Clip a pixel span to the current buffer/window boundaries:
539 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
540 * window clipping and scissoring.
541 * Return: GL_TRUE some pixels still visible
542 * GL_FALSE nothing visible
545 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
547 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
548 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
549 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
550 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
552 if (span
->arrayMask
& SPAN_XY
) {
553 /* arrays of x/y pixel coords */
554 const GLint
*x
= span
->array
->x
;
555 const GLint
*y
= span
->array
->y
;
556 const GLint n
= span
->end
;
557 GLubyte
*mask
= span
->array
->mask
;
559 if (span
->arrayMask
& SPAN_MASK
) {
560 /* note: using & intead of && to reduce branches */
561 for (i
= 0; i
< n
; i
++) {
562 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
563 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
567 /* note: using & intead of && to reduce branches */
568 for (i
= 0; i
< n
; i
++) {
569 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
570 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
573 return GL_TRUE
; /* some pixels visible */
576 /* horizontal span of pixels */
577 const GLint x
= span
->x
;
578 const GLint y
= span
->y
;
579 const GLint n
= span
->end
;
581 /* Trivial rejection tests */
582 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
584 return GL_FALSE
; /* all pixels clipped */
587 /* Clip to the left */
589 ASSERT(x
+ n
> xmin
);
590 span
->writeAll
= GL_FALSE
;
591 BZERO(span
->array
->mask
, (xmin
- x
) * sizeof(GLubyte
));
597 span
->end
= xmax
- x
;
600 return GL_TRUE
; /* some pixels visible */
607 * Draw to more than one color buffer (or none).
610 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
612 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
615 /* loop over four possible dest color buffers */
616 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
617 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
618 GLuint indexTmp
[MAX_WIDTH
];
619 ASSERT(span
->end
< MAX_WIDTH
);
621 /* Set the current read/draw buffer */
622 swrast
->CurrentBuffer
= bufferBit
;
623 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
625 /* make copy of incoming indexes */
626 MEMCPY( indexTmp
, span
->array
->index
, span
->end
* sizeof(GLuint
) );
628 if (ctx
->Color
.IndexLogicOpEnabled
) {
629 _mesa_logicop_ci_span(ctx
, span
, indexTmp
);
632 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
633 _mesa_mask_index_span(ctx
, span
, indexTmp
);
636 if (span
->arrayMask
& SPAN_XY
) {
637 /* array of pixel coords */
638 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
639 span
->array
->x
, span
->array
->y
,
640 indexTmp
, span
->array
->mask
);
643 /* horizontal run of pixels */
644 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
645 indexTmp
, span
->array
->mask
);
650 /* restore default dest buffer */
651 _swrast_use_draw_buffer(ctx
);
656 * Draw to more than one RGBA color buffer (or none).
657 * All fragment operations, up to (but not) blending/logicop should
658 * have been done first.
661 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
663 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
665 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
667 ASSERT(colorMask
!= 0x0);
669 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
672 /* loop over four possible dest color buffers */
673 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
674 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
675 GLchan rgbaTmp
[MAX_WIDTH
][4];
676 ASSERT(span
->end
< MAX_WIDTH
);
678 /* Set the current read/draw buffer */
679 swrast
->CurrentBuffer
= bufferBit
;
680 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
682 /* make copy of incoming colors */
683 MEMCPY( rgbaTmp
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
) );
685 if (ctx
->Color
.ColorLogicOpEnabled
) {
686 _mesa_logicop_rgba_span(ctx
, span
, rgbaTmp
);
688 else if (ctx
->Color
.BlendEnabled
) {
689 _mesa_blend_span(ctx
, span
, rgbaTmp
);
692 if (colorMask
!= 0xffffffff) {
693 _mesa_mask_rgba_span(ctx
, span
, rgbaTmp
);
696 if (span
->arrayMask
& SPAN_XY
) {
697 /* array of pixel coords */
698 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
699 span
->array
->x
, span
->array
->y
,
700 (const GLchan (*)[4]) rgbaTmp
,
702 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
703 _mesa_write_alpha_pixels(ctx
, span
->end
,
704 span
->array
->x
, span
->array
->y
,
705 (const GLchan (*)[4]) rgbaTmp
,
710 /* horizontal run of pixels */
711 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
712 (const GLchan (*)[4]) rgbaTmp
,
714 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
715 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
716 (const GLchan (*)[4]) rgbaTmp
,
723 /* restore default dest buffer */
724 _swrast_use_draw_buffer(ctx
);
730 * This function may modify any of the array values in the span.
731 * span->interpMask and span->arrayMask may be changed but will be restored
732 * to their original values before returning.
735 _mesa_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
737 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
738 const GLuint origInterpMask
= span
->interpMask
;
739 const GLuint origArrayMask
= span
->arrayMask
;
741 ASSERT(span
->end
<= MAX_WIDTH
);
742 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
743 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
744 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
745 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
747 if (span
->arrayMask
& SPAN_MASK
) {
748 /* mask was initialized by caller, probably glBitmap */
749 span
->writeAll
= GL_FALSE
;
752 MEMSET(span
->array
->mask
, 1, span
->end
);
753 span
->writeAll
= GL_TRUE
;
757 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
758 if (!clip_span(ctx
, span
)) {
764 if (span
->arrayMask
& SPAN_XY
) {
766 for (i
= 0; i
< span
->end
; i
++) {
767 if (span
->array
->mask
[i
]) {
768 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
769 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
770 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
771 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
777 /* Polygon Stippling */
778 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
779 stipple_polygon_span(ctx
, span
);
782 /* Depth test and stencil */
783 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
784 if (span
->interpMask
& SPAN_Z
)
785 _mesa_span_interpolate_z(ctx
, span
);
787 if (ctx
->Stencil
.Enabled
) {
788 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
789 span
->arrayMask
= origArrayMask
;
794 ASSERT(ctx
->Depth
.Test
);
795 if (!_mesa_depth_test_span(ctx
, span
)) {
796 span
->arrayMask
= origArrayMask
;
802 /* if we get here, something passed the depth test */
803 ctx
->OcclusionResult
= GL_TRUE
;
805 /* we have to wait until after occlusion to do this test */
806 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
807 /* write no pixels */
808 span
->arrayMask
= origArrayMask
;
812 /* Interpolate the color indexes if needed */
813 if (span
->interpMask
& SPAN_INDEX
) {
814 interpolate_indexes(ctx
, span
);
815 /* clear the bit - this allows the WriteMonoCISpan optimization below */
816 span
->interpMask
&= ~SPAN_INDEX
;
820 if (ctx
->Fog
.Enabled
) {
821 _mesa_fog_ci_span(ctx
, span
);
824 /* Antialias coverage application */
825 if (span
->arrayMask
& SPAN_COVERAGE
) {
827 GLuint
*index
= span
->array
->index
;
828 GLfloat
*coverage
= span
->array
->coverage
;
829 for (i
= 0; i
< span
->end
; i
++) {
830 ASSERT(coverage
[i
] < 16);
831 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) coverage
[i
]);
835 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
836 /* draw to zero or two or more buffers */
837 multi_write_index_span(ctx
, span
);
840 /* normal situation: draw to exactly one buffer */
841 if (ctx
->Color
.IndexLogicOpEnabled
) {
842 _mesa_logicop_ci_span(ctx
, span
, span
->array
->index
);
845 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
846 _mesa_mask_index_span(ctx
, span
, span
->array
->index
);
850 if (span
->arrayMask
& SPAN_XY
) {
851 /* array of pixel coords */
852 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
853 /* all pixels have same color index */
854 (*swrast
->Driver
.WriteMonoCIPixels
)(ctx
, span
->end
,
855 span
->array
->x
, span
->array
->y
,
856 FixedToInt(span
->index
),
860 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->array
->x
,
861 span
->array
->y
, span
->array
->index
,
866 /* horizontal run of pixels */
867 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
868 /* all pixels have same color index */
869 (*swrast
->Driver
.WriteMonoCISpan
)(ctx
, span
->end
, span
->x
, span
->y
,
870 FixedToInt(span
->index
),
874 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
881 span
->interpMask
= origInterpMask
;
882 span
->arrayMask
= origArrayMask
;
887 * This function may modify any of the array values in the span.
888 * span->interpMask and span->arrayMask may be changed but will be restored
889 * to their original values before returning.
892 _mesa_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
894 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
895 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
896 const GLuint origInterpMask
= span
->interpMask
;
897 const GLuint origArrayMask
= span
->arrayMask
;
900 ASSERT(span
->end
<= MAX_WIDTH
);
901 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
902 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
903 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
904 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_RGBA
);
906 if (ctx
->Fog
.Enabled
)
907 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
909 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_Z
);
912 if (span
->arrayMask
& SPAN_MASK
) {
913 /* mask was initialized by caller, probably glBitmap */
914 span
->writeAll
= GL_FALSE
;
917 MEMSET(span
->array
->mask
, 1, span
->end
);
918 span
->writeAll
= GL_TRUE
;
921 /* Determine if we have mono-chromatic colors */
922 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
923 span
->redStep
== 0 && span
->greenStep
== 0 &&
924 span
->blueStep
== 0 && span
->alphaStep
== 0;
927 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
928 if (!clip_span(ctx
, span
)) {
934 if (span
->arrayMask
& SPAN_XY
) {
936 for (i
= 0; i
< span
->end
; i
++) {
937 if (span
->array
->mask
[i
]) {
938 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
939 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
940 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
941 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
947 /* Polygon Stippling */
948 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
949 stipple_polygon_span(ctx
, span
);
952 /* Do the alpha test */
953 if (ctx
->Color
.AlphaEnabled
) {
954 if (!_mesa_alpha_test(ctx
, span
)) {
955 span
->interpMask
= origInterpMask
;
956 span
->arrayMask
= origArrayMask
;
961 /* Stencil and Z testing */
962 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
963 if (span
->interpMask
& SPAN_Z
)
964 _mesa_span_interpolate_z(ctx
, span
);
966 if (ctx
->Stencil
.Enabled
) {
967 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
968 span
->interpMask
= origInterpMask
;
969 span
->arrayMask
= origArrayMask
;
974 ASSERT(ctx
->Depth
.Test
);
975 ASSERT(span
->arrayMask
& SPAN_Z
);
976 /* regular depth testing */
977 if (!_mesa_depth_test_span(ctx
, span
)) {
978 span
->interpMask
= origInterpMask
;
979 span
->arrayMask
= origArrayMask
;
985 /* if we get here, something passed the depth test */
986 ctx
->OcclusionResult
= GL_TRUE
;
988 /* can't abort span-writing until after occlusion testing */
989 if (colorMask
== 0x0) {
990 span
->interpMask
= origInterpMask
;
991 span
->arrayMask
= origArrayMask
;
995 /* Now we may need to interpolate the colors */
996 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
997 interpolate_colors(ctx
, span
);
998 /* clear the bit - this allows the WriteMonoCISpan optimization below */
999 span
->interpMask
&= ~SPAN_RGBA
;
1003 if (ctx
->Fog
.Enabled
) {
1004 _mesa_fog_rgba_span(ctx
, span
);
1005 monoColor
= GL_FALSE
;
1008 /* Antialias coverage application */
1009 if (span
->arrayMask
& SPAN_COVERAGE
) {
1010 GLchan (*rgba
)[4] = span
->array
->rgba
;
1011 GLfloat
*coverage
= span
->array
->coverage
;
1013 for (i
= 0; i
< span
->end
; i
++) {
1014 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1016 monoColor
= GL_FALSE
;
1019 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1020 multi_write_rgba_span(ctx
, span
);
1023 /* normal: write to exactly one buffer */
1024 if (ctx
->Color
.ColorLogicOpEnabled
) {
1025 _mesa_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1026 monoColor
= GL_FALSE
;
1028 else if (ctx
->Color
.BlendEnabled
) {
1029 _mesa_blend_span(ctx
, span
, span
->array
->rgba
);
1030 monoColor
= GL_FALSE
;
1033 /* Color component masking */
1034 if (colorMask
!= 0xffffffff) {
1035 _mesa_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1036 monoColor
= GL_FALSE
;
1040 if (span
->arrayMask
& SPAN_XY
) {
1041 /* array of pixel coords */
1042 /* XXX test for mono color */
1043 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1044 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1045 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1046 _mesa_write_alpha_pixels(ctx
, span
->end
,
1047 span
->array
->x
, span
->array
->y
,
1048 (const GLchan (*)[4]) span
->array
->rgba
,
1053 /* horizontal run of pixels */
1055 /* all pixels have same color */
1057 color
[RCOMP
] = FixedToChan(span
->red
);
1058 color
[GCOMP
] = FixedToChan(span
->green
);
1059 color
[BCOMP
] = FixedToChan(span
->blue
);
1060 color
[ACOMP
] = FixedToChan(span
->alpha
);
1061 (*swrast
->Driver
.WriteMonoRGBASpan
)(ctx
, span
->end
, span
->x
,
1062 span
->y
, color
, span
->array
->mask
);
1063 /* XXX software alpha buffer writes! */
1066 /* each pixel is a different color */
1067 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1068 (const GLchan (*)[4]) span
->array
->rgba
,
1069 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1070 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1071 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1072 (const GLchan (*)[4]) span
->array
->rgba
,
1073 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1079 span
->interpMask
= origInterpMask
;
1080 span
->arrayMask
= origArrayMask
;
1085 * Add specular color to base color. This is used only when
1086 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1089 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1092 for (i
= 0; i
< n
; i
++) {
1093 #if CHAN_TYPE == GL_FLOAT
1095 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1096 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1097 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1099 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1100 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1101 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1102 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1103 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1104 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1111 * This function may modify any of the array values in the span.
1112 * span->interpMask and span->arrayMask may be changed but will be restored
1113 * to their original values before returning.
1116 _mesa_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
1118 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1119 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1120 const GLuint origArrayMask
= span
->arrayMask
;
1122 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1123 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1124 ASSERT(span
->end
<= MAX_WIDTH
);
1125 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1126 ASSERT(ctx
->Texture
._EnabledUnits
);
1129 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1132 if (span
->arrayMask
& SPAN_MASK
) {
1133 /* mask was initialized by caller, probably glBitmap */
1134 span
->writeAll
= GL_FALSE
;
1137 MEMSET(span
->array
->mask
, 1, span
->end
);
1138 span
->writeAll
= GL_TRUE
;
1142 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1143 if (!clip_span(ctx
, span
)) {
1149 if (span
->arrayMask
& SPAN_XY
) {
1151 for (i
= 0; i
< span
->end
; i
++) {
1152 if (span
->array
->mask
[i
]) {
1153 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1154 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1155 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1156 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1162 /* Polygon Stippling */
1163 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1164 stipple_polygon_span(ctx
, span
);
1167 /* Need texture coordinates now */
1168 if ((span
->interpMask
& SPAN_TEXTURE
)
1169 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1170 interpolate_texcoords(ctx
, span
);
1172 /* Texture with alpha test */
1173 if (ctx
->Color
.AlphaEnabled
) {
1175 /* Now we need the rgba array, fill it in if needed */
1176 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1177 interpolate_colors(ctx
, span
);
1179 /* Texturing without alpha is done after depth-testing which
1180 * gives a potential speed-up.
1182 _swrast_texture_span( ctx
, span
);
1184 /* Do the alpha test */
1185 if (!_mesa_alpha_test(ctx
, span
)) {
1186 span
->arrayMask
= origArrayMask
;
1191 /* Stencil and Z testing */
1192 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1193 if (span
->interpMask
& SPAN_Z
)
1194 _mesa_span_interpolate_z(ctx
, span
);
1196 if (ctx
->Stencil
.Enabled
) {
1197 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
1198 span
->arrayMask
= origArrayMask
;
1203 ASSERT(ctx
->Depth
.Test
);
1204 ASSERT(span
->arrayMask
& SPAN_Z
);
1205 /* regular depth testing */
1206 if (!_mesa_depth_test_span(ctx
, span
)) {
1207 span
->arrayMask
= origArrayMask
;
1213 /* if we get here, some fragments passed the depth test */
1214 ctx
->OcclusionResult
= GL_TRUE
;
1216 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1217 * the occlusion test.
1219 if (colorMask
== 0x0) {
1220 span
->arrayMask
= origArrayMask
;
1224 /* Texture without alpha test */
1225 if (!ctx
->Color
.AlphaEnabled
) {
1227 /* Now we need the rgba array, fill it in if needed */
1228 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1229 interpolate_colors(ctx
, span
);
1231 _swrast_texture_span( ctx
, span
);
1234 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1236 /* Add base and specular colors */
1237 if (ctx
->Fog
.ColorSumEnabled
||
1238 (ctx
->Light
.Enabled
&&
1239 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1240 if (span
->interpMask
& SPAN_SPEC
) {
1241 interpolate_specular(ctx
, span
);
1243 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1244 add_colors( span
->end
, span
->array
->rgba
, span
->array
->spec
);
1248 if (ctx
->Fog
.Enabled
) {
1249 _mesa_fog_rgba_span(ctx
, span
);
1252 /* Antialias coverage application */
1253 if (span
->arrayMask
& SPAN_COVERAGE
) {
1254 GLchan (*rgba
)[4] = span
->array
->rgba
;
1255 GLfloat
*coverage
= span
->array
->coverage
;
1257 for (i
= 0; i
< span
->end
; i
++) {
1258 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1262 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1263 multi_write_rgba_span(ctx
, span
);
1266 /* normal: write to exactly one buffer */
1267 if (ctx
->Color
.ColorLogicOpEnabled
) {
1268 _mesa_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1270 else if (ctx
->Color
.BlendEnabled
) {
1271 _mesa_blend_span(ctx
, span
, span
->array
->rgba
);
1274 if (colorMask
!= 0xffffffff) {
1275 _mesa_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1279 if (span
->arrayMask
& SPAN_XY
) {
1280 /* array of pixel coords */
1281 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1282 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1283 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1284 _mesa_write_alpha_pixels(ctx
, span
->end
,
1285 span
->array
->x
, span
->array
->y
,
1286 (const GLchan (*)[4]) span
->array
->rgba
,
1291 /* horizontal run of pixels */
1292 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1293 (const GLchan (*)[4]) span
->array
->rgba
,
1294 span
->writeAll
? NULL
: span
->array
->mask
);
1295 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1296 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1297 (const GLchan (*)[4]) span
->array
->rgba
,
1298 span
->writeAll
? NULL
: span
->array
->mask
);
1303 span
->arrayMask
= origArrayMask
;
1309 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1310 * reading ouside the buffer's boundaries.
1313 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1314 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1316 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1317 const GLint bufWidth
= (GLint
) buffer
->Width
;
1318 const GLint bufHeight
= (GLint
) buffer
->Height
;
1320 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1321 /* completely above, below, or right */
1322 /* XXX maybe leave undefined? */
1323 BZERO(rgba
, 4 * n
* sizeof(GLchan
));
1328 /* left edge clippping */
1330 length
= (GLint
) n
- skip
;
1332 /* completely left of window */
1335 if (length
> bufWidth
) {
1339 else if ((GLint
) (x
+ n
) > bufWidth
) {
1340 /* right edge clipping */
1342 length
= bufWidth
- x
;
1344 /* completely to right of window */
1354 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1355 if (buffer
->UseSoftwareAlphaBuffers
) {
1356 _mesa_read_alpha_span(ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1363 * Read CI pixels from frame buffer. Clipping will be done to prevent
1364 * reading ouside the buffer's boundaries.
1367 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1368 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1370 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1371 const GLint bufWidth
= (GLint
) buffer
->Width
;
1372 const GLint bufHeight
= (GLint
) buffer
->Height
;
1374 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1375 /* completely above, below, or right */
1376 BZERO(indx
, n
* sizeof(GLuint
));
1381 /* left edge clippping */
1383 length
= (GLint
) n
- skip
;
1385 /* completely left of window */
1388 if (length
> bufWidth
) {
1392 else if ((GLint
) (x
+ n
) > bufWidth
) {
1393 /* right edge clipping */
1395 length
= bufWidth
- x
;
1397 /* completely to right of window */
1407 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);