52c7501df840a024a54ce25bed9ebde3535204bc
[mesa.git] / src / mesa / swrast / s_span.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
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.
23 */
24
25
26 /**
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
30 * \author Brian Paul
31 */
32
33 #include "glheader.h"
34 #include "colormac.h"
35 #include "context.h"
36 #include "macros.h"
37 #include "imports.h"
38 #include "image.h"
39
40 #include "s_atifragshader.h"
41 #include "s_alpha.h"
42 #include "s_blend.h"
43 #include "s_context.h"
44 #include "s_depth.h"
45 #include "s_fog.h"
46 #include "s_logic.h"
47 #include "s_masking.h"
48 #include "s_fragprog.h"
49 #include "s_span.h"
50 #include "s_stencil.h"
51 #include "s_texcombine.h"
52
53
54 /**
55 * Init span's Z interpolation values to the RasterPos Z.
56 * Used during setup for glDraw/CopyPixels.
57 */
58 void
59 _swrast_span_default_z( GLcontext *ctx, SWspan *span )
60 {
61 const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
62 if (ctx->DrawBuffer->Visual.depthBits <= 16)
63 span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
64 else
65 span->z = (GLint) (ctx->Current.RasterPos[2] * depthMax + 0.5F);
66 span->zStep = 0;
67 span->interpMask |= SPAN_Z;
68 }
69
70
71 /**
72 * Init span's fog interpolation values to the RasterPos fog.
73 * Used during setup for glDraw/CopyPixels.
74 */
75 void
76 _swrast_span_default_fog( GLcontext *ctx, SWspan *span )
77 {
78 span->attrStart[FRAG_ATTRIB_FOGC][0] = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
79 span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0;
80 span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0;
81 span->interpMask |= SPAN_FOG;
82 }
83
84
85 /**
86 * Init span's rgba or index interpolation values to the RasterPos color.
87 * Used during setup for glDraw/CopyPixels.
88 */
89 void
90 _swrast_span_default_color( GLcontext *ctx, SWspan *span )
91 {
92 if (ctx->Visual.rgbMode) {
93 GLchan r, g, b, a;
94 UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
95 UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
96 UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
97 UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
98 #if CHAN_TYPE == GL_FLOAT
99 span->red = r;
100 span->green = g;
101 span->blue = b;
102 span->alpha = a;
103 #else
104 span->red = IntToFixed(r);
105 span->green = IntToFixed(g);
106 span->blue = IntToFixed(b);
107 span->alpha = IntToFixed(a);
108 #endif
109 span->redStep = 0;
110 span->greenStep = 0;
111 span->blueStep = 0;
112 span->alphaStep = 0;
113 span->interpMask |= SPAN_RGBA;
114 }
115 else {
116 span->index = FloatToFixed(ctx->Current.RasterIndex);
117 span->indexStep = 0;
118 span->interpMask |= SPAN_INDEX;
119 }
120 }
121
122
123 /**
124 * Init span's texcoord interpolation values to the RasterPos texcoords.
125 * Used during setup for glDraw/CopyPixels.
126 */
127 void
128 _swrast_span_default_texcoords( GLcontext *ctx, SWspan *span )
129 {
130 GLuint i;
131 for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
132 const GLfloat *tc = ctx->Current.RasterTexCoords[i];
133 if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) {
134 COPY_4V(span->tex[i], tc);
135 }
136 else if (tc[3] > 0.0F) {
137 /* use (s/q, t/q, r/q, 1) */
138 span->tex[i][0] = tc[0] / tc[3];
139 span->tex[i][1] = tc[1] / tc[3];
140 span->tex[i][2] = tc[2] / tc[3];
141 span->tex[i][3] = 1.0;
142 }
143 else {
144 ASSIGN_4V(span->tex[i], 0.0F, 0.0F, 0.0F, 1.0F);
145 }
146 ASSIGN_4V(span->texStepX[i], 0.0F, 0.0F, 0.0F, 0.0F);
147 ASSIGN_4V(span->texStepY[i], 0.0F, 0.0F, 0.0F, 0.0F);
148 }
149 span->interpMask |= SPAN_TEXTURE;
150 }
151
152
153 /**
154 * Interpolate primary colors to fill in the span->array->color array.
155 */
156 static INLINE void
157 interpolate_colors(SWspan *span)
158 {
159 const GLuint n = span->end;
160 GLuint i;
161
162 ASSERT((span->interpMask & SPAN_RGBA) &&
163 !(span->arrayMask & SPAN_RGBA));
164
165 switch (span->array->ChanType) {
166 #if CHAN_BITS != 32
167 case GL_UNSIGNED_BYTE:
168 {
169 GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
170 if (span->interpMask & SPAN_FLAT) {
171 GLubyte color[4];
172 color[RCOMP] = FixedToInt(span->red);
173 color[GCOMP] = FixedToInt(span->green);
174 color[BCOMP] = FixedToInt(span->blue);
175 color[ACOMP] = FixedToInt(span->alpha);
176 for (i = 0; i < n; i++) {
177 COPY_4UBV(rgba[i], color);
178 }
179 }
180 else {
181 GLfixed r = span->red;
182 GLfixed g = span->green;
183 GLfixed b = span->blue;
184 GLfixed a = span->alpha;
185 GLint dr = span->redStep;
186 GLint dg = span->greenStep;
187 GLint db = span->blueStep;
188 GLint da = span->alphaStep;
189 for (i = 0; i < n; i++) {
190 rgba[i][RCOMP] = FixedToChan(r);
191 rgba[i][GCOMP] = FixedToChan(g);
192 rgba[i][BCOMP] = FixedToChan(b);
193 rgba[i][ACOMP] = FixedToChan(a);
194 r += dr;
195 g += dg;
196 b += db;
197 a += da;
198 }
199 }
200 }
201 break;
202 case GL_UNSIGNED_SHORT:
203 {
204 GLushort (*rgba)[4] = span->array->color.sz2.rgba;
205 if (span->interpMask & SPAN_FLAT) {
206 GLushort color[4];
207 color[RCOMP] = FixedToInt(span->red);
208 color[GCOMP] = FixedToInt(span->green);
209 color[BCOMP] = FixedToInt(span->blue);
210 color[ACOMP] = FixedToInt(span->alpha);
211 for (i = 0; i < n; i++) {
212 COPY_4V(rgba[i], color);
213 }
214 }
215 else {
216 GLushort (*rgba)[4] = span->array->color.sz2.rgba;
217 GLfixed r, g, b, a;
218 GLint dr, dg, db, da;
219 r = span->red;
220 g = span->green;
221 b = span->blue;
222 a = span->alpha;
223 dr = span->redStep;
224 dg = span->greenStep;
225 db = span->blueStep;
226 da = span->alphaStep;
227 for (i = 0; i < n; i++) {
228 rgba[i][RCOMP] = FixedToChan(r);
229 rgba[i][GCOMP] = FixedToChan(g);
230 rgba[i][BCOMP] = FixedToChan(b);
231 rgba[i][ACOMP] = FixedToChan(a);
232 r += dr;
233 g += dg;
234 b += db;
235 a += da;
236 }
237 }
238 }
239 break;
240 #endif
241 case GL_FLOAT:
242 {
243 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
244 GLfloat r, g, b, a, dr, dg, db, da;
245 r = span->red;
246 g = span->green;
247 b = span->blue;
248 a = span->alpha;
249 if (span->interpMask & SPAN_FLAT) {
250 dr = dg = db = da = 0.0;
251 }
252 else {
253 dr = span->redStep;
254 dg = span->greenStep;
255 db = span->blueStep;
256 da = span->alphaStep;
257 }
258 for (i = 0; i < n; i++) {
259 rgba[i][RCOMP] = r;
260 rgba[i][GCOMP] = g;
261 rgba[i][BCOMP] = b;
262 rgba[i][ACOMP] = a;
263 r += dr;
264 g += dg;
265 b += db;
266 a += da;
267 }
268 }
269 break;
270 default:
271 _mesa_problem(NULL, "bad datatype in interpolate_colors");
272 }
273 span->arrayMask |= SPAN_RGBA;
274 }
275
276
277 /**
278 * Interpolate specular/secondary colors.
279 */
280 static INLINE void
281 interpolate_specular(SWspan *span)
282 {
283 const GLuint n = span->end;
284 GLuint i;
285
286 switch (span->array->ChanType) {
287 #if CHAN_BITS != 32
288 case GL_UNSIGNED_BYTE:
289 {
290 GLubyte (*spec)[4] = span->array->color.sz1.spec;
291 if (span->interpMask & SPAN_FLAT) {
292 GLubyte color[4];
293 color[RCOMP] = FixedToInt(span->specRed);
294 color[GCOMP] = FixedToInt(span->specGreen);
295 color[BCOMP] = FixedToInt(span->specBlue);
296 color[ACOMP] = 0;
297 for (i = 0; i < n; i++) {
298 COPY_4UBV(spec[i], color);
299 }
300 }
301 else {
302 GLfixed r = span->specRed;
303 GLfixed g = span->specGreen;
304 GLfixed b = span->specBlue;
305 GLint dr = span->specRedStep;
306 GLint dg = span->specGreenStep;
307 GLint db = span->specBlueStep;
308 for (i = 0; i < n; i++) {
309 spec[i][RCOMP] = CLAMP(FixedToChan(r), 0, 255);
310 spec[i][GCOMP] = CLAMP(FixedToChan(g), 0, 255);
311 spec[i][BCOMP] = CLAMP(FixedToChan(b), 0, 255);
312 spec[i][ACOMP] = 0;
313 r += dr;
314 g += dg;
315 b += db;
316 }
317 }
318 }
319 break;
320 case GL_UNSIGNED_SHORT:
321 {
322 GLushort (*spec)[4] = span->array->color.sz2.spec;
323 if (span->interpMask & SPAN_FLAT) {
324 GLushort color[4];
325 color[RCOMP] = FixedToInt(span->specRed);
326 color[GCOMP] = FixedToInt(span->specGreen);
327 color[BCOMP] = FixedToInt(span->specBlue);
328 color[ACOMP] = 0;
329 for (i = 0; i < n; i++) {
330 COPY_4V(spec[i], color);
331 }
332 }
333 else {
334 GLfixed r = FloatToFixed(span->specRed);
335 GLfixed g = FloatToFixed(span->specGreen);
336 GLfixed b = FloatToFixed(span->specBlue);
337 GLint dr = FloatToFixed(span->specRedStep);
338 GLint dg = FloatToFixed(span->specGreenStep);
339 GLint db = FloatToFixed(span->specBlueStep);
340 for (i = 0; i < n; i++) {
341 spec[i][RCOMP] = FixedToInt(r);
342 spec[i][GCOMP] = FixedToInt(g);
343 spec[i][BCOMP] = FixedToInt(b);
344 spec[i][ACOMP] = 0;
345 r += dr;
346 g += dg;
347 b += db;
348 }
349 }
350 }
351 break;
352 #endif
353 case GL_FLOAT:
354 {
355 GLfloat (*spec)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
356 #if CHAN_BITS <= 16
357 GLfloat r = CHAN_TO_FLOAT(FixedToChan(span->specRed));
358 GLfloat g = CHAN_TO_FLOAT(FixedToChan(span->specGreen));
359 GLfloat b = CHAN_TO_FLOAT(FixedToChan(span->specBlue));
360 #else
361 GLfloat r = span->specRed;
362 GLfloat g = span->specGreen;
363 GLfloat b = span->specBlue;
364 #endif
365 GLfloat dr, dg, db;
366 if (span->interpMask & SPAN_FLAT) {
367 dr = dg = db = 0.0;
368 }
369 else {
370 #if CHAN_BITS <= 16
371 dr = CHAN_TO_FLOAT(FixedToChan(span->specRedStep));
372 dg = CHAN_TO_FLOAT(FixedToChan(span->specGreenStep));
373 db = CHAN_TO_FLOAT(FixedToChan(span->specBlueStep));
374 #else
375 dr = span->specRedStep;
376 dg = span->specGreenStep;
377 db = span->specBlueStep;
378 #endif
379 }
380 for (i = 0; i < n; i++) {
381 spec[i][RCOMP] = r;
382 spec[i][GCOMP] = g;
383 spec[i][BCOMP] = b;
384 spec[i][ACOMP] = 0.0F;
385 r += dr;
386 g += dg;
387 b += db;
388 }
389 }
390 break;
391 default:
392 _mesa_problem(NULL, "bad datatype in interpolate_specular");
393 }
394 span->arrayMask |= SPAN_SPEC;
395 }
396
397
398 /* Fill in the span.color.index array from the interpolation values */
399 static INLINE void
400 interpolate_indexes(GLcontext *ctx, SWspan *span)
401 {
402 GLfixed index = span->index;
403 const GLint indexStep = span->indexStep;
404 const GLuint n = span->end;
405 GLuint *indexes = span->array->index;
406 GLuint i;
407 (void) ctx;
408 ASSERT((span->interpMask & SPAN_INDEX) &&
409 !(span->arrayMask & SPAN_INDEX));
410
411 if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
412 /* constant color */
413 index = FixedToInt(index);
414 for (i = 0; i < n; i++) {
415 indexes[i] = index;
416 }
417 }
418 else {
419 /* interpolate */
420 for (i = 0; i < n; i++) {
421 indexes[i] = FixedToInt(index);
422 index += indexStep;
423 }
424 }
425 span->arrayMask |= SPAN_INDEX;
426 span->interpMask &= ~SPAN_INDEX;
427 }
428
429
430 /* Fill in the span.array.fog values from the interpolation values */
431 static INLINE void
432 interpolate_fog(const GLcontext *ctx, SWspan *span)
433 {
434 GLfloat (*fog)[4] = span->array->attribs[FRAG_ATTRIB_FOGC];
435 const GLfloat fogStep = span->attrStepX[FRAG_ATTRIB_FOGC][0];
436 GLfloat fogCoord = span->attrStart[FRAG_ATTRIB_FOGC][0];
437 const GLuint haveW = (span->interpMask & SPAN_W);
438 const GLfloat wStep = haveW ? span->dwdx : 0.0F;
439 GLfloat w = haveW ? span->w : 1.0F;
440 GLuint i;
441 for (i = 0; i < span->end; i++) {
442 fog[i][0] = fogCoord / w;
443 fogCoord += fogStep;
444 w += wStep;
445 }
446 span->arrayMask |= SPAN_FOG;
447 }
448
449
450 /* Fill in the span.zArray array from the interpolation values */
451 void
452 _swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span )
453 {
454 const GLuint n = span->end;
455 GLuint i;
456
457 ASSERT((span->interpMask & SPAN_Z) &&
458 !(span->arrayMask & SPAN_Z));
459
460 if (ctx->DrawBuffer->Visual.depthBits <= 16) {
461 GLfixed zval = span->z;
462 GLuint *z = span->array->z;
463 for (i = 0; i < n; i++) {
464 z[i] = FixedToInt(zval);
465 zval += span->zStep;
466 }
467 }
468 else {
469 /* Deep Z buffer, no fixed->int shift */
470 GLuint zval = span->z;
471 GLuint *z = span->array->z;
472 for (i = 0; i < n; i++) {
473 z[i] = zval;
474 zval += span->zStep;
475 }
476 }
477 span->interpMask &= ~SPAN_Z;
478 span->arrayMask |= SPAN_Z;
479 }
480
481
482 /*
483 * This the ideal solution, as given in the OpenGL spec.
484 */
485 #if 0
486 static GLfloat
487 compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
488 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
489 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
490 {
491 GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
492 GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
493 GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
494 GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
495 GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
496 GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
497 GLfloat rho = MAX2(x, y);
498 GLfloat lambda = LOG2(rho);
499 return lambda;
500 }
501 #endif
502
503
504 /*
505 * This is a faster approximation
506 */
507 GLfloat
508 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
509 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
510 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
511 {
512 GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
513 GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
514 GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
515 GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
516 GLfloat maxU, maxV, rho, lambda;
517 dsdx2 = FABSF(dsdx2);
518 dsdy2 = FABSF(dsdy2);
519 dtdx2 = FABSF(dtdx2);
520 dtdy2 = FABSF(dtdy2);
521 maxU = MAX2(dsdx2, dsdy2) * texW;
522 maxV = MAX2(dtdx2, dtdy2) * texH;
523 rho = MAX2(maxU, maxV);
524 lambda = LOG2(rho);
525 return lambda;
526 }
527
528
529 /**
530 * Fill in the span.texcoords array from the interpolation values.
531 * Note: in the places where we divide by Q (or mult by invQ) we're
532 * really doing two things: perspective correction and texcoord
533 * projection. Remember, for texcoord (s,t,r,q) we need to index
534 * texels with (s/q, t/q, r/q).
535 * If we're using a fragment program, we never do the division
536 * for texcoord projection. That's done by the TXP instruction
537 * or user-written code.
538 */
539 static void
540 interpolate_texcoords(GLcontext *ctx, SWspan *span)
541 {
542 ASSERT(span->interpMask & SPAN_TEXTURE);
543 ASSERT(!(span->arrayMask & SPAN_TEXTURE));
544
545 if (ctx->Texture._EnabledCoordUnits > 1) {
546 /* multitexture */
547 GLuint u;
548 span->arrayMask |= SPAN_TEXTURE;
549 /* XXX CoordUnits vs. ImageUnits */
550 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
551 if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
552 const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
553 GLfloat texW, texH;
554 GLboolean needLambda;
555 if (obj) {
556 const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
557 needLambda = (obj->MinFilter != obj->MagFilter)
558 || ctx->FragmentProgram._Current;
559 texW = img->WidthScale;
560 texH = img->HeightScale;
561 }
562 else {
563 /* using a fragment program */
564 texW = 1.0;
565 texH = 1.0;
566 needLambda = GL_FALSE;
567 }
568 if (needLambda) {
569 GLfloat (*texcoord)[4] = span->array->attribs[FRAG_ATTRIB_TEX0 + u];
570 GLfloat *lambda = span->array->lambda[u];
571 const GLfloat dsdx = span->texStepX[u][0];
572 const GLfloat dsdy = span->texStepY[u][0];
573 const GLfloat dtdx = span->texStepX[u][1];
574 const GLfloat dtdy = span->texStepY[u][1];
575 const GLfloat drdx = span->texStepX[u][2];
576 const GLfloat dqdx = span->texStepX[u][3];
577 const GLfloat dqdy = span->texStepY[u][3];
578 GLfloat s = span->tex[u][0];
579 GLfloat t = span->tex[u][1];
580 GLfloat r = span->tex[u][2];
581 GLfloat q = span->tex[u][3];
582 GLuint i;
583 if (ctx->FragmentProgram._Current
584 || ctx->ATIFragmentShader._Enabled) {
585 /* do perspective correction but don't divide s, t, r by q */
586 const GLfloat dwdx = span->dwdx;
587 GLfloat w = span->w;
588 for (i = 0; i < span->end; i++) {
589 const GLfloat invW = 1.0F / w;
590 texcoord[i][0] = s * invW;
591 texcoord[i][1] = t * invW;
592 texcoord[i][2] = r * invW;
593 texcoord[i][3] = q * invW;
594 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
595 dqdx, dqdy, texW, texH,
596 s, t, q, invW);
597 s += dsdx;
598 t += dtdx;
599 r += drdx;
600 q += dqdx;
601 w += dwdx;
602 }
603 }
604 else {
605 for (i = 0; i < span->end; i++) {
606 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
607 texcoord[i][0] = s * invQ;
608 texcoord[i][1] = t * invQ;
609 texcoord[i][2] = r * invQ;
610 texcoord[i][3] = q;
611 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
612 dqdx, dqdy, texW, texH,
613 s, t, q, invQ);
614 s += dsdx;
615 t += dtdx;
616 r += drdx;
617 q += dqdx;
618 }
619 }
620 span->arrayMask |= SPAN_LAMBDA;
621 }
622 else {
623 GLfloat (*texcoord)[4] = span->array->attribs[FRAG_ATTRIB_TEX0 + u];
624 GLfloat *lambda = span->array->lambda[u];
625 const GLfloat dsdx = span->texStepX[u][0];
626 const GLfloat dtdx = span->texStepX[u][1];
627 const GLfloat drdx = span->texStepX[u][2];
628 const GLfloat dqdx = span->texStepX[u][3];
629 GLfloat s = span->tex[u][0];
630 GLfloat t = span->tex[u][1];
631 GLfloat r = span->tex[u][2];
632 GLfloat q = span->tex[u][3];
633 GLuint i;
634 if (ctx->FragmentProgram._Current ||
635 ctx->ATIFragmentShader._Enabled) {
636 /* do perspective correction but don't divide s, t, r by q */
637 const GLfloat dwdx = span->dwdx;
638 GLfloat w = span->w;
639 for (i = 0; i < span->end; i++) {
640 const GLfloat invW = 1.0F / w;
641 texcoord[i][0] = s * invW;
642 texcoord[i][1] = t * invW;
643 texcoord[i][2] = r * invW;
644 texcoord[i][3] = q * invW;
645 lambda[i] = 0.0;
646 s += dsdx;
647 t += dtdx;
648 r += drdx;
649 q += dqdx;
650 w += dwdx;
651 }
652 }
653 else if (dqdx == 0.0F) {
654 /* Ortho projection or polygon's parallel to window X axis */
655 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
656 for (i = 0; i < span->end; i++) {
657 texcoord[i][0] = s * invQ;
658 texcoord[i][1] = t * invQ;
659 texcoord[i][2] = r * invQ;
660 texcoord[i][3] = q;
661 lambda[i] = 0.0;
662 s += dsdx;
663 t += dtdx;
664 r += drdx;
665 }
666 }
667 else {
668 for (i = 0; i < span->end; i++) {
669 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
670 texcoord[i][0] = s * invQ;
671 texcoord[i][1] = t * invQ;
672 texcoord[i][2] = r * invQ;
673 texcoord[i][3] = q;
674 lambda[i] = 0.0;
675 s += dsdx;
676 t += dtdx;
677 r += drdx;
678 q += dqdx;
679 }
680 }
681 } /* lambda */
682 } /* if */
683 } /* for */
684 }
685 else {
686 /* single texture */
687 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
688 GLfloat texW, texH;
689 GLboolean needLambda;
690 if (obj) {
691 const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
692 needLambda = (obj->MinFilter != obj->MagFilter)
693 || ctx->FragmentProgram._Current;
694 texW = (GLfloat) img->WidthScale;
695 texH = (GLfloat) img->HeightScale;
696 }
697 else {
698 needLambda = GL_FALSE;
699 texW = texH = 1.0;
700 }
701 span->arrayMask |= SPAN_TEXTURE;
702 if (needLambda) {
703 /* just texture unit 0, with lambda */
704 GLfloat (*texcoord)[4] = span->array->attribs[FRAG_ATTRIB_TEX0];
705 GLfloat *lambda = span->array->lambda[0];
706 const GLfloat dsdx = span->texStepX[0][0];
707 const GLfloat dsdy = span->texStepY[0][0];
708 const GLfloat dtdx = span->texStepX[0][1];
709 const GLfloat dtdy = span->texStepY[0][1];
710 const GLfloat drdx = span->texStepX[0][2];
711 const GLfloat dqdx = span->texStepX[0][3];
712 const GLfloat dqdy = span->texStepY[0][3];
713 GLfloat s = span->tex[0][0];
714 GLfloat t = span->tex[0][1];
715 GLfloat r = span->tex[0][2];
716 GLfloat q = span->tex[0][3];
717 GLuint i;
718 if (ctx->FragmentProgram._Current
719 || ctx->ATIFragmentShader._Enabled) {
720 /* do perspective correction but don't divide s, t, r by q */
721 const GLfloat dwdx = span->dwdx;
722 GLfloat w = span->w;
723 for (i = 0; i < span->end; i++) {
724 const GLfloat invW = 1.0F / w;
725 texcoord[i][0] = s * invW;
726 texcoord[i][1] = t * invW;
727 texcoord[i][2] = r * invW;
728 texcoord[i][3] = q * invW;
729 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
730 dqdx, dqdy, texW, texH,
731 s, t, q, invW);
732 s += dsdx;
733 t += dtdx;
734 r += drdx;
735 q += dqdx;
736 w += dwdx;
737 }
738 }
739 else {
740 /* tex.c */
741 for (i = 0; i < span->end; i++) {
742 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
743 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
744 dqdx, dqdy, texW, texH,
745 s, t, q, invQ);
746 texcoord[i][0] = s * invQ;
747 texcoord[i][1] = t * invQ;
748 texcoord[i][2] = r * invQ;
749 texcoord[i][3] = q;
750 s += dsdx;
751 t += dtdx;
752 r += drdx;
753 q += dqdx;
754 }
755 }
756 span->arrayMask |= SPAN_LAMBDA;
757 }
758 else {
759 /* just texture 0, without lambda */
760 GLfloat (*texcoord)[4] = span->array->attribs[FRAG_ATTRIB_TEX0];
761 const GLfloat dsdx = span->texStepX[0][0];
762 const GLfloat dtdx = span->texStepX[0][1];
763 const GLfloat drdx = span->texStepX[0][2];
764 const GLfloat dqdx = span->texStepX[0][3];
765 GLfloat s = span->tex[0][0];
766 GLfloat t = span->tex[0][1];
767 GLfloat r = span->tex[0][2];
768 GLfloat q = span->tex[0][3];
769 GLuint i;
770 if (ctx->FragmentProgram._Current
771 || ctx->ATIFragmentShader._Enabled) {
772 /* do perspective correction but don't divide s, t, r by q */
773 const GLfloat dwdx = span->dwdx;
774 GLfloat w = span->w;
775 for (i = 0; i < span->end; i++) {
776 const GLfloat invW = 1.0F / w;
777 texcoord[i][0] = s * invW;
778 texcoord[i][1] = t * invW;
779 texcoord[i][2] = r * invW;
780 texcoord[i][3] = q * invW;
781 s += dsdx;
782 t += dtdx;
783 r += drdx;
784 q += dqdx;
785 w += dwdx;
786 }
787 }
788 else if (dqdx == 0.0F) {
789 /* Ortho projection or polygon's parallel to window X axis */
790 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
791 for (i = 0; i < span->end; i++) {
792 texcoord[i][0] = s * invQ;
793 texcoord[i][1] = t * invQ;
794 texcoord[i][2] = r * invQ;
795 texcoord[i][3] = q;
796 s += dsdx;
797 t += dtdx;
798 r += drdx;
799 }
800 }
801 else {
802 for (i = 0; i < span->end; i++) {
803 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
804 texcoord[i][0] = s * invQ;
805 texcoord[i][1] = t * invQ;
806 texcoord[i][2] = r * invQ;
807 texcoord[i][3] = q;
808 s += dsdx;
809 t += dtdx;
810 r += drdx;
811 q += dqdx;
812 }
813 }
814 }
815 }
816 }
817
818
819 /**
820 * Fill in the arrays->attribs[FRAG_ATTRIB_VARx] arrays from the
821 * interpolation values.
822 * XXX since interpolants/arrays are getting uniformed, we might merge
823 * this with interpolate_texcoords(), interpolate_Fog(), etc. someday.
824 */
825 static INLINE void
826 interpolate_varying(GLcontext *ctx, SWspan *span)
827 {
828 GLuint var;
829 const GLbitfield inputsUsed = ctx->FragmentProgram._Current->Base.InputsRead;
830
831 ASSERT(span->interpMask & SPAN_VARYING);
832 ASSERT(!(span->arrayMask & SPAN_VARYING));
833
834 span->arrayMask |= SPAN_VARYING;
835
836 for (var = 0; var < MAX_VARYING; var++) {
837 if (inputsUsed & FRAG_BIT_VAR(var)) {
838 const GLuint attr = FRAG_ATTRIB_VAR0 + var;
839 GLuint j;
840 for (j = 0; j < 4; j++) {
841 const GLfloat dvdx = span->attrStepX[attr][j];
842 GLfloat v = span->attrStart[attr][j];
843 const GLfloat dwdx = span->dwdx;
844 GLfloat w = span->w;
845 GLuint k;
846 for (k = 0; k < span->end; k++) {
847 GLfloat invW = 1.0f / w;
848 span->array->attribs[attr][k][j] = v * invW;
849 v += dvdx;
850 w += dwdx;
851 }
852 }
853 }
854 }
855 }
856
857
858 /**
859 * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array.
860 */
861 static INLINE void
862 interpolate_wpos(GLcontext *ctx, SWspan *span)
863 {
864 GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS];
865 GLuint i;
866 if (span->arrayMask & SPAN_XY) {
867 for (i = 0; i < span->end; i++) {
868 wpos[i][0] = (GLfloat) span->array->x[i];
869 wpos[i][1] = (GLfloat) span->array->y[i];
870 }
871 }
872 else {
873 for (i = 0; i < span->end; i++) {
874 wpos[i][0] = (GLfloat) span->x + i;
875 wpos[i][1] = (GLfloat) span->y;
876 }
877 }
878 for (i = 0; i < span->end; i++) {
879 wpos[i][2] = (GLfloat) span->array->z[i] / ctx->DrawBuffer->_DepthMaxF;
880 wpos[i][3] = span->w + i * span->dwdx;
881 }
882 }
883
884
885 /**
886 * Apply the current polygon stipple pattern to a span of pixels.
887 */
888 static INLINE void
889 stipple_polygon_span(GLcontext *ctx, SWspan *span)
890 {
891 GLubyte *mask = span->array->mask;
892
893 ASSERT(ctx->Polygon.StippleFlag);
894
895 if (span->arrayMask & SPAN_XY) {
896 /* arrays of x/y pixel coords */
897 GLuint i;
898 for (i = 0; i < span->end; i++) {
899 const GLint col = span->array->x[i] % 32;
900 const GLint row = span->array->y[i] % 32;
901 const GLuint stipple = ctx->PolygonStipple[row];
902 if (((1 << col) & stipple) == 0) {
903 mask[i] = 0;
904 }
905 }
906 }
907 else {
908 /* horizontal span of pixels */
909 const GLuint highBit = 1 << 31;
910 const GLuint stipple = ctx->PolygonStipple[span->y % 32];
911 GLuint i, m = highBit >> (GLuint) (span->x % 32);
912 for (i = 0; i < span->end; i++) {
913 if ((m & stipple) == 0) {
914 mask[i] = 0;
915 }
916 m = m >> 1;
917 if (m == 0) {
918 m = highBit;
919 }
920 }
921 }
922 span->writeAll = GL_FALSE;
923 }
924
925
926 /**
927 * Clip a pixel span to the current buffer/window boundaries:
928 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
929 * window clipping and scissoring.
930 * Return: GL_TRUE some pixels still visible
931 * GL_FALSE nothing visible
932 */
933 static INLINE GLuint
934 clip_span( GLcontext *ctx, SWspan *span )
935 {
936 const GLint xmin = ctx->DrawBuffer->_Xmin;
937 const GLint xmax = ctx->DrawBuffer->_Xmax;
938 const GLint ymin = ctx->DrawBuffer->_Ymin;
939 const GLint ymax = ctx->DrawBuffer->_Ymax;
940
941 if (span->arrayMask & SPAN_XY) {
942 /* arrays of x/y pixel coords */
943 const GLint *x = span->array->x;
944 const GLint *y = span->array->y;
945 const GLint n = span->end;
946 GLubyte *mask = span->array->mask;
947 GLint i;
948 if (span->arrayMask & SPAN_MASK) {
949 /* note: using & intead of && to reduce branches */
950 for (i = 0; i < n; i++) {
951 mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
952 & (y[i] >= ymin) & (y[i] < ymax);
953 }
954 }
955 else {
956 /* note: using & intead of && to reduce branches */
957 for (i = 0; i < n; i++) {
958 mask[i] = (x[i] >= xmin) & (x[i] < xmax)
959 & (y[i] >= ymin) & (y[i] < ymax);
960 }
961 }
962 return GL_TRUE; /* some pixels visible */
963 }
964 else {
965 /* horizontal span of pixels */
966 const GLint x = span->x;
967 const GLint y = span->y;
968 const GLint n = span->end;
969
970 /* Trivial rejection tests */
971 if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
972 span->end = 0;
973 return GL_FALSE; /* all pixels clipped */
974 }
975
976 /* Clip to the left */
977 if (x < xmin) {
978 ASSERT(x + n > xmin);
979 span->writeAll = GL_FALSE;
980 _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
981 }
982
983 /* Clip to right */
984 if (x + n > xmax) {
985 ASSERT(x < xmax);
986 span->end = xmax - x;
987 }
988
989 return GL_TRUE; /* some pixels visible */
990 }
991 }
992
993
994 /**
995 * Apply all the per-fragment opertions to a span of color index fragments
996 * and write them to the enabled color drawbuffers.
997 * The 'span' parameter can be considered to be const. Note that
998 * span->interpMask and span->arrayMask may be changed but will be restored
999 * to their original values before returning.
1000 */
1001 void
1002 _swrast_write_index_span( GLcontext *ctx, SWspan *span)
1003 {
1004 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1005 const GLbitfield origInterpMask = span->interpMask;
1006 const GLbitfield origArrayMask = span->arrayMask;
1007
1008 ASSERT(span->end <= MAX_WIDTH);
1009 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
1010 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
1011 ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
1012 ASSERT((span->interpMask & span->arrayMask) == 0);
1013
1014 if (span->arrayMask & SPAN_MASK) {
1015 /* mask was initialized by caller, probably glBitmap */
1016 span->writeAll = GL_FALSE;
1017 }
1018 else {
1019 _mesa_memset(span->array->mask, 1, span->end);
1020 span->writeAll = GL_TRUE;
1021 }
1022
1023 /* Clipping */
1024 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1025 if (!clip_span(ctx, span)) {
1026 return;
1027 }
1028 }
1029
1030 /* Depth bounds test */
1031 if (ctx->Depth.BoundsTest && ctx->DrawBuffer->Visual.depthBits > 0) {
1032 if (!_swrast_depth_bounds_test(ctx, span)) {
1033 return;
1034 }
1035 }
1036
1037 #ifdef DEBUG
1038 /* Make sure all fragments are within window bounds */
1039 if (span->arrayMask & SPAN_XY) {
1040 GLuint i;
1041 for (i = 0; i < span->end; i++) {
1042 if (span->array->mask[i]) {
1043 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
1044 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
1045 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
1046 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1047 }
1048 }
1049 }
1050 #endif
1051
1052 /* Polygon Stippling */
1053 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1054 stipple_polygon_span(ctx, span);
1055 }
1056
1057 /* Stencil and Z testing */
1058 if (ctx->Depth.Test || ctx->Stencil.Enabled) {
1059 if (span->interpMask & SPAN_Z)
1060 _swrast_span_interpolate_z(ctx, span);
1061
1062 if (ctx->Stencil.Enabled) {
1063 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1064 span->arrayMask = origArrayMask;
1065 return;
1066 }
1067 }
1068 else {
1069 ASSERT(ctx->Depth.Test);
1070 if (!_swrast_depth_test_span(ctx, span)) {
1071 span->interpMask = origInterpMask;
1072 span->arrayMask = origArrayMask;
1073 return;
1074 }
1075 }
1076 }
1077
1078 #if FEATURE_ARB_occlusion_query
1079 if (ctx->Query.CurrentOcclusionObject) {
1080 /* update count of 'passed' fragments */
1081 struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1082 GLuint i;
1083 for (i = 0; i < span->end; i++)
1084 q->Result += span->array->mask[i];
1085 }
1086 #endif
1087
1088 /* we have to wait until after occlusion to do this test */
1089 if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
1090 /* write no pixels */
1091 span->arrayMask = origArrayMask;
1092 return;
1093 }
1094
1095 /* Interpolate the color indexes if needed */
1096 if (swrast->_FogEnabled ||
1097 ctx->Color.IndexLogicOpEnabled ||
1098 ctx->Color.IndexMask != 0xffffffff ||
1099 (span->arrayMask & SPAN_COVERAGE)) {
1100 if (span->interpMask & SPAN_INDEX) {
1101 interpolate_indexes(ctx, span);
1102 }
1103 }
1104
1105 /* Fog */
1106 if (swrast->_FogEnabled) {
1107 _swrast_fog_ci_span(ctx, span);
1108 }
1109
1110 /* Antialias coverage application */
1111 if (span->arrayMask & SPAN_COVERAGE) {
1112 const GLfloat *coverage = span->array->coverage;
1113 GLuint *index = span->array->index;
1114 GLuint i;
1115 for (i = 0; i < span->end; i++) {
1116 ASSERT(coverage[i] < 16);
1117 index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
1118 }
1119 }
1120
1121 /*
1122 * Write to renderbuffers
1123 */
1124 {
1125 struct gl_framebuffer *fb = ctx->DrawBuffer;
1126 const GLuint output = 0; /* only frag progs can write to other outputs */
1127 const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
1128 GLuint indexSave[MAX_WIDTH];
1129 GLuint buf;
1130
1131 if (numDrawBuffers > 1) {
1132 /* save indexes for second, third renderbuffer writes */
1133 _mesa_memcpy(indexSave, span->array->index,
1134 span->end * sizeof(indexSave[0]));
1135 }
1136
1137 for (buf = 0; buf < fb->_NumColorDrawBuffers[output]; buf++) {
1138 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1139 ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1140
1141 if (ctx->Color.IndexLogicOpEnabled) {
1142 _swrast_logicop_ci_span(ctx, rb, span);
1143 }
1144
1145 if (ctx->Color.IndexMask != 0xffffffff) {
1146 _swrast_mask_ci_span(ctx, rb, span);
1147 }
1148
1149 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
1150 /* all fragments have same color index */
1151 GLubyte index8;
1152 GLushort index16;
1153 GLuint index32;
1154 void *value;
1155
1156 if (rb->DataType == GL_UNSIGNED_BYTE) {
1157 index8 = FixedToInt(span->index);
1158 value = &index8;
1159 }
1160 else if (rb->DataType == GL_UNSIGNED_SHORT) {
1161 index16 = FixedToInt(span->index);
1162 value = &index16;
1163 }
1164 else {
1165 ASSERT(rb->DataType == GL_UNSIGNED_INT);
1166 index32 = FixedToInt(span->index);
1167 value = &index32;
1168 }
1169
1170 if (span->arrayMask & SPAN_XY) {
1171 rb->PutMonoValues(ctx, rb, span->end, span->array->x,
1172 span->array->y, value, span->array->mask);
1173 }
1174 else {
1175 rb->PutMonoRow(ctx, rb, span->end, span->x, span->y,
1176 value, span->array->mask);
1177 }
1178 }
1179 else {
1180 /* each fragment is a different color */
1181 GLubyte index8[MAX_WIDTH];
1182 GLushort index16[MAX_WIDTH];
1183 void *values;
1184
1185 if (rb->DataType == GL_UNSIGNED_BYTE) {
1186 GLuint k;
1187 for (k = 0; k < span->end; k++) {
1188 index8[k] = (GLubyte) span->array->index[k];
1189 }
1190 values = index8;
1191 }
1192 else if (rb->DataType == GL_UNSIGNED_SHORT) {
1193 GLuint k;
1194 for (k = 0; k < span->end; k++) {
1195 index16[k] = (GLushort) span->array->index[k];
1196 }
1197 values = index16;
1198 }
1199 else {
1200 ASSERT(rb->DataType == GL_UNSIGNED_INT);
1201 values = span->array->index;
1202 }
1203
1204 if (span->arrayMask & SPAN_XY) {
1205 rb->PutValues(ctx, rb, span->end,
1206 span->array->x, span->array->y,
1207 values, span->array->mask);
1208 }
1209 else {
1210 rb->PutRow(ctx, rb, span->end, span->x, span->y,
1211 values, span->array->mask);
1212 }
1213 }
1214
1215 if (buf + 1 < numDrawBuffers) {
1216 /* restore original span values */
1217 _mesa_memcpy(span->array->index, indexSave,
1218 span->end * sizeof(indexSave[0]));
1219 }
1220 } /* for buf */
1221 }
1222
1223 span->interpMask = origInterpMask;
1224 span->arrayMask = origArrayMask;
1225 }
1226
1227
1228 /**
1229 * Add specular color to base color. This is used only when
1230 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1231 */
1232 static INLINE void
1233 add_specular(GLcontext *ctx, SWspan *span)
1234 {
1235 switch (span->array->ChanType) {
1236 case GL_UNSIGNED_BYTE:
1237 {
1238 GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
1239 GLubyte (*spec)[4] = span->array->color.sz1.spec;
1240 GLuint i;
1241 for (i = 0; i < span->end; i++) {
1242 GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
1243 GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
1244 GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
1245 GLint a = rgba[i][ACOMP] + spec[i][ACOMP];
1246 rgba[i][RCOMP] = MIN2(r, 255);
1247 rgba[i][GCOMP] = MIN2(g, 255);
1248 rgba[i][BCOMP] = MIN2(b, 255);
1249 rgba[i][ACOMP] = MIN2(a, 255);
1250 }
1251 }
1252 break;
1253 case GL_UNSIGNED_SHORT:
1254 {
1255 GLushort (*rgba)[4] = span->array->color.sz2.rgba;
1256 GLushort (*spec)[4] = span->array->color.sz2.spec;
1257 GLuint i;
1258 for (i = 0; i < span->end; i++) {
1259 GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
1260 GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
1261 GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
1262 GLint a = rgba[i][ACOMP] + spec[i][ACOMP];
1263 rgba[i][RCOMP] = MIN2(r, 65535);
1264 rgba[i][GCOMP] = MIN2(g, 65535);
1265 rgba[i][BCOMP] = MIN2(b, 65535);
1266 rgba[i][ACOMP] = MIN2(a, 65535);
1267 }
1268 }
1269 break;
1270 case GL_FLOAT:
1271 {
1272 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
1273 GLfloat (*spec)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
1274 GLuint i;
1275 for (i = 0; i < span->end; i++) {
1276 rgba[i][RCOMP] += spec[i][RCOMP];
1277 rgba[i][GCOMP] += spec[i][GCOMP];
1278 rgba[i][BCOMP] += spec[i][BCOMP];
1279 rgba[i][ACOMP] += spec[i][ACOMP];
1280 }
1281 }
1282 break;
1283 default:
1284 _mesa_problem(ctx, "Invalid datatype in add_specular");
1285 }
1286 }
1287
1288
1289 /**
1290 * Apply antialiasing coverage value to alpha values.
1291 */
1292 static INLINE void
1293 apply_aa_coverage(SWspan *span)
1294 {
1295 const GLfloat *coverage = span->array->coverage;
1296 GLuint i;
1297 if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1298 GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
1299 for (i = 0; i < span->end; i++) {
1300 const GLfloat a = rgba[i][ACOMP] * coverage[i];
1301 rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0);
1302 ASSERT(coverage[i] >= 0.0);
1303 ASSERT(coverage[i] <= 1.0);
1304 }
1305 }
1306 else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
1307 GLushort (*rgba)[4] = span->array->color.sz2.rgba;
1308 for (i = 0; i < span->end; i++) {
1309 const GLfloat a = rgba[i][ACOMP] * coverage[i];
1310 rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0);
1311 }
1312 }
1313 else {
1314 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
1315 for (i = 0; i < span->end; i++) {
1316 rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
1317 }
1318 }
1319 }
1320
1321
1322 /**
1323 * Clamp span's float colors to [0,1]
1324 */
1325 static INLINE void
1326 clamp_colors(SWspan *span)
1327 {
1328 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
1329 GLuint i;
1330 ASSERT(span->array->ChanType == GL_FLOAT);
1331 for (i = 0; i < span->end; i++) {
1332 rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
1333 rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
1334 rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
1335 rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
1336 }
1337 }
1338
1339
1340 /**
1341 * Convert the span's color arrays to the given type.
1342 */
1343 static INLINE void
1344 convert_color_type(SWspan *span, GLenum newType)
1345 {
1346 GLvoid *src, *dst;
1347 if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1348 src = span->array->color.sz1.rgba;
1349 }
1350 else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1351 src = span->array->color.sz2.rgba;
1352 }
1353 else {
1354 src = span->array->attribs[FRAG_ATTRIB_COL0];
1355 }
1356 if (newType == GL_UNSIGNED_BYTE) {
1357 dst = span->array->color.sz1.rgba;
1358 }
1359 else if (newType == GL_UNSIGNED_BYTE) {
1360 dst = span->array->color.sz2.rgba;
1361 }
1362 else {
1363 dst = span->array->attribs[FRAG_ATTRIB_COL0];
1364 }
1365
1366 _mesa_convert_colors(span->array->ChanType, src,
1367 newType, dst,
1368 span->end, span->array->mask);
1369
1370 span->array->ChanType = newType;
1371 }
1372
1373
1374
1375 /**
1376 * Apply fragment shader, fragment program or normal texturing to span.
1377 */
1378 static INLINE void
1379 shade_texture_span(GLcontext *ctx, SWspan *span)
1380 {
1381 /* Now we need the rgba array, fill it in if needed */
1382 if (span->interpMask & SPAN_RGBA)
1383 interpolate_colors(span);
1384
1385 if (ctx->Texture._EnabledCoordUnits && (span->interpMask & SPAN_TEXTURE))
1386 interpolate_texcoords(ctx, span);
1387
1388 if (ctx->FragmentProgram._Current ||
1389 ctx->ATIFragmentShader._Enabled) {
1390
1391 /* use float colors if running a fragment program or shader */
1392 const GLenum oldType = span->array->ChanType;
1393 const GLenum newType = GL_FLOAT;
1394 if (oldType != newType) {
1395 GLvoid *src = (oldType == GL_UNSIGNED_BYTE)
1396 ? (GLvoid *) span->array->color.sz1.rgba
1397 : (GLvoid *) span->array->color.sz2.rgba;
1398 _mesa_convert_colors(oldType, src,
1399 newType, span->array->attribs[FRAG_ATTRIB_COL0],
1400 span->end, span->array->mask);
1401 span->array->ChanType = newType;
1402 }
1403
1404 /* fragment programs/shaders may need specular, fog and Z coords */
1405 if (span->interpMask & SPAN_SPEC)
1406 interpolate_specular(span);
1407
1408 if (span->interpMask & SPAN_FOG)
1409 interpolate_fog(ctx, span);
1410
1411 if (span->interpMask & SPAN_Z)
1412 _swrast_span_interpolate_z (ctx, span);
1413
1414 if (ctx->Shader.CurrentProgram && span->interpMask & SPAN_VARYING)
1415 interpolate_varying(ctx, span);
1416
1417 if (ctx->FragmentProgram._Current &&
1418 (ctx->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_WPOS))
1419 interpolate_wpos(ctx, span);
1420
1421 /* Run fragment program/shader now */
1422 if (ctx->FragmentProgram._Current) {
1423 _swrast_exec_fragment_program(ctx, span);
1424 }
1425 else {
1426 ASSERT(ctx->ATIFragmentShader._Enabled);
1427 _swrast_exec_fragment_shader(ctx, span);
1428 }
1429 }
1430 else if (ctx->Texture._EnabledUnits && (span->arrayMask & SPAN_TEXTURE)) {
1431 /* conventional texturing */
1432 _swrast_texture_span(ctx, span);
1433 }
1434 }
1435
1436
1437
1438 /**
1439 * Apply all the per-fragment operations to a span.
1440 * This now includes texturing (_swrast_write_texture_span() is history).
1441 * This function may modify any of the array values in the span.
1442 * span->interpMask and span->arrayMask may be changed but will be restored
1443 * to their original values before returning.
1444 */
1445 void
1446 _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
1447 {
1448 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1449 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1450 const GLbitfield origInterpMask = span->interpMask;
1451 const GLbitfield origArrayMask = span->arrayMask;
1452 const GLenum chanType = span->array->ChanType;
1453 const GLboolean shader = (ctx->FragmentProgram._Current
1454 || ctx->ATIFragmentShader._Enabled);
1455 const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledUnits;
1456 GLboolean deferredTexture;
1457
1458 /*
1459 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__,
1460 span->interpMask, span->arrayMask);
1461 */
1462
1463 ASSERT(span->primitive == GL_POINT ||
1464 span->primitive == GL_LINE ||
1465 span->primitive == GL_POLYGON ||
1466 span->primitive == GL_BITMAP);
1467 ASSERT(span->end <= MAX_WIDTH);
1468 ASSERT((span->interpMask & span->arrayMask) == 0);
1469 ASSERT((span->interpMask & SPAN_RGBA) ^ (span->arrayMask & SPAN_RGBA));
1470
1471 /* check for conditions that prevent deferred shading */
1472 if (ctx->Color.AlphaEnabled) {
1473 /* alpha test depends on post-texture/shader colors */
1474 deferredTexture = GL_FALSE;
1475 }
1476 else if (shaderOrTexture) {
1477 if (ctx->FragmentProgram._Current) {
1478 if (ctx->FragmentProgram.Current->Base.OutputsWritten
1479 & (1 << FRAG_RESULT_DEPR)) {
1480 /* Z comes from fragment program/shader */
1481 deferredTexture = GL_FALSE;
1482 }
1483 else {
1484 deferredTexture = GL_TRUE;
1485 }
1486 }
1487 else {
1488 /* ATI frag shader or conventional texturing */
1489 deferredTexture = GL_TRUE;
1490 }
1491 }
1492 else {
1493 /* no texturing or shadering */
1494 deferredTexture = GL_FALSE;
1495 }
1496
1497 /* Fragment write masks */
1498 if (span->arrayMask & SPAN_MASK) {
1499 /* mask was initialized by caller, probably glBitmap */
1500 span->writeAll = GL_FALSE;
1501 }
1502 else {
1503 _mesa_memset(span->array->mask, 1, span->end);
1504 span->writeAll = GL_TRUE;
1505 }
1506
1507 /* Clip to window/scissor box */
1508 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1509 if (!clip_span(ctx, span)) {
1510 return;
1511 }
1512 }
1513
1514 #ifdef DEBUG
1515 /* Make sure all fragments are within window bounds */
1516 if (span->arrayMask & SPAN_XY) {
1517 GLuint i;
1518 for (i = 0; i < span->end; i++) {
1519 if (span->array->mask[i]) {
1520 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
1521 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
1522 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
1523 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1524 }
1525 }
1526 }
1527 #endif
1528
1529 /* Polygon Stippling */
1530 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1531 stipple_polygon_span(ctx, span);
1532 }
1533
1534 /* This is the normal place to compute the resulting fragment color/Z.
1535 * As an optimization, we try to defer this until after Z/stencil
1536 * testing in order to try to avoid computing colors that we won't
1537 * actually need.
1538 */
1539 if (shaderOrTexture && !deferredTexture) {
1540 shade_texture_span(ctx, span);
1541 }
1542
1543 /* Do the alpha test */
1544 if (ctx->Color.AlphaEnabled) {
1545 if (!_swrast_alpha_test(ctx, span)) {
1546 goto end;
1547 }
1548 }
1549
1550 /* Stencil and Z testing */
1551 if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1552 if (span->interpMask & SPAN_Z)
1553 _swrast_span_interpolate_z(ctx, span);
1554
1555 if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) {
1556 /* Combined Z/stencil tests */
1557 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1558 goto end;
1559 }
1560 }
1561 else if (ctx->DrawBuffer->Visual.depthBits > 0) {
1562 /* Just regular depth testing */
1563 ASSERT(ctx->Depth.Test);
1564 ASSERT(span->arrayMask & SPAN_Z);
1565 if (!_swrast_depth_test_span(ctx, span)) {
1566 goto end;
1567 }
1568 }
1569 }
1570
1571 #if FEATURE_ARB_occlusion_query
1572 if (ctx->Query.CurrentOcclusionObject) {
1573 /* update count of 'passed' fragments */
1574 struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1575 GLuint i;
1576 for (i = 0; i < span->end; i++)
1577 q->Result += span->array->mask[i];
1578 }
1579 #endif
1580
1581 /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1582 * the occlusion test.
1583 */
1584 if (colorMask == 0x0) {
1585 goto end;
1586 }
1587
1588 /* If we were able to defer fragment color computation to now, there's
1589 * a good chance that many fragments will have already been killed by
1590 * Z/stencil testing.
1591 */
1592 if (deferredTexture) {
1593 ASSERT(shaderOrTexture);
1594 shade_texture_span(ctx, span);
1595 }
1596
1597 if ((span->arrayMask & SPAN_RGBA) == 0) {
1598 interpolate_colors(span);
1599 }
1600
1601 ASSERT(span->arrayMask & SPAN_RGBA);
1602
1603 if (!shader) {
1604 /* Add base and specular colors */
1605 if (ctx->Fog.ColorSumEnabled ||
1606 (ctx->Light.Enabled &&
1607 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1608 if (span->interpMask & SPAN_SPEC) {
1609 interpolate_specular(span);
1610 }
1611 if (span->arrayMask & SPAN_SPEC) {
1612 add_specular(ctx, span);
1613 }
1614 else {
1615 /* We probably added the base/specular colors during the
1616 * vertex stage!
1617 */
1618 }
1619 }
1620 }
1621
1622 /* Fog */
1623 if (swrast->_FogEnabled) {
1624 _swrast_fog_rgba_span(ctx, span);
1625 }
1626
1627 /* Antialias coverage application */
1628 if (span->arrayMask & SPAN_COVERAGE) {
1629 apply_aa_coverage(span);
1630 }
1631
1632 /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
1633 if (ctx->Color.ClampFragmentColor == GL_TRUE &&
1634 span->array->ChanType == GL_FLOAT) {
1635 clamp_colors(span);
1636 }
1637
1638 /*
1639 * Write to renderbuffers
1640 */
1641 {
1642 struct gl_framebuffer *fb = ctx->DrawBuffer;
1643 const GLuint output = 0; /* only frag progs can write to other outputs */
1644 const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
1645 GLchan rgbaSave[MAX_WIDTH][4];
1646 GLuint buf;
1647
1648 if (numDrawBuffers > 0) {
1649 if (fb->_ColorDrawBuffers[output][0]->DataType
1650 != span->array->ChanType) {
1651 convert_color_type(span,
1652 fb->_ColorDrawBuffers[output][0]->DataType);
1653 }
1654 }
1655
1656 if (numDrawBuffers > 1) {
1657 /* save colors for second, third renderbuffer writes */
1658 _mesa_memcpy(rgbaSave, span->array->rgba,
1659 4 * span->end * sizeof(GLchan));
1660 }
1661
1662 for (buf = 0; buf < numDrawBuffers; buf++) {
1663 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1664 ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
1665
1666 if (ctx->Color._LogicOpEnabled) {
1667 _swrast_logicop_rgba_span(ctx, rb, span);
1668 }
1669 else if (ctx->Color.BlendEnabled) {
1670 _swrast_blend_span(ctx, rb, span);
1671 }
1672
1673 if (colorMask != 0xffffffff) {
1674 _swrast_mask_rgba_span(ctx, rb, span);
1675 }
1676
1677 if (span->arrayMask & SPAN_XY) {
1678 /* array of pixel coords */
1679 ASSERT(rb->PutValues);
1680 rb->PutValues(ctx, rb, span->end,
1681 span->array->x, span->array->y,
1682 span->array->rgba, span->array->mask);
1683 }
1684 else {
1685 /* horizontal run of pixels */
1686 ASSERT(rb->PutRow);
1687 rb->PutRow(ctx, rb, span->end, span->x, span->y, span->array->rgba,
1688 span->writeAll ? NULL: span->array->mask);
1689 }
1690
1691 if (buf + 1 < numDrawBuffers) {
1692 /* restore original span values */
1693 _mesa_memcpy(span->array->rgba, rgbaSave,
1694 4 * span->end * sizeof(GLchan));
1695 }
1696 } /* for buf */
1697
1698 }
1699
1700 end:
1701 /* restore these values before returning */
1702 span->interpMask = origInterpMask;
1703 span->arrayMask = origArrayMask;
1704 span->array->ChanType = chanType;
1705 }
1706
1707
1708 /**
1709 * Read RGBA pixels from a renderbuffer. Clipping will be done to prevent
1710 * reading ouside the buffer's boundaries.
1711 * \param dstType datatype for returned colors
1712 * \param rgba the returned colors
1713 */
1714 void
1715 _swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1716 GLuint n, GLint x, GLint y, GLenum dstType,
1717 GLvoid *rgba)
1718 {
1719 const GLint bufWidth = (GLint) rb->Width;
1720 const GLint bufHeight = (GLint) rb->Height;
1721
1722 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1723 /* completely above, below, or right */
1724 /* XXX maybe leave rgba values undefined? */
1725 _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1726 }
1727 else {
1728 GLint skip, length;
1729 if (x < 0) {
1730 /* left edge clipping */
1731 skip = -x;
1732 length = (GLint) n - skip;
1733 if (length < 0) {
1734 /* completely left of window */
1735 return;
1736 }
1737 if (length > bufWidth) {
1738 length = bufWidth;
1739 }
1740 }
1741 else if ((GLint) (x + n) > bufWidth) {
1742 /* right edge clipping */
1743 skip = 0;
1744 length = bufWidth - x;
1745 if (length < 0) {
1746 /* completely to right of window */
1747 return;
1748 }
1749 }
1750 else {
1751 /* no clipping */
1752 skip = 0;
1753 length = (GLint) n;
1754 }
1755
1756 ASSERT(rb);
1757 ASSERT(rb->GetRow);
1758 ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
1759
1760 if (rb->DataType == dstType) {
1761 rb->GetRow(ctx, rb, length, x + skip, y,
1762 (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
1763 }
1764 else {
1765 GLuint temp[MAX_WIDTH * 4];
1766 rb->GetRow(ctx, rb, length, x + skip, y, temp);
1767 _mesa_convert_colors(rb->DataType, temp,
1768 dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
1769 length, NULL);
1770 }
1771 }
1772 }
1773
1774
1775 /**
1776 * Read CI pixels from a renderbuffer. Clipping will be done to prevent
1777 * reading ouside the buffer's boundaries.
1778 */
1779 void
1780 _swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1781 GLuint n, GLint x, GLint y, GLuint index[] )
1782 {
1783 const GLint bufWidth = (GLint) rb->Width;
1784 const GLint bufHeight = (GLint) rb->Height;
1785
1786 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1787 /* completely above, below, or right */
1788 _mesa_bzero(index, n * sizeof(GLuint));
1789 }
1790 else {
1791 GLint skip, length;
1792 if (x < 0) {
1793 /* left edge clipping */
1794 skip = -x;
1795 length = (GLint) n - skip;
1796 if (length < 0) {
1797 /* completely left of window */
1798 return;
1799 }
1800 if (length > bufWidth) {
1801 length = bufWidth;
1802 }
1803 }
1804 else if ((GLint) (x + n) > bufWidth) {
1805 /* right edge clipping */
1806 skip = 0;
1807 length = bufWidth - x;
1808 if (length < 0) {
1809 /* completely to right of window */
1810 return;
1811 }
1812 }
1813 else {
1814 /* no clipping */
1815 skip = 0;
1816 length = (GLint) n;
1817 }
1818
1819 ASSERT(rb->GetRow);
1820 ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1821
1822 if (rb->DataType == GL_UNSIGNED_BYTE) {
1823 GLubyte index8[MAX_WIDTH];
1824 GLint i;
1825 rb->GetRow(ctx, rb, length, x + skip, y, index8);
1826 for (i = 0; i < length; i++)
1827 index[skip + i] = index8[i];
1828 }
1829 else if (rb->DataType == GL_UNSIGNED_SHORT) {
1830 GLushort index16[MAX_WIDTH];
1831 GLint i;
1832 rb->GetRow(ctx, rb, length, x + skip, y, index16);
1833 for (i = 0; i < length; i++)
1834 index[skip + i] = index16[i];
1835 }
1836 else if (rb->DataType == GL_UNSIGNED_INT) {
1837 rb->GetRow(ctx, rb, length, x + skip, y, index + skip);
1838 }
1839 }
1840 }
1841
1842
1843 /**
1844 * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
1845 * reading values outside the buffer bounds.
1846 * We can use this for reading any format/type of renderbuffer.
1847 * \param valueSize is the size in bytes of each value (pixel) put into the
1848 * values array.
1849 */
1850 void
1851 _swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
1852 GLuint count, const GLint x[], const GLint y[],
1853 void *values, GLuint valueSize)
1854 {
1855 GLuint i, inCount = 0, inStart = 0;
1856
1857 for (i = 0; i < count; i++) {
1858 if (x[i] >= 0 && y[i] >= 0 &&
1859 x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
1860 /* inside */
1861 if (inCount == 0)
1862 inStart = i;
1863 inCount++;
1864 }
1865 else {
1866 if (inCount > 0) {
1867 /* read [inStart, inStart + inCount) */
1868 rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
1869 (GLubyte *) values + inStart * valueSize);
1870 inCount = 0;
1871 }
1872 }
1873 }
1874 if (inCount > 0) {
1875 /* read last values */
1876 rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
1877 (GLubyte *) values + inStart * valueSize);
1878 }
1879 }
1880
1881
1882 /**
1883 * Wrapper for gl_renderbuffer::PutRow() which does clipping.
1884 * \param valueSize size of each value (pixel) in bytes
1885 */
1886 void
1887 _swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1888 GLuint count, GLint x, GLint y,
1889 const GLvoid *values, GLuint valueSize)
1890 {
1891 GLint skip = 0;
1892
1893 if (y < 0 || y >= (GLint) rb->Height)
1894 return; /* above or below */
1895
1896 if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
1897 return; /* entirely left or right */
1898
1899 if ((GLint) (x + count) > (GLint) rb->Width) {
1900 /* right clip */
1901 GLint clip = x + count - rb->Width;
1902 count -= clip;
1903 }
1904
1905 if (x < 0) {
1906 /* left clip */
1907 skip = -x;
1908 x = 0;
1909 count -= skip;
1910 }
1911
1912 rb->PutRow(ctx, rb, count, x, y,
1913 (const GLubyte *) values + skip * valueSize, NULL);
1914 }
1915
1916
1917 /**
1918 * Wrapper for gl_renderbuffer::GetRow() which does clipping.
1919 * \param valueSize size of each value (pixel) in bytes
1920 */
1921 void
1922 _swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1923 GLuint count, GLint x, GLint y,
1924 GLvoid *values, GLuint valueSize)
1925 {
1926 GLint skip = 0;
1927
1928 if (y < 0 || y >= (GLint) rb->Height)
1929 return; /* above or below */
1930
1931 if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
1932 return; /* entirely left or right */
1933
1934 if (x + count > rb->Width) {
1935 /* right clip */
1936 GLint clip = x + count - rb->Width;
1937 count -= clip;
1938 }
1939
1940 if (x < 0) {
1941 /* left clip */
1942 skip = -x;
1943 x = 0;
1944 count -= skip;
1945 }
1946
1947 rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
1948 }
1949
1950
1951 /**
1952 * Get RGBA pixels from the given renderbuffer. Put the pixel colors into
1953 * the span's specular color arrays. The specular color arrays should no
1954 * longer be needed by time this function is called.
1955 * Used by blending, logicop and masking functions.
1956 * \return pointer to the colors we read.
1957 */
1958 void *
1959 _swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
1960 SWspan *span)
1961 {
1962 const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
1963 void *rbPixels;
1964
1965 /*
1966 * Determine pixel size (in bytes).
1967 * Point rbPixels to a temporary space (use specular color arrays).
1968 */
1969 if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1970 rbPixels = span->array->color.sz1.spec;
1971 }
1972 else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
1973 rbPixels = span->array->color.sz2.spec;
1974 }
1975 else {
1976 rbPixels = span->array->attribs[FRAG_ATTRIB_COL1];
1977 }
1978
1979 /* Get destination values from renderbuffer */
1980 if (span->arrayMask & SPAN_XY) {
1981 _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
1982 rbPixels, pixelSize);
1983 }
1984 else {
1985 _swrast_get_row(ctx, rb, span->end, span->x, span->y,
1986 rbPixels, pixelSize);
1987 }
1988
1989 return rbPixels;
1990 }