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