1 /* $Id: s_span.c,v 1.59 2003/03/16 22:02:37 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2003 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
42 #include "s_alphabuf.h"
44 #include "s_context.h"
48 #include "s_masking.h"
49 #include "s_nvfragprog.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
+ 0.5F
);
65 span
->z
= (GLint
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMax
+ 0.5F
);
67 span
->interpMask
|= SPAN_Z
;
72 * Init span's fog interpolation values to the RasterPos fog.
73 * Used during setup for glDraw/CopyPixels.
76 _mesa_span_default_fog( GLcontext
*ctx
, struct sw_span
*span
)
78 span
->fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
79 span
->fogStep
= span
->dfogdx
= span
->dfogdy
= 0.0F
;
80 span
->interpMask
|= SPAN_FOG
;
85 * Init span's 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 const GLuint n
= span
->end
;
144 GLchan (*rgba
)[4] = span
->array
->rgba
;
147 ASSERT((span
->interpMask
& SPAN_RGBA
) &&
148 !(span
->arrayMask
& SPAN_RGBA
));
150 if (span
->interpMask
& SPAN_FLAT
) {
153 color
[RCOMP
] = FixedToChan(span
->red
);
154 color
[GCOMP
] = FixedToChan(span
->green
);
155 color
[BCOMP
] = FixedToChan(span
->blue
);
156 color
[ACOMP
] = FixedToChan(span
->alpha
);
157 for (i
= 0; i
< n
; i
++) {
158 COPY_CHAN4(span
->array
->rgba
[i
], color
);
163 #if CHAN_TYPE == GL_FLOAT
164 GLfloat r
= span
->red
;
165 GLfloat g
= span
->green
;
166 GLfloat b
= span
->blue
;
167 GLfloat a
= span
->alpha
;
168 const GLfloat dr
= span
->redStep
;
169 const GLfloat dg
= span
->greenStep
;
170 const GLfloat db
= span
->blueStep
;
171 const GLfloat da
= span
->alphaStep
;
173 GLfixed r
= span
->red
;
174 GLfixed g
= span
->green
;
175 GLfixed b
= span
->blue
;
176 GLfixed a
= span
->alpha
;
177 const GLint dr
= span
->redStep
;
178 const GLint dg
= span
->greenStep
;
179 const GLint db
= span
->blueStep
;
180 const GLint da
= span
->alphaStep
;
182 for (i
= 0; i
< n
; i
++) {
183 rgba
[i
][RCOMP
] = FixedToChan(r
);
184 rgba
[i
][GCOMP
] = FixedToChan(g
);
185 rgba
[i
][BCOMP
] = FixedToChan(b
);
186 rgba
[i
][ACOMP
] = FixedToChan(a
);
193 span
->arrayMask
|= SPAN_RGBA
;
197 /* Fill in the span.color.index array from the interpolation values */
199 interpolate_indexes(GLcontext
*ctx
, struct sw_span
*span
)
201 GLfixed index
= span
->index
;
202 const GLint indexStep
= span
->indexStep
;
203 const GLuint n
= span
->end
;
204 GLuint
*indexes
= span
->array
->index
;
206 ASSERT((span
->interpMask
& SPAN_INDEX
) &&
207 !(span
->arrayMask
& SPAN_INDEX
));
209 if ((span
->interpMask
& SPAN_FLAT
) || (indexStep
== 0)) {
211 index
= FixedToInt(index
);
212 for (i
= 0; i
< n
; i
++) {
218 for (i
= 0; i
< n
; i
++) {
219 indexes
[i
] = FixedToInt(index
);
223 span
->arrayMask
|= SPAN_INDEX
;
227 /* Fill in the span.->array->spec array from the interpolation values */
229 interpolate_specular(GLcontext
*ctx
, struct sw_span
*span
)
231 if (span
->interpMask
& SPAN_FLAT
) {
233 const GLchan r
= FixedToChan(span
->specRed
);
234 const GLchan g
= FixedToChan(span
->specGreen
);
235 const GLchan b
= FixedToChan(span
->specBlue
);
237 for (i
= 0; i
< span
->end
; i
++) {
238 span
->array
->spec
[i
][RCOMP
] = r
;
239 span
->array
->spec
[i
][GCOMP
] = g
;
240 span
->array
->spec
[i
][BCOMP
] = b
;
245 #if CHAN_TYPE == GL_FLOAT
246 GLfloat r
= span
->specRed
;
247 GLfloat g
= span
->specGreen
;
248 GLfloat b
= span
->specBlue
;
250 GLfixed r
= span
->specRed
;
251 GLfixed g
= span
->specGreen
;
252 GLfixed b
= span
->specBlue
;
255 for (i
= 0; i
< span
->end
; i
++) {
256 span
->array
->spec
[i
][RCOMP
] = FixedToChan(r
);
257 span
->array
->spec
[i
][GCOMP
] = FixedToChan(g
);
258 span
->array
->spec
[i
][BCOMP
] = FixedToChan(b
);
259 r
+= span
->specRedStep
;
260 g
+= span
->specGreenStep
;
261 b
+= span
->specBlueStep
;
264 span
->arrayMask
|= SPAN_SPEC
;
268 /* Fill in the span.zArray array from the interpolation values */
270 _mesa_span_interpolate_z( const GLcontext
*ctx
, struct sw_span
*span
)
272 const GLuint n
= span
->end
;
275 ASSERT((span
->interpMask
& SPAN_Z
) &&
276 !(span
->arrayMask
& SPAN_Z
));
278 if (ctx
->Visual
.depthBits
<= 16) {
279 GLfixed zval
= span
->z
;
280 GLdepth
*z
= span
->array
->z
;
281 for (i
= 0; i
< n
; i
++) {
282 z
[i
] = FixedToInt(zval
);
287 /* Deep Z buffer, no fixed->int shift */
288 GLfixed zval
= span
->z
;
289 GLdepth
*z
= span
->array
->z
;
290 for (i
= 0; i
< n
; i
++) {
295 span
->arrayMask
|= SPAN_Z
;
300 * This the ideal solution, as given in the OpenGL spec.
304 compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
305 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
306 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
308 GLfloat dudx
= texW
* ((s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
);
309 GLfloat dvdx
= texH
* ((t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
);
310 GLfloat dudy
= texW
* ((s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
);
311 GLfloat dvdy
= texH
* ((t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
);
312 GLfloat x
= SQRTF(dudx
* dudx
+ dvdx
* dvdx
);
313 GLfloat y
= SQRTF(dudy
* dudy
+ dvdy
* dvdy
);
314 GLfloat rho
= MAX2(x
, y
);
315 GLfloat lambda
= LOG2(rho
);
322 * This is a faster approximation
325 _mesa_compute_lambda(GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
326 GLfloat dqdx
, GLfloat dqdy
, GLfloat texW
, GLfloat texH
,
327 GLfloat s
, GLfloat t
, GLfloat q
, GLfloat invQ
)
329 GLfloat dsdx2
= (s
+ dsdx
) / (q
+ dqdx
) - s
* invQ
;
330 GLfloat dtdx2
= (t
+ dtdx
) / (q
+ dqdx
) - t
* invQ
;
331 GLfloat dsdy2
= (s
+ dsdy
) / (q
+ dqdy
) - s
* invQ
;
332 GLfloat dtdy2
= (t
+ dtdy
) / (q
+ dqdy
) - t
* invQ
;
333 GLfloat maxU
, maxV
, rho
, lambda
;
334 dsdx2
= FABSF(dsdx2
);
335 dsdy2
= FABSF(dsdy2
);
336 dtdx2
= FABSF(dtdx2
);
337 dtdy2
= FABSF(dtdy2
);
338 maxU
= MAX2(dsdx2
, dsdy2
) * texW
;
339 maxV
= MAX2(dtdx2
, dtdy2
) * texH
;
340 rho
= MAX2(maxU
, maxV
);
346 * Fill in the span.texcoords array from the interpolation values.
347 * XXX We could optimize here for the case when dq = 0. That would
348 * usually be the case when using an orthographic projection.
351 interpolate_texcoords(GLcontext
*ctx
, struct sw_span
*span
)
353 ASSERT(span
->interpMask
& SPAN_TEXTURE
);
354 ASSERT(!(span
->arrayMask
& SPAN_TEXTURE
));
356 if (ctx
->Texture
._EnabledUnits
> 1) {
359 span
->arrayMask
|= SPAN_TEXTURE
;
360 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
361 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
362 const struct gl_texture_object
*obj
=ctx
->Texture
.Unit
[u
]._Current
;
363 const struct gl_texture_image
*img
= obj
->Image
[obj
->BaseLevel
];
364 const GLboolean needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
365 || ctx
->FragmentProgram
.Enabled
;
367 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[u
];
368 GLfloat
*lambda
= span
->array
->lambda
[u
];
369 const GLfloat texW
= (GLfloat
) img
->WidthScale
;
370 const GLfloat texH
= (GLfloat
) img
->HeightScale
;
371 const GLfloat dsdx
= span
->texStepX
[u
][0];
372 const GLfloat dsdy
= span
->texStepY
[u
][0];
373 const GLfloat dtdx
= span
->texStepX
[u
][1];
374 const GLfloat dtdy
= span
->texStepY
[u
][1];
375 const GLfloat drdx
= span
->texStepX
[u
][2];
376 const GLfloat dqdx
= span
->texStepX
[u
][3];
377 const GLfloat dqdy
= span
->texStepY
[u
][3];
378 GLfloat s
= span
->tex
[u
][0];
379 GLfloat t
= span
->tex
[u
][1];
380 GLfloat r
= span
->tex
[u
][2];
381 GLfloat q
= span
->tex
[u
][3];
383 for (i
= 0; i
< span
->end
; i
++) {
384 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
385 texcoord
[i
][0] = s
* invQ
;
386 texcoord
[i
][1] = t
* invQ
;
387 texcoord
[i
][2] = r
* invQ
;
389 lambda
[i
] = _mesa_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
390 dqdx
, dqdy
, texW
, texH
,
397 span
->arrayMask
|= SPAN_LAMBDA
;
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 dtdx
= span
->texStepX
[u
][1];
404 const GLfloat drdx
= span
->texStepX
[u
][2];
405 const GLfloat dqdx
= span
->texStepX
[u
][3];
406 GLfloat s
= span
->tex
[u
][0];
407 GLfloat t
= span
->tex
[u
][1];
408 GLfloat r
= span
->tex
[u
][2];
409 GLfloat q
= span
->tex
[u
][3];
412 /* Ortho projection or polygon's parallel to window X axis */
413 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
414 for (i
= 0; i
< span
->end
; i
++) {
415 texcoord
[i
][0] = s
* invQ
;
416 texcoord
[i
][1] = t
* invQ
;
417 texcoord
[i
][2] = r
* invQ
;
425 for (i
= 0; i
< span
->end
; i
++) {
426 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
427 texcoord
[i
][0] = s
* invQ
;
428 texcoord
[i
][1] = t
* invQ
;
429 texcoord
[i
][2] = r
* invQ
;
443 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
444 const struct gl_texture_image
*img
= obj
->Image
[obj
->BaseLevel
];
445 const GLboolean needLambda
= (obj
->MinFilter
!= obj
->MagFilter
)
446 || ctx
->FragmentProgram
.Enabled
;
447 span
->arrayMask
|= SPAN_TEXTURE
;
449 /* just texture unit 0, with lambda */
450 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
451 GLfloat
*lambda
= span
->array
->lambda
[0];
452 const GLfloat texW
= (GLfloat
) img
->WidthScale
;
453 const GLfloat texH
= (GLfloat
) img
->HeightScale
;
454 const GLfloat dsdx
= span
->texStepX
[0][0];
455 const GLfloat dsdy
= span
->texStepY
[0][0];
456 const GLfloat dtdx
= span
->texStepX
[0][1];
457 const GLfloat dtdy
= span
->texStepY
[0][1];
458 const GLfloat drdx
= span
->texStepX
[0][2];
459 const GLfloat dqdx
= span
->texStepX
[0][3];
460 const GLfloat dqdy
= span
->texStepY
[0][3];
461 GLfloat s
= span
->tex
[0][0];
462 GLfloat t
= span
->tex
[0][1];
463 GLfloat r
= span
->tex
[0][2];
464 GLfloat q
= span
->tex
[0][3];
466 for (i
= 0; i
< span
->end
; i
++) {
467 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
468 lambda
[i
] = _mesa_compute_lambda(dsdx
, dsdy
, dtdx
, dtdy
,
469 dqdx
, dqdy
, texW
, texH
,
471 texcoord
[i
][0] = s
* invQ
;
472 texcoord
[i
][1] = t
* invQ
;
473 texcoord
[i
][2] = r
* invQ
;
480 span
->arrayMask
|= SPAN_LAMBDA
;
483 /* just texture 0, without lambda */
484 GLfloat (*texcoord
)[4] = span
->array
->texcoords
[0];
485 const GLfloat dsdx
= span
->texStepX
[0][0];
486 const GLfloat dtdx
= span
->texStepX
[0][1];
487 const GLfloat drdx
= span
->texStepX
[0][2];
488 const GLfloat dqdx
= span
->texStepX
[0][3];
489 GLfloat s
= span
->tex
[0][0];
490 GLfloat t
= span
->tex
[0][1];
491 GLfloat r
= span
->tex
[0][2];
492 GLfloat q
= span
->tex
[0][3];
495 /* Ortho projection or polygon's parallel to window X axis */
496 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
497 for (i
= 0; i
< span
->end
; i
++) {
498 texcoord
[i
][0] = s
* invQ
;
499 texcoord
[i
][1] = t
* invQ
;
500 texcoord
[i
][2] = r
* invQ
;
507 for (i
= 0; i
< span
->end
; i
++) {
508 const GLfloat invQ
= (q
== 0.0F
) ? 1.0F
: (1.0F
/ q
);
509 texcoord
[i
][0] = s
* invQ
;
510 texcoord
[i
][1] = t
* invQ
;
511 texcoord
[i
][2] = r
* invQ
;
524 * Apply the current polygon stipple pattern to a span of pixels.
527 stipple_polygon_span( GLcontext
*ctx
, struct sw_span
*span
)
529 const GLuint highbit
= 0x80000000;
530 const GLuint stipple
= ctx
->PolygonStipple
[span
->y
% 32];
531 GLubyte
*mask
= span
->array
->mask
;
534 ASSERT(ctx
->Polygon
.StippleFlag
);
535 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
537 m
= highbit
>> (GLuint
) (span
->x
% 32);
539 for (i
= 0; i
< span
->end
; i
++) {
540 if ((m
& stipple
) == 0) {
548 span
->writeAll
= GL_FALSE
;
553 * Clip a pixel span to the current buffer/window boundaries:
554 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
555 * window clipping and scissoring.
556 * Return: GL_TRUE some pixels still visible
557 * GL_FALSE nothing visible
560 clip_span( GLcontext
*ctx
, struct sw_span
*span
)
562 const GLint xmin
= ctx
->DrawBuffer
->_Xmin
;
563 const GLint xmax
= ctx
->DrawBuffer
->_Xmax
;
564 const GLint ymin
= ctx
->DrawBuffer
->_Ymin
;
565 const GLint ymax
= ctx
->DrawBuffer
->_Ymax
;
567 if (span
->arrayMask
& SPAN_XY
) {
568 /* arrays of x/y pixel coords */
569 const GLint
*x
= span
->array
->x
;
570 const GLint
*y
= span
->array
->y
;
571 const GLint n
= span
->end
;
572 GLubyte
*mask
= span
->array
->mask
;
574 if (span
->arrayMask
& SPAN_MASK
) {
575 /* note: using & intead of && to reduce branches */
576 for (i
= 0; i
< n
; i
++) {
577 mask
[i
] &= (x
[i
] >= xmin
) & (x
[i
] < xmax
)
578 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
582 /* note: using & intead of && to reduce branches */
583 for (i
= 0; i
< n
; i
++) {
584 mask
[i
] = (x
[i
] >= xmin
) & (x
[i
] < xmax
)
585 & (y
[i
] >= ymin
) & (y
[i
] < ymax
);
588 return GL_TRUE
; /* some pixels visible */
591 /* horizontal span of pixels */
592 const GLint x
= span
->x
;
593 const GLint y
= span
->y
;
594 const GLint n
= span
->end
;
596 /* Trivial rejection tests */
597 if (y
< ymin
|| y
>= ymax
|| x
+ n
<= xmin
|| x
>= xmax
) {
599 return GL_FALSE
; /* all pixels clipped */
602 /* Clip to the left */
604 ASSERT(x
+ n
> xmin
);
605 span
->writeAll
= GL_FALSE
;
606 _mesa_bzero(span
->array
->mask
, (xmin
- x
) * sizeof(GLubyte
));
612 span
->end
= xmax
- x
;
615 return GL_TRUE
; /* some pixels visible */
622 * Draw to more than one color buffer (or none).
625 multi_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
627 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
630 /* loop over four possible dest color buffers */
631 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
632 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
633 GLuint indexTmp
[MAX_WIDTH
];
634 ASSERT(span
->end
< MAX_WIDTH
);
636 /* Set the current read/draw buffer */
637 swrast
->CurrentBuffer
= bufferBit
;
638 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
640 /* make copy of incoming indexes */
641 MEMCPY( indexTmp
, span
->array
->index
, span
->end
* sizeof(GLuint
) );
643 if (ctx
->Color
.IndexLogicOpEnabled
) {
644 _mesa_logicop_ci_span(ctx
, span
, indexTmp
);
647 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
648 _mesa_mask_index_span(ctx
, span
, indexTmp
);
651 if (span
->arrayMask
& SPAN_XY
) {
652 /* array of pixel coords */
653 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
,
654 span
->array
->x
, span
->array
->y
,
655 indexTmp
, span
->array
->mask
);
658 /* horizontal run of pixels */
659 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
660 indexTmp
, span
->array
->mask
);
665 /* restore default dest buffer */
666 _swrast_use_draw_buffer(ctx
);
671 * Draw to more than one RGBA color buffer (or none).
672 * All fragment operations, up to (but not) blending/logicop should
673 * have been done first.
676 multi_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
678 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
680 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
682 ASSERT(colorMask
!= 0x0);
684 if (ctx
->Color
.DrawBuffer
== GL_NONE
)
687 /* loop over four possible dest color buffers */
688 for (bufferBit
= 1; bufferBit
<= 8; bufferBit
<<= 1) {
689 if (bufferBit
& ctx
->Color
._DrawDestMask
) {
690 GLchan rgbaTmp
[MAX_WIDTH
][4];
691 ASSERT(span
->end
< MAX_WIDTH
);
693 /* Set the current read/draw buffer */
694 swrast
->CurrentBuffer
= bufferBit
;
695 (*swrast
->Driver
.SetBuffer
)(ctx
, ctx
->DrawBuffer
, bufferBit
);
697 /* make copy of incoming colors */
698 MEMCPY( rgbaTmp
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
) );
700 if (ctx
->Color
.ColorLogicOpEnabled
) {
701 _mesa_logicop_rgba_span(ctx
, span
, rgbaTmp
);
703 else if (ctx
->Color
.BlendEnabled
) {
704 _mesa_blend_span(ctx
, span
, rgbaTmp
);
707 if (colorMask
!= 0xffffffff) {
708 _mesa_mask_rgba_span(ctx
, span
, rgbaTmp
);
711 if (span
->arrayMask
& SPAN_XY
) {
712 /* array of pixel coords */
713 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
,
714 span
->array
->x
, span
->array
->y
,
715 (const GLchan (*)[4]) rgbaTmp
,
717 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
718 _mesa_write_alpha_pixels(ctx
, span
->end
,
719 span
->array
->x
, span
->array
->y
,
720 (const GLchan (*)[4]) rgbaTmp
,
725 /* horizontal run of pixels */
726 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
727 (const GLchan (*)[4]) rgbaTmp
,
729 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
730 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
731 (const GLchan (*)[4]) rgbaTmp
,
738 /* restore default dest buffer */
739 _swrast_use_draw_buffer(ctx
);
745 * This function may modify any of the array values in the span.
746 * span->interpMask and span->arrayMask may be changed but will be restored
747 * to their original values before returning.
750 _mesa_write_index_span( GLcontext
*ctx
, struct sw_span
*span
)
752 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
753 const GLuint origInterpMask
= span
->interpMask
;
754 const GLuint origArrayMask
= span
->arrayMask
;
756 ASSERT(span
->end
<= MAX_WIDTH
);
757 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
758 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
759 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_INDEX
);
760 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
762 if (span
->arrayMask
& SPAN_MASK
) {
763 /* mask was initialized by caller, probably glBitmap */
764 span
->writeAll
= GL_FALSE
;
767 MEMSET(span
->array
->mask
, 1, span
->end
);
768 span
->writeAll
= GL_TRUE
;
772 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
773 if (!clip_span(ctx
, span
)) {
779 if (span
->arrayMask
& SPAN_XY
) {
781 for (i
= 0; i
< span
->end
; i
++) {
782 if (span
->array
->mask
[i
]) {
783 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
784 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
785 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
786 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
792 /* Polygon Stippling */
793 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
794 stipple_polygon_span(ctx
, span
);
797 /* Depth test and stencil */
798 if (ctx
->Depth
.Test
|| ctx
->Stencil
.Enabled
) {
799 if (span
->interpMask
& SPAN_Z
)
800 _mesa_span_interpolate_z(ctx
, span
);
802 if (ctx
->Stencil
.Enabled
) {
803 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
804 span
->arrayMask
= origArrayMask
;
809 ASSERT(ctx
->Depth
.Test
);
810 if (!_mesa_depth_test_span(ctx
, span
)) {
811 span
->arrayMask
= origArrayMask
;
817 /* if we get here, something passed the depth test */
818 ctx
->OcclusionResult
= GL_TRUE
;
820 /* we have to wait until after occlusion to do this test */
821 if (ctx
->Color
.DrawBuffer
== GL_NONE
|| ctx
->Color
.IndexMask
== 0) {
822 /* write no pixels */
823 span
->arrayMask
= origArrayMask
;
827 /* Interpolate the color indexes if needed */
828 if (span
->interpMask
& SPAN_INDEX
) {
829 interpolate_indexes(ctx
, span
);
830 /* clear the bit - this allows the WriteMonoCISpan optimization below */
831 span
->interpMask
&= ~SPAN_INDEX
;
835 if (ctx
->Fog
.Enabled
) {
836 _mesa_fog_ci_span(ctx
, span
);
839 /* Antialias coverage application */
840 if (span
->arrayMask
& SPAN_COVERAGE
) {
842 GLuint
*index
= span
->array
->index
;
843 GLfloat
*coverage
= span
->array
->coverage
;
844 for (i
= 0; i
< span
->end
; i
++) {
845 ASSERT(coverage
[i
] < 16);
846 index
[i
] = (index
[i
] & ~0xf) | ((GLuint
) coverage
[i
]);
850 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
851 /* draw to zero or two or more buffers */
852 multi_write_index_span(ctx
, span
);
855 /* normal situation: draw to exactly one buffer */
856 if (ctx
->Color
.IndexLogicOpEnabled
) {
857 _mesa_logicop_ci_span(ctx
, span
, span
->array
->index
);
860 if (ctx
->Color
.IndexMask
!= 0xffffffff) {
861 _mesa_mask_index_span(ctx
, span
, span
->array
->index
);
865 if (span
->arrayMask
& SPAN_XY
) {
866 /* array of pixel coords */
867 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
868 /* all pixels have same color index */
869 (*swrast
->Driver
.WriteMonoCIPixels
)(ctx
, span
->end
,
870 span
->array
->x
, span
->array
->y
,
871 FixedToInt(span
->index
),
875 (*swrast
->Driver
.WriteCI32Pixels
)(ctx
, span
->end
, span
->array
->x
,
876 span
->array
->y
, span
->array
->index
,
881 /* horizontal run of pixels */
882 if ((span
->interpMask
& SPAN_INDEX
) && span
->indexStep
== 0) {
883 /* all pixels have same color index */
884 (*swrast
->Driver
.WriteMonoCISpan
)(ctx
, span
->end
, span
->x
, span
->y
,
885 FixedToInt(span
->index
),
889 (*swrast
->Driver
.WriteCI32Span
)(ctx
, span
->end
, span
->x
, span
->y
,
896 span
->interpMask
= origInterpMask
;
897 span
->arrayMask
= origArrayMask
;
902 * This function may modify any of the array values in the span.
903 * span->interpMask and span->arrayMask may be changed but will be restored
904 * to their original values before returning.
907 _mesa_write_rgba_span( GLcontext
*ctx
, struct sw_span
*span
)
909 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
910 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
911 const GLuint origInterpMask
= span
->interpMask
;
912 const GLuint origArrayMask
= span
->arrayMask
;
915 ASSERT(span
->end
<= MAX_WIDTH
);
916 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
917 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
918 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
919 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_RGBA
);
921 if (ctx
->Fog
.Enabled
)
922 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
924 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_Z
);
927 if (span
->arrayMask
& SPAN_MASK
) {
928 /* mask was initialized by caller, probably glBitmap */
929 span
->writeAll
= GL_FALSE
;
932 MEMSET(span
->array
->mask
, 1, span
->end
);
933 span
->writeAll
= GL_TRUE
;
936 /* Determine if we have mono-chromatic colors */
937 monoColor
= (span
->interpMask
& SPAN_RGBA
) &&
938 span
->redStep
== 0 && span
->greenStep
== 0 &&
939 span
->blueStep
== 0 && span
->alphaStep
== 0;
942 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
943 if (!clip_span(ctx
, span
)) {
949 if (span
->arrayMask
& SPAN_XY
) {
951 for (i
= 0; i
< span
->end
; i
++) {
952 if (span
->array
->mask
[i
]) {
953 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
954 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
955 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
956 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
962 /* Polygon Stippling */
963 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
964 stipple_polygon_span(ctx
, span
);
967 /* Fragment program */
968 if (ctx
->FragmentProgram
.Enabled
) {
969 /* Now we may need to interpolate the colors */
970 if ((span
->interpMask
& SPAN_RGBA
) &&
971 (span
->arrayMask
& SPAN_RGBA
) == 0) {
972 interpolate_colors(ctx
, span
);
973 span
->interpMask
&= ~SPAN_RGBA
;
975 _swrast_exec_nv_fragment_program(ctx
, span
);
976 monoColor
= GL_FALSE
;
979 /* Do the alpha test */
980 if (ctx
->Color
.AlphaEnabled
) {
981 if (!_mesa_alpha_test(ctx
, span
)) {
982 span
->interpMask
= origInterpMask
;
983 span
->arrayMask
= origArrayMask
;
988 /* Stencil and Z testing */
989 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
990 if (span
->interpMask
& SPAN_Z
)
991 _mesa_span_interpolate_z(ctx
, span
);
993 if (ctx
->Stencil
.Enabled
) {
994 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
995 span
->interpMask
= origInterpMask
;
996 span
->arrayMask
= origArrayMask
;
1001 ASSERT(ctx
->Depth
.Test
);
1002 ASSERT(span
->arrayMask
& SPAN_Z
);
1003 /* regular depth testing */
1004 if (!_mesa_depth_test_span(ctx
, span
)) {
1005 span
->interpMask
= origInterpMask
;
1006 span
->arrayMask
= origArrayMask
;
1012 /* if we get here, something passed the depth test */
1013 ctx
->OcclusionResult
= GL_TRUE
;
1015 /* can't abort span-writing until after occlusion testing */
1016 if (colorMask
== 0x0) {
1017 span
->interpMask
= origInterpMask
;
1018 span
->arrayMask
= origArrayMask
;
1022 /* Now we may need to interpolate the colors */
1023 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0) {
1024 interpolate_colors(ctx
, span
);
1025 /* clear the bit - this allows the WriteMonoCISpan optimization below */
1026 span
->interpMask
&= ~SPAN_RGBA
;
1030 if (ctx
->Fog
.Enabled
) {
1031 _mesa_fog_rgba_span(ctx
, span
);
1032 monoColor
= GL_FALSE
;
1035 /* Antialias coverage application */
1036 if (span
->arrayMask
& SPAN_COVERAGE
) {
1037 GLchan (*rgba
)[4] = span
->array
->rgba
;
1038 GLfloat
*coverage
= span
->array
->coverage
;
1040 for (i
= 0; i
< span
->end
; i
++) {
1041 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1043 monoColor
= GL_FALSE
;
1046 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1047 multi_write_rgba_span(ctx
, span
);
1050 /* normal: write to exactly one buffer */
1051 if (ctx
->Color
.ColorLogicOpEnabled
) {
1052 _mesa_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1053 monoColor
= GL_FALSE
;
1055 else if (ctx
->Color
.BlendEnabled
) {
1056 _mesa_blend_span(ctx
, span
, span
->array
->rgba
);
1057 monoColor
= GL_FALSE
;
1060 /* Color component masking */
1061 if (colorMask
!= 0xffffffff) {
1062 _mesa_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1063 monoColor
= GL_FALSE
;
1067 if (span
->arrayMask
& SPAN_XY
) {
1068 /* array of pixel coords */
1069 /* XXX test for mono color */
1070 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1071 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1072 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1073 _mesa_write_alpha_pixels(ctx
, span
->end
,
1074 span
->array
->x
, span
->array
->y
,
1075 (const GLchan (*)[4]) span
->array
->rgba
,
1080 /* horizontal run of pixels */
1082 /* all pixels have same color */
1084 color
[RCOMP
] = FixedToChan(span
->red
);
1085 color
[GCOMP
] = FixedToChan(span
->green
);
1086 color
[BCOMP
] = FixedToChan(span
->blue
);
1087 color
[ACOMP
] = FixedToChan(span
->alpha
);
1088 (*swrast
->Driver
.WriteMonoRGBASpan
)(ctx
, span
->end
, span
->x
,
1089 span
->y
, color
, span
->array
->mask
);
1090 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1091 _mesa_write_mono_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1093 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1097 /* each pixel is a different color */
1098 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1099 (const GLchan (*)[4]) span
->array
->rgba
,
1100 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1101 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1102 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1103 (const GLchan (*)[4]) span
->array
->rgba
,
1104 span
->writeAll
? ((const GLubyte
*) NULL
) : span
->array
->mask
);
1110 span
->interpMask
= origInterpMask
;
1111 span
->arrayMask
= origArrayMask
;
1116 * Add specular color to base color. This is used only when
1117 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1120 add_colors(GLuint n
, GLchan rgba
[][4], GLchan specular
[][4] )
1123 for (i
= 0; i
< n
; i
++) {
1124 #if CHAN_TYPE == GL_FLOAT
1126 rgba
[i
][RCOMP
] += specular
[i
][RCOMP
];
1127 rgba
[i
][GCOMP
] += specular
[i
][GCOMP
];
1128 rgba
[i
][BCOMP
] += specular
[i
][BCOMP
];
1130 GLint r
= rgba
[i
][RCOMP
] + specular
[i
][RCOMP
];
1131 GLint g
= rgba
[i
][GCOMP
] + specular
[i
][GCOMP
];
1132 GLint b
= rgba
[i
][BCOMP
] + specular
[i
][BCOMP
];
1133 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
1134 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
1135 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
1142 * This function may modify any of the array values in the span.
1143 * span->interpMask and span->arrayMask may be changed but will be restored
1144 * to their original values before returning.
1147 _mesa_write_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
1149 const GLuint colorMask
= *((GLuint
*) ctx
->Color
.ColorMask
);
1150 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1151 const GLuint origArrayMask
= span
->arrayMask
;
1153 ASSERT(span
->primitive
== GL_POINT
|| span
->primitive
== GL_LINE
||
1154 span
->primitive
== GL_POLYGON
|| span
->primitive
== GL_BITMAP
);
1155 ASSERT(span
->end
<= MAX_WIDTH
);
1156 ASSERT((span
->interpMask
& span
->arrayMask
) == 0);
1157 ASSERT(ctx
->Texture
._EnabledUnits
);
1160 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1163 if (span
->arrayMask
& SPAN_MASK
) {
1164 /* mask was initialized by caller, probably glBitmap */
1165 span
->writeAll
= GL_FALSE
;
1168 MEMSET(span
->array
->mask
, 1, span
->end
);
1169 span
->writeAll
= GL_TRUE
;
1173 if ((swrast
->_RasterMask
& CLIP_BIT
) || (span
->primitive
!= GL_POLYGON
)) {
1174 if (!clip_span(ctx
, span
)) {
1180 if (span
->arrayMask
& SPAN_XY
) {
1182 for (i
= 0; i
< span
->end
; i
++) {
1183 if (span
->array
->mask
[i
]) {
1184 assert(span
->array
->x
[i
] >= ctx
->DrawBuffer
->_Xmin
);
1185 assert(span
->array
->x
[i
] < ctx
->DrawBuffer
->_Xmax
);
1186 assert(span
->array
->y
[i
] >= ctx
->DrawBuffer
->_Ymin
);
1187 assert(span
->array
->y
[i
] < ctx
->DrawBuffer
->_Ymax
);
1193 /* Polygon Stippling */
1194 if (ctx
->Polygon
.StippleFlag
&& span
->primitive
== GL_POLYGON
) {
1195 stipple_polygon_span(ctx
, span
);
1198 /* Need texture coordinates now */
1199 if ((span
->interpMask
& SPAN_TEXTURE
)
1200 && (span
->arrayMask
& SPAN_TEXTURE
) == 0)
1201 interpolate_texcoords(ctx
, span
);
1203 /* Texture with alpha test */
1204 if (ctx
->Color
.AlphaEnabled
) {
1206 /* Now we need the rgba array, fill it in if needed */
1207 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1208 interpolate_colors(ctx
, span
);
1210 /* Texturing without alpha is done after depth-testing which
1211 * gives a potential speed-up.
1213 if (ctx
->FragmentProgram
.Enabled
)
1214 _swrast_exec_nv_fragment_program( ctx
, span
);
1216 _swrast_texture_span( ctx
, span
);
1218 /* Do the alpha test */
1219 if (!_mesa_alpha_test(ctx
, span
)) {
1220 span
->arrayMask
= origArrayMask
;
1225 /* Stencil and Z testing */
1226 if (ctx
->Stencil
.Enabled
|| ctx
->Depth
.Test
) {
1227 if (span
->interpMask
& SPAN_Z
)
1228 _mesa_span_interpolate_z(ctx
, span
);
1230 if (ctx
->Stencil
.Enabled
) {
1231 if (!_mesa_stencil_and_ztest_span(ctx
, span
)) {
1232 span
->arrayMask
= origArrayMask
;
1237 ASSERT(ctx
->Depth
.Test
);
1238 ASSERT(span
->arrayMask
& SPAN_Z
);
1239 /* regular depth testing */
1240 if (!_mesa_depth_test_span(ctx
, span
)) {
1241 span
->arrayMask
= origArrayMask
;
1247 /* if we get here, some fragments passed the depth test */
1248 ctx
->OcclusionResult
= GL_TRUE
;
1250 /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1251 * the occlusion test.
1253 if (colorMask
== 0x0) {
1254 span
->arrayMask
= origArrayMask
;
1258 /* Texture without alpha test */
1259 if (!ctx
->Color
.AlphaEnabled
) {
1261 /* Now we need the rgba array, fill it in if needed */
1262 if ((span
->interpMask
& SPAN_RGBA
) && (span
->arrayMask
& SPAN_RGBA
) == 0)
1263 interpolate_colors(ctx
, span
);
1265 if (ctx
->FragmentProgram
.Enabled
)
1266 _swrast_exec_nv_fragment_program( ctx
, span
);
1268 _swrast_texture_span( ctx
, span
);
1271 ASSERT(span
->arrayMask
& SPAN_RGBA
);
1273 /* Add base and specular colors */
1274 if (ctx
->Fog
.ColorSumEnabled
||
1275 (ctx
->Light
.Enabled
&&
1276 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)) {
1277 if (span
->interpMask
& SPAN_SPEC
) {
1278 interpolate_specular(ctx
, span
);
1280 ASSERT(span
->arrayMask
& SPAN_SPEC
);
1281 add_colors( span
->end
, span
->array
->rgba
, span
->array
->spec
);
1285 if (ctx
->Fog
.Enabled
) {
1286 _mesa_fog_rgba_span(ctx
, span
);
1289 /* Antialias coverage application */
1290 if (span
->arrayMask
& SPAN_COVERAGE
) {
1291 GLchan (*rgba
)[4] = span
->array
->rgba
;
1292 GLfloat
*coverage
= span
->array
->coverage
;
1294 for (i
= 0; i
< span
->end
; i
++) {
1295 rgba
[i
][ACOMP
] = (GLchan
) (rgba
[i
][ACOMP
] * coverage
[i
]);
1299 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
) {
1300 multi_write_rgba_span(ctx
, span
);
1303 /* normal: write to exactly one buffer */
1304 if (ctx
->Color
.ColorLogicOpEnabled
) {
1305 _mesa_logicop_rgba_span(ctx
, span
, span
->array
->rgba
);
1307 else if (ctx
->Color
.BlendEnabled
) {
1308 _mesa_blend_span(ctx
, span
, span
->array
->rgba
);
1311 if (colorMask
!= 0xffffffff) {
1312 _mesa_mask_rgba_span(ctx
, span
, span
->array
->rgba
);
1316 if (span
->arrayMask
& SPAN_XY
) {
1317 /* array of pixel coords */
1318 (*swrast
->Driver
.WriteRGBAPixels
)(ctx
, span
->end
, span
->array
->x
,
1319 span
->array
->y
, (const GLchan (*)[4]) span
->array
->rgba
, span
->array
->mask
);
1320 if (SWRAST_CONTEXT(ctx
)->_RasterMask
& ALPHABUF_BIT
) {
1321 _mesa_write_alpha_pixels(ctx
, span
->end
,
1322 span
->array
->x
, span
->array
->y
,
1323 (const GLchan (*)[4]) span
->array
->rgba
,
1328 /* horizontal run of pixels */
1329 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
->end
, span
->x
, span
->y
,
1330 (const GLchan (*)[4]) span
->array
->rgba
,
1331 span
->writeAll
? NULL
: span
->array
->mask
);
1332 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
1333 _mesa_write_alpha_span(ctx
, span
->end
, span
->x
, span
->y
,
1334 (const GLchan (*)[4]) span
->array
->rgba
,
1335 span
->writeAll
? NULL
: span
->array
->mask
);
1340 span
->arrayMask
= origArrayMask
;
1346 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
1347 * reading ouside the buffer's boundaries.
1350 _mesa_read_rgba_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1351 GLuint n
, GLint x
, GLint y
, GLchan rgba
[][4] )
1353 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1354 const GLint bufWidth
= (GLint
) buffer
->Width
;
1355 const GLint bufHeight
= (GLint
) buffer
->Height
;
1357 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1358 /* completely above, below, or right */
1359 /* XXX maybe leave undefined? */
1360 _mesa_bzero(rgba
, 4 * n
* sizeof(GLchan
));
1365 /* left edge clippping */
1367 length
= (GLint
) n
- skip
;
1369 /* completely left of window */
1372 if (length
> bufWidth
) {
1376 else if ((GLint
) (x
+ n
) > bufWidth
) {
1377 /* right edge clipping */
1379 length
= bufWidth
- x
;
1381 /* completely to right of window */
1391 (*swrast
->Driver
.ReadRGBASpan
)( ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1392 if (buffer
->UseSoftwareAlphaBuffers
) {
1393 _mesa_read_alpha_span(ctx
, length
, x
+ skip
, y
, rgba
+ skip
);
1400 * Read CI pixels from frame buffer. Clipping will be done to prevent
1401 * reading ouside the buffer's boundaries.
1404 _mesa_read_index_span( GLcontext
*ctx
, GLframebuffer
*buffer
,
1405 GLuint n
, GLint x
, GLint y
, GLuint indx
[] )
1407 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1408 const GLint bufWidth
= (GLint
) buffer
->Width
;
1409 const GLint bufHeight
= (GLint
) buffer
->Height
;
1411 if (y
< 0 || y
>= bufHeight
|| x
+ (GLint
) n
< 0 || x
>= bufWidth
) {
1412 /* completely above, below, or right */
1413 _mesa_bzero(indx
, n
* sizeof(GLuint
));
1418 /* left edge clippping */
1420 length
= (GLint
) n
- skip
;
1422 /* completely left of window */
1425 if (length
> bufWidth
) {
1429 else if ((GLint
) (x
+ n
) > bufWidth
) {
1430 /* right edge clipping */
1432 length
= bufWidth
- x
;
1434 /* completely to right of window */
1444 (*swrast
->Driver
.ReadCI32Span
)( ctx
, length
, skip
+ x
, y
, indx
+ skip
);