[MESA]
[reactos.git] / reactos / dll / opengl / mesa / src / mesa / swrast / s_span.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.5
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 /**
28 * \file swrast/s_span.c
29 * \brief Span processing functions used by all rasterization functions.
30 * This is where all the per-fragment tests are performed
31 * \author Brian Paul
32 */
33
34 #include "main/glheader.h"
35 #include "main/colormac.h"
36 #include "main/format_pack.h"
37 #include "main/format_unpack.h"
38 #include "main/macros.h"
39 #include "main/imports.h"
40 #include "main/image.h"
41
42 #include "s_alpha.h"
43 #include "s_blend.h"
44 #include "s_context.h"
45 #include "s_depth.h"
46 #include "s_fog.h"
47 #include "s_logic.h"
48 #include "s_masking.h"
49 #include "s_span.h"
50 #include "s_stencil.h"
51 #include "s_texcombine.h"
52
53 #include <stdbool.h>
54
55 /**
56 * Set default fragment attributes for the span using the
57 * current raster values. Used prior to glDraw/CopyPixels
58 * and glBitmap.
59 */
60 void
61 _swrast_span_default_attribs(struct gl_context *ctx, SWspan *span)
62 {
63 GLchan r, g, b, a;
64 /* Z*/
65 {
66 const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
67 if (ctx->DrawBuffer->Visual.depthBits <= 16)
68 span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
69 else {
70 GLfloat tmpf = ctx->Current.RasterPos[2] * depthMax;
71 tmpf = MIN2(tmpf, depthMax);
72 span->z = (GLint)tmpf;
73 }
74 span->zStep = 0;
75 span->interpMask |= SPAN_Z;
76 }
77
78 /* W (for perspective correction) */
79 span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0;
80 span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0;
81 span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;
82
83 /* primary color, or color index */
84 UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
85 UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
86 UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
87 UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
88 #if CHAN_TYPE == GL_FLOAT
89 span->red = r;
90 span->green = g;
91 span->blue = b;
92 span->alpha = a;
93 #else
94 span->red = IntToFixed(r);
95 span->green = IntToFixed(g);
96 span->blue = IntToFixed(b);
97 span->alpha = IntToFixed(a);
98 #endif
99 span->redStep = 0;
100 span->greenStep = 0;
101 span->blueStep = 0;
102 span->alphaStep = 0;
103 span->interpMask |= SPAN_RGBA;
104
105 COPY_4V(span->attrStart[FRAG_ATTRIB_COL0], ctx->Current.RasterColor);
106 ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
107 ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
108
109 /* Secondary color */
110 if (ctx->Light.Enabled || ctx->Fog.ColorSumEnabled)
111 {
112 COPY_4V(span->attrStart[FRAG_ATTRIB_COL1], ctx->Current.RasterSecondaryColor);
113 ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
114 ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
115 }
116
117 /* fog */
118 {
119 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
120 GLfloat fogVal; /* a coord or a blend factor */
121 if (swrast->_PreferPixelFog) {
122 /* fog blend factors will be computed from fog coordinates per pixel */
123 fogVal = ctx->Current.RasterDistance;
124 }
125 else {
126 /* fog blend factor should be computed from fogcoord now */
127 fogVal = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
128 }
129 span->attrStart[FRAG_ATTRIB_FOGC][0] = fogVal;
130 span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0;
131 span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0;
132 }
133
134 /* texcoords */
135 {
136 const GLuint attr = FRAG_ATTRIB_TEX;
137 const GLfloat *tc = ctx->Current.RasterTexCoords;
138 if (tc[3] > 0.0F) {
139 /* use (s/q, t/q, r/q, 1) */
140 span->attrStart[attr][0] = tc[0] / tc[3];
141 span->attrStart[attr][1] = tc[1] / tc[3];
142 span->attrStart[attr][2] = tc[2] / tc[3];
143 span->attrStart[attr][3] = 1.0;
144 }
145 else {
146 ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F);
147 }
148 ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F);
149 ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F);
150 }
151 }
152
153
154 /**
155 * Interpolate the active attributes (and'd with attrMask) to
156 * fill in span->array->attribs[].
157 * Perspective correction will be done. The point/line/triangle function
158 * should have computed attrStart/Step values for FRAG_ATTRIB_WPOS[3]!
159 */
160 static inline void
161 interpolate_active_attribs(struct gl_context *ctx, SWspan *span,
162 GLbitfield64 attrMask)
163 {
164 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
165
166 /*
167 * Don't overwrite existing array values, such as colors that may have
168 * been produced by glDraw/CopyPixels.
169 */
170 attrMask &= ~span->arrayAttribs;
171
172 ATTRIB_LOOP_BEGIN
173 if (attrMask & BITFIELD64_BIT(attr)) {
174 const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
175 GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
176 const GLfloat dv0dx = span->attrStepX[attr][0];
177 const GLfloat dv1dx = span->attrStepX[attr][1];
178 const GLfloat dv2dx = span->attrStepX[attr][2];
179 const GLfloat dv3dx = span->attrStepX[attr][3];
180 GLfloat v0 = span->attrStart[attr][0] + span->leftClip * dv0dx;
181 GLfloat v1 = span->attrStart[attr][1] + span->leftClip * dv1dx;
182 GLfloat v2 = span->attrStart[attr][2] + span->leftClip * dv2dx;
183 GLfloat v3 = span->attrStart[attr][3] + span->leftClip * dv3dx;
184 GLuint k;
185 for (k = 0; k < span->end; k++) {
186 const GLfloat invW = 1.0f / w;
187 span->array->attribs[attr][k][0] = v0 * invW;
188 span->array->attribs[attr][k][1] = v1 * invW;
189 span->array->attribs[attr][k][2] = v2 * invW;
190 span->array->attribs[attr][k][3] = v3 * invW;
191 v0 += dv0dx;
192 v1 += dv1dx;
193 v2 += dv2dx;
194 v3 += dv3dx;
195 w += dwdx;
196 }
197 ASSERT((span->arrayAttribs & BITFIELD64_BIT(attr)) == 0);
198 span->arrayAttribs |= BITFIELD64_BIT(attr);
199 }
200 ATTRIB_LOOP_END
201 }
202
203
204 /**
205 * Interpolate primary colors to fill in the span->array->rgba8 (or rgb16)
206 * color array.
207 */
208 static inline void
209 interpolate_int_colors(struct gl_context *ctx, SWspan *span)
210 {
211 #if CHAN_BITS != 32
212 const GLuint n = span->end;
213 GLuint i;
214
215 ASSERT(!(span->arrayMask & SPAN_RGBA));
216 #endif
217
218 switch (span->array->ChanType) {
219 #if CHAN_BITS != 32
220 case GL_UNSIGNED_BYTE:
221 {
222 GLubyte (*rgba)[4] = span->array->rgba8;
223 if (span->interpMask & SPAN_FLAT) {
224 GLubyte color[4];
225 color[RCOMP] = FixedToInt(span->red);
226 color[GCOMP] = FixedToInt(span->green);
227 color[BCOMP] = FixedToInt(span->blue);
228 color[ACOMP] = FixedToInt(span->alpha);
229 for (i = 0; i < n; i++) {
230 COPY_4UBV(rgba[i], color);
231 }
232 }
233 else {
234 GLfixed r = span->red;
235 GLfixed g = span->green;
236 GLfixed b = span->blue;
237 GLfixed a = span->alpha;
238 GLint dr = span->redStep;
239 GLint dg = span->greenStep;
240 GLint db = span->blueStep;
241 GLint da = span->alphaStep;
242 for (i = 0; i < n; i++) {
243 rgba[i][RCOMP] = FixedToChan(r);
244 rgba[i][GCOMP] = FixedToChan(g);
245 rgba[i][BCOMP] = FixedToChan(b);
246 rgba[i][ACOMP] = FixedToChan(a);
247 r += dr;
248 g += dg;
249 b += db;
250 a += da;
251 }
252 }
253 }
254 break;
255 case GL_UNSIGNED_SHORT:
256 {
257 GLushort (*rgba)[4] = span->array->rgba16;
258 if (span->interpMask & SPAN_FLAT) {
259 GLushort color[4];
260 color[RCOMP] = FixedToInt(span->red);
261 color[GCOMP] = FixedToInt(span->green);
262 color[BCOMP] = FixedToInt(span->blue);
263 color[ACOMP] = FixedToInt(span->alpha);
264 for (i = 0; i < n; i++) {
265 COPY_4V(rgba[i], color);
266 }
267 }
268 else {
269 GLushort (*rgba)[4] = span->array->rgba16;
270 GLfixed r, g, b, a;
271 GLint dr, dg, db, da;
272 r = span->red;
273 g = span->green;
274 b = span->blue;
275 a = span->alpha;
276 dr = span->redStep;
277 dg = span->greenStep;
278 db = span->blueStep;
279 da = span->alphaStep;
280 for (i = 0; i < n; i++) {
281 rgba[i][RCOMP] = FixedToChan(r);
282 rgba[i][GCOMP] = FixedToChan(g);
283 rgba[i][BCOMP] = FixedToChan(b);
284 rgba[i][ACOMP] = FixedToChan(a);
285 r += dr;
286 g += dg;
287 b += db;
288 a += da;
289 }
290 }
291 }
292 break;
293 #endif
294 case GL_FLOAT:
295 interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
296 break;
297 default:
298 _mesa_problem(ctx, "bad datatype 0x%x in interpolate_int_colors",
299 span->array->ChanType);
300 }
301 span->arrayMask |= SPAN_RGBA;
302 }
303
304
305 /**
306 * Populate the FRAG_ATTRIB_COL0 array.
307 */
308 static inline void
309 interpolate_float_colors(SWspan *span)
310 {
311 GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
312 const GLuint n = span->end;
313 GLuint i;
314
315 assert(!(span->arrayAttribs & FRAG_BIT_COL0));
316
317 if (span->arrayMask & SPAN_RGBA) {
318 /* convert array of int colors */
319 for (i = 0; i < n; i++) {
320 col0[i][0] = UBYTE_TO_FLOAT(span->array->rgba8[i][0]);
321 col0[i][1] = UBYTE_TO_FLOAT(span->array->rgba8[i][1]);
322 col0[i][2] = UBYTE_TO_FLOAT(span->array->rgba8[i][2]);
323 col0[i][3] = UBYTE_TO_FLOAT(span->array->rgba8[i][3]);
324 }
325 }
326 else {
327 /* interpolate red/green/blue/alpha to get float colors */
328 ASSERT(span->interpMask & SPAN_RGBA);
329 if (span->interpMask & SPAN_FLAT) {
330 GLfloat r = FixedToFloat(span->red);
331 GLfloat g = FixedToFloat(span->green);
332 GLfloat b = FixedToFloat(span->blue);
333 GLfloat a = FixedToFloat(span->alpha);
334 for (i = 0; i < n; i++) {
335 ASSIGN_4V(col0[i], r, g, b, a);
336 }
337 }
338 else {
339 GLfloat r = FixedToFloat(span->red);
340 GLfloat g = FixedToFloat(span->green);
341 GLfloat b = FixedToFloat(span->blue);
342 GLfloat a = FixedToFloat(span->alpha);
343 GLfloat dr = FixedToFloat(span->redStep);
344 GLfloat dg = FixedToFloat(span->greenStep);
345 GLfloat db = FixedToFloat(span->blueStep);
346 GLfloat da = FixedToFloat(span->alphaStep);
347 for (i = 0; i < n; i++) {
348 col0[i][0] = r;
349 col0[i][1] = g;
350 col0[i][2] = b;
351 col0[i][3] = a;
352 r += dr;
353 g += dg;
354 b += db;
355 a += da;
356 }
357 }
358 }
359
360 span->arrayAttribs |= FRAG_BIT_COL0;
361 span->array->ChanType = GL_FLOAT;
362 }
363
364
365
366 /**
367 * Fill in the span.zArray array from the span->z, zStep values.
368 */
369 void
370 _swrast_span_interpolate_z( const struct gl_context *ctx, SWspan *span )
371 {
372 const GLuint n = span->end;
373 GLuint i;
374
375 ASSERT(!(span->arrayMask & SPAN_Z));
376
377 if (ctx->DrawBuffer->Visual.depthBits <= 16) {
378 GLfixed zval = span->z;
379 GLuint *z = span->array->z;
380 for (i = 0; i < n; i++) {
381 z[i] = FixedToInt(zval);
382 zval += span->zStep;
383 }
384 }
385 else {
386 /* Deep Z buffer, no fixed->int shift */
387 GLuint zval = span->z;
388 GLuint *z = span->array->z;
389 for (i = 0; i < n; i++) {
390 z[i] = zval;
391 zval += span->zStep;
392 }
393 }
394 span->interpMask &= ~SPAN_Z;
395 span->arrayMask |= SPAN_Z;
396 }
397
398
399 /**
400 * Compute mipmap LOD from partial derivatives.
401 * This the ideal solution, as given in the OpenGL spec.
402 */
403 GLfloat
404 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
405 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
406 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
407 {
408 GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
409 GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
410 GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
411 GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
412 GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
413 GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
414 GLfloat rho = MAX2(x, y);
415 GLfloat lambda = LOG2(rho);
416 return lambda;
417 }
418
419
420 /**
421 * Compute mipmap LOD from partial derivatives.
422 * This is a faster approximation than above function.
423 */
424 #if 0
425 GLfloat
426 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
427 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
428 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
429 {
430 GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
431 GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
432 GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
433 GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
434 GLfloat maxU, maxV, rho, lambda;
435 dsdx2 = FABSF(dsdx2);
436 dsdy2 = FABSF(dsdy2);
437 dtdx2 = FABSF(dtdx2);
438 dtdy2 = FABSF(dtdy2);
439 maxU = MAX2(dsdx2, dsdy2) * texW;
440 maxV = MAX2(dtdx2, dtdy2) * texH;
441 rho = MAX2(maxU, maxV);
442 lambda = LOG2(rho);
443 return lambda;
444 }
445 #endif
446
447
448 /**
449 * Fill in the span.array->attrib[FRAG_ATTRIB_TEXn] arrays from the
450 * using the attrStart/Step values.
451 *
452 * This function only used during fixed-function fragment processing.
453 *
454 * Note: in the places where we divide by Q (or mult by invQ) we're
455 * really doing two things: perspective correction and texcoord
456 * projection. Remember, for texcoord (s,t,r,q) we need to index
457 * texels with (s/q, t/q, r/q).
458 */
459 static void
460 interpolate_texcoords(struct gl_context *ctx, SWspan *span)
461 {
462 if (ctx->Texture._EnabledCoord) {
463 const GLuint attr = FRAG_ATTRIB_TEX;
464 const struct gl_texture_object *obj = ctx->Texture.Unit._Current;
465 GLfloat texW, texH;
466 GLboolean needLambda;
467 GLfloat (*texcoord)[4] = span->array->attribs[attr];
468 GLfloat *lambda = span->array->lambda;
469 const GLfloat dsdx = span->attrStepX[attr][0];
470 const GLfloat dsdy = span->attrStepY[attr][0];
471 const GLfloat dtdx = span->attrStepX[attr][1];
472 const GLfloat dtdy = span->attrStepY[attr][1];
473 const GLfloat drdx = span->attrStepX[attr][2];
474 const GLfloat dqdx = span->attrStepX[attr][3];
475 const GLfloat dqdy = span->attrStepY[attr][3];
476 GLfloat s = span->attrStart[attr][0] + span->leftClip * dsdx;
477 GLfloat t = span->attrStart[attr][1] + span->leftClip * dtdx;
478 GLfloat r = span->attrStart[attr][2] + span->leftClip * drdx;
479 GLfloat q = span->attrStart[attr][3] + span->leftClip * dqdx;
480
481 if (obj) {
482 const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
483 const struct swrast_texture_image *swImg =
484 swrast_texture_image_const(img);
485
486 needLambda = (obj->Sampler.MinFilter != obj->Sampler.MagFilter);
487 /* LOD is calculated directly in the ansiotropic filter, we can
488 * skip the normal lambda function as the result is ignored.
489 */
490 if (obj->Sampler.MaxAnisotropy > 1.0 &&
491 obj->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
492 needLambda = GL_FALSE;
493 }
494 texW = swImg->WidthScale;
495 texH = swImg->HeightScale;
496 }
497 else {
498 /* using a fragment program */
499 texW = 1.0;
500 texH = 1.0;
501 needLambda = GL_FALSE;
502 }
503
504 if (needLambda) {
505 GLuint i;
506 for (i = 0; i < span->end; i++) {
507 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
508 texcoord[i][0] = s * invQ;
509 texcoord[i][1] = t * invQ;
510 texcoord[i][2] = r * invQ;
511 texcoord[i][3] = q;
512 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
513 dqdx, dqdy, texW, texH,
514 s, t, q, invQ);
515 s += dsdx;
516 t += dtdx;
517 r += drdx;
518 q += dqdx;
519 }
520 span->arrayMask |= SPAN_LAMBDA;
521 }
522 else {
523 GLuint i;
524 if (dqdx == 0.0F) {
525 /* Ortho projection or polygon's parallel to window X axis */
526 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
527 for (i = 0; i < span->end; i++) {
528 texcoord[i][0] = s * invQ;
529 texcoord[i][1] = t * invQ;
530 texcoord[i][2] = r * invQ;
531 texcoord[i][3] = q;
532 lambda[i] = 0.0;
533 s += dsdx;
534 t += dtdx;
535 r += drdx;
536 }
537 }
538 else {
539 for (i = 0; i < span->end; i++) {
540 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
541 texcoord[i][0] = s * invQ;
542 texcoord[i][1] = t * invQ;
543 texcoord[i][2] = r * invQ;
544 texcoord[i][3] = q;
545 lambda[i] = 0.0;
546 s += dsdx;
547 t += dtdx;
548 r += drdx;
549 q += dqdx;
550 }
551 }
552 } /* lambda */
553 } /* if */
554 }
555
556
557 /**
558 * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array.
559 */
560 static inline void
561 interpolate_wpos(struct gl_context *ctx, SWspan *span)
562 {
563 GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS];
564 GLuint i;
565 const GLfloat zScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
566 GLfloat w, dw;
567
568 if (span->arrayMask & SPAN_XY) {
569 for (i = 0; i < span->end; i++) {
570 wpos[i][0] = (GLfloat) span->array->x[i];
571 wpos[i][1] = (GLfloat) span->array->y[i];
572 }
573 }
574 else {
575 for (i = 0; i < span->end; i++) {
576 wpos[i][0] = (GLfloat) span->x + i;
577 wpos[i][1] = (GLfloat) span->y;
578 }
579 }
580
581 dw = span->attrStepX[FRAG_ATTRIB_WPOS][3];
582 w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dw;
583 for (i = 0; i < span->end; i++) {
584 wpos[i][2] = (GLfloat) span->array->z[i] * zScale;
585 wpos[i][3] = w;
586 w += dw;
587 }
588 }
589
590
591 /**
592 * Apply the current polygon stipple pattern to a span of pixels.
593 */
594 static inline void
595 stipple_polygon_span(struct gl_context *ctx, SWspan *span)
596 {
597 GLubyte *mask = span->array->mask;
598
599 ASSERT(ctx->Polygon.StippleFlag);
600
601 if (span->arrayMask & SPAN_XY) {
602 /* arrays of x/y pixel coords */
603 GLuint i;
604 for (i = 0; i < span->end; i++) {
605 const GLint col = span->array->x[i] % 32;
606 const GLint row = span->array->y[i] % 32;
607 const GLuint stipple = ctx->PolygonStipple[row];
608 if (((1 << col) & stipple) == 0) {
609 mask[i] = 0;
610 }
611 }
612 }
613 else {
614 /* horizontal span of pixels */
615 const GLuint highBit = 1 << 31;
616 const GLuint stipple = ctx->PolygonStipple[span->y % 32];
617 GLuint i, m = highBit >> (GLuint) (span->x % 32);
618 for (i = 0; i < span->end; i++) {
619 if ((m & stipple) == 0) {
620 mask[i] = 0;
621 }
622 m = m >> 1;
623 if (m == 0) {
624 m = highBit;
625 }
626 }
627 }
628 span->writeAll = GL_FALSE;
629 }
630
631
632 /**
633 * Clip a pixel span to the current buffer/window boundaries:
634 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
635 * window clipping and scissoring.
636 * Return: GL_TRUE some pixels still visible
637 * GL_FALSE nothing visible
638 */
639 static inline GLuint
640 clip_span( struct gl_context *ctx, SWspan *span )
641 {
642 const GLint xmin = ctx->DrawBuffer->_Xmin;
643 const GLint xmax = ctx->DrawBuffer->_Xmax;
644 const GLint ymin = ctx->DrawBuffer->_Ymin;
645 const GLint ymax = ctx->DrawBuffer->_Ymax;
646
647 span->leftClip = 0;
648
649 if (span->arrayMask & SPAN_XY) {
650 /* arrays of x/y pixel coords */
651 const GLint *x = span->array->x;
652 const GLint *y = span->array->y;
653 const GLint n = span->end;
654 GLubyte *mask = span->array->mask;
655 GLint i;
656 GLuint passed = 0;
657 if (span->arrayMask & SPAN_MASK) {
658 /* note: using & intead of && to reduce branches */
659 for (i = 0; i < n; i++) {
660 mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
661 & (y[i] >= ymin) & (y[i] < ymax);
662 passed += mask[i];
663 }
664 }
665 else {
666 /* note: using & intead of && to reduce branches */
667 for (i = 0; i < n; i++) {
668 mask[i] = (x[i] >= xmin) & (x[i] < xmax)
669 & (y[i] >= ymin) & (y[i] < ymax);
670 passed += mask[i];
671 }
672 }
673 return passed > 0;
674 }
675 else {
676 /* horizontal span of pixels */
677 const GLint x = span->x;
678 const GLint y = span->y;
679 GLint n = span->end;
680
681 /* Trivial rejection tests */
682 if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
683 span->end = 0;
684 return GL_FALSE; /* all pixels clipped */
685 }
686
687 /* Clip to right */
688 if (x + n > xmax) {
689 ASSERT(x < xmax);
690 n = span->end = xmax - x;
691 }
692
693 /* Clip to the left */
694 if (x < xmin) {
695 const GLint leftClip = xmin - x;
696 GLuint i;
697
698 ASSERT(leftClip > 0);
699 ASSERT(x + n > xmin);
700
701 /* Clip 'leftClip' pixels from the left side.
702 * The span->leftClip field will be applied when we interpolate
703 * fragment attributes.
704 * For arrays of values, shift them left.
705 */
706 for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
707 if (span->interpMask & (1 << i)) {
708 GLuint j;
709 for (j = 0; j < 4; j++) {
710 span->attrStart[i][j] += leftClip * span->attrStepX[i][j];
711 }
712 }
713 }
714
715 span->red += leftClip * span->redStep;
716 span->green += leftClip * span->greenStep;
717 span->blue += leftClip * span->blueStep;
718 span->alpha += leftClip * span->alphaStep;
719 span->index += leftClip * span->indexStep;
720 span->z += leftClip * span->zStep;
721 span->intTex[0] += leftClip * span->intTexStep[0];
722 span->intTex[1] += leftClip * span->intTexStep[1];
723
724 #define SHIFT_ARRAY(ARRAY, SHIFT, LEN) \
725 memmove(ARRAY, ARRAY + (SHIFT), (LEN) * sizeof(ARRAY[0]))
726
727 for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
728 if (span->arrayAttribs & (1 << i)) {
729 /* shift array elements left by 'leftClip' */
730 SHIFT_ARRAY(span->array->attribs[i], leftClip, n - leftClip);
731 }
732 }
733
734 SHIFT_ARRAY(span->array->mask, leftClip, n - leftClip);
735 SHIFT_ARRAY(span->array->rgba8, leftClip, n - leftClip);
736 SHIFT_ARRAY(span->array->rgba16, leftClip, n - leftClip);
737 SHIFT_ARRAY(span->array->x, leftClip, n - leftClip);
738 SHIFT_ARRAY(span->array->y, leftClip, n - leftClip);
739 SHIFT_ARRAY(span->array->z, leftClip, n - leftClip);
740 SHIFT_ARRAY(span->array->index, leftClip, n - leftClip);
741 SHIFT_ARRAY(span->array->lambda, leftClip, n - leftClip);
742 SHIFT_ARRAY(span->array->coverage, leftClip, n - leftClip);
743
744 #undef SHIFT_ARRAY
745
746 span->leftClip = leftClip;
747 span->x = xmin;
748 span->end -= leftClip;
749 span->writeAll = GL_FALSE;
750 }
751
752 ASSERT(span->x >= xmin);
753 ASSERT(span->x + span->end <= xmax);
754 ASSERT(span->y >= ymin);
755 ASSERT(span->y < ymax);
756
757 return GL_TRUE; /* some pixels visible */
758 }
759 }
760
761
762 /**
763 * Add specular colors to primary colors.
764 * Only called during fixed-function operation.
765 * Result is float color array (FRAG_ATTRIB_COL0).
766 */
767 static inline void
768 add_specular(struct gl_context *ctx, SWspan *span)
769 {
770 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
771 const GLubyte *mask = span->array->mask;
772 GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
773 GLfloat (*col1)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
774 GLuint i;
775
776 ASSERT(!_swrast_use_fragment_program(ctx));
777 ASSERT(span->arrayMask & SPAN_RGBA);
778 ASSERT(swrast->_ActiveAttribMask & FRAG_BIT_COL1);
779 (void) swrast; /* silence warning */
780
781 if (span->array->ChanType == GL_FLOAT) {
782 if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
783 interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
784 }
785 }
786 else {
787 /* need float colors */
788 if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
789 interpolate_float_colors(span);
790 }
791 }
792
793 if ((span->arrayAttribs & FRAG_BIT_COL1) == 0) {
794 /* XXX could avoid this and interpolate COL1 in the loop below */
795 interpolate_active_attribs(ctx, span, FRAG_BIT_COL1);
796 }
797
798 ASSERT(span->arrayAttribs & FRAG_BIT_COL0);
799 ASSERT(span->arrayAttribs & FRAG_BIT_COL1);
800
801 for (i = 0; i < span->end; i++) {
802 if (mask[i]) {
803 col0[i][0] += col1[i][0];
804 col0[i][1] += col1[i][1];
805 col0[i][2] += col1[i][2];
806 }
807 }
808
809 span->array->ChanType = GL_FLOAT;
810 }
811
812
813 /**
814 * Apply antialiasing coverage value to alpha values.
815 */
816 static inline void
817 apply_aa_coverage(SWspan *span)
818 {
819 const GLfloat *coverage = span->array->coverage;
820 GLuint i;
821 if (span->array->ChanType == GL_UNSIGNED_BYTE) {
822 GLubyte (*rgba)[4] = span->array->rgba8;
823 for (i = 0; i < span->end; i++) {
824 const GLfloat a = rgba[i][ACOMP] * coverage[i];
825 rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0);
826 ASSERT(coverage[i] >= 0.0);
827 ASSERT(coverage[i] <= 1.0);
828 }
829 }
830 else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
831 GLushort (*rgba)[4] = span->array->rgba16;
832 for (i = 0; i < span->end; i++) {
833 const GLfloat a = rgba[i][ACOMP] * coverage[i];
834 rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0);
835 }
836 }
837 else {
838 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
839 for (i = 0; i < span->end; i++) {
840 rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
841 /* clamp later */
842 }
843 }
844 }
845
846
847 /**
848 * Clamp span's float colors to [0,1]
849 */
850 static inline void
851 clamp_colors(SWspan *span)
852 {
853 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
854 GLuint i;
855 ASSERT(span->array->ChanType == GL_FLOAT);
856 for (i = 0; i < span->end; i++) {
857 rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
858 rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
859 rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
860 rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
861 }
862 }
863
864
865 /**
866 * Convert the span's color arrays to the given type.
867 * The only way 'output' can be greater than zero is when we have a fragment
868 * program that writes to gl_FragData[1] or higher.
869 * \param output which fragment program color output is being processed
870 */
871 static inline void
872 convert_color_type(SWspan *span, GLenum newType, GLuint output)
873 {
874 GLvoid *src, *dst;
875
876 if (output > 0 || span->array->ChanType == GL_FLOAT) {
877 src = span->array->attribs[FRAG_ATTRIB_COL0 + output];
878 span->array->ChanType = GL_FLOAT;
879 }
880 else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
881 src = span->array->rgba8;
882 }
883 else {
884 ASSERT(span->array->ChanType == GL_UNSIGNED_SHORT);
885 src = span->array->rgba16;
886 }
887
888 if (newType == GL_UNSIGNED_BYTE) {
889 dst = span->array->rgba8;
890 }
891 else if (newType == GL_UNSIGNED_SHORT) {
892 dst = span->array->rgba16;
893 }
894 else {
895 dst = span->array->attribs[FRAG_ATTRIB_COL0];
896 }
897
898 _mesa_convert_colors(span->array->ChanType, src,
899 newType, dst,
900 span->end, span->array->mask);
901
902 span->array->ChanType = newType;
903 span->array->rgba = dst;
904 }
905
906
907
908 /**
909 * Apply fragment shader, fragment program or normal texturing to span.
910 */
911 static inline void
912 shade_texture_span(struct gl_context *ctx, SWspan *span)
913 {
914 if (ctx->Texture._EnabledCoord) {
915 /* conventional texturing */
916
917 #if CHAN_BITS == 32
918 if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
919 interpolate_int_colors(ctx, span);
920 }
921 #else
922 if (!(span->arrayMask & SPAN_RGBA))
923 interpolate_int_colors(ctx, span);
924 #endif
925 if (!(span->arrayAttribs & FRAG_BIT_TEX))
926 interpolate_texcoords(ctx, span);
927
928 _swrast_texture_span(ctx, span);
929 }
930 }
931
932
933 /** Put colors at x/y locations into a renderbuffer */
934 static void
935 put_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
936 GLenum datatype,
937 GLuint count, const GLint x[], const GLint y[],
938 const void *values, const GLubyte *mask)
939 {
940 gl_pack_ubyte_rgba_func pack_ubyte;
941 gl_pack_float_rgba_func pack_float;
942 GLuint i;
943
944 if (datatype == GL_UNSIGNED_BYTE)
945 pack_ubyte = _mesa_get_pack_ubyte_rgba_function(rb->Format);
946 else
947 pack_float = _mesa_get_pack_float_rgba_function(rb->Format);
948
949 for (i = 0; i < count; i++) {
950 if (mask[i]) {
951 GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]);
952
953 if (datatype == GL_UNSIGNED_BYTE) {
954 pack_ubyte((const GLubyte *) values + 4 * i, dst);
955 }
956 else {
957 assert(datatype == GL_FLOAT);
958 pack_float((const GLfloat *) values + 4 * i, dst);
959 }
960 }
961 }
962 }
963
964
965 /** Put row of colors into renderbuffer */
966 void
967 _swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
968 GLenum datatype,
969 GLuint count, GLint x, GLint y,
970 const void *values, const GLubyte *mask)
971 {
972 GLubyte *dst = _swrast_pixel_address(rb, x, y);
973
974 if (!mask) {
975 if (datatype == GL_UNSIGNED_BYTE) {
976 _mesa_pack_ubyte_rgba_row(rb->Format, count,
977 (const GLubyte (*)[4]) values, dst);
978 }
979 else {
980 assert(datatype == GL_FLOAT);
981 _mesa_pack_float_rgba_row(rb->Format, count,
982 (const GLfloat (*)[4]) values, dst);
983 }
984 }
985 else {
986 const GLuint bpp = _mesa_get_format_bytes(rb->Format);
987 GLuint i, runLen, runStart;
988 /* We can't pass a 'mask' array to the _mesa_pack_rgba_row() functions
989 * so look for runs where mask=1...
990 */
991 runLen = runStart = 0;
992 for (i = 0; i < count; i++) {
993 if (mask[i]) {
994 if (runLen == 0)
995 runStart = i;
996 runLen++;
997 }
998
999 if (!mask[i] || i == count - 1) {
1000 /* might be the end of a run of pixels */
1001 if (runLen > 0) {
1002 if (datatype == GL_UNSIGNED_BYTE) {
1003 _mesa_pack_ubyte_rgba_row(rb->Format, runLen,
1004 (const GLubyte (*)[4]) values + runStart,
1005 dst + runStart * bpp);
1006 }
1007 else {
1008 assert(datatype == GL_FLOAT);
1009 _mesa_pack_float_rgba_row(rb->Format, runLen,
1010 (const GLfloat (*)[4]) values + runStart,
1011 dst + runStart * bpp);
1012 }
1013 runLen = 0;
1014 }
1015 }
1016 }
1017 }
1018 }
1019
1020
1021
1022 /**
1023 * Apply all the per-fragment operations to a span.
1024 * This now includes texturing (_swrast_write_texture_span() is history).
1025 * This function may modify any of the array values in the span.
1026 * span->interpMask and span->arrayMask may be changed but will be restored
1027 * to their original values before returning.
1028 */
1029 void
1030 _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
1031 {
1032 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1033 const GLuint colorMask = *((GLuint *)ctx->Color.ColorMask);
1034 const GLbitfield origInterpMask = span->interpMask;
1035 const GLbitfield origArrayMask = span->arrayMask;
1036 const GLbitfield64 origArrayAttribs = span->arrayAttribs;
1037 const GLenum origChanType = span->array->ChanType;
1038 void * const origRgba = span->array->rgba;
1039 const GLboolean texture = ctx->Texture._EnabledCoord;
1040 struct gl_framebuffer *fb = ctx->DrawBuffer;
1041
1042 /*
1043 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__,
1044 span->interpMask, span->arrayMask);
1045 */
1046
1047 ASSERT(span->primitive == GL_POINT ||
1048 span->primitive == GL_LINE ||
1049 span->primitive == GL_POLYGON ||
1050 span->primitive == GL_BITMAP);
1051
1052 /* Fragment write masks */
1053 if (span->arrayMask & SPAN_MASK) {
1054 /* mask was initialized by caller, probably glBitmap */
1055 span->writeAll = GL_FALSE;
1056 }
1057 else {
1058 memset(span->array->mask, 1, span->end);
1059 span->writeAll = GL_TRUE;
1060 }
1061
1062 /* Clip to window/scissor box */
1063 if (!clip_span(ctx, span)) {
1064 return;
1065 }
1066
1067 ASSERT(span->end <= MAX_WIDTH);
1068
1069 /* Depth bounds test */
1070 if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) {
1071 if (!_swrast_depth_bounds_test(ctx, span)) {
1072 return;
1073 }
1074 }
1075
1076 #ifdef DEBUG
1077 /* Make sure all fragments are within window bounds */
1078 if (span->arrayMask & SPAN_XY) {
1079 /* array of pixel locations */
1080 GLuint i;
1081 for (i = 0; i < span->end; i++) {
1082 if (span->array->mask[i]) {
1083 assert(span->array->x[i] >= fb->_Xmin);
1084 assert(span->array->x[i] < fb->_Xmax);
1085 assert(span->array->y[i] >= fb->_Ymin);
1086 assert(span->array->y[i] < fb->_Ymax);
1087 }
1088 }
1089 }
1090 #endif
1091
1092 /* Polygon Stippling */
1093 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1094 stipple_polygon_span(ctx, span);
1095 }
1096
1097 /* This is the normal place to compute the fragment color/Z
1098 * from texturing or shading.
1099 */
1100 if (texture && !swrast->_DeferredTexture) {
1101 shade_texture_span(ctx, span);
1102 }
1103
1104 /* Do the alpha test */
1105 if (ctx->Color.AlphaEnabled) {
1106 if (!_swrast_alpha_test(ctx, span)) {
1107 /* all fragments failed test */
1108 goto end;
1109 }
1110 }
1111
1112 /* Stencil and Z testing */
1113 if (ctx->Stencil._Enabled || ctx->Depth.Test) {
1114 if (!(span->arrayMask & SPAN_Z))
1115 _swrast_span_interpolate_z(ctx, span);
1116
1117 if (ctx->Stencil._Enabled) {
1118 /* Combined Z/stencil tests */
1119 if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1120 /* all fragments failed test */
1121 goto end;
1122 }
1123 }
1124 else if (fb->Visual.depthBits > 0) {
1125 /* Just regular depth testing */
1126 ASSERT(ctx->Depth.Test);
1127 ASSERT(span->arrayMask & SPAN_Z);
1128 if (!_swrast_depth_test_span(ctx, span)) {
1129 /* all fragments failed test */
1130 goto end;
1131 }
1132 }
1133 }
1134
1135 /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1136 * the occlusion test.
1137 */
1138 if (colorMask == 0) {
1139 /* no colors to write */
1140 goto end;
1141 }
1142
1143 /* If we were able to defer fragment color computation to now, there's
1144 * a good chance that many fragments will have already been killed by
1145 * Z/stencil testing.
1146 */
1147 if (texture && swrast->_DeferredTexture) {
1148 shade_texture_span(ctx, span);
1149 }
1150
1151 #if CHAN_BITS == 32
1152 if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
1153 interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
1154 }
1155 #else
1156 if ((span->arrayMask & SPAN_RGBA) == 0) {
1157 interpolate_int_colors(ctx, span);
1158 }
1159 #endif
1160
1161 ASSERT(span->arrayMask & SPAN_RGBA);
1162
1163 if (span->primitive == GL_BITMAP || !swrast->SpecularVertexAdd) {
1164 /* Add primary and specular (diffuse + specular) colors */
1165 if (ctx->Fog.ColorSumEnabled ||
1166 (ctx->Light.Enabled &&
1167 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1168 add_specular(ctx, span);
1169 }
1170 }
1171
1172 /* Fog */
1173 if (swrast->_FogEnabled) {
1174 _swrast_fog_rgba_span(ctx, span);
1175 }
1176
1177 /* Antialias coverage application */
1178 if (span->arrayMask & SPAN_COVERAGE) {
1179 apply_aa_coverage(span);
1180 }
1181
1182 /*
1183 * Write to renderbuffers.
1184 * Depending on glDrawBuffer() state and the which color outputs are
1185 * written by the fragment shader, we may either replicate one color to
1186 * all renderbuffers or write a different color to each renderbuffer.
1187 * multiFragOutputs=TRUE for the later case.
1188 */
1189 {
1190 struct gl_renderbuffer *rb = fb->_ColorDrawBuffer;
1191
1192 /* color[fragOutput] will be written to buffer */
1193
1194 if (rb) {
1195 struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
1196 GLenum colorType = srb->ColorType;
1197
1198 assert(colorType == GL_UNSIGNED_BYTE ||
1199 colorType == GL_FLOAT);
1200
1201 /* set span->array->rgba to colors for renderbuffer's datatype */
1202 if (span->array->ChanType != colorType) {
1203 convert_color_type(span, colorType, 0);
1204 }
1205 else {
1206 if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1207 span->array->rgba = span->array->rgba8;
1208 }
1209 else {
1210 span->array->rgba = (void *)span->array->attribs[FRAG_ATTRIB_COL0];
1211 }
1212 }
1213
1214
1215 ASSERT(rb->_BaseFormat == GL_RGBA ||
1216 rb->_BaseFormat == GL_RGB ||
1217 rb->_BaseFormat == GL_RED ||
1218 rb->_BaseFormat == GL_RG ||
1219 rb->_BaseFormat == GL_ALPHA);
1220
1221 if (ctx->Color.ColorLogicOpEnabled) {
1222 _swrast_logicop_rgba_span(ctx, rb, span);
1223 }
1224 else if (ctx->Color.BlendEnabled) {
1225 _swrast_blend_span(ctx, rb, span);
1226 }
1227
1228 if (colorMask != 0xffffffff) {
1229 _swrast_mask_rgba_span(ctx, rb, span);
1230 }
1231
1232 if (span->arrayMask & SPAN_XY) {
1233 /* array of pixel coords */
1234 put_values(ctx, rb,
1235 span->array->ChanType, span->end,
1236 span->array->x, span->array->y,
1237 span->array->rgba, span->array->mask);
1238 }
1239 else {
1240 /* horizontal run of pixels */
1241 _swrast_put_row(ctx, rb,
1242 span->array->ChanType,
1243 span->end, span->x, span->y,
1244 span->array->rgba,
1245 span->writeAll ? NULL: span->array->mask);
1246 }
1247
1248 } /* if rb */
1249 }
1250
1251 end:
1252 /* restore these values before returning */
1253 span->interpMask = origInterpMask;
1254 span->arrayMask = origArrayMask;
1255 span->arrayAttribs = origArrayAttribs;
1256 span->array->ChanType = origChanType;
1257 span->array->rgba = origRgba;
1258 }
1259
1260
1261 /**
1262 * Read float RGBA pixels from a renderbuffer. Clipping will be done to
1263 * prevent reading ouside the buffer's boundaries.
1264 * \param rgba the returned colors
1265 */
1266 void
1267 _swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb,
1268 GLuint n, GLint x, GLint y,
1269 GLvoid *rgba)
1270 {
1271 struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
1272 GLenum dstType = GL_FLOAT;
1273 const GLint bufWidth = (GLint) rb->Width;
1274 const GLint bufHeight = (GLint) rb->Height;
1275
1276 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1277 /* completely above, below, or right */
1278 /* XXX maybe leave rgba values undefined? */
1279 memset(rgba, 0, 4 * n * sizeof(GLchan));
1280 }
1281 else {
1282 GLint skip, length;
1283 GLubyte *src;
1284
1285 if (x < 0) {
1286 /* left edge clipping */
1287 skip = -x;
1288 length = (GLint) n - skip;
1289 if (length < 0) {
1290 /* completely left of window */
1291 return;
1292 }
1293 if (length > bufWidth) {
1294 length = bufWidth;
1295 }
1296 }
1297 else if ((GLint) (x + n) > bufWidth) {
1298 /* right edge clipping */
1299 skip = 0;
1300 length = bufWidth - x;
1301 if (length < 0) {
1302 /* completely to right of window */
1303 return;
1304 }
1305 }
1306 else {
1307 /* no clipping */
1308 skip = 0;
1309 length = (GLint) n;
1310 }
1311
1312 ASSERT(rb);
1313 ASSERT(rb->_BaseFormat == GL_RGBA ||
1314 rb->_BaseFormat == GL_RGB ||
1315 rb->_BaseFormat == GL_RG ||
1316 rb->_BaseFormat == GL_RED ||
1317 rb->_BaseFormat == GL_LUMINANCE ||
1318 rb->_BaseFormat == GL_INTENSITY ||
1319 rb->_BaseFormat == GL_LUMINANCE_ALPHA ||
1320 rb->_BaseFormat == GL_ALPHA);
1321
1322 assert(srb->Map);
1323
1324 src = _swrast_pixel_address(rb, x + skip, y);
1325
1326 if (dstType == GL_UNSIGNED_BYTE) {
1327 _mesa_unpack_ubyte_rgba_row(rb->Format, length, src,
1328 (GLubyte (*)[4]) rgba + skip);
1329 }
1330 else if (dstType == GL_FLOAT) {
1331 _mesa_unpack_rgba_row(rb->Format, length, src,
1332 (GLfloat (*)[4]) rgba + skip);
1333 }
1334 else {
1335 _mesa_problem(ctx, "unexpected type in _swrast_read_rgba_span()");
1336 }
1337 }
1338 }
1339
1340
1341 /**
1342 * Get colors at x/y positions with clipping.
1343 * \param type type of values to return
1344 */
1345 static void
1346 get_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
1347 GLuint count, const GLint x[], const GLint y[],
1348 void *values, GLenum type)
1349 {
1350 GLuint i;
1351
1352 for (i = 0; i < count; i++) {
1353 if (x[i] >= 0 && y[i] >= 0 &&
1354 x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
1355 /* inside */
1356 const GLubyte *src = _swrast_pixel_address(rb, x[i], y[i]);
1357
1358 if (type == GL_UNSIGNED_BYTE) {
1359 _mesa_unpack_ubyte_rgba_row(rb->Format, 1, src,
1360 (GLubyte (*)[4]) values + i);
1361 }
1362 else if (type == GL_FLOAT) {
1363 _mesa_unpack_rgba_row(rb->Format, 1, src,
1364 (GLfloat (*)[4]) values + i);
1365 }
1366 else {
1367 _mesa_problem(ctx, "unexpected type in get_values()");
1368 }
1369 }
1370 }
1371 }
1372
1373
1374 /**
1375 * Get row of colors with clipping.
1376 * \param type type of values to return
1377 */
1378 static void
1379 get_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
1380 GLuint count, GLint x, GLint y,
1381 GLvoid *values, GLenum type)
1382 {
1383 GLint skip = 0;
1384 GLubyte *src;
1385
1386 if (y < 0 || y >= (GLint) rb->Height)
1387 return; /* above or below */
1388
1389 if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
1390 return; /* entirely left or right */
1391
1392 if (x + count > rb->Width) {
1393 /* right clip */
1394 GLint clip = x + count - rb->Width;
1395 count -= clip;
1396 }
1397
1398 if (x < 0) {
1399 /* left clip */
1400 skip = -x;
1401 x = 0;
1402 count -= skip;
1403 }
1404
1405 src = _swrast_pixel_address(rb, x, y);
1406
1407 if (type == GL_UNSIGNED_BYTE) {
1408 _mesa_unpack_ubyte_rgba_row(rb->Format, count, src,
1409 (GLubyte (*)[4]) values + skip);
1410 }
1411 else if (type == GL_FLOAT) {
1412 _mesa_unpack_rgba_row(rb->Format, count, src,
1413 (GLfloat (*)[4]) values + skip);
1414 }
1415 else {
1416 _mesa_problem(ctx, "unexpected type in get_row()");
1417 }
1418 }
1419
1420
1421 /**
1422 * Get RGBA pixels from the given renderbuffer.
1423 * Used by blending, logicop and masking functions.
1424 * \return pointer to the colors we read.
1425 */
1426 void *
1427 _swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb,
1428 SWspan *span)
1429 {
1430 void *rbPixels;
1431
1432 /* Point rbPixels to a temporary space */
1433 rbPixels = span->array->attribs[FRAG_ATTRIB_MAX - 1];
1434
1435 /* Get destination values from renderbuffer */
1436 if (span->arrayMask & SPAN_XY) {
1437 get_values(ctx, rb, span->end, span->array->x, span->array->y,
1438 rbPixels, span->array->ChanType);
1439 }
1440 else {
1441 get_row(ctx, rb, span->end, span->x, span->y,
1442 rbPixels, span->array->ChanType);
1443 }
1444
1445 return rbPixels;
1446 }